diff --git a/CHANGES.md b/CHANGES.md index ec42849938..31f97d2092 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -51,7 +51,6 @@ - Fix opacity on stroke gradients [Taiga #11646](https://tree.taiga.io/project/penpot/issue/11646) - Fix change from gradient to solid color [Taiga #11648](https://tree.taiga.io/project/penpot/issue/11648) - Fix the context menu always closes after any action [Taiga #11624](https://tree.taiga.io/project/penpot/issue/11624) -- Fix font selector highlight inconsistency when using keyboard navigation [Taiga #11668](https://tree.taiga.io/project/penpot/issue/11668) - Fix X & Y position do not sincronize with tokens [Taiga #11617](https://tree.taiga.io/project/penpot/issue/11617) - Fix tooltip position after first time [Taiga #11688](https://tree.taiga.io/project/penpot/issue/11688) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs index 609e4a822e..92fab80bad 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs @@ -10,6 +10,7 @@ ["react-virtualized" :as rvt] [app.common.data :as d] [app.common.data.macros :as dm] + [app.common.exceptions :as ex] [app.common.text :as txt] [app.main.constants :refer [max-input-length]] [app.main.data.common :as dcm] @@ -40,9 +41,25 @@ "" (ust/format-precision value 2))) +(defn- get-next-font + [{:keys [id] :as current} fonts] + (if (seq fonts) + (let [index (d/index-of-pred fonts #(= (:id %) id)) + index (or index -1) + next (ex/ignoring (nth fonts (inc index)))] + (or next (first fonts))) + current)) + +(defn- get-prev-font + [{:keys [id] :as current} fonts] + (if (seq fonts) + (let [index (d/index-of-pred fonts #(= (:id %) id)) + next (ex/ignoring (nth fonts (dec index)))] + (or next (peek fonts))) + current)) + (mf/defc font-item* - {::mf/wrap [mf/memo] - ::mf/private true} + {::mf/wrap [mf/memo]} [{:keys [font is-current on-click style]}] (let [item-ref (mf/use-ref) on-click (mf/use-fn (mf/deps font) #(on-click font))] @@ -66,7 +83,7 @@ (declare row-renderer) -(defn- filter-fonts +(defn filter-fonts [{:keys [term backends]} fonts] (let [term (str/lower term) xform (cond-> (map identity) @@ -79,7 +96,8 @@ (mf/defc font-selector* [{:keys [on-select on-close current-font show-recent full-size]}] - (let [state* (mf/use-state + (let [selected (mf/use-state current-font) + state* (mf/use-state #(do {:term "" :backends #{}})) state (deref state*) @@ -94,41 +112,23 @@ recent-fonts (mf/with-memo [state recent-fonts] (filter-fonts state recent-fonts)) - ;; Combine recent fonts with filtered fonts, avoiding duplicates - combined-fonts - (mf/with-memo [recent-fonts fonts] - (let [recent-ids (into #{} d/xf:map-id recent-fonts)] - (into recent-fonts (remove #(contains? recent-ids (:id %))) fonts))) - - ;; Initialize selected with current font index - selected-index - (mf/use-state - (fn [] - (or (some (fn [[idx font]] - (when (= (:id current-font) (:id font)) idx)) - (map-indexed vector combined-fonts)) - 0))) - - full-size? - (boolean (and full-size show-recent)) + full-size? (boolean (and full-size show-recent)) select-next (mf/use-fn - (mf/deps combined-fonts) + (mf/deps fonts) (fn [event] (dom/stop-propagation event) (dom/prevent-default event) - (let [next-idx (mod (inc @selected-index) (count combined-fonts))] - (reset! selected-index next-idx)))) + (swap! selected get-next-font fonts))) select-prev (mf/use-fn - (mf/deps combined-fonts) + (mf/deps fonts) (fn [event] (dom/stop-propagation event) (dom/prevent-default event) - (let [prev-idx (mod (dec @selected-index) (count combined-fonts))] - (reset! selected-index prev-idx)))) + (swap! selected get-prev-font fonts))) on-select-and-close (mf/use-fn @@ -139,32 +139,35 @@ on-key-down (mf/use-fn - (mf/deps combined-fonts) + (mf/deps fonts) (fn [event] (cond (kbd/up-arrow? event) (select-prev event) (kbd/down-arrow? event) (select-next event) (kbd/esc? event) (on-close) - (kbd/enter? event) (do - (let [selected-font (nth combined-fonts @selected-index)] - (on-select-and-close selected-font))) + (kbd/enter? event) (do (on-select-and-close @selected)) :else (dom/focus! (mf/ref-val input))))) on-filter-change (mf/use-fn (fn [event] - (swap! state* assoc :term event) - ;; Reset selection to first item when filter changes - (reset! selected-index 0)))] + (swap! state* assoc :term event))) + + on-select-and-close + (mf/use-fn + (mf/deps on-select on-close) + (fn [font] + (on-select font) + (on-close)))] (mf/with-effect [fonts] (let [key (events/listen js/document "keydown" on-key-down)] #(events/unlistenByKey key))) - (mf/with-effect [@selected-index] + (mf/with-effect [@selected] (when-let [inst (mf/ref-val flist)] - (when (and (>= @selected-index 0) (< @selected-index (count combined-fonts))) - (.scrollToRow ^js inst @selected-index)))) + (when-let [index (:index @selected)] + (.scrollToRow ^js inst index)))) (mf/with-effect [] (st/emit! (dsc/push-shortcuts :typography {})) @@ -172,12 +175,15 @@ (st/emit! (dsc/pop-shortcuts :typography)))) (mf/with-effect [] - (let [index (d/index-of-pred combined-fonts #(= (:id %) (:id current-font))) + (let [index (d/index-of-pred fonts #(= (:id %) (:id current-font))) inst (mf/ref-val flist)] - (when (and index (>= index 0)) - (tm/schedule - #(let [offset (.getOffsetForRow ^js inst #js {:alignment "center" :index index})] - (.scrollToPosition ^js inst offset)))))) + (tm/schedule + #(let [offset (.getOffsetForRow ^js inst #js {:alignment "center" :index index})] + (.scrollToPosition ^js inst offset))))) + + (mf/with-effect [(:term state) fonts] + (when (and (seq fonts) (not= (:id @selected) (:id (first fonts)))) + (reset! selected (first fonts)))) [:div {:class (stl/css :font-selector)} [:div {:class (stl/css-case :font-selector-dropdown true :font-selector-dropdown-full-size full-size?)} @@ -194,7 +200,7 @@ :font font :style {} :on-click on-select-and-close - :is-current (= idx @selected-index)}])])] + :is-current (= (:id font) (:id @selected))}])])] [:div {:class (stl/css-case :fonts-list true :fonts-list-full-size full-size?)} @@ -202,17 +208,17 @@ (fn [props] (let [width (unchecked-get props "width") height (unchecked-get props "height") - render #(row-renderer combined-fonts @selected-index on-select-and-close %)] + render #(row-renderer fonts @selected on-select-and-close %)] (mf/html [:> rvt/List #js {:height height :ref flist :width width - :rowCount (count combined-fonts) + :rowCount (count fonts) :rowHeight 36 :rowRenderer render}])))]]]])) (defn row-renderer - [fonts selected-index on-select props] + [fonts selected on-select props] (let [index (unchecked-get props "index") key (unchecked-get props "key") style (unchecked-get props "style") @@ -222,7 +228,7 @@ :font font :style style :on-click on-select - :is-current (= index selected-index)}]))) + :is-current (= (:id font) (:id selected))}]))) (mf/defc font-options {::mf/wrap-props false}