mirror of
https://github.com/penpot/penpot.git
synced 2026-02-12 22:53:02 +00:00
Merge pull request #7182 from penpot/niwinz-measures-menu-changes
♻️ Add efficiency refactor for sidebar
This commit is contained in:
@@ -517,7 +517,7 @@
|
||||
([objects id]
|
||||
(item-absolute? (get objects id)))
|
||||
([shape]
|
||||
(true? (:layout-item-absolute shape))))
|
||||
(true? (get shape :layout-item-absolute))))
|
||||
|
||||
(defn position-absolute?
|
||||
([objects id]
|
||||
|
||||
@@ -30,7 +30,20 @@
|
||||
|
||||
(def workspace-read-only? (mf/create-context nil))
|
||||
(def is-component? (mf/create-context false))
|
||||
(def sidebar (mf/create-context nil))
|
||||
|
||||
(def sidebar
|
||||
"A context that intends to store the current sidebar position,
|
||||
usefull for components that behaves distinctly if they are showed in
|
||||
right sidebar or left sidebar.
|
||||
|
||||
Possible values: `:right:` and `:left`."
|
||||
(mf/create-context nil))
|
||||
|
||||
(def permissions (mf/create-context nil))
|
||||
(def can-edit? (mf/create-context nil))
|
||||
|
||||
(def active-tokens-by-type
|
||||
"Active tokens by type, used mainly for provide tokens data to the
|
||||
right sidebar menu options components."
|
||||
(mf/create-context nil))
|
||||
|
||||
|
||||
@@ -65,14 +65,17 @@
|
||||
|
||||
(defn- get-option-by-name
|
||||
[options name]
|
||||
(d/seek #(= name (get % :name)) options))
|
||||
(let [options (if (delay? options) (deref options) options)]
|
||||
(d/seek #(= name (get % :name)) options)))
|
||||
|
||||
(defn- get-token-op
|
||||
[tokens name]
|
||||
(->> tokens
|
||||
vals
|
||||
(apply concat)
|
||||
(some #(when (= (:name %) name) %))))
|
||||
(let [tokens (if (delay? tokens) @tokens tokens)
|
||||
xform (filter #(= (:name %) name))]
|
||||
(reduce-kv (fn [result _ tokens]
|
||||
(into result xform tokens))
|
||||
[]
|
||||
tokens)))
|
||||
|
||||
(defn- clean-token-name
|
||||
[s]
|
||||
@@ -114,14 +117,14 @@
|
||||
(subs s (inc start))))
|
||||
|
||||
(defn- filter-token-groups-by-name
|
||||
[tokens-by-type filter-text]
|
||||
[tokens filter-text]
|
||||
(let [lc-filter (str/lower filter-text)]
|
||||
(into {}
|
||||
(keep (fn [[group tokens]]
|
||||
(let [filtered (filter #(str/includes? (str/lower (:name %)) lc-filter) tokens)]
|
||||
(when (seq filtered)
|
||||
[group filtered]))))
|
||||
tokens-by-type)))
|
||||
tokens)))
|
||||
|
||||
(defn- focusable-option?
|
||||
[option]
|
||||
@@ -183,7 +186,9 @@
|
||||
is-selected-on-focus nillable
|
||||
tokens applied-token empty-to-end
|
||||
on-change on-blur on-focus on-detach
|
||||
property align ref] :rest props}]
|
||||
property align ref]
|
||||
:rest props}]
|
||||
|
||||
(let [;; NOTE: we use mfu/bean here for transparently handle
|
||||
;; options provide as clojure data structures or javascript
|
||||
;; plain objects and lists.
|
||||
@@ -253,12 +258,14 @@
|
||||
|
||||
dropdown-options
|
||||
(mf/with-memo [tokens filter-id]
|
||||
(let [partial (extract-partial-brace-text filter-id)
|
||||
options (if (seq partial)
|
||||
(filter-token-groups-by-name tokens partial)
|
||||
tokens)
|
||||
no-sets? (nil? tokens)]
|
||||
(generate-dropdown-options options no-sets?)))
|
||||
(delay
|
||||
(let [tokens (if (delay? tokens) @tokens tokens)
|
||||
partial (extract-partial-brace-text filter-id)
|
||||
options (if (seq partial)
|
||||
(filter-token-groups-by-name tokens partial)
|
||||
tokens)
|
||||
no-sets? (nil? tokens)]
|
||||
(generate-dropdown-options options no-sets?))))
|
||||
|
||||
selected-id*
|
||||
(mf/use-state (fn []
|
||||
@@ -351,23 +358,27 @@
|
||||
|
||||
on-option-click
|
||||
(mf/use-fn
|
||||
(mf/deps dropdown-options on-token-apply)
|
||||
(mf/deps on-token-apply)
|
||||
(fn [event]
|
||||
(let [node (dom/get-current-target event)
|
||||
id (dom/get-data node "id")
|
||||
option (get-option dropdown-options id)
|
||||
value (get option :resolved-value)
|
||||
name (get option :name)]
|
||||
(let [node (dom/get-current-target event)
|
||||
id (dom/get-data node "id")
|
||||
options (mf/ref-val options-ref)
|
||||
options (if (delay? options) @options options)
|
||||
option (get-option options id)
|
||||
value (get option :resolved-value)
|
||||
name (get option :name)]
|
||||
(on-token-apply id value name)
|
||||
(reset! filter-id* ""))))
|
||||
|
||||
on-option-enter
|
||||
(mf/use-fn
|
||||
(mf/deps dropdown-options focused-id on-token-apply)
|
||||
(mf/deps focused-id on-token-apply)
|
||||
(fn [_]
|
||||
(let [option (get-option dropdown-options focused-id)
|
||||
value (get option :resolved-value)
|
||||
name (get option :name)]
|
||||
(let [options (mf/ref-val options-ref)
|
||||
options (if (delay? options) @options options)
|
||||
option (get-option options focused-id)
|
||||
value (get option :resolved-value)
|
||||
name (get option :name)]
|
||||
(on-token-apply focused-id value name)
|
||||
(reset! filter-id* ""))))
|
||||
|
||||
@@ -386,9 +397,9 @@
|
||||
(when (fn? on-blur)
|
||||
(on-blur event)))))
|
||||
|
||||
handle-key-down
|
||||
on-key-down
|
||||
(mf/use-fn
|
||||
(mf/deps dropdown-options is-open apply-value update-input is-open focused-id handle-focus-change)
|
||||
(mf/deps is-open apply-value update-input is-open focused-id handle-focus-change)
|
||||
(fn [event]
|
||||
(mf/set-ref-val! dirty-ref true)
|
||||
(let [up? (kbd/up-arrow? event)
|
||||
@@ -398,7 +409,8 @@
|
||||
node (mf/ref-val ref)
|
||||
open-tokens (kbd/is-key? event "{")
|
||||
close-tokens (kbd/is-key? event "}")
|
||||
options (mf/ref-val options-ref)]
|
||||
options (mf/ref-val options-ref)
|
||||
options (if (delay? options) @options options)]
|
||||
|
||||
(cond
|
||||
(and (some? options) open-tokens)
|
||||
@@ -418,8 +430,8 @@
|
||||
(dom/prevent-default event)
|
||||
(if focused-id
|
||||
(on-option-enter event)
|
||||
(let [option-id (first-focusable-id dropdown-options)
|
||||
option (get-option dropdown-options option-id)
|
||||
(let [option-id (first-focusable-id options)
|
||||
option (get-option options option-id)
|
||||
value (get option :resolved-value)
|
||||
name (get option :name)]
|
||||
(on-token-apply option-id value name)
|
||||
@@ -461,7 +473,7 @@
|
||||
(update-input (fmt/format-number new-val))
|
||||
(apply-value (dm/str new-val))))))))
|
||||
|
||||
handle-focus
|
||||
on-focus
|
||||
(mf/use-fn
|
||||
(mf/deps on-focus select-on-focus)
|
||||
(fn [event]
|
||||
@@ -473,7 +485,7 @@
|
||||
;; In webkit browsers the mouseup event will be called after the on-focus causing and unselect
|
||||
(.addEventListener target "mouseup" dom/prevent-default #js {:once true})))))
|
||||
|
||||
handle-mouse-wheel
|
||||
on-mouse-wheel
|
||||
(mf/use-fn
|
||||
(mf/deps apply-value parse-value min max nillable ref default step min max)
|
||||
(fn [event]
|
||||
@@ -580,8 +592,8 @@
|
||||
placeholder)
|
||||
:default-value (or (mf/ref-val last-value*) (fmt/format-number value))
|
||||
:on-blur on-blur
|
||||
:on-key-down handle-key-down
|
||||
:on-focus handle-focus
|
||||
:on-key-down on-key-down
|
||||
:on-focus on-focus
|
||||
:on-change store-raw-value
|
||||
:disabled disabled
|
||||
:slot-start (when icon
|
||||
@@ -603,11 +615,12 @@
|
||||
|
||||
token-props
|
||||
(when (and token-applied (not= :multiple token-applied))
|
||||
(let [token (get-option-by-name dropdown-options token-applied)
|
||||
id (get token :id)
|
||||
label (get token :name)
|
||||
(let [token (get-option-by-name dropdown-options token-applied)
|
||||
id (get token :id)
|
||||
label (get token :name)
|
||||
token-value (or (get token :resolved-value)
|
||||
(or (mf/ref-val last-value*) (fmt/format-number value)))]
|
||||
(or (mf/ref-val last-value*)
|
||||
(fmt/format-number value)))]
|
||||
(mf/spread-props props
|
||||
{:id id
|
||||
:label label
|
||||
@@ -649,9 +662,9 @@
|
||||
(when-let [node (mf/ref-val ref)]
|
||||
(dom/set-value! node value'))))
|
||||
|
||||
(mf/with-layout-effect [handle-mouse-wheel]
|
||||
(mf/with-layout-effect [on-mouse-wheel]
|
||||
(when-let [node (mf/ref-val ref)]
|
||||
(let [key (events/listen node "wheel" handle-mouse-wheel #js {:passive false})]
|
||||
(let [key (events/listen node "wheel" on-mouse-wheel #js {:passive false})]
|
||||
#(events/unlistenByKey key))))
|
||||
|
||||
(mf/with-effect [dropdown-options]
|
||||
@@ -666,11 +679,12 @@
|
||||
[:> input-field* input-props])
|
||||
|
||||
(when ^boolean is-open
|
||||
[:> options-dropdown* {:on-click on-option-click
|
||||
:id listbox-id
|
||||
:options dropdown-options
|
||||
:selected selected-id
|
||||
:focused focused-id
|
||||
:align align
|
||||
:empty-to-end empty-to-end
|
||||
:ref set-option-ref}])]))
|
||||
(let [options (if (delay? dropdown-options) @dropdown-options dropdown-options)]
|
||||
[:> options-dropdown* {:on-click on-option-click
|
||||
:id listbox-id
|
||||
:options options
|
||||
:selected selected-id
|
||||
:focused focused-id
|
||||
:align align
|
||||
:empty-to-end empty-to-end
|
||||
:ref set-option-ref}]))]))
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
|
||||
(defn get-option
|
||||
[options id]
|
||||
(or (d/seek #(= id (get % :id)) options)
|
||||
(nth options 0)))
|
||||
(let [options (if (delay? options) @options options)]
|
||||
(or (d/seek #(= id (get % :id)) options)
|
||||
(nth options 0))))
|
||||
|
||||
(defn- get-selected-option-id
|
||||
[options default]
|
||||
|
||||
@@ -13,8 +13,8 @@ const Padded = ({ children }) => (
|
||||
<div style={{ padding: "10px" }}>{children}</div>
|
||||
);
|
||||
|
||||
const TabSwitcherWrapper = ({tabs, ...props}) => {
|
||||
const navTabs = tabs.map(({content, ...item}) => {
|
||||
const TabSwitcherWrapper = ({ tabs, ...props }) => {
|
||||
const navTabs = tabs.map(({ content, ...item }) => {
|
||||
return item;
|
||||
});
|
||||
|
||||
@@ -28,7 +28,12 @@ const TabSwitcherWrapper = ({tabs, ...props}) => {
|
||||
}, {});
|
||||
|
||||
return (
|
||||
<TabSwitcher tabs={navTabs} selected={selected} onChange={setSelected} {...props}>
|
||||
<TabSwitcher
|
||||
tabs={navTabs}
|
||||
selected={selected}
|
||||
onChange={setSelected}
|
||||
{...props}
|
||||
>
|
||||
{content[selected]}
|
||||
</TabSwitcher>
|
||||
);
|
||||
@@ -77,12 +82,7 @@ export default {
|
||||
},
|
||||
parameters: {
|
||||
controls: {
|
||||
exclude: [
|
||||
"tabs",
|
||||
"actionButton",
|
||||
"default",
|
||||
"actionButtonPosition",
|
||||
],
|
||||
exclude: ["tabs", "actionButton", "default", "actionButtonPosition"],
|
||||
},
|
||||
},
|
||||
render: ({ ...args }) => <TabSwitcherWrapper {...args} />,
|
||||
|
||||
@@ -160,11 +160,7 @@
|
||||
tooltip-brect (assoc tooltip-brect :height (or saved-height (:height tooltip-brect)) :width (or saved-width (:width tooltip-brect)))
|
||||
window-size (dom/get-window-size)]
|
||||
(when-let [[placement placement-rect] (find-matching-placement placement tooltip-brect origin-brect window-size offset)]
|
||||
(let [height (if (or (= placement "right") (= placement "left"))
|
||||
(- (:height placement-rect) arrow-height)
|
||||
(:height placement-rect))]
|
||||
(dom/set-data! tooltip "height" (:height tooltip-brect))
|
||||
(dom/set-data! tooltip "width" (:width tooltip-brect))
|
||||
(let [height (:height placement-rect)]
|
||||
(dom/set-css-property! tooltip "block-size" (dm/str height "px"))
|
||||
(dom/set-css-property! tooltip "inset-block-start" (dm/str (:top placement-rect) "px"))
|
||||
(dom/set-css-property! tooltip "inset-inline-start" (dm/str (:left placement-rect) "px")))
|
||||
@@ -253,7 +249,7 @@
|
||||
:on-focus on-show
|
||||
:on-blur on-hide
|
||||
:on-key-down handle-key-down
|
||||
:class (stl/css :tooltip-trigger)
|
||||
:class [class (stl/css :tooltip-trigger)]
|
||||
:aria-describedby id})
|
||||
content
|
||||
(if (fn? content)
|
||||
@@ -262,7 +258,7 @@
|
||||
|
||||
[:> :div props
|
||||
children
|
||||
[:div {:class [class (stl/css :tooltip)]
|
||||
[:div {:class (stl/css :tooltip)
|
||||
:id id
|
||||
:popover "auto"
|
||||
:role "tooltip"}
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
[app.main.ui.workspace.nudge]
|
||||
[app.main.ui.workspace.palette :refer [palette]]
|
||||
[app.main.ui.workspace.plugins]
|
||||
[app.main.ui.workspace.sidebar :refer [left-sidebar* right-sidebar*]]
|
||||
[app.main.ui.workspace.sidebar.collapsable-button :refer [collapsed-button]]
|
||||
[app.main.ui.workspace.sidebar :refer [sidebar*]]
|
||||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
|
||||
[app.main.ui.workspace.tokens.export]
|
||||
[app.main.ui.workspace.tokens.export.modal]
|
||||
@@ -114,18 +113,14 @@
|
||||
@palete-size)}]]]
|
||||
|
||||
(when-not hide-ui?
|
||||
[:*
|
||||
(if (:collapse-left-sidebar layout)
|
||||
[:& collapsed-button]
|
||||
[:> left-sidebar* {:layout layout
|
||||
:file file
|
||||
:page-id page-id}])
|
||||
[:> right-sidebar* {:section options-mode
|
||||
:selected selected
|
||||
:drawing-tool (get drawing :tool)
|
||||
:layout layout
|
||||
:file file
|
||||
:page-id page-id}]])]))
|
||||
[:> sidebar* {:layout layout
|
||||
;; FIXME
|
||||
:file-id (get file :id)
|
||||
:page-id page-id
|
||||
:file file
|
||||
:selected selected
|
||||
:section options-mode
|
||||
:drawing-tool (get drawing :tool)}])]))
|
||||
|
||||
(mf/defc workspace-loader*
|
||||
{::mf/private true}
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.constants :refer [sidebar-default-width sidebar-default-max-width]]
|
||||
[app.main.data.common :as dcm]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.style-dictionary :as sd]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
@@ -25,6 +27,7 @@
|
||||
[app.main.ui.workspace.left-header :refer [left-header*]]
|
||||
[app.main.ui.workspace.right-header :refer [right-header*]]
|
||||
[app.main.ui.workspace.sidebar.assets :refer [assets-toolbox*]]
|
||||
[app.main.ui.workspace.sidebar.collapsable-button :refer [collapsed-button*]]
|
||||
[app.main.ui.workspace.sidebar.debug :refer [debug-panel*]]
|
||||
[app.main.ui.workspace.sidebar.debug-shape-info :refer [debug-shape-info*]]
|
||||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
|
||||
@@ -96,7 +99,7 @@
|
||||
|
||||
(mf/defc left-sidebar*
|
||||
{::mf/memo true}
|
||||
[{:keys [layout file page-id] :as props}]
|
||||
[{:keys [layout file page-id tokens-lib active-tokens resolved-active-tokens]}]
|
||||
(let [options-mode (mf/deref refs/options-mode-global)
|
||||
project (mf/deref refs/project)
|
||||
file-id (get file :id)
|
||||
@@ -147,7 +150,7 @@
|
||||
:left-settings-bar true
|
||||
:global/two-row (<= width 300)
|
||||
:global/three-row (and (> width 300) (<= width 400))
|
||||
:global/four-row (> width 400))
|
||||
:global/four-row (> width 400))
|
||||
|
||||
tabs-action-button
|
||||
(mf/with-memo []
|
||||
@@ -197,7 +200,10 @@
|
||||
:file-id file-id}]
|
||||
|
||||
:tokens
|
||||
[:> tokens-sidebar-tab*]
|
||||
[:> tokens-sidebar-tab*
|
||||
{:tokens-lib tokens-lib
|
||||
:active-tokens active-tokens
|
||||
:resolved-active-tokens resolved-active-tokens}]
|
||||
|
||||
:layers
|
||||
[:> layers-content*
|
||||
@@ -255,8 +261,7 @@
|
||||
[:> history-toolbox*]])]))
|
||||
|
||||
(mf/defc right-sidebar*
|
||||
{::mf/memo true}
|
||||
[{:keys [layout section file page-id drawing-tool] :as props}]
|
||||
[{:keys [layout section file page-id drawing-tool active-tokens] :as props}]
|
||||
(let [is-comments? (= drawing-tool :comments)
|
||||
is-history? (contains? layout :document-history)
|
||||
is-inspect? (= section :inspect)
|
||||
@@ -289,45 +294,84 @@
|
||||
(fn []
|
||||
(set-width (if (> width sidebar-default-width)
|
||||
sidebar-default-width
|
||||
sidebar-default-max-width))))]
|
||||
sidebar-default-max-width))))
|
||||
|
||||
active-tokens-by-type
|
||||
(mf/with-memo [active-tokens]
|
||||
(delay (ctob/group-by-type active-tokens)))]
|
||||
|
||||
[:> (mf/provider muc/sidebar) {:value :right}
|
||||
[:aside
|
||||
{:class (stl/css-case :right-settings-bar true
|
||||
:not-expand (not can-be-expanded?)
|
||||
:expanded (> width sidebar-default-width))
|
||||
[:> (mf/provider muc/active-tokens-by-type) {:value active-tokens-by-type}
|
||||
|
||||
:id "right-sidebar-aside"
|
||||
:data-testid "right-sidebar"
|
||||
:data-size (str width)
|
||||
:style {:--width (if can-be-expanded?
|
||||
(dm/str width "px")
|
||||
(dm/str sidebar-default-width "px"))}}
|
||||
[:aside
|
||||
{:class (stl/css-case :right-settings-bar true
|
||||
:not-expand (not can-be-expanded?)
|
||||
:expanded (> width sidebar-default-width))
|
||||
|
||||
(when can-be-expanded?
|
||||
[:div {:class (stl/css :resize-area)
|
||||
:on-pointer-down on-pointer-down
|
||||
:on-lost-pointer-capture on-lost-pointer-capture
|
||||
:on-pointer-move on-pointer-move}])
|
||||
:id "right-sidebar-aside"
|
||||
:data-testid "right-sidebar"
|
||||
:data-size (str width)
|
||||
:style {:--width (if can-be-expanded?
|
||||
(dm/str width "px")
|
||||
(dm/str sidebar-default-width "px"))}}
|
||||
|
||||
[:> right-header*
|
||||
{:file file
|
||||
:layout layout
|
||||
:page-id page-id}]
|
||||
(when can-be-expanded?
|
||||
[:div {:class (stl/css :resize-area)
|
||||
:on-pointer-down on-pointer-down
|
||||
:on-lost-pointer-capture on-lost-pointer-capture
|
||||
:on-pointer-move on-pointer-move}])
|
||||
|
||||
[:div {:class (stl/css :settings-bar-inside)}
|
||||
(cond
|
||||
dbg-shape-panel?
|
||||
[:> debug-shape-info*]
|
||||
[:> right-header*
|
||||
{:file file
|
||||
:layout layout
|
||||
:page-id page-id}]
|
||||
|
||||
is-comments?
|
||||
[:> comments-sidebar* {}]
|
||||
[:div {:class (stl/css :settings-bar-inside)}
|
||||
(cond
|
||||
dbg-shape-panel?
|
||||
[:> debug-shape-info*]
|
||||
|
||||
is-history?
|
||||
[:> history-content* {}]
|
||||
is-comments?
|
||||
[:> comments-sidebar* {}]
|
||||
|
||||
:else
|
||||
(let [props (mf/spread-props props
|
||||
{:on-change-section on-change-section
|
||||
:on-expand on-expand})]
|
||||
[:> options-toolbox* props]))]]]))
|
||||
is-history?
|
||||
[:> history-content* {}]
|
||||
|
||||
:else
|
||||
(let [props (mf/spread-props props
|
||||
{:on-change-section on-change-section
|
||||
:on-expand on-expand})]
|
||||
[:> options-toolbox* props]))]]]]))
|
||||
|
||||
(mf/defc sidebar*
|
||||
[{:keys [layout file file-id page-id section drawing-tool selected]}]
|
||||
(let [tokens-lib
|
||||
(mf/deref refs/tokens-lib)
|
||||
|
||||
active-tokens
|
||||
(mf/with-memo [tokens-lib]
|
||||
(if tokens-lib
|
||||
(ctob/get-tokens-in-active-sets tokens-lib)
|
||||
{}))
|
||||
|
||||
resolved-active-tokens
|
||||
(sd/use-resolved-tokens* active-tokens)]
|
||||
|
||||
[:*
|
||||
(if (:collapse-left-sidebar layout)
|
||||
[:> collapsed-button*]
|
||||
[:> left-sidebar* {:layout layout
|
||||
:file file
|
||||
:page-id page-id
|
||||
:tokens-lib tokens-lib
|
||||
:active-tokens active-tokens
|
||||
:resolved-active-tokens resolved-active-tokens}])
|
||||
[:> right-sidebar* {:section section
|
||||
:selected selected
|
||||
:drawing-tool drawing-tool
|
||||
:layout layout
|
||||
:file file
|
||||
:file-id file-id
|
||||
:page-id page-id
|
||||
:tokens-lib tokens-lib
|
||||
:active-tokens resolved-active-tokens}]]))
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
[app.util.i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc collapsed-button
|
||||
{::mf/wrap-props false}
|
||||
(mf/defc collapsed-button*
|
||||
{::mf/memo true}
|
||||
[]
|
||||
(let [on-click (mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))]
|
||||
[:div {:id "left-sidebar-aside"
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||
[app.main.ui.inspect.right-sidebar :as hrs]
|
||||
[app.main.ui.workspace.sidebar.options.drawing :as drawing]
|
||||
[app.main.ui.workspace.sidebar.options.menus.align :refer [align-options]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.bool :refer [bool-options]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.align :refer [align-options*]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.bool :refer [bool-options*]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.exports :refer [exports-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
|
||||
@@ -32,7 +32,6 @@
|
||||
[app.main.ui.workspace.sidebar.options.shapes.circle :as circle]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.frame :as frame]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.group :as group]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.image :as image]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.multiple :as multiple]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.path :as path]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.rect :as rect]
|
||||
@@ -57,14 +56,13 @@
|
||||
[:*
|
||||
(case shape-type
|
||||
:frame [:> frame/options* props]
|
||||
:group [:& group/options {:shape shape :shape-with-children shapes-with-children :file-id file-id :libraries libraries}]
|
||||
:text [:& text/options {:shape shape :file-id file-id :libraries libraries}]
|
||||
:rect [:& rect/options {:shape shape}]
|
||||
:circle [:& circle/options {:shape shape}]
|
||||
:path [:& path/options {:shape shape}]
|
||||
:image [:& image/options {:shape shape}]
|
||||
:svg-raw [:& svg-raw/options {:shape shape}]
|
||||
:bool [:& bool/options {:shape shape}]
|
||||
:group [:> group/options* {:shape shape :shape-with-children shapes-with-children :file-id file-id :libraries libraries}]
|
||||
:text [:> text/options* {:shape shape :file-id file-id :libraries libraries}]
|
||||
:rect [:> rect/options* {:shape shape}]
|
||||
:circle [:> circle/options* {:shape shape}]
|
||||
:path [:> path/options* {:shape shape}]
|
||||
:svg-raw [:> svg-raw/options* {:shape shape}]
|
||||
:bool [:> bool/options* {:shape shape}]
|
||||
nil)
|
||||
[:& exports-menu
|
||||
{:ids [(:id shape)]
|
||||
@@ -73,7 +71,7 @@
|
||||
:page-id page-id
|
||||
:file-id file-id}]]))
|
||||
|
||||
(mf/defc specialized-panel
|
||||
(mf/defc specialized-panel*
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [panel]}]
|
||||
(when (= (:type panel) :component-swap)
|
||||
@@ -92,8 +90,8 @@
|
||||
(map #(dm/get-in objects [edition :layout-grid-cells %])))]
|
||||
|
||||
[:div {:class (stl/css :element-options :design-options)}
|
||||
[:& align-options]
|
||||
[:& bool-options]
|
||||
[:> align-options*]
|
||||
[:> bool-options*]
|
||||
|
||||
(cond
|
||||
(and edit-grid? (d/not-empty? selected-cells))
|
||||
@@ -107,7 +105,7 @@
|
||||
:values (get objects edition)}]
|
||||
|
||||
(not (nil? sp-panel))
|
||||
[:& specialized-panel {:panel sp-panel}]
|
||||
[:> specialized-panel* {:panel sp-panel}]
|
||||
|
||||
(d/not-empty? drawing)
|
||||
[:> drawing/drawing-options*
|
||||
@@ -125,7 +123,7 @@
|
||||
:shapes-with-children shapes-with-children}]
|
||||
|
||||
:else
|
||||
[:& multiple/options
|
||||
[:> multiple/options*
|
||||
{:shapes-with-children shapes-with-children
|
||||
:shapes selected-shapes
|
||||
:page-id page-id
|
||||
@@ -210,12 +208,9 @@
|
||||
|
||||
(mf/defc options-toolbox*
|
||||
{::mf/memo true}
|
||||
[{:keys [section selected on-change-section on-expand]}]
|
||||
(let [page-id (mf/use-ctx ctx/current-page-id)
|
||||
file-id (mf/use-ctx ctx/current-file-id)
|
||||
shapes (mf/deref refs/selected-objects)
|
||||
[{:keys [page-id file-id section selected on-change-section on-expand]}]
|
||||
(let [shapes (mf/deref refs/selected-objects)
|
||||
shapes-with-children (mf/deref refs/selected-shapes-with-children)]
|
||||
|
||||
[:> options-content* {:shapes shapes
|
||||
:selected selected
|
||||
:shapes-with-children shapes-with-children
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc align-options
|
||||
(mf/defc align-options*
|
||||
{::mf/memo true}
|
||||
[]
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
;; don't need to watch objects, only read the value
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
(def ^:private flatten-icon
|
||||
(i/icon-xref :boolean-flatten (stl/css :flatten-icon)))
|
||||
|
||||
(mf/defc bool-options
|
||||
(mf/defc bool-options*
|
||||
{::mf/memo true}
|
||||
[]
|
||||
(let [selected (mf/deref refs/selected-objects)
|
||||
head (first selected)
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.rect :as grc]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.logic.shapes :as cls]
|
||||
[app.common.types.shape :as cts]
|
||||
@@ -25,7 +27,6 @@
|
||||
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
|
||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :as ds-i]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.menus.border-radius :refer [border-radius-menu*]]
|
||||
[app.util.dom :as dom]
|
||||
@@ -61,7 +62,6 @@
|
||||
:circle generic-options
|
||||
:frame frame-options
|
||||
:group generic-options
|
||||
:image rect-options
|
||||
:path generic-options
|
||||
:rect rect-options
|
||||
:svg-raw generic-options
|
||||
@@ -87,92 +87,139 @@
|
||||
shape)]
|
||||
(select-keys shape measure-attrs)))
|
||||
|
||||
(def ^:private xf:map-type (map :type))
|
||||
(def ^:private xf:mapcat-type-to-options (mapcat type->options))
|
||||
|
||||
(mf/defc measures-menu*
|
||||
{::mf/props :obj
|
||||
::mf/wrap [mf/memo]}
|
||||
[{:keys [ids ids-with-children values type all-types shape]}]
|
||||
(let [options
|
||||
{::mf/memo true}
|
||||
[{:keys [ids ids-with-children values type shapes]}]
|
||||
(let [all-types
|
||||
(mf/with-memo [type shapes]
|
||||
;; We only need this when multiple type is used
|
||||
(when (= type :multiple)
|
||||
(into #{} xf:map-type shapes)))
|
||||
|
||||
options
|
||||
(mf/with-memo [type all-types]
|
||||
(if (= type :multiple)
|
||||
(into #{} (mapcat type->options) all-types)
|
||||
(into #{} xf:mapcat-type-to-options all-types)
|
||||
(type->options type)))
|
||||
|
||||
ids-with-children
|
||||
(or ids-with-children ids)
|
||||
|
||||
old-shapes
|
||||
(if (= type :multiple)
|
||||
(deref (refs/objects-by-id ids))
|
||||
[shape])
|
||||
(d/nilv ids-with-children ids)
|
||||
|
||||
frames
|
||||
(map #(deref (refs/object-by-id (:frame-id %))) old-shapes)
|
||||
(mf/with-memo [shapes]
|
||||
(let [objects (deref refs/workspace-page-objects)]
|
||||
(into [] (comp (keep :frame-id)
|
||||
(map (d/getf objects)))
|
||||
shapes)))
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
selection-parents-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/parents-by-ids ids))
|
||||
|
||||
selection-parents-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
selection-parents (mf/deref selection-parents-ref)
|
||||
selection-parents
|
||||
(mf/deref selection-parents-ref)
|
||||
|
||||
flex-child? (->> selection-parents (some ctl/flex-layout?))
|
||||
absolute? (ctl/item-absolute? shape)
|
||||
flex-container? (ctl/flex-layout? shape)
|
||||
flex-auto-width? (ctl/auto-width? shape)
|
||||
flex-fill-width? (ctl/fill-width? shape)
|
||||
flex-auto-height? (ctl/auto-height? shape)
|
||||
flex-fill-height? (ctl/fill-height? shape)
|
||||
shape
|
||||
(first shapes)
|
||||
|
||||
disabled-position-x? (and flex-child? (not absolute?))
|
||||
disabled-position-y? (and flex-child? (not absolute?))
|
||||
disabled-width-sizing? (and (or flex-child? flex-container?)
|
||||
(or flex-auto-width? flex-fill-width?)
|
||||
(not absolute?))
|
||||
disabled-height-sizing? (and (or flex-child? flex-container?)
|
||||
(or flex-auto-height? flex-fill-height?)
|
||||
(not absolute?))
|
||||
flex-child?
|
||||
(some ctl/flex-layout? selection-parents)
|
||||
|
||||
absolute?
|
||||
(ctl/item-absolute? shape)
|
||||
|
||||
flex-container?
|
||||
(ctl/flex-layout? shape)
|
||||
|
||||
flex-auto-width?
|
||||
(ctl/auto-width? shape)
|
||||
|
||||
flex-fill-width?
|
||||
(ctl/fill-width? shape)
|
||||
|
||||
flex-auto-height?
|
||||
(ctl/auto-height? shape)
|
||||
|
||||
flex-fill-height?
|
||||
(ctl/fill-height? shape)
|
||||
|
||||
disabled-position?
|
||||
(and flex-child? (not absolute?))
|
||||
|
||||
disabled-width-sizing?
|
||||
(and (or flex-child? flex-container?)
|
||||
(or flex-auto-width? flex-fill-width?)
|
||||
(not absolute?))
|
||||
|
||||
disabled-height-sizing?
|
||||
(and (or flex-child? flex-container?)
|
||||
(or flex-auto-height? flex-fill-height?)
|
||||
(not absolute?))
|
||||
|
||||
;; To show interactively the measures while the user is manipulating
|
||||
;; the shape with the mouse, generate a copy of the shapes applying
|
||||
;; the transient transformations.
|
||||
shapes (as-> old-shapes $
|
||||
(map gsh/translate-to-frame $ frames))
|
||||
shapes
|
||||
(mf/with-memo [shapes frames]
|
||||
(map gsh/translate-to-frame shapes frames))
|
||||
|
||||
;; We repeatedly obtain the first shape after the
|
||||
;; transformation.
|
||||
shape
|
||||
(first shapes)
|
||||
|
||||
;; For rotated or stretched shapes, the origin point we show in the menu
|
||||
;; is not the (:x :y) shape attribute, but the top left coordinate of the
|
||||
;; wrapping rectangle.
|
||||
values (let [{:keys [x y]} (gsh/shapes->rect [(first shapes)])]
|
||||
(cond-> values
|
||||
(not= (:x values) :multiple) (assoc :x x)
|
||||
(not= (:y values) :multiple) (assoc :y y)
|
||||
;; In case of multiple selection, the origin point has been already
|
||||
;; calculated and given in the fake :ox and :oy attributes. See
|
||||
;; common/src/app/common/attrs.cljc
|
||||
(and (= (:x values) :multiple)
|
||||
(some? (:ox values))) (assoc :x (:ox values))
|
||||
(and (= (:y values) :multiple)
|
||||
(some? (:oy values))) (assoc :y (:oy values))))
|
||||
values
|
||||
(let [rect (-> (get shape :points)
|
||||
(grc/points->rect))
|
||||
val-x (get values :x)
|
||||
val-y (get values :y)]
|
||||
(cond-> values
|
||||
(not= val-x :multiple) (assoc :x (dm/get-prop rect :x))
|
||||
(not= val-y :multiple) (assoc :y (dm/get-prop rect :y))
|
||||
;; In case of multiple selection, the origin point has been already
|
||||
;; calculated and given in the fake :ox and :oy attributes. See
|
||||
;; common/src/app/common/attrs.cljc
|
||||
(and (= val-x :multiple)
|
||||
(some? (:ox values)))
|
||||
(assoc :x (:ox values))
|
||||
|
||||
(and (= val-y :multiple)
|
||||
(some? (:oy values)))
|
||||
(assoc :y (:oy values))))
|
||||
|
||||
;; For :height and :width we take those in the :selrect attribute, because
|
||||
;; not all shapes have an own :width and :height (e. g. paths). Here the
|
||||
;; rotation is ignored (selrect always has the original size excluding
|
||||
;; transforms).
|
||||
values (let [{:keys [width height]} (-> shapes first :selrect)]
|
||||
(cond-> values
|
||||
(not= (:width values) :multiple) (assoc :width width)
|
||||
(not= (:height values) :multiple) (assoc :height height)))
|
||||
values
|
||||
(let [selrect (get shape :selrect)
|
||||
rotation (get shape :rotation 0)]
|
||||
(cond-> values
|
||||
(not= (:width values) :multiple) (assoc :width (dm/get-prop selrect :width))
|
||||
(not= (:height values) :multiple) (assoc :height (dm/get-prop selrect :height))
|
||||
(not= (:rotation values) :multiple) (assoc :rotation rotation)))
|
||||
|
||||
;; The :rotation, however, does use the transforms.
|
||||
values (let [{:keys [rotation] :or {rotation 0}} (-> shapes first)]
|
||||
(cond-> values
|
||||
(not= (:rotation values) :multiple) (assoc :rotation rotation)))
|
||||
proportion-lock
|
||||
(get values :proportion-lock)
|
||||
|
||||
proportion-lock (:proportion-lock values)
|
||||
clip-content-ref
|
||||
(mf/use-ref nil)
|
||||
|
||||
clip-content-ref (mf/use-ref nil)
|
||||
show-in-viewer-ref (mf/use-ref nil)
|
||||
show-in-viewer-ref
|
||||
(mf/use-ref nil)
|
||||
|
||||
;; PRESETS
|
||||
preset-state* (mf/use-state false)
|
||||
show-presets-dropdown? (deref preset-state*)
|
||||
preset-state*
|
||||
(mf/use-state false)
|
||||
|
||||
show-presets-dropdown?
|
||||
(deref preset-state*)
|
||||
|
||||
open-presets
|
||||
(mf/use-fn
|
||||
@@ -254,10 +301,17 @@
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||
(udw/increase-rotation ids value)))))
|
||||
|
||||
on-width-change #(on-size-change % :width)
|
||||
on-height-change #(on-size-change % :height)
|
||||
on-pos-x-change #(on-position-change % :x)
|
||||
on-pos-y-change #(on-position-change % :y)
|
||||
on-width-change
|
||||
(mf/use-fn (mf/deps on-size-change) #(on-size-change % :width))
|
||||
|
||||
on-height-change
|
||||
(mf/use-fn (mf/deps on-size-change) #(on-size-change % :height))
|
||||
|
||||
on-pos-x-change
|
||||
(mf/use-fn (mf/deps on-position-change) #(on-position-change % :x))
|
||||
|
||||
on-pos-y-change
|
||||
(mf/use-fn (mf/deps on-position-change) #(on-position-change % :y))
|
||||
|
||||
;; CLIP CONTENT AND SHOW IN VIEWER
|
||||
on-change-clip-content
|
||||
@@ -277,9 +331,9 @@
|
||||
(dwsh/update-shapes ids (fn [shape] (cls/change-show-in-viewer shape (not value)))))
|
||||
|
||||
(when-not value
|
||||
;; when a frame is no longer shown in view mode, cannot have
|
||||
;; interactions that navigate to it.
|
||||
(apply st/emit! (map #(dwi/remove-all-interactions-nav-to %) ids)))
|
||||
;; when a frame is no longer shown in view mode, cannot
|
||||
;; have interactions that navigate to it.
|
||||
(run! st/emit! (map #(dwi/remove-all-interactions-nav-to %) ids)))
|
||||
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
@@ -373,27 +427,28 @@
|
||||
(when (options :position)
|
||||
[:div {:class (stl/css :position)}
|
||||
[:div {:class (stl/css-case :x-position true
|
||||
:disabled disabled-position-x?)
|
||||
:disabled disabled-position?)
|
||||
:title (tr "workspace.options.x")}
|
||||
[:span {:class (stl/css :icon-text)} "X"]
|
||||
[:> numeric-input* {:no-validate true
|
||||
:placeholder (if (= :multiple (:x values)) (tr "settings.multiple") "--")
|
||||
:on-change on-pos-x-change
|
||||
:disabled disabled-position-x?
|
||||
:disabled disabled-position?
|
||||
:class (stl/css :numeric-input)
|
||||
:value (:x values)}]]
|
||||
|
||||
[:div {:class (stl/css-case :y-position true
|
||||
:disabled disabled-position-y?)
|
||||
:disabled disabled-position?)
|
||||
:title (tr "workspace.options.y")}
|
||||
[:span {:class (stl/css :icon-text)} "Y"]
|
||||
[:> numeric-input* {:no-validate true
|
||||
:placeholder (if (= :multiple (:y values)) (tr "settings.multiple") "--")
|
||||
:disabled disabled-position-y?
|
||||
:disabled disabled-position?
|
||||
:on-change on-pos-y-change
|
||||
:class (stl/css :numeric-input)
|
||||
:value (:y values)}]]])
|
||||
(when (or (options :rotation) (options :radius))
|
||||
(when (or (options :rotation)
|
||||
(options :radius))
|
||||
[:div {:class (stl/css :rotation-radius)}
|
||||
(when (options :rotation)
|
||||
[:div {:class (stl/css :rotation)
|
||||
@@ -409,7 +464,11 @@
|
||||
:class (stl/css :numeric-input)
|
||||
:value (:rotation values)}]])
|
||||
(when (options :radius)
|
||||
[:> border-radius-menu* {:class (stl/css :border-radius) :ids ids :ids-with-children ids-with-children :values values :shape shape}])])
|
||||
[:> border-radius-menu* {:class (stl/css :border-radius)
|
||||
:ids ids
|
||||
:ids-with-children ids-with-children
|
||||
:values values
|
||||
:shape shape}])])
|
||||
(when (or (options :clip-content) (options :show-in-viewer))
|
||||
[:div {:class (stl/css :clip-show)}
|
||||
(when (options :clip-content)
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.bool
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[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 :as fill]
|
||||
@@ -21,31 +21,61 @@
|
||||
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc options
|
||||
(mf/defc options*
|
||||
[{:keys [shape] :as props}]
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
(let [id (dm/get-prop shape :id)
|
||||
type (dm/get-prop shape :type)
|
||||
ids (mf/with-memo [id] [id])
|
||||
shapes (mf/with-memo [shape] [shape])
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
measure-values
|
||||
(select-keys shape measure-attrs)
|
||||
|
||||
is-flex-parent-ref (mf/use-memo (mf/deps ids) #(refs/flex-layout-child? ids))
|
||||
is-flex-parent? (mf/deref is-flex-parent-ref)
|
||||
stroke-values
|
||||
(select-keys shape stroke-attrs)
|
||||
|
||||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
layer-values
|
||||
(select-keys shape layer-attrs)
|
||||
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
constraint-values
|
||||
(select-keys shape constraint-attrs)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
parents (mf/deref parents-by-ids-ref)]
|
||||
layout-item-values
|
||||
(select-keys shape layout-item-attrs)
|
||||
|
||||
layout-container-values
|
||||
(select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/is-layout-child? ids))
|
||||
|
||||
is-layout-child?
|
||||
(mf/deref is-layout-child-ref)
|
||||
|
||||
is-flex-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/flex-layout-child? ids))
|
||||
|
||||
is-flex-parent?
|
||||
(mf/deref is-flex-parent-ref)
|
||||
|
||||
is-grid-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/grid-layout-child? ids))
|
||||
|
||||
is-grid-parent?
|
||||
(mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute?
|
||||
(ctl/item-absolute? shape)
|
||||
|
||||
parents-by-ids-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/parents-by-ids ids))
|
||||
|
||||
parents
|
||||
(mf/deref parents-by-ids-ref)]
|
||||
|
||||
[:*
|
||||
[:& layer-menu {:ids ids
|
||||
@@ -55,7 +85,7 @@
|
||||
[:> measures-menu* {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
:shapes shapes}]
|
||||
|
||||
[:& layout-container-menu
|
||||
{:type type
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.circle
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[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 :as fill]
|
||||
@@ -22,32 +22,61 @@
|
||||
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc options
|
||||
(mf/defc options*
|
||||
[{:keys [shape] :as props}]
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
(let [id (dm/get-prop shape :id)
|
||||
type (dm/get-prop shape :type)
|
||||
ids (mf/with-memo [id] [id])
|
||||
shapes (mf/with-memo [shape] [shape])
|
||||
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
measure-values
|
||||
(select-keys shape measure-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
stroke-values
|
||||
(select-keys shape stroke-attrs)
|
||||
|
||||
is-flex-parent-ref (mf/use-memo (mf/deps ids) #(refs/flex-layout-child? ids))
|
||||
is-flex-parent? (mf/deref is-flex-parent-ref)
|
||||
layer-values
|
||||
(select-keys shape layer-attrs)
|
||||
|
||||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
constraint-values
|
||||
(select-keys shape constraint-attrs)
|
||||
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
layout-item-values
|
||||
(select-keys shape layout-item-attrs)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
parents (mf/deref parents-by-ids-ref)]
|
||||
layout-container-values
|
||||
(select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/is-layout-child? ids))
|
||||
|
||||
is-layout-child?
|
||||
(mf/deref is-layout-child-ref)
|
||||
|
||||
is-flex-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/flex-layout-child? ids))
|
||||
|
||||
is-flex-parent?
|
||||
(mf/deref is-flex-parent-ref)
|
||||
|
||||
is-grid-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/grid-layout-child? ids))
|
||||
|
||||
is-grid-parent?
|
||||
(mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute?
|
||||
(ctl/item-absolute? shape)
|
||||
|
||||
parents-by-ids-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/parents-by-ids ids))
|
||||
|
||||
parents
|
||||
(mf/deref parents-by-ids-ref)]
|
||||
[:*
|
||||
[:& layer-menu {:ids ids
|
||||
:type type
|
||||
@@ -56,7 +85,7 @@
|
||||
[:> measures-menu* {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
:shapes shapes}]
|
||||
|
||||
[:& layout-container-menu
|
||||
{:type type
|
||||
|
||||
@@ -31,49 +31,77 @@
|
||||
(let [shape-id (dm/get-prop shape :id)
|
||||
shape-type (dm/get-prop shape :type)
|
||||
|
||||
ids (mf/with-memo [shape-id]
|
||||
[shape-id])
|
||||
ids
|
||||
(mf/with-memo [shape-id]
|
||||
[shape-id])
|
||||
|
||||
shapes (mf/with-memo [shape]
|
||||
[shape])
|
||||
shapes
|
||||
(mf/with-memo [shape]
|
||||
[shape])
|
||||
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
measure-values (select-measure-keys shape)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
stroke-values
|
||||
(select-keys shape stroke-attrs)
|
||||
|
||||
layer-values
|
||||
(select-keys shape layer-attrs)
|
||||
|
||||
measure-values
|
||||
(select-measure-keys shape)
|
||||
|
||||
constraint-values
|
||||
(select-keys shape constraint-attrs)
|
||||
|
||||
layout-container-values
|
||||
(select-keys shape layout-container-flex-attrs)
|
||||
|
||||
layout-item-values
|
||||
(select-keys shape layout-item-attrs)
|
||||
|
||||
is-layout-child-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/is-layout-child? ids))
|
||||
|
||||
is-layout-child?
|
||||
(mf/deref is-layout-child-ref)
|
||||
|
||||
is-flex-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/flex-layout-child? ids))
|
||||
|
||||
is-flex-parent?
|
||||
(mf/deref is-flex-parent-ref)
|
||||
|
||||
is-grid-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/grid-layout-child? ids))
|
||||
|
||||
is-grid-parent?
|
||||
(mf/deref is-grid-parent-ref)
|
||||
|
||||
parents-by-ids-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/parents-by-ids ids))
|
||||
|
||||
parents
|
||||
(mf/deref parents-by-ids-ref)
|
||||
|
||||
is-layout-container? (ctl/any-layout? shape)
|
||||
is-flex-layout? (ctl/flex-layout? shape)
|
||||
is-grid-layout? (ctl/grid-layout? shape)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
variants? (features/use-feature "variants/v1")
|
||||
is-variant? (when variants? (ctk/is-variant-container? shape))]
|
||||
is-layout-container?
|
||||
(ctl/any-layout? shape)
|
||||
|
||||
is-flex-layout?
|
||||
(ctl/flex-layout? shape)
|
||||
|
||||
is-grid-layout?
|
||||
(ctl/grid-layout? shape)
|
||||
|
||||
is-layout-child-absolute?
|
||||
(ctl/item-absolute? shape)
|
||||
|
||||
variants?
|
||||
(features/use-feature "variants/v1")
|
||||
|
||||
is-variant?
|
||||
(when variants? (ctk/is-variant-container? shape))]
|
||||
|
||||
[:*
|
||||
[:& layer-menu {:ids ids
|
||||
@@ -82,7 +110,7 @@
|
||||
[:> measures-menu* {:ids ids
|
||||
:values measure-values
|
||||
:type shape-type
|
||||
:shape shape}]
|
||||
:shapes shapes}]
|
||||
|
||||
[:& component-menu {:shapes shapes}]
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraints-menu]]
|
||||
@@ -27,48 +27,89 @@
|
||||
[app.main.ui.workspace.sidebar.options.shapes.multiple :refer [get-attrs]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc options
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
shape-with-children (unchecked-get props "shape-with-children")
|
||||
libraries (unchecked-get props "libraries")
|
||||
objects (->> shape-with-children (group-by :id) (d/mapm (fn [_ v] (first v))))
|
||||
file-id (unchecked-get props "file-id")
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
ids [(:id shape)]
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
(mf/defc options*
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [shape shapes-with-children libraries file-id] :as props}]
|
||||
|
||||
is-flex-parent-ref (mf/use-memo (mf/deps ids) #(refs/flex-layout-child? ids))
|
||||
is-flex-parent? (mf/deref is-flex-parent-ref)
|
||||
(let [id (dm/get-prop shape :id)
|
||||
type (dm/get-prop shape :type)
|
||||
ids (mf/with-memo [id] [id])
|
||||
shapes (mf/with-memo [shape] [shape])
|
||||
|
||||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
objects
|
||||
(mf/with-memo [shapes-with-children]
|
||||
(d/index-by :id shapes-with-children))
|
||||
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
layout-container-values
|
||||
(select-keys shape layout-container-flex-attrs)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
parents (mf/deref parents-by-ids-ref)
|
||||
svg-values
|
||||
(select-keys shape [:svg-attrs])
|
||||
|
||||
type :group
|
||||
[measure-ids measure-values] (get-attrs [shape] objects :measure)
|
||||
[layer-ids layer-values] (get-attrs [shape] objects :layer)
|
||||
[constraint-ids constraint-values] (get-attrs [shape] objects :constraint)
|
||||
[fill-ids fill-values] (get-attrs [shape] objects :fill)
|
||||
[shadow-ids _] (get-attrs [shape] objects :shadow)
|
||||
[blur-ids blur-values] (get-attrs [shape] objects :blur)
|
||||
[stroke-ids stroke-values] (get-attrs [shape] objects :stroke)
|
||||
[text-ids text-values] (get-attrs [shape] objects :text)
|
||||
[svg-ids svg-values] [[(:id shape)] (select-keys shape [:svg-attrs])]
|
||||
[layout-item-ids layout-item-values] (get-attrs [shape] objects :layout-item)]
|
||||
is-layout-child-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/is-layout-child? ids))
|
||||
|
||||
is-layout-child?
|
||||
(mf/deref is-layout-child-ref)
|
||||
|
||||
is-flex-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/flex-layout-child? ids))
|
||||
|
||||
is-flex-parent?
|
||||
(mf/deref is-flex-parent-ref)
|
||||
|
||||
is-grid-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/grid-layout-child? ids))
|
||||
|
||||
is-grid-parent?
|
||||
(mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute?
|
||||
(ctl/item-absolute? shape)
|
||||
|
||||
parents-by-ids-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/parents-by-ids ids))
|
||||
|
||||
parents
|
||||
(mf/deref parents-by-ids-ref)
|
||||
|
||||
[measure-ids measure-values]
|
||||
(get-attrs shapes objects :measure)
|
||||
|
||||
[layer-ids layer-values]
|
||||
(get-attrs shapes objects :layer)
|
||||
|
||||
[constraint-ids constraint-values]
|
||||
(get-attrs shapes objects :constraint)
|
||||
|
||||
[fill-ids fill-values]
|
||||
(get-attrs shapes objects :fill)
|
||||
|
||||
[shadow-ids]
|
||||
(get-attrs shapes objects :shadow)
|
||||
|
||||
[blur-ids blur-values]
|
||||
(get-attrs shapes objects :blur)
|
||||
|
||||
[stroke-ids stroke-values]
|
||||
(get-attrs shapes objects :stroke)
|
||||
|
||||
[text-ids text-values]
|
||||
(get-attrs shapes objects :text)
|
||||
|
||||
[layout-item-ids layout-item-values]
|
||||
(get-attrs shapes objects :layout-item)]
|
||||
|
||||
[:div {:class (stl/css :options)}
|
||||
[:& layer-menu {:type type :ids layer-ids :values layer-values}]
|
||||
[:> measures-menu* {:type type :ids measure-ids :values measure-values :shape shape}]
|
||||
[:> measures-menu* {:type type
|
||||
:ids measure-ids
|
||||
:values measure-values
|
||||
:shapes shapes}]
|
||||
|
||||
[:& layout-container-menu
|
||||
{:type type
|
||||
@@ -116,7 +157,6 @@
|
||||
[:& ot/text-menu {:type type :ids text-ids :values text-values}])
|
||||
|
||||
(when-not (empty? svg-values)
|
||||
[:& svg-attrs-menu {:ids svg-ids
|
||||
:values svg-values}])]))
|
||||
[:& svg-attrs-menu {:ids ids :values svg-values}])]))
|
||||
|
||||
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.image
|
||||
(:require
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[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 :as fill]
|
||||
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-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*]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc options
|
||||
[{:keys [shape] :as props}]
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
|
||||
is-flex-parent-ref (mf/use-memo (mf/deps ids) #(refs/flex-layout-child? ids))
|
||||
is-flex-parent? (mf/deref is-flex-parent-ref)
|
||||
|
||||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
parents (mf/deref parents-by-ids-ref)]
|
||||
[:*
|
||||
[:& layer-menu {:ids ids
|
||||
:type type
|
||||
:values layer-values}]
|
||||
|
||||
[:> measures-menu* {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
|
||||
[:& layout-container-menu
|
||||
{:type type
|
||||
:ids [(:id shape)]
|
||||
:values layout-container-values
|
||||
:multiple false}]
|
||||
|
||||
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)
|
||||
[:& grid-cell/options
|
||||
{:shape (first parents)
|
||||
:cell (ctl/get-cell-by-shape-id (first parents) (first ids))}])
|
||||
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? true
|
||||
:is-flex-parent? is-flex-parent?
|
||||
:is-grid-parent? is-grid-parent?
|
||||
:shape shape}])
|
||||
|
||||
(when (or (not ^boolean is-layout-child?) ^boolean is-layout-child-absolute?)
|
||||
[:& constraints-menu {:ids ids
|
||||
:values constraint-values}])
|
||||
|
||||
[:> fill/fill-menu*
|
||||
{:ids ids
|
||||
:type type
|
||||
:values shape}]
|
||||
|
||||
[:& stroke-menu {:ids ids
|
||||
:type type
|
||||
:values stroke-values}]
|
||||
|
||||
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
||||
|
||||
[:& blur-menu {:ids ids
|
||||
:values (select-keys shape [:blur])}]]))
|
||||
@@ -9,14 +9,16 @@
|
||||
(:require
|
||||
[app.common.attrs :as attrs]
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.path :as path]
|
||||
[app.common.types.shape.attrs :refer [editable-attrs]]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.types.text :as txt]
|
||||
[app.common.weak :as weak]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-attrs blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu]]
|
||||
@@ -202,10 +204,6 @@
|
||||
applies (some of them ignore some attributes)"
|
||||
[shapes objects attr-group]
|
||||
(let [attrs (group->attrs attr-group)
|
||||
|
||||
default-text-attrs
|
||||
(txt/get-default-text-attrs)
|
||||
|
||||
merge-attrs
|
||||
(fn [v1 v2]
|
||||
(cond
|
||||
@@ -213,8 +211,21 @@
|
||||
(= attr-group :blur) (attrs/get-attrs-multi [v1 v2] attrs blur-eq blur-sel)
|
||||
:else (attrs/get-attrs-multi [v1 v2] attrs)))
|
||||
|
||||
merge-token-values
|
||||
(fn [acc keys attrs]
|
||||
(reduce
|
||||
(fn [accum key]
|
||||
(let [new-val (get attrs key)
|
||||
existing (get accum key ::not-found)]
|
||||
(cond
|
||||
(= existing ::not-found) (assoc accum key new-val)
|
||||
(= existing new-val) accum
|
||||
:else (assoc accum key :multiple))))
|
||||
acc
|
||||
keys))
|
||||
|
||||
extract-attrs
|
||||
(fn [[ids values] {:keys [id type] :as shape}]
|
||||
(fn [[ids values token-acc] {:keys [id type applied-tokens] :as shape}]
|
||||
(let [read-mode (get-in type->read-mode [type attr-group])
|
||||
editable-attrs (filter (get editable-attrs (:type shape)) attrs)]
|
||||
(case read-mode
|
||||
@@ -228,144 +239,192 @@
|
||||
(into {} (map #(vector % nil)) editable-attrs)
|
||||
(cond
|
||||
(= attr-group :measure) (select-measure-keys shape)
|
||||
:else (select-keys shape editable-attrs)))]
|
||||
:else (select-keys shape editable-attrs)))
|
||||
new-token-acc (merge-token-values token-acc editable-attrs applied-tokens)]
|
||||
[(conj ids id)
|
||||
(merge-attrs values shape-values)])
|
||||
(merge-attrs values shape-values)
|
||||
new-token-acc])
|
||||
|
||||
:text
|
||||
(let [shape-attrs (select-keys shape attrs)
|
||||
|
||||
content-attrs
|
||||
(attrs/get-text-attrs-multi shape default-text-attrs attrs)
|
||||
(attrs/get-text-attrs-multi shape txt/default-text-attrs attrs)
|
||||
|
||||
new-values
|
||||
(-> values
|
||||
(merge-attrs shape-attrs)
|
||||
(merge-attrs content-attrs))]
|
||||
(merge-attrs content-attrs))
|
||||
|
||||
new-token-acc (merge-token-values token-acc content-attrs applied-tokens)]
|
||||
[(conj ids id)
|
||||
new-values])
|
||||
new-values
|
||||
new-token-acc])
|
||||
|
||||
:children
|
||||
(let [children (->> (:shapes shape []) (map #(get objects %)))
|
||||
[new-ids new-values] (get-attrs* children objects attr-group)]
|
||||
[(d/concat-vec ids new-ids) (merge-attrs values new-values)])
|
||||
[(d/concat-vec ids new-ids) (merge-attrs values new-values) {}])
|
||||
|
||||
[])))]
|
||||
|
||||
(reduce extract-attrs [[] []] shapes)))
|
||||
(reduce extract-attrs [[] {} {}] shapes)))
|
||||
|
||||
(def get-attrs (memoize get-attrs*))
|
||||
|
||||
(defn basic-shape [_ shape]
|
||||
(cond-> shape
|
||||
:always
|
||||
(dissoc :selrect :points :x :y :width :height :transform :transform-inverse :rotation :svg-transform :svg-viewbox :thumbnail)
|
||||
|
||||
(= (:type shape) :path)
|
||||
(dissoc :content)))
|
||||
(def get-attrs
|
||||
(weak/memoize get-attrs*))
|
||||
|
||||
(defn- is-bool-descendant?
|
||||
[[_ shape] objects selected-shape-ids]
|
||||
[objects selected-shape-ids shape]
|
||||
|
||||
(let [parent-id (:parent-id shape)
|
||||
parent (get objects parent-id)]
|
||||
(cond
|
||||
(nil? shape) false ;; failsafe
|
||||
(contains? selected-shape-ids (:id shape)) false ;; if it is one of the selected shapes, it is considerer not a bool descendant
|
||||
(= :bool (:type parent)) true ;; if its parent is of type bool, it is a bool descendant
|
||||
(nil? shape) false ;; failsafe
|
||||
(contains? selected-shape-ids (:id shape)) false ;; if it is one of the selected shapes, it is considerer not a bool descendant
|
||||
(= :bool (:type parent)) true ;; if its parent is of type bool, it is a bool descendant
|
||||
:else (recur [parent-id parent] objects selected-shape-ids)))) ;; else, check its parent
|
||||
|
||||
(mf/defc options
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["shapes" "shapes-with-children" "page-id" "file-id"]))]
|
||||
::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shapes (unchecked-get props "shapes")
|
||||
shapes-with-children (unchecked-get props "shapes-with-children")
|
||||
(defn- check-options-props
|
||||
[new-props old-props]
|
||||
(and (= (unchecked-get new-props "shapes")
|
||||
(unchecked-get old-props "shapes"))
|
||||
(= (unchecked-get new-props "shapesWithChildren")
|
||||
(unchecked-get old-props "shapesWithChildren"))
|
||||
(= (unchecked-get new-props "pageId")
|
||||
(unchecked-get old-props "pageId"))
|
||||
(= (unchecked-get new-props "fileId")
|
||||
(unchecked-get old-props "fileId"))))
|
||||
|
||||
;; remove children from bool shapes
|
||||
shape-ids (into #{} (map :id) shapes)
|
||||
(mf/defc options*
|
||||
{::mf/wrap [#(mf/memo' % check-options-props)]}
|
||||
[{:keys [shapes shapes-with-children page-id file-id libraries] :as props}]
|
||||
(let [shape-ids
|
||||
(mf/with-memo [shapes]
|
||||
(into #{} d/xf:map-id shapes))
|
||||
|
||||
is-layout-child-ref
|
||||
(mf/with-memo [shape-ids]
|
||||
(refs/is-layout-child? shape-ids))
|
||||
|
||||
is-layout-child?
|
||||
(mf/deref is-layout-child-ref)
|
||||
|
||||
is-flex-parent-ref
|
||||
(mf/with-memo [shape-ids]
|
||||
(refs/flex-layout-child? shape-ids))
|
||||
|
||||
is-flex-parent?
|
||||
(mf/deref is-flex-parent-ref)
|
||||
|
||||
is-grid-parent-ref
|
||||
(mf/with-memo [shape-ids]
|
||||
(refs/grid-layout-child? shape-ids))
|
||||
|
||||
is-grid-parent?
|
||||
(mf/deref is-grid-parent-ref)
|
||||
|
||||
has-flex-layout-container?
|
||||
(some ctl/flex-layout? shapes)
|
||||
|
||||
all-layout-child-ref
|
||||
(mf/with-memo [shape-ids]
|
||||
(refs/all-layout-child? shape-ids))
|
||||
|
||||
all-layout-child?
|
||||
(mf/deref all-layout-child-ref)
|
||||
|
||||
all-flex-layout-container?
|
||||
(mf/with-memo [shapes]
|
||||
(every? ctl/flex-layout? shapes))
|
||||
|
||||
show-caps?
|
||||
(mf/with-memo [shapes]
|
||||
(some #(and (cfh/path-shape? %)
|
||||
(path/shape-with-open-path? %))
|
||||
shapes))
|
||||
|
||||
has-text?
|
||||
(mf/with-memo [shapes]
|
||||
(some cfh/text-shape? shapes))
|
||||
|
||||
objects (->> shapes-with-children (group-by :id) (d/mapm (fn [_ v] (first v))))
|
||||
objects
|
||||
(into {}
|
||||
(filter #(not (is-bool-descendant? % objects shape-ids)))
|
||||
objects)
|
||||
(mf/with-memo [shapes-with-children]
|
||||
(let [objects (d/index-by :id shapes-with-children)]
|
||||
(reduce-kv (fn [objects id object]
|
||||
(if (is-bool-descendant? objects shape-ids object)
|
||||
(dissoc objects id)
|
||||
objects))
|
||||
objects
|
||||
objects)))
|
||||
|
||||
workspace-modifiers (mf/deref refs/workspace-modifiers)
|
||||
shapes (map #(gsh/transform-shape % (get-in workspace-modifiers [(:id %) :modifiers])) shapes)
|
||||
[layer-ids layer-values]
|
||||
(get-attrs shapes objects :layer)
|
||||
|
||||
page-id (unchecked-get props "page-id")
|
||||
file-id (unchecked-get props "file-id")
|
||||
shared-libs (unchecked-get props "libraries")
|
||||
[text-ids text-values]
|
||||
(get-attrs shapes objects :text)
|
||||
|
||||
show-caps (some #(and (= :path (:type %)) (path/shape-with-open-path? %)) shapes)
|
||||
[constraint-ids constraint-values]
|
||||
(get-attrs shapes objects :constraint)
|
||||
|
||||
;; Selrect/points only used for measures and it's the one that changes the most. We separate it
|
||||
;; so we can memoize it
|
||||
objects-no-measures (->> objects (d/mapm basic-shape))
|
||||
objects-no-measures (hooks/use-equal-memo objects-no-measures)
|
||||
[fill-ids fill-values]
|
||||
(get-attrs shapes objects :fill)
|
||||
|
||||
[shadow-ids shadow-values]
|
||||
(get-attrs shapes objects :shadow)
|
||||
|
||||
[blur-ids blur-values]
|
||||
(get-attrs shapes objects :blur)
|
||||
|
||||
[stroke-ids stroke-values]
|
||||
(get-attrs shapes objects :stroke)
|
||||
|
||||
[exports-ids exports-values]
|
||||
(get-attrs shapes objects :exports)
|
||||
|
||||
[layout-container-ids layout-container-values]
|
||||
(get-attrs shapes objects :layout-container)
|
||||
|
||||
[layout-item-ids layout-item-values {}]
|
||||
(get-attrs shapes objects :layout-item)
|
||||
|
||||
components
|
||||
(mf/with-memo [shapes]
|
||||
(not-empty (filter ctk/instance-head? shapes)))
|
||||
|
||||
workspace-modifiers
|
||||
(mf/deref refs/workspace-modifiers)
|
||||
|
||||
shapes
|
||||
(mf/with-memo [workspace-modifiers shapes]
|
||||
(into []
|
||||
(map (fn [shape]
|
||||
(let [shape-id (dm/get-prop shape :id)
|
||||
modifiers (dm/get-in workspace-modifiers [shape-id :modifiers])]
|
||||
(gsh/transform-shape shape modifiers))))
|
||||
shapes))
|
||||
|
||||
type :multiple
|
||||
all-types (into #{} (map :type shapes))
|
||||
|
||||
ids (->> shapes (map :id))
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
|
||||
is-flex-parent-ref (mf/use-memo (mf/deps ids) #(refs/flex-layout-child? ids))
|
||||
is-flex-parent? (mf/deref is-flex-parent-ref)
|
||||
|
||||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
|
||||
has-text? (contains? all-types :text)
|
||||
|
||||
has-flex-layout-container? (->> shapes (some ctl/flex-layout?))
|
||||
|
||||
all-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/all-layout-child? ids))
|
||||
all-layout-child? (mf/deref all-layout-child-ref)
|
||||
|
||||
all-flex-layout-container? (->> shapes (every? ctl/flex-layout?))
|
||||
|
||||
[measure-ids measure-values] (get-attrs shapes objects :measure)
|
||||
|
||||
[layer-ids layer-values
|
||||
text-ids text-values
|
||||
constraint-ids constraint-values
|
||||
fill-ids fill-values
|
||||
shadow-ids shadow-values
|
||||
blur-ids blur-values
|
||||
stroke-ids stroke-values
|
||||
exports-ids exports-values
|
||||
layout-container-ids layout-container-values
|
||||
layout-item-ids layout-item-values]
|
||||
(mf/use-memo
|
||||
(mf/deps shapes objects-no-measures)
|
||||
(fn []
|
||||
(into
|
||||
[]
|
||||
(mapcat identity)
|
||||
[(get-attrs shapes objects-no-measures :layer)
|
||||
(get-attrs shapes objects-no-measures :text)
|
||||
(get-attrs shapes objects-no-measures :constraint)
|
||||
(get-attrs shapes objects-no-measures :fill)
|
||||
(get-attrs shapes objects-no-measures :shadow)
|
||||
(get-attrs shapes objects-no-measures :blur)
|
||||
(get-attrs shapes objects-no-measures :stroke)
|
||||
(get-attrs shapes objects-no-measures :exports)
|
||||
(get-attrs shapes objects-no-measures :layout-container)
|
||||
(get-attrs shapes objects-no-measures :layout-item)])))
|
||||
|
||||
components (filter ctk/instance-head? shapes)]
|
||||
;; NOTE: we only need transformed shapes for the measure menu,
|
||||
;; the rest of menus can live with shapes not transformed; we
|
||||
;; also don't use the memoized version of get-attrs because it
|
||||
;; makes no sense because the shapes object are changed on
|
||||
;; each rerender.
|
||||
[measure-ids measure-values]
|
||||
(get-attrs* shapes objects :measure)]
|
||||
|
||||
[:div {:class (stl/css :options)}
|
||||
(when-not (empty? layer-ids)
|
||||
[:& layer-menu {:type type :ids layer-ids :values layer-values}])
|
||||
|
||||
(when-not (empty? measure-ids)
|
||||
[:> measures-menu* {:type type :all-types all-types :ids measure-ids :values measure-values :shape shapes}])
|
||||
[:> measures-menu*
|
||||
{:type type
|
||||
:ids measure-ids
|
||||
:values measure-values
|
||||
:shapes shapes}])
|
||||
|
||||
(when-not (empty? components)
|
||||
(when (some? components)
|
||||
[:& component-menu {:shapes components}])
|
||||
|
||||
[:& layout-container-menu
|
||||
@@ -394,15 +453,18 @@
|
||||
[:> fill/fill-menu* {:type type :ids fill-ids :values fill-values}])
|
||||
|
||||
(when-not (empty? stroke-ids)
|
||||
[:& stroke-menu {:type type :ids stroke-ids :show-caps show-caps :values stroke-values
|
||||
[:& stroke-menu {:type type
|
||||
:ids stroke-ids
|
||||
:show-caps show-caps?
|
||||
:values stroke-values
|
||||
:disable-stroke-style has-text?}])
|
||||
|
||||
(when-not (empty? shapes)
|
||||
[:> color-selection-menu*
|
||||
{:file-id file-id
|
||||
:type type
|
||||
:shapes (vals objects-no-measures)
|
||||
:libraries shared-libs}])
|
||||
:shapes shapes
|
||||
:libraries libraries}])
|
||||
|
||||
(when-not (empty? shadow-ids)
|
||||
[:> shadow-menu* {:type type
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.path
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[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 :as fill]
|
||||
@@ -22,32 +22,68 @@
|
||||
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc options
|
||||
(mf/defc options*
|
||||
[{:keys [shape] :as props}]
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
(let [ids
|
||||
(mf/with-memo [shape]
|
||||
[(dm/get-prop shape :id)])
|
||||
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
shapes
|
||||
(mf/with-memo [shape]
|
||||
[shape])
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
type
|
||||
(dm/get-prop shape :type)
|
||||
|
||||
is-flex-parent-ref (mf/use-memo (mf/deps ids) #(refs/flex-layout-child? ids))
|
||||
is-flex-parent? (mf/deref is-flex-parent-ref)
|
||||
measure-values
|
||||
(select-keys shape measure-attrs)
|
||||
|
||||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
stroke-values
|
||||
(select-keys shape stroke-attrs)
|
||||
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
layer-values
|
||||
(select-keys shape layer-attrs)
|
||||
|
||||
constraint-values
|
||||
(select-keys shape constraint-attrs)
|
||||
|
||||
layout-item-values
|
||||
(select-keys shape layout-item-attrs)
|
||||
|
||||
layout-container-values
|
||||
(select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/is-layout-child? ids))
|
||||
|
||||
is-layout-child?
|
||||
(mf/deref is-layout-child-ref)
|
||||
|
||||
is-flex-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/flex-layout-child? ids))
|
||||
|
||||
is-flex-parent?
|
||||
(mf/deref is-flex-parent-ref)
|
||||
|
||||
is-grid-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/grid-layout-child? ids))
|
||||
|
||||
is-grid-parent?
|
||||
(mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute?
|
||||
(ctl/item-absolute? shape)
|
||||
|
||||
parents-by-ids-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/parents-by-ids ids))
|
||||
|
||||
parents
|
||||
(mf/deref parents-by-ids-ref)]
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
parents (mf/deref parents-by-ids-ref)]
|
||||
[:*
|
||||
[:& layer-menu {:ids ids
|
||||
:type type
|
||||
@@ -55,7 +91,7 @@
|
||||
[:> measures-menu* {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
:shapes shapes}]
|
||||
|
||||
[:& layout-container-menu
|
||||
{:type type
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.rect
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[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 :as fill]
|
||||
@@ -16,39 +16,67 @@
|
||||
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.measures :refer [select-measure-keys measures-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*]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.svg-attrs :refer [svg-attrs-menu]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc options
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
(mf/defc options*
|
||||
[{:keys [shape]}]
|
||||
(let [shape-id (:id shape)
|
||||
ids (hooks/use-equal-memo [shape-id])
|
||||
type (:type shape)
|
||||
measure-values (select-measure-keys shape)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
(let [id (dm/get-prop shape :id)
|
||||
type (dm/get-prop shape :type)
|
||||
ids (mf/with-memo [id] [id])
|
||||
shapes (mf/with-memo [shape] [shape])
|
||||
|
||||
is-layout-child* (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child*)
|
||||
measure-values
|
||||
(select-keys shape measure-attrs)
|
||||
|
||||
is-flex-parent* (mf/use-memo (mf/deps ids) #(refs/flex-layout-child? ids))
|
||||
is-flex-parent? (mf/deref is-flex-parent*)
|
||||
stroke-values
|
||||
(select-keys shape stroke-attrs)
|
||||
|
||||
is-grid-parent* (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent*)
|
||||
layer-values
|
||||
(select-keys shape layer-attrs)
|
||||
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
constraint-values
|
||||
(select-keys shape constraint-attrs)
|
||||
|
||||
parents-by-ids* (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
parents (mf/deref parents-by-ids*)]
|
||||
layout-item-values
|
||||
(select-keys shape layout-item-attrs)
|
||||
|
||||
layout-container-values
|
||||
(select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/is-layout-child? ids))
|
||||
|
||||
is-layout-child?
|
||||
(mf/deref is-layout-child-ref)
|
||||
|
||||
is-flex-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/flex-layout-child? ids))
|
||||
|
||||
is-flex-parent?
|
||||
(mf/deref is-flex-parent-ref)
|
||||
|
||||
is-grid-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/grid-layout-child? ids))
|
||||
|
||||
is-grid-parent?
|
||||
(mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute?
|
||||
(ctl/item-absolute? shape)
|
||||
|
||||
parents-by-ids-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/parents-by-ids ids))
|
||||
|
||||
parents
|
||||
(mf/deref parents-by-ids-ref)]
|
||||
|
||||
[:*
|
||||
[:& layer-menu {:ids ids
|
||||
@@ -57,7 +85,7 @@
|
||||
[:> measures-menu* {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
:shapes shapes}]
|
||||
|
||||
[:& layout-container-menu
|
||||
{:type type
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.svg-raw
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.color :as cc]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[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 :as fill]
|
||||
@@ -26,15 +26,10 @@
|
||||
|
||||
;; This is a list of svg tags that can be grouped in shape-container
|
||||
;; this allows them to have gradients, shadows and masks
|
||||
(def svg-elements #{:svg :g :circle :ellipse :image :line :path :polygon :polyline :rect :symbol :text :textPath})
|
||||
(def ^:private svg-elements
|
||||
#{:svg :g :circle :ellipse :image :line :path :polygon :polyline :rect :symbol :text :textPath})
|
||||
|
||||
(defn hex->number [_] 1)
|
||||
|
||||
(defn shorthex->longhex [hex]
|
||||
(let [[_ r g b] hex]
|
||||
(str "#" r r g g b b)))
|
||||
|
||||
(defn parse-color [color]
|
||||
(defn- parse-color [color]
|
||||
(try
|
||||
(cond
|
||||
(or (not color) (= color "none")) nil
|
||||
@@ -51,8 +46,7 @@
|
||||
(.error js/console "Error parsing color" e)
|
||||
nil)))
|
||||
|
||||
|
||||
(defn get-fill-values [shape]
|
||||
(defn- get-fill-values [shape]
|
||||
(let [fill-values (select-keys shape fill/fill-attrs)
|
||||
color (-> (or (get-in shape [:content :attrs :fill])
|
||||
(get-in shape [:content :attrs :style :fill]))
|
||||
@@ -64,7 +58,7 @@
|
||||
fill-values)]
|
||||
fill-values))
|
||||
|
||||
(defn get-stroke-values [shape]
|
||||
(defn- get-stroke-values [shape]
|
||||
(let [stroke-values (select-keys shape stroke-attrs)
|
||||
color (-> (or (get-in shape [:content :attrs :stroke])
|
||||
(get-in shape [:content :attrs :style :stroke]))
|
||||
@@ -92,42 +86,75 @@
|
||||
stroke-values)]
|
||||
stroke-values))
|
||||
|
||||
(mf/defc options
|
||||
(mf/defc options*
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [shape] :as props}]
|
||||
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
(let [id (dm/get-prop shape :id)
|
||||
type (dm/get-prop shape :type)
|
||||
ids (mf/with-memo [id] [id])
|
||||
shapes (mf/with-memo [shape] [shape])
|
||||
|
||||
{:keys [tag] :as content} (:content shape)
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
fill-values (get-fill-values shape)
|
||||
stroke-values (get-stroke-values shape)
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
{:keys [tag] :as content}
|
||||
(get shape :content)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
fill-values
|
||||
(mf/with-memo [shape]
|
||||
(get-fill-values shape))
|
||||
|
||||
is-flex-parent-ref (mf/use-memo (mf/deps ids) #(refs/flex-layout-child? ids))
|
||||
is-flex-parent? (mf/deref is-flex-parent-ref)
|
||||
stroke-values
|
||||
(mf/with-memo [shape]
|
||||
(get-stroke-values shape))
|
||||
|
||||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
measure-values
|
||||
(select-keys shape measure-attrs)
|
||||
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
constraint-values
|
||||
(select-keys shape constraint-attrs)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
parents (mf/deref parents-by-ids-ref)]
|
||||
layout-item-values
|
||||
(select-keys shape layout-item-attrs)
|
||||
|
||||
layout-container-values
|
||||
(select-keys shape layout-container-flex-attrs)
|
||||
|
||||
is-layout-child-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/is-layout-child? ids))
|
||||
|
||||
is-layout-child?
|
||||
(mf/deref is-layout-child-ref)
|
||||
|
||||
is-flex-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/flex-layout-child? ids))
|
||||
|
||||
is-flex-parent?
|
||||
(mf/deref is-flex-parent-ref)
|
||||
|
||||
is-grid-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/grid-layout-child? ids))
|
||||
|
||||
is-grid-parent?
|
||||
(mf/deref is-grid-parent-ref)
|
||||
|
||||
is-layout-child-absolute?
|
||||
(ctl/item-absolute? shape)
|
||||
|
||||
parents-by-ids-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/parents-by-ids ids))
|
||||
|
||||
parents
|
||||
(mf/deref parents-by-ids-ref)]
|
||||
|
||||
(when (contains? svg-elements tag)
|
||||
[:*
|
||||
[:> measures-menu* {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
:shapes shapes}]
|
||||
|
||||
[:& layout-container-menu
|
||||
{:type type
|
||||
|
||||
@@ -6,14 +6,13 @@
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.text
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.types.text :as txt]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
@@ -28,68 +27,102 @@
|
||||
[app.main.ui.workspace.sidebar.options.menus.text :refer [text-menu]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc options
|
||||
(mf/defc options*
|
||||
[{:keys [shape file-id libraries] :as props}]
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
(let [id (dm/get-prop shape :id)
|
||||
type (dm/get-prop shape :type)
|
||||
ids (mf/with-memo [id] [id])
|
||||
shapes (mf/with-memo [shape] [shape])
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
measure-values
|
||||
(select-keys shape measure-attrs)
|
||||
|
||||
is-flex-parent-ref (mf/use-memo (mf/deps ids) #(refs/flex-layout-child? ids))
|
||||
is-flex-parent? (mf/deref is-flex-parent-ref)
|
||||
stroke-values
|
||||
(select-keys shape stroke-attrs)
|
||||
|
||||
is-grid-parent-ref (mf/use-memo (mf/deps ids) #(refs/grid-layout-child? ids))
|
||||
is-grid-parent? (mf/deref is-grid-parent-ref)
|
||||
layer-values
|
||||
(select-keys shape layer-attrs)
|
||||
|
||||
layout-container-values (select-keys shape layout-container-flex-attrs)
|
||||
is-layout-child-absolute? (ctl/item-absolute? shape)
|
||||
layout-item-values
|
||||
(select-keys shape layout-item-attrs)
|
||||
|
||||
ids (hooks/use-equal-memo ids)
|
||||
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
parents (mf/deref parents-by-ids-ref)
|
||||
layout-container-values
|
||||
(select-keys shape layout-container-flex-attrs)
|
||||
|
||||
state-map (if (features/active-feature? @st/state "text-editor/v2")
|
||||
(mf/deref refs/workspace-v2-editor-state)
|
||||
(mf/deref refs/workspace-editor-state))
|
||||
is-layout-child-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/is-layout-child? ids))
|
||||
|
||||
editor-state (when (not (features/active-feature? @st/state "text-editor/v2"))
|
||||
(get state-map (:id shape)))
|
||||
is-layout-child?
|
||||
(mf/deref is-layout-child-ref)
|
||||
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
editor-instance (when (features/active-feature? @st/state "text-editor/v2")
|
||||
(mf/deref refs/workspace-editor))
|
||||
is-flex-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/flex-layout-child? ids))
|
||||
|
||||
fill-values (dwt/current-text-values
|
||||
{:editor-state editor-state
|
||||
:editor-instance editor-instance
|
||||
:shape shape
|
||||
:attrs (conj txt/text-fill-attrs :fills)})
|
||||
is-flex-parent?
|
||||
(mf/deref is-flex-parent-ref)
|
||||
|
||||
fill-values (if (not (contains? fill-values :fills))
|
||||
;; Old fill format
|
||||
{:fills [fill-values]}
|
||||
fill-values)
|
||||
is-grid-parent-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/grid-layout-child? ids))
|
||||
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
is-grid-parent?
|
||||
(mf/deref is-grid-parent-ref)
|
||||
|
||||
text-values (d/merge
|
||||
(select-keys shape [:grow-type])
|
||||
(select-keys shape fill/fill-attrs)
|
||||
(dwt/current-root-values
|
||||
{:shape shape
|
||||
:attrs txt/root-attrs})
|
||||
(dwt/current-paragraph-values
|
||||
{:editor-state editor-state
|
||||
:editor-instance editor-instance
|
||||
:shape shape
|
||||
:attrs txt/paragraph-attrs})
|
||||
(dwt/current-text-values
|
||||
{:editor-state editor-state
|
||||
:editor-instance editor-instance
|
||||
:shape shape
|
||||
:attrs txt/text-node-attrs}))
|
||||
layout-item-values (select-keys shape layout-item-attrs)]
|
||||
is-layout-child-absolute?
|
||||
(ctl/item-absolute? shape)
|
||||
|
||||
parents-by-ids-ref
|
||||
(mf/with-memo [ids]
|
||||
(refs/parents-by-ids ids))
|
||||
|
||||
parents
|
||||
(mf/deref parents-by-ids-ref)
|
||||
|
||||
state-map
|
||||
(if (features/active-feature? @st/state "text-editor/v2")
|
||||
(mf/deref refs/workspace-v2-editor-state)
|
||||
(mf/deref refs/workspace-editor-state))
|
||||
|
||||
editor-state
|
||||
(when (not (features/active-feature? @st/state "text-editor/v2"))
|
||||
(get state-map id))
|
||||
|
||||
editor-instance
|
||||
(when (features/active-feature? @st/state "text-editor/v2")
|
||||
(mf/deref refs/workspace-editor))
|
||||
|
||||
fill-values
|
||||
(dwt/current-text-values
|
||||
{:editor-state editor-state
|
||||
:editor-instance editor-instance
|
||||
:shape shape
|
||||
:attrs (conj txt/text-fill-attrs :fills)})
|
||||
|
||||
fill-values
|
||||
(if (not (contains? fill-values :fills))
|
||||
;; Old fill format
|
||||
{:fills [fill-values]}
|
||||
fill-values)
|
||||
|
||||
text-values
|
||||
(merge
|
||||
(select-keys shape [:grow-type])
|
||||
(select-keys shape fill/fill-attrs)
|
||||
(dwt/current-root-values
|
||||
{:shape shape
|
||||
:attrs txt/root-attrs})
|
||||
(dwt/current-paragraph-values
|
||||
{:editor-state editor-state
|
||||
:editor-instance editor-instance
|
||||
:shape shape
|
||||
:attrs txt/paragraph-attrs})
|
||||
(dwt/current-text-values
|
||||
{:editor-state editor-state
|
||||
:editor-instance editor-instance
|
||||
:shape shape
|
||||
:attrs txt/text-node-attrs}))]
|
||||
|
||||
[:*
|
||||
[:& layer-menu {:ids ids
|
||||
@@ -98,12 +131,12 @@
|
||||
[:> measures-menu*
|
||||
{:ids ids
|
||||
:type type
|
||||
:values (select-keys shape measure-attrs)
|
||||
:shape shape}]
|
||||
:values measure-values
|
||||
:shapes shapes}]
|
||||
|
||||
[:& layout-container-menu
|
||||
{:type type
|
||||
:ids [(:id shape)]
|
||||
:ids ids
|
||||
:values layout-container-values
|
||||
:multiple false}]
|
||||
|
||||
@@ -145,7 +178,7 @@
|
||||
(when (= :multiple (:fills fill-values))
|
||||
[:> color-selection-menu*
|
||||
{:type type
|
||||
:shapes [shape]
|
||||
:shapes shapes
|
||||
:file-id file-id
|
||||
:libraries libraries}])
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
(mf/defc tokens-section*
|
||||
{::mf/private true}
|
||||
[{:keys [tokens-lib]}]
|
||||
[{:keys [tokens-lib active-tokens resolved-active-tokens]}]
|
||||
(let [objects (mf/deref refs/workspace-page-objects)
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
open-status (mf/deref ref:token-type-open-status)
|
||||
@@ -66,18 +66,9 @@
|
||||
(mf/with-memo [selected-shapes objects]
|
||||
(some #(ctsl/any-layout-immediate-child? objects %) selected-shapes))
|
||||
|
||||
active-theme-tokens
|
||||
(mf/with-memo [tokens-lib]
|
||||
(if tokens-lib
|
||||
(ctob/get-tokens-in-active-sets tokens-lib)
|
||||
{}))
|
||||
|
||||
;; Resolve tokens as second step
|
||||
active-theme-tokens'
|
||||
(sd/use-resolved-tokens* active-theme-tokens)
|
||||
|
||||
;; This only checks for the currently explicitly selected set
|
||||
;; name, it is ephimeral and can be nil
|
||||
;; FIXME: this is a repeated deref for the same `:workspace-tokens` state
|
||||
selected-token-set-name
|
||||
(mf/deref refs/selected-token-set-name)
|
||||
|
||||
@@ -92,8 +83,8 @@
|
||||
(ctob/get-tokens-map selected-token-set))
|
||||
|
||||
tokens
|
||||
(mf/with-memo [active-theme-tokens selected-token-set-tokens]
|
||||
(merge active-theme-tokens selected-token-set-tokens))
|
||||
(mf/with-memo [active-tokens selected-token-set-tokens]
|
||||
(merge active-tokens selected-token-set-tokens))
|
||||
|
||||
tokens
|
||||
(sd/use-resolved-tokens* tokens)
|
||||
@@ -154,7 +145,7 @@
|
||||
:type type
|
||||
:selected-shapes selected-shapes
|
||||
:is-selected-inside-layout is-selected-inside-layout
|
||||
:active-theme-tokens active-theme-tokens'
|
||||
:active-theme-tokens resolved-active-tokens
|
||||
:tokens tokens}]))
|
||||
|
||||
(for [type empty-group]
|
||||
@@ -162,5 +153,5 @@
|
||||
:type type
|
||||
:selected-shapes selected-shapes
|
||||
:is-selected-inside-layout :is-selected-inside-layout
|
||||
:active-theme-tokens active-theme-tokens'
|
||||
:active-theme-tokens resolved-active-tokens
|
||||
:tokens []}])]))
|
||||
|
||||
@@ -144,16 +144,12 @@
|
||||
:on-click open-settings-modal}])]))
|
||||
|
||||
(mf/defc tokens-sidebar-tab*
|
||||
{::mf/wrap [mf/memo]}
|
||||
[]
|
||||
[{:keys [tokens-lib] :as props}]
|
||||
(let [{on-pointer-down-pages :on-pointer-down
|
||||
on-lost-pointer-capture-pages :on-lost-pointer-capture
|
||||
on-pointer-move-pages :on-pointer-move
|
||||
size-pages-opened :size}
|
||||
(use-resize-hook :tokens 200 38 "0.6" :y false nil)
|
||||
|
||||
tokens-lib
|
||||
(mf/deref refs/tokens-lib)]
|
||||
(use-resize-hook :tokens 200 38 "0.6" :y false nil)]
|
||||
|
||||
[:div {:class (stl/css :sidebar-wrapper)}
|
||||
[:> token-management-section*
|
||||
@@ -166,5 +162,5 @@
|
||||
:on-lost-pointer-capture on-lost-pointer-capture-pages
|
||||
:on-pointer-move on-pointer-move-pages}
|
||||
[:div {:class (stl/css :resize-handle-horiz)}]]
|
||||
[:> tokens-section* {:tokens-lib tokens-lib}]]
|
||||
[:> tokens-section* props]]
|
||||
[:> import-export-button*]]))
|
||||
|
||||
Reference in New Issue
Block a user