mirror of
https://github.com/penpot/penpot.git
synced 2026-08-06 21:08:34 +00:00
✨ Add Tab/Shift+Tab navigation to rename layers sequentially
This commit is contained in:
parent
23e77b5f03
commit
c18375c66e
@ -58,7 +58,8 @@
|
|||||||
is-filtered is-expanded dnd-over dnd-over-top dnd-over-bot hide-toggle
|
is-filtered is-expanded dnd-over dnd-over-top dnd-over-bot hide-toggle
|
||||||
;; Callbacks
|
;; Callbacks
|
||||||
on-select-shape on-context-menu on-pointer-enter on-pointer-leave on-zoom-to-selected
|
on-select-shape on-context-menu on-pointer-enter on-pointer-leave on-zoom-to-selected
|
||||||
on-toggle-collapse on-enable-drag on-disable-drag on-toggle-visibility on-toggle-blocking]}]
|
on-toggle-collapse on-enable-drag on-disable-drag on-toggle-visibility on-toggle-blocking
|
||||||
|
on-tab-press]}]
|
||||||
|
|
||||||
(let [id (:id item)
|
(let [id (:id item)
|
||||||
name (:name item)
|
name (:name item)
|
||||||
@ -164,7 +165,8 @@
|
|||||||
:variant-properties variant-properties
|
:variant-properties variant-properties
|
||||||
:variant-error variant-error
|
:variant-error variant-error
|
||||||
:component-id component-id
|
:component-id component-id
|
||||||
:is-hidden hidden?}]]
|
:is-hidden hidden?
|
||||||
|
:on-tab-press on-tab-press}]]
|
||||||
(when (not ^boolean is-read-only)
|
(when (not ^boolean is-read-only)
|
||||||
[:div {:class (stl/css-case
|
[:div {:class (stl/css-case
|
||||||
:element-actions true
|
:element-actions true
|
||||||
@ -416,7 +418,24 @@
|
|||||||
;; We don't want to change the structure of component copies
|
;; We don't want to change the structure of component copies
|
||||||
:draggable? (and ^boolean is-sortable
|
:draggable? (and ^boolean is-sortable
|
||||||
^boolean (not is-read-only)
|
^boolean (not is-read-only)
|
||||||
^boolean (not (ctn/has-any-copy-parent? objects item))))]
|
^boolean (not (ctn/has-any-copy-parent? objects item))))
|
||||||
|
|
||||||
|
on-tab-press
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps id objects)
|
||||||
|
(fn [shift?]
|
||||||
|
(let [shape (get objects id)
|
||||||
|
parent (get objects (:parent-id shape))
|
||||||
|
siblings (:shapes parent)
|
||||||
|
pos (d/index-of siblings id)]
|
||||||
|
(when (some? pos)
|
||||||
|
(let [;; Layers render in reverse: Tab (visually down) = dec index,
|
||||||
|
;; Shift+Tab (visually up) = inc index
|
||||||
|
target-id (if shift?
|
||||||
|
(get siblings (inc pos))
|
||||||
|
(get siblings (dec pos)))]
|
||||||
|
(when (some? target-id)
|
||||||
|
(st/emit! (dw/start-rename-shape target-id)))))))))]
|
||||||
|
|
||||||
(mf/with-effect [is-selected selected]
|
(mf/with-effect [is-selected selected]
|
||||||
(let [single? (= (count selected) 1)
|
(let [single? (= (count selected) 1)
|
||||||
@ -531,6 +550,7 @@
|
|||||||
:on-disable-drag disable-drag
|
:on-disable-drag disable-drag
|
||||||
:on-toggle-visibility toggle-visibility
|
:on-toggle-visibility toggle-visibility
|
||||||
:on-toggle-blocking toggle-blocking
|
:on-toggle-blocking toggle-blocking
|
||||||
|
:on-tab-press on-tab-press
|
||||||
:style style}
|
:style style}
|
||||||
|
|
||||||
(when (and ^boolean render-children
|
(when (and ^boolean render-children
|
||||||
|
|||||||
@ -24,11 +24,17 @@
|
|||||||
[{:keys [shape-id rename-id shape-name is-shape-touched disabled-double-click
|
[{:keys [shape-id rename-id shape-name is-shape-touched disabled-double-click
|
||||||
on-start-edit on-stop-edit depth parent-size is-selected
|
on-start-edit on-stop-edit depth parent-size is-selected
|
||||||
type-comp type-frame component-id is-hidden is-blocked
|
type-comp type-frame component-id is-hidden is-blocked
|
||||||
variant-id variant-name variant-properties variant-error ref]}]
|
variant-id variant-name variant-properties variant-error
|
||||||
|
on-tab-press ref]}]
|
||||||
(let [edition* (mf/use-state false)
|
(let [edition* (mf/use-state false)
|
||||||
edition? (deref edition*)
|
edition? (deref edition*)
|
||||||
|
|
||||||
|
;; Mutable ref to track editing state inside mf/use-fn callbacks.
|
||||||
|
;; mf/use-state wraps React useState, so @edition* inside memoized
|
||||||
|
;; callbacks captures a stale State object. A ref is a stable mutable
|
||||||
|
;; container that always reflects the latest value.
|
||||||
|
editing-ref (mf/use-ref false)
|
||||||
|
|
||||||
local-ref (mf/use-ref)
|
local-ref (mf/use-ref)
|
||||||
ref (d/nilv ref local-ref)
|
ref (d/nilv ref local-ref)
|
||||||
|
|
||||||
@ -53,6 +59,7 @@
|
|||||||
(when (and (not is-blocked)
|
(when (and (not is-blocked)
|
||||||
(not disabled-double-click))
|
(not disabled-double-click))
|
||||||
(on-start-edit)
|
(on-start-edit)
|
||||||
|
(mf/set-ref-val! editing-ref true)
|
||||||
(reset! edition* true)
|
(reset! edition* true)
|
||||||
(st/emit! (dw/start-rename-shape shape-id)))))
|
(st/emit! (dw/start-rename-shape shape-id)))))
|
||||||
|
|
||||||
@ -60,26 +67,42 @@
|
|||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps shape-id on-stop-edit component-id variant-id variant-name variant-properties)
|
(mf/deps shape-id on-stop-edit component-id variant-id variant-name variant-properties)
|
||||||
(fn []
|
(fn []
|
||||||
(let [name-input (mf/ref-val ref)
|
(when (mf/ref-val editing-ref)
|
||||||
name (str/trim (dom/get-value name-input))]
|
(let [name-input (mf/ref-val ref)
|
||||||
(on-stop-edit)
|
name (str/trim (dom/get-value name-input))]
|
||||||
(reset! edition* false)
|
(on-stop-edit)
|
||||||
(st/emit! (dw/rename-shape-or-variant shape-id name)))))
|
(mf/set-ref-val! editing-ref false)
|
||||||
|
(reset! edition* false)
|
||||||
|
(st/emit! (dw/rename-shape-or-variant shape-id name))))))
|
||||||
|
|
||||||
cancel-edit
|
cancel-edit
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps shape-id on-stop-edit)
|
(mf/deps shape-id on-stop-edit)
|
||||||
(fn []
|
(fn []
|
||||||
(on-stop-edit)
|
(on-stop-edit)
|
||||||
|
(mf/set-ref-val! editing-ref false)
|
||||||
(reset! edition* false)
|
(reset! edition* false)
|
||||||
(st/emit! (dw/end-rename-shape shape-id nil))))
|
(st/emit! (dw/end-rename-shape shape-id nil))))
|
||||||
|
|
||||||
on-key-down
|
on-key-down
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps accept-edit cancel-edit)
|
(mf/deps accept-edit cancel-edit on-tab-press shape-id on-stop-edit)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (kbd/enter? event) (accept-edit))
|
(when (kbd/enter? event) (accept-edit))
|
||||||
(when (kbd/esc? event) (cancel-edit))))
|
(when (kbd/esc? event) (cancel-edit))
|
||||||
|
(when (kbd/tab? event)
|
||||||
|
(dom/prevent-default event)
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(when (mf/ref-val editing-ref)
|
||||||
|
(let [shift? (kbd/shift? event)
|
||||||
|
name-input (mf/ref-val ref)
|
||||||
|
name (str/trim (dom/get-value name-input))]
|
||||||
|
(on-stop-edit)
|
||||||
|
(mf/set-ref-val! editing-ref false)
|
||||||
|
(reset! edition* false)
|
||||||
|
(st/emit! (dw/end-rename-shape shape-id name))
|
||||||
|
(when (fn? on-tab-press)
|
||||||
|
(on-tab-press shift?)))))))
|
||||||
|
|
||||||
parent-size
|
parent-size
|
||||||
(dm/str (- parent-size space-for-icons) "px")]
|
(dm/str (- parent-size space-for-icons) "px")]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user