0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-13 02:28:18 -05:00

🐛 Fix text focus issues

This commit is contained in:
alonso.torres 2021-07-16 13:09:57 +02:00
parent 9ebafddac2
commit 1fc5182979
10 changed files with 118 additions and 57 deletions

View file

@ -60,7 +60,7 @@
(a/close! output)))
(defn- send-mattermost-notification!
[cfg {:keys [host version id] :as cdata}]
[cfg {:keys [host id] :as cdata}]
(try
(let [uri (:uri cfg)
text (str "Unhandled exception (host: " host ", url: " (cfg/get :public-uri) "/dbg/error-by-id/" id "\n"

View file

@ -258,7 +258,7 @@
(defmethod migrate 11
[data]
(letfn [(update-object [objects id shape]
(letfn [(update-object [objects _id shape]
(if (= :frame (:type shape))
(d/update-when shape :shapes (fn [shapes]
(filterv (fn [id] (contains? objects id)) shapes)))

View file

@ -203,8 +203,11 @@
(when-not (some? (get-in state [:workspace-editor-state id]))
(let [objects (wsh/lookup-page-objects state)
shape (get objects id)
update-node? (fn [node]
(or (txt/is-text-node? node)
(txt/is-paragraph-node? node)))
update-fn #(update-shape % txt/is-text-node? attrs/merge attrs)
update-fn #(update-shape % update-node? attrs/merge attrs)
shape-ids (cond (= (:type shape) :text) [id]
(= (:type shape) :group) (cp/get-children id objects))]
(rx/of (dch/update-shapes shape-ids update-fn)))))))
@ -325,8 +328,8 @@
(ptk/reify ::save-font
ptk/UpdateEvent
(update [_ state]
;; Check if the data has any multiple
(assoc-in state
[:workspace-local :defaults :font]
data))))
(let [multiple? (->> data vals (d/seek #(= % :multiple)))]
(cond-> state
(not multiple?)
(assoc-in [:workspace-local :defaults :font] data))))))

View file

@ -14,19 +14,23 @@
[app.util.timers :as timers]
[rumext.alpha :as mf]))
(mf/defc editable-select [{:keys [value type options class on-change placeholder]}]
(mf/defc editable-select [{:keys [value type options class on-change placeholder on-blur]}]
(let [state (mf/use-state {:id (uuid/next)
:is-open? false
:current-value value
:top nil
:left nil
:bottom nil})
emit-blur? (mf/use-ref nil)
open-dropdown #(swap! state assoc :is-open? true)
close-dropdown #(swap! state assoc :is-open? false)
select-item (fn [value]
(fn [_]
(swap! state assoc :current-value value)
(when on-change (on-change value))))
(when on-change (on-change value))
(when on-blur (on-blur))))
as-key-value (fn [item] (if (map? item) [(:value item) (:label item)] [item item]))
@ -55,21 +59,38 @@
assoc
:left left
:top top
:bottom bottom))))))]
:bottom bottom))))))
handle-focus
(mf/use-callback
(fn []
(mf/set-ref-val! emit-blur? false)))
handle-blur
(mf/use-callback
(fn []
(mf/set-ref-val! emit-blur? true)
(timers/schedule
200
(fn []
(when (and on-blur (mf/ref-val emit-blur?)) (on-blur))))))]
(mf/use-effect
(mf/deps value)
#(reset! state {:current-value value}))
(mf/deps value (:current-value @state))
#(when (not= value (:current-value @state))
(reset! state {:current-value value})))
(mf/use-effect
(mf/deps options)
#(reset! state {:is-open? false
:current-value value}))
(mf/deps (:is-open? @state))
(fn []
(mf/set-ref-val! emit-blur? (not (:is-open? @state)))))
[:div.editable-select {:class class
:ref on-node-load}
[:input.input-text {:value (or (-> @state :current-value value->label) "")
:on-change handle-change-input
:on-focus handle-focus
:on-blur handle-blur
:placeholder placeholder
:type type}]
[:span.dropdown-button {:on-click open-dropdown} i/arrow-down]

View file

@ -157,11 +157,11 @@
on-change
(mf/use-callback
(fn [val]
(let [val (handle-change val)]
(let [val (if (true? @blured)
(ted/add-editor-blur-selection val)
(ted/remove-editor-blur-selection val))]
(st/emit! (dwt/update-editor-state shape val))))))
(let [val (handle-change val)
val (if (true? @blured)
(ted/add-editor-blur-selection val)
(ted/remove-editor-blur-selection val))]
(st/emit! (dwt/update-editor-state shape val)))))
on-editor
(mf/use-callback

View file

@ -20,6 +20,7 @@
[app.main.ui.workspace.sidebar.options.menus.typography :refer [typography-entry typography-options]]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.timers :as tm]
[cuerdas.core :as str]
[rumext.alpha :as mf]))
@ -80,11 +81,12 @@
(def attrs (d/concat #{} shape-attrs root-attrs paragraph-attrs text-attrs))
(mf/defc text-align-options
[{:keys [values on-change] :as props}]
[{:keys [values on-change on-blur] :as props}]
(let [{:keys [text-align]} values
handle-change
(fn [_ new-align]
(on-change {:text-align new-align}))]
(on-change {:text-align new-align})
(when (some? on-blur) (on-blur)))]
;; --- Align
[:div.align-icons
@ -110,10 +112,12 @@
i/text-align-justify]]))
(mf/defc text-direction-options
[{:keys [values on-change] :as props}]
[{:keys [values on-change on-blur] :as props}]
(let [direction (:text-direction values)
handle-change (fn [_ val]
(on-change {:text-direction val}))]
handle-change
(fn [_ val]
(on-change {:text-direction val})
(when (some? on-blur) (on-blur)))]
;; --- Align
[:div.align-icons
[:span.tooltip.tooltip-bottom-left
@ -128,12 +132,13 @@
i/text-direction-rtl]]))
(mf/defc vertical-align
[{:keys [values on-change] :as props}]
[{:keys [values on-change on-blur] :as props}]
(let [{:keys [vertical-align]} values
vertical-align (or vertical-align "top")
handle-change
(fn [_ new-align]
(on-change {:vertical-align new-align}))]
(on-change {:vertical-align new-align})
(when (some? on-blur) (on-blur)))]
[:div.align-icons
[:span.tooltip.tooltip-bottom-left
@ -153,11 +158,12 @@
i/align-bottom]]))
(mf/defc grow-options
[{:keys [ids values] :as props}]
[{:keys [ids values on-blur] :as props}]
(let [grow-type (:grow-type values)
handle-change-grow
(fn [_ grow-type]
(st/emit! (dch/update-shapes ids #(assoc % :grow-type grow-type))))]
(st/emit! (dch/update-shapes ids #(assoc % :grow-type grow-type)))
(when (some? on-blur) (on-blur)))]
[:div.align-icons
[:span.tooltip.tooltip-bottom
@ -177,11 +183,12 @@
i/auto-height]]))
(mf/defc text-decoration-options
[{:keys [values on-change] :as props}]
[{:keys [values on-change on-blur] :as props}]
(let [text-decoration (or (:text-decoration values) "none")
handle-change
(fn [_ type]
(on-change {:text-decoration type}))]
(on-change {:text-decoration type})
(when (some? on-blur) (on-blur)))]
[:div.align-icons
[:span.tooltip.tooltip-bottom
{:alt (tr "workspace.options.text-options.none")
@ -222,7 +229,8 @@
(mf/use-callback
(mf/deps values)
(fn [id attrs]
(st/emit! (dwt/save-font (merge txt/default-text-attrs values attrs)))
(st/emit! (dwt/save-font (-> (merge txt/default-text-attrs values attrs)
(select-keys text-attrs))))
(let [attrs (select-keys attrs root-attrs)]
(when-not (empty? attrs)
@ -290,7 +298,15 @@
opts #js {:ids ids
:values values
:on-change on-change}]
:on-change on-change
:on-blur
(fn []
(tm/schedule
100
(fn []
(when (not= "INPUT" (-> (dom/get-active) (dom/get-tag-name)))
(let [node (dom/get-element-by-class "public-DraftEditor-content")]
(dom/focus! node))))))}]
[:div.element-set
[:div.element-set-title

View file

@ -230,7 +230,7 @@
:current? (= (:id font) (:id selected))}])))
(mf/defc font-options
[{:keys [values on-change] :as props}]
[{:keys [values on-change on-blur] :as props}]
(let [{:keys [font-id font-size font-variant-id]} values
font-id (or font-id (:font-id txt/default-text-attrs))
@ -271,18 +271,26 @@
:font-family (:family font)
:font-variant-id new-variant-id
:font-weight (:weight variant)
:font-style (:style variant)}))))
:font-style (:style variant)})
(dom/blur! (dom/get-target event)))))
on-font-select
(mf/use-callback
(mf/deps change-font)
(fn [font*]
(when (not= font font*)
(change-font (:id font*)))))
(change-font (:id font*)))
(when (some? on-blur)
(on-blur))))
on-font-selector-close
(mf/use-callback
#(reset! open-selector? false))]
(fn []
(reset! open-selector? false)
(when (some? on-blur)
(on-blur))
))]
[:*
(when @open-selector?
@ -314,12 +322,14 @@
:options size-options
:type "number"
:placeholder "--"
:on-change on-font-size-change}])
:on-change on-font-size-change
:on-blur on-blur}])
[:select.input-select.variant-option
{:disabled (= font-id :multiple)
:value (attr->string font-variant-id)
:on-change on-font-variant-change}
:on-change on-font-variant-change
:on-blur on-blur}
(when (or (= font-id :multiple) (= font-variant-id :multiple))
[:option {:value ""} "--"])
(for [variant (:variants font)]
@ -329,7 +339,7 @@
(mf/defc spacing-options
[{:keys [values on-change] :as props}]
[{:keys [values on-change on-blur] :as props}]
(let [{:keys [line-height
letter-spacing]} values
@ -353,7 +363,8 @@
:max "200"
:value (attr->string line-height)
:placeholder (tr "settings.multiple")
:on-change #(handle-change % :line-height)}]]
:on-change #(handle-change % :line-height)
:on-blur on-blur}]]
[:div.input-icon
[:span.icon-before.tooltip.tooltip-bottom
@ -366,18 +377,21 @@
:max "200"
:value (attr->string letter-spacing)
:placeholder (tr "settings.multiple")
:on-change #(handle-change % :letter-spacing)}]]]))
:on-change #(handle-change % :letter-spacing)
:on-blur on-blur}]]]))
(mf/defc text-transform-options
[{:keys [values on-change] :as props}]
[{:keys [values on-change on-blur] :as props}]
(let [text-transform (or (:text-transform values) "none")
handle-change
(fn [_ type]
(on-change {:text-transform type}))]
(on-change {:text-transform type})
(when (some? on-blur) (on-blur)))]
[:div.align-icons
[:span.tooltip.tooltip-bottom
{:alt (tr "workspace.options.text-options.none")
:class (dom/classnames :current (= "none" text-transform))
:focus #(dom/prevent-default %)
:on-click #(handle-change % "none")}
i/minus]
[:span.tooltip.tooltip-bottom
@ -397,11 +411,12 @@
i/titlecase]]))
(mf/defc typography-options
[{:keys [ids editor values on-change]}]
[{:keys [ids editor values on-change on-blur]}]
(let [opts #js {:editor editor
:ids ids
:values values
:on-change on-change}]
:on-change on-change
:on-blur on-blur}]
[:div.element-set-content
[:> font-options opts]
[:div.row-flex

View file

@ -9,10 +9,9 @@
[app.common.data :as d]
[app.main.data.workspace.texts :as dwt]
[app.main.refs :as refs]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs]]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu fill-attrs]]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu]]

View file

@ -223,11 +223,13 @@
(defn focus!
[node]
(.focus node))
(when (some? node)
(.focus node)))
(defn blur!
[node]
(.blur node))
(when (some? node)
(.blur node)))
(defn fullscreen?
[]
@ -291,8 +293,11 @@
(defn get-user-agent []
(.-userAgent globals/navigator))
(defn get-active []
(.-activeElement globals/document))
(defn active? [node]
(= (.-activeElement globals/document) node))
(= (get-active) node))
(defn get-data [^js node ^string attr]
(.getAttribute node (str "data-" attr)))

View file

@ -34,7 +34,7 @@ function mergeBlockData(block, newData) {
}
}
return block.merge({
return block.mergeDeep({
data: data
});
}
@ -119,29 +119,31 @@ export function updateCurrentBlockData(state, attrs) {
}
export function applyInlineStyle(state, styles) {
let selection = state.getSelection();
const userSelection = state.getSelection();
let selection = userSelection;
if (selection.isCollapsed()) {
selection = getSelectAllSelection(state);
}
let result = state;
let content = null;
for (let style of styles) {
const [p, k, v] = style.split("$$$");
const prefix = [p, k, ""].join("$$$");
content = state.getCurrentContent();
content = result.getCurrentContent();
content = removeInlineStylePrefix(content, selection, prefix);
if (v !== "z:null") {
content = Modifier.applyInlineStyle(content, selection, style);
}
state = EditorState.push(state, content, "change-inline-style");
result = EditorState.push(result, content, "change-inline-style");
}
return state;
return EditorState.acceptSelection(result, userSelection);
}
export function splitBlockPreservingData(state) {
@ -308,7 +310,7 @@ export function updateBlockData(state, blockKey, data) {
);
const result = EditorState.push(state, newContent, 'change-block-data');
return EditorState.acceptSelection(result, userSelection)
return EditorState.acceptSelection(result, userSelection);
}
export function getSelection(state) {