mirror of
https://github.com/penpot/penpot.git
synced 2025-08-07 14:38:33 +02:00
♻️ Refactor tab-switcher* component (#6815)
* 💄 Add minor style adjustments to workspace sidebar * 💄 Add style enhacement to sitemap component * ♻️ Refactor tab-switcher* component
This commit is contained in:
parent
3d45080e3c
commit
41994703a9
19 changed files with 532 additions and 460 deletions
|
@ -1148,12 +1148,3 @@
|
||||||
:position :right})
|
:position :right})
|
||||||
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
||||||
:asset-type "color"}))))))
|
:asset-type "color"}))))))
|
||||||
|
|
||||||
(defn get-active-color-tab
|
|
||||||
[]
|
|
||||||
(let [tab (::tab storage/user)]
|
|
||||||
(or tab :ramp)))
|
|
||||||
|
|
||||||
(defn set-active-color-tab!
|
|
||||||
[tab]
|
|
||||||
(swap! storage/user assoc ::tab tab))
|
|
||||||
|
|
|
@ -6,20 +6,21 @@
|
||||||
|
|
||||||
(ns app.main.ui.ds.layout.tab-switcher
|
(ns app.main.ui.ds.layout.tab-switcher
|
||||||
(:require-macros
|
(:require-macros
|
||||||
[app.common.data.macros :as dm]
|
|
||||||
[app.main.style :as stl])
|
[app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]]
|
[app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]]
|
||||||
[app.util.array :as array]
|
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]
|
||||||
|
[rumext.v2.util :as mfu]))
|
||||||
|
|
||||||
(mf/defc tab*
|
(mf/defc tab*
|
||||||
{::mf/private true}
|
{::mf/private true}
|
||||||
[{:keys [selected icon label aria-label id on-ref] :rest props}]
|
[{:keys [selected icon label aria-label id ref] :rest props}]
|
||||||
(let [class (stl/css-case :tab true
|
(let [class (stl/css-case
|
||||||
|
:tab true
|
||||||
:selected selected)
|
:selected selected)
|
||||||
props (mf/spread-props props
|
props (mf/spread-props props
|
||||||
{:class class
|
{:class class
|
||||||
|
@ -27,8 +28,7 @@
|
||||||
:aria-selected selected
|
:aria-selected selected
|
||||||
:title (or label aria-label)
|
:title (or label aria-label)
|
||||||
:tab-index (if selected nil -1)
|
:tab-index (if selected nil -1)
|
||||||
:ref (fn [node]
|
:ref ref
|
||||||
(on-ref node id))
|
|
||||||
:data-id id
|
:data-id id
|
||||||
;; This prop is to be used for accessibility purposes only.
|
;; This prop is to be used for accessibility purposes only.
|
||||||
:id id})]
|
:id id})]
|
||||||
|
@ -41,62 +41,57 @@
|
||||||
:aria-hidden (when label true)
|
:aria-hidden (when label true)
|
||||||
:aria-label (when (not label) aria-label)}])
|
:aria-label (when (not label) aria-label)}])
|
||||||
(when (string? label)
|
(when (string? label)
|
||||||
[:span {:class (stl/css-case :tab-text true
|
[:span {:class (stl/css-case
|
||||||
|
:tab-text true
|
||||||
:tab-text-and-icon icon)}
|
:tab-text-and-icon icon)}
|
||||||
label])]]))
|
label])]]))
|
||||||
|
|
||||||
(mf/defc tab-nav*
|
(mf/defc tab-nav*
|
||||||
{::mf/props :obj
|
{::mf/private true
|
||||||
::mf/private true}
|
::mf/memo true}
|
||||||
[{:keys [on-ref tabs selected on-click button-position action-button] :rest props}]
|
[{:keys [ref tabs selected on-click button-position action-button] :rest props}]
|
||||||
(let [class (stl/css-case :tab-nav true
|
(let [nav-class
|
||||||
|
(stl/css-case :tab-nav true
|
||||||
:tab-nav-start (= "start" button-position)
|
:tab-nav-start (= "start" button-position)
|
||||||
:tab-nav-end (= "end" button-position))
|
:tab-nav-end (= "end" button-position))
|
||||||
props (mf/spread-props props
|
props
|
||||||
|
(mf/spread-props props
|
||||||
{:class (stl/css :tab-list)
|
{:class (stl/css :tab-list)
|
||||||
:role "tablist"
|
:role "tablist"
|
||||||
:aria-orientation "horizontal"})]
|
:aria-orientation "horizontal"})]
|
||||||
[:nav {:class class}
|
[:nav {:class nav-class}
|
||||||
(when (= button-position "start")
|
(when (= button-position "start")
|
||||||
action-button)
|
action-button)
|
||||||
|
|
||||||
[:> "ul" props
|
[:> :ul props
|
||||||
(for [element ^js tabs]
|
(for [element tabs]
|
||||||
(let [icon (obj/get element "icon")
|
(let [icon (get element :icon)
|
||||||
label (obj/get element "label")
|
label (get element :label)
|
||||||
aria-label (obj/get element "aria-label")
|
aria-label (get element :aria-label)
|
||||||
id (obj/get element "id")]
|
id (get element :id)]
|
||||||
|
|
||||||
[:> tab* {:icon icon
|
[:> tab* {:icon icon
|
||||||
:key (dm/str "tab-" id)
|
:key id
|
||||||
:label label
|
:label label
|
||||||
:aria-label aria-label
|
:aria-label aria-label
|
||||||
:selected (= id selected)
|
:selected (= id selected)
|
||||||
:on-click on-click
|
:on-click on-click
|
||||||
:on-ref on-ref
|
:ref ref
|
||||||
:id id}]))]
|
:id id}]))]
|
||||||
|
|
||||||
(when (= button-position "end")
|
(when (= button-position "end")
|
||||||
action-button)]))
|
action-button)]))
|
||||||
|
|
||||||
(defn- get-tab
|
(def ^:private schema:tab-attrs
|
||||||
[tabs id]
|
|
||||||
(or (array/find #(= id (obj/get % "id")) tabs)
|
|
||||||
(aget tabs 0)))
|
|
||||||
|
|
||||||
(defn- get-selected-tab-id
|
|
||||||
[tabs default]
|
|
||||||
(let [tab (get-tab tabs default)]
|
|
||||||
(obj/get tab "id")))
|
|
||||||
|
|
||||||
(def ^:private schema:tab
|
|
||||||
[:and
|
|
||||||
[:map {:title "tab"}
|
[:map {:title "tab"}
|
||||||
[:icon {:optional true}
|
[:icon {:optional true}
|
||||||
[:and :string [:fn #(contains? icon-list %)]]]
|
[:and :string [:fn #(contains? icon-list %)]]]
|
||||||
[:label {:optional true} :string]
|
[:label {:optional true} :string]
|
||||||
[:aria-label {:optional true} :string]
|
[:aria-label {:optional true} :string]])
|
||||||
[:content some?]]
|
|
||||||
|
(def ^:private schema:tab
|
||||||
|
[:and
|
||||||
|
schema:tab-attrs
|
||||||
[:fn {:error/message "invalid data: missing required props"}
|
[:fn {:error/message "invalid data: missing required props"}
|
||||||
(fn [tab]
|
(fn [tab]
|
||||||
(or (and (contains? tab :icon)
|
(or (and (contains? tab :icon)
|
||||||
|
@ -108,95 +103,91 @@
|
||||||
[:map
|
[:map
|
||||||
[:tabs [:vector {:min 1} schema:tab]]
|
[:tabs [:vector {:min 1} schema:tab]]
|
||||||
[:class {:optional true} :string]
|
[:class {:optional true} :string]
|
||||||
[:on-change-tab {:optional true} fn?]
|
[:on-change fn?]
|
||||||
[:default-selected {:optional true} :string]
|
[:selected :string]
|
||||||
[:selected {:optional true} :string]
|
|
||||||
[:action-button {:optional true} some?]
|
[:action-button {:optional true} some?]
|
||||||
[:action-button-position {:optional true}
|
[:action-button-position {:optional true}
|
||||||
[:maybe [:enum "start" "end"]]]])
|
[:maybe [:enum "start" "end"]]]])
|
||||||
|
|
||||||
(mf/defc tab-switcher*
|
(mf/defc tab-switcher*
|
||||||
{::mf/props :obj
|
{::mf/schema schema:tab-switcher}
|
||||||
::mf/schema schema:tab-switcher}
|
[{:keys [tabs class on-change selected action-button-position action-button children] :rest props}]
|
||||||
[{:keys [tabs class on-change-tab default-selected selected action-button-position action-button] :rest props}]
|
(let [nodes-ref (mf/use-ref nil)
|
||||||
(let [selected* (mf/use-state #(or selected (get-selected-tab-id tabs default-selected)))
|
|
||||||
selected (or selected (deref selected*))
|
tabs
|
||||||
|
(if (array? tabs)
|
||||||
|
(mfu/bean tabs)
|
||||||
|
tabs)
|
||||||
|
|
||||||
tabs-nodes-refs (mf/use-ref nil)
|
|
||||||
tabs-ref (mf/use-ref nil)
|
|
||||||
|
|
||||||
on-click
|
on-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps on-change-tab)
|
(mf/deps on-change)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [node (dom/get-current-target event)
|
(let [node (dom/get-current-target event)
|
||||||
id (dom/get-data node "id")]
|
id (dom/get-data node "id")]
|
||||||
(reset! selected* id)
|
(when (fn? on-change)
|
||||||
|
(on-change id)))))
|
||||||
(when (fn? on-change-tab)
|
|
||||||
(on-change-tab id)))))
|
|
||||||
|
|
||||||
on-ref
|
on-ref
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [node id]
|
(fn [node]
|
||||||
(let [refs (or (mf/ref-val tabs-nodes-refs) #js {})
|
(let [state (mf/ref-val nodes-ref)
|
||||||
refs (if node
|
state (d/nilv state #js {})
|
||||||
(obj/set! refs id node)
|
id (dom/get-data node "id")
|
||||||
(obj/unset! refs id))]
|
state (obj/set! state id node)]
|
||||||
(mf/set-ref-val! tabs-nodes-refs refs))))
|
(mf/set-ref-val! nodes-ref state)
|
||||||
|
(fn []
|
||||||
|
(let [state (mf/ref-val nodes-ref)
|
||||||
|
state (d/nilv state #js {})
|
||||||
|
id (dom/get-data node "id")
|
||||||
|
state (obj/unset! state id)]
|
||||||
|
(mf/set-ref-val! nodes-ref state))))))
|
||||||
|
|
||||||
on-key-down
|
on-key-down
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps selected)
|
(mf/deps selected tabs on-change)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [tabs (mf/ref-val tabs-ref)
|
(let [len (count tabs)
|
||||||
len (alength tabs)
|
sel? #(= selected (get % :id))
|
||||||
sel? #(= selected (obj/get % "id"))
|
|
||||||
id (cond
|
id (cond
|
||||||
(kbd/home? event)
|
(kbd/home? event)
|
||||||
(let [tab (aget tabs 0)]
|
(let [tab (nth tabs 0)]
|
||||||
(obj/get tab "id"))
|
(get tab :id))
|
||||||
|
|
||||||
(kbd/left-arrow? event)
|
(kbd/left-arrow? event)
|
||||||
(let [index (array/find-index sel? tabs)
|
(let [index (d/index-of-pred tabs sel?)
|
||||||
index (mod (- index 1) len)
|
index (mod (- index 1) len)
|
||||||
tab (aget tabs index)]
|
tab (nth tabs index)]
|
||||||
(obj/get tab "id"))
|
(get tab :id))
|
||||||
|
|
||||||
(kbd/right-arrow? event)
|
(kbd/right-arrow? event)
|
||||||
(let [index (array/find-index sel? tabs)
|
(let [index (d/index-of-pred tabs sel?)
|
||||||
index (mod (+ index 1) len)
|
index (mod (+ index 1) len)
|
||||||
tab (aget tabs index)]
|
tab (nth tabs index)]
|
||||||
(obj/get tab "id")))]
|
(get tab :id)))]
|
||||||
|
|
||||||
(when (some? id)
|
(when (some? id)
|
||||||
(reset! selected* id)
|
(on-change id)
|
||||||
(let [nodes (mf/ref-val tabs-nodes-refs)
|
(let [nodes (mf/ref-val nodes-ref)
|
||||||
node (obj/get nodes id)]
|
node (obj/get nodes id)]
|
||||||
(dom/focus! node))))))
|
(dom/focus! node))))))
|
||||||
|
|
||||||
class (dm/str class " " (stl/css :tabs))
|
props
|
||||||
|
(mf/spread-props props {:class [class (stl/css :tabs)]})]
|
||||||
props (mf/spread-props props {:class class})]
|
|
||||||
|
|
||||||
(mf/with-effect [tabs]
|
|
||||||
(mf/set-ref-val! tabs-ref tabs))
|
|
||||||
|
|
||||||
[:> :article props
|
[:> :article props
|
||||||
[:div {:class (stl/css :padding-wrapper)}
|
[:div {:class (stl/css :padding-wrapper)}
|
||||||
[:> tab-nav* {:button-position action-button-position
|
[:> tab-nav* {:button-position action-button-position
|
||||||
:action-button action-button
|
:action-button action-button
|
||||||
:tabs tabs
|
:tabs tabs
|
||||||
:on-ref on-ref
|
:ref on-ref
|
||||||
:selected selected
|
:selected selected
|
||||||
:on-key-down on-key-down
|
:on-key-down on-key-down
|
||||||
:on-click on-click}]]
|
:on-click on-click}]]
|
||||||
|
|
||||||
(let [active-tab (get-tab tabs selected)
|
|
||||||
content (obj/get active-tab "content")
|
|
||||||
id (obj/get active-tab "id")]
|
|
||||||
[:section {:class (stl/css :tab-panel)
|
[:section {:class (stl/css :tab-panel)
|
||||||
:tab-index 0
|
:tab-index 0
|
||||||
:role "tabpanel"
|
:role "tabpanel"
|
||||||
:aria-labelledby id}
|
:aria-labelledby selected}
|
||||||
content])]))
|
children]]))
|
||||||
|
|
|
@ -49,21 +49,33 @@ These are available in the `app.main.ds.foundations.assets.icon` namespace.
|
||||||
[app.main.ui.ds.foundations.assets.icon :as i]))
|
[app.main.ui.ds.foundations.assets.icon :as i]))
|
||||||
```
|
```
|
||||||
|
|
||||||
```clj
|
```clojure
|
||||||
[:> tab_switcher*
|
(let [selected-tab* (mf/use-state "code")
|
||||||
{:tabs [{ :label "Code"
|
selected-tab (deref selected-tab*)
|
||||||
:id "tab-code"
|
on-change-tab (mf/use-fn #(reset! selected-tab* %))
|
||||||
:icon i/fill-content
|
tabs (mf/with-memo []
|
||||||
:content [:p Lorem Ipsum ]}
|
[{:label "Code"
|
||||||
|
:id "code"
|
||||||
|
:icon i/fill-content}
|
||||||
{:label "Design"
|
{:label "Design"
|
||||||
:id "tab-design"
|
:id "design"
|
||||||
:icon i/pentool
|
:icon i/pentool}
|
||||||
:content [:p Dolor sit amet ]}
|
|
||||||
{:label "Menu"
|
{:label "Menu"
|
||||||
:id "tab-menu"
|
:id "menu"
|
||||||
:icon i/mask
|
:icon i/mask}])]
|
||||||
:content [:p Consectetur adipiscing elit ]}
|
[:> tab_switcher* {:tabs tabs
|
||||||
]}]
|
:selected selected-tab
|
||||||
|
:on-change on-change-tab}
|
||||||
|
(case selected-tab
|
||||||
|
"code"
|
||||||
|
[:p "Lorem Ipsum"]
|
||||||
|
|
||||||
|
"design"
|
||||||
|
[:p "Dolor sit amet"]
|
||||||
|
|
||||||
|
"menu"
|
||||||
|
[:p "Consectetur adipiscing elit"])])
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<Canvas of={TabSwitcher.WithIconsAndText} />
|
<Canvas of={TabSwitcher.WithIconsAndText} />
|
||||||
|
|
|
@ -13,9 +13,30 @@ const Padded = ({ children }) => (
|
||||||
<div style={{ padding: "10px" }}>{children}</div>
|
<div style={{ padding: "10px" }}>{children}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const TabSwitcherWrapper = ({tabs, ...props}) => {
|
||||||
|
const navTabs = tabs.map(({content, ...item}) => {
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
const [selected, setSelected] = React.useState(() => {
|
||||||
|
return props.default || tabs[0].id;
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = tabs.reduce((result, tab) => {
|
||||||
|
result[tab.id] = tab.content;
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TabSwitcher tabs={navTabs} selected={selected} onChange={setSelected} {...props}>
|
||||||
|
{content[selected]}
|
||||||
|
</TabSwitcher>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "Layout/Tab switcher",
|
title: "Layout/Tab switcher",
|
||||||
component: TabSwitcher,
|
component: TabSwitcherWrapper,
|
||||||
args: {
|
args: {
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
|
@ -46,7 +67,7 @@ export default {
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
defaultSelected: "tab-code",
|
default: "tab-code",
|
||||||
},
|
},
|
||||||
argTypes: {
|
argTypes: {
|
||||||
actionButtonPosition: {
|
actionButtonPosition: {
|
||||||
|
@ -59,12 +80,12 @@ export default {
|
||||||
exclude: [
|
exclude: [
|
||||||
"tabs",
|
"tabs",
|
||||||
"actionButton",
|
"actionButton",
|
||||||
"defaultSelected",
|
"default",
|
||||||
"actionButtonPosition",
|
"actionButtonPosition",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
render: ({ ...args }) => <TabSwitcher {...args} />,
|
render: ({ ...args }) => <TabSwitcherWrapper {...args} />,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Default = {};
|
export const Default = {};
|
||||||
|
|
|
@ -324,6 +324,22 @@
|
||||||
|
|
||||||
state*))
|
state*))
|
||||||
|
|
||||||
|
(defn use-persisted-state
|
||||||
|
"A specialized hook that adds persistence to the default mf/use-state hook.
|
||||||
|
|
||||||
|
The state is automatically persisted under the provided key on
|
||||||
|
localStorage. And it will keep watching events with type equals to
|
||||||
|
`key` for new values."
|
||||||
|
[key default]
|
||||||
|
(let [id (mf/use-id)
|
||||||
|
state* (mf/use-state #(get storage/user key default))
|
||||||
|
state (deref state*)]
|
||||||
|
|
||||||
|
(mf/with-effect [state key id]
|
||||||
|
(swap! storage/user assoc key state))
|
||||||
|
|
||||||
|
state*))
|
||||||
|
|
||||||
(defonce ^:private intersection-subject (rx/subject))
|
(defonce ^:private intersection-subject (rx/subject))
|
||||||
(defonce ^:private intersection-observer
|
(defonce ^:private intersection-observer
|
||||||
(delay (js/IntersectionObserver.
|
(delay (js/IntersectionObserver.
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
(mf/defc right-sidebar
|
(mf/defc right-sidebar
|
||||||
[{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
|
[{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
|
||||||
:or {from :viewer}}]
|
:or {from :viewer}}]
|
||||||
(let [section (mf/use-state :info #_:code)
|
(let [section (mf/use-state #(do :info))
|
||||||
objects (or objects (:objects page))
|
objects (or objects (:objects page))
|
||||||
shapes (or shapes
|
shapes (or shapes
|
||||||
(resolve-shapes objects selected))
|
(resolve-shapes objects selected))
|
||||||
|
@ -81,31 +81,13 @@
|
||||||
(fn []
|
(fn []
|
||||||
(dom/open-new-window "https://help.penpot.app/user-guide/inspect/")))
|
(dom/open-new-window "https://help.penpot.app/user-guide/inspect/")))
|
||||||
|
|
||||||
info-content
|
|
||||||
(mf/html [:& attributes {:page-id page-id
|
|
||||||
:objects objects
|
|
||||||
:file-id file-id
|
|
||||||
:frame frame
|
|
||||||
:shapes shapes
|
|
||||||
:from from
|
|
||||||
:libraries libraries
|
|
||||||
:share-id share-id}])
|
|
||||||
|
|
||||||
code-content
|
|
||||||
(mf/html [:& code {:frame frame
|
|
||||||
:shapes shapes
|
|
||||||
:on-expand handle-expand
|
|
||||||
:from from}])
|
|
||||||
|
|
||||||
tabs
|
tabs
|
||||||
#js [#js {:label (tr "inspect.tabs.info")
|
(mf/with-memo []
|
||||||
:id "info"
|
[{:label (tr "inspect.tabs.info")
|
||||||
:content info-content}
|
:id "info"}
|
||||||
|
{:label (tr "inspect.tabs.code")
|
||||||
#js {:label (tr "inspect.tabs.code")
|
|
||||||
:data-testid "code"
|
:data-testid "code"
|
||||||
:id "code"
|
:id "code"}])]
|
||||||
:content code-content}]]
|
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps shapes handle-change-tab)
|
(mf/deps shapes handle-change-tab)
|
||||||
|
@ -148,9 +130,25 @@
|
||||||
[:div {:class (stl/css :inspect-content)}
|
[:div {:class (stl/css :inspect-content)}
|
||||||
|
|
||||||
[:> tab-switcher* {:tabs tabs
|
[:> tab-switcher* {:tabs tabs
|
||||||
:default-selected "info"
|
:selected (name @section)
|
||||||
:on-change-tab handle-change-tab
|
:on-change handle-change-tab
|
||||||
:class (stl/css :viewer-tab-switcher)}]]]
|
:class (stl/css :viewer-tab-switcher)}
|
||||||
|
(case @section
|
||||||
|
:info
|
||||||
|
[:& attributes {:page-id page-id
|
||||||
|
:objects objects
|
||||||
|
:file-id file-id
|
||||||
|
:frame frame
|
||||||
|
:shapes shapes
|
||||||
|
:from from
|
||||||
|
:libraries libraries
|
||||||
|
:share-id share-id}]
|
||||||
|
|
||||||
|
:code
|
||||||
|
[:& code {:frame frame
|
||||||
|
:shapes shapes
|
||||||
|
:on-expand handle-expand
|
||||||
|
:from from}])]]]
|
||||||
[:div {:class (stl/css :empty)}
|
[:div {:class (stl/css :empty)}
|
||||||
[:div {:class (stl/css :code-info)}
|
[:div {:class (stl/css :code-info)}
|
||||||
[:span {:class (stl/css :placeholder-icon)}
|
[:span {:class (stl/css :placeholder-icon)}
|
||||||
|
|
|
@ -59,6 +59,13 @@
|
||||||
{:keys [vport] :as wlocal} (mf/deref refs/workspace-local)
|
{:keys [vport] :as wlocal} (mf/deref refs/workspace-local)
|
||||||
{:keys [options-mode]} wglobal
|
{:keys [options-mode]} wglobal
|
||||||
|
|
||||||
|
|
||||||
|
;; FIXME: pass this down to viewport and reuse it from here
|
||||||
|
;; instead of making an other deref on viewport for the same
|
||||||
|
;; data
|
||||||
|
drawing
|
||||||
|
(mf/deref refs/workspace-drawing)
|
||||||
|
|
||||||
colorpalette? (:colorpalette layout)
|
colorpalette? (:colorpalette layout)
|
||||||
textpalette? (:textpalette layout)
|
textpalette? (:textpalette layout)
|
||||||
hide-ui? (:hide-ui layout)
|
hide-ui? (:hide-ui layout)
|
||||||
|
@ -77,7 +84,7 @@
|
||||||
|
|
||||||
node-ref (use-resize-observer on-resize)]
|
node-ref (use-resize-observer on-resize)]
|
||||||
[:*
|
[:*
|
||||||
(when (not hide-ui?)
|
(when (not ^boolean hide-ui?)
|
||||||
[:& palette {:layout layout
|
[:& palette {:layout layout
|
||||||
:on-change-palette-size on-resize-palette}])
|
:on-change-palette-size on-resize-palette}])
|
||||||
|
|
||||||
|
@ -115,6 +122,7 @@
|
||||||
:page-id page-id}])
|
:page-id page-id}])
|
||||||
[:> right-sidebar* {:section options-mode
|
[:> right-sidebar* {:section options-mode
|
||||||
:selected selected
|
:selected selected
|
||||||
|
:drawing-tool (get drawing :tool)
|
||||||
:layout layout
|
:layout layout
|
||||||
:file file
|
:file file
|
||||||
:page-id page-id}]])]))
|
:page-id page-id}]])]))
|
||||||
|
@ -147,7 +155,8 @@
|
||||||
(-> file
|
(-> file
|
||||||
(dissoc :data)
|
(dissoc :data)
|
||||||
(assoc ::has-data (contains? file :data))))))
|
(assoc ::has-data (contains? file :data))))))
|
||||||
st/state))
|
st/state
|
||||||
|
=))
|
||||||
|
|
||||||
(defn- make-page-ref
|
(defn- make-page-ref
|
||||||
[file-id page-id]
|
[file-id page-id]
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
[app.main.ui.components.select :refer [select]]
|
[app.main.ui.components.select :refer [select]]
|
||||||
[app.main.ui.ds.foundations.assets.icon :as ic]
|
[app.main.ui.ds.foundations.assets.icon :as ic]
|
||||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||||
|
[app.main.ui.hooks :as hooks]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.workspace.colorpicker.color-inputs :refer [color-inputs]]
|
[app.main.ui.workspace.colorpicker.color-inputs :refer [color-inputs]]
|
||||||
[app.main.ui.workspace.colorpicker.gradients :refer [gradients*]]
|
[app.main.ui.workspace.colorpicker.gradients :refer [gradients*]]
|
||||||
|
@ -112,11 +113,14 @@
|
||||||
:linear :linear-gradient
|
:linear :linear-gradient
|
||||||
:radial :radial-gradient)
|
:radial :radial-gradient)
|
||||||
:color))
|
:color))
|
||||||
active-color-tab (mf/use-state #(dc/get-active-color-tab))
|
|
||||||
|
active-color-tab* (hooks/use-persisted-state ::color-tab "ramp")
|
||||||
|
active-color-tab (deref active-color-tab*)
|
||||||
|
|
||||||
drag?* (mf/use-state false)
|
drag?* (mf/use-state false)
|
||||||
drag? (deref drag?*)
|
drag? (deref drag?*)
|
||||||
|
|
||||||
type (if (= @active-color-tab "hsva") :hsv :rgb)
|
type (if (= active-color-tab "hsva") :hsv :rgb)
|
||||||
|
|
||||||
fill-image-ref (mf/use-ref nil)
|
fill-image-ref (mf/use-ref nil)
|
||||||
|
|
||||||
|
@ -163,10 +167,7 @@
|
||||||
:checked keep-aspect-ratio?})))))
|
:checked keep-aspect-ratio?})))))
|
||||||
|
|
||||||
on-change-tab
|
on-change-tab
|
||||||
(mf/use-fn
|
(mf/use-fn #(reset! active-color-tab* %))
|
||||||
(fn [tab]
|
|
||||||
(reset! active-color-tab tab)
|
|
||||||
(dc/set-active-color-tab! tab)))
|
|
||||||
|
|
||||||
handle-change-mode
|
handle-change-mode
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -282,12 +283,10 @@
|
||||||
|
|
||||||
handle-stop-edit-start
|
handle-stop-edit-start
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn []
|
#(reset! should-update? false))
|
||||||
(reset! should-update? false)))
|
|
||||||
|
|
||||||
handle-stop-edit-finish
|
handle-stop-edit-finish
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps state)
|
|
||||||
(fn []
|
(fn []
|
||||||
(reset! should-update? true)
|
(reset! should-update? true)
|
||||||
|
|
||||||
|
@ -338,50 +337,24 @@
|
||||||
(fn [value]
|
(fn [value]
|
||||||
(st/emit! (dc/update-colorpicker-gradient-opacity (/ value 100)))))
|
(st/emit! (dc/update-colorpicker-gradient-opacity (/ value 100)))))
|
||||||
|
|
||||||
cap-stops? (or (features/use-feature "render-wasm/v1") (contains? cfg/flags :frontend-binary-fills))
|
render-wasm?
|
||||||
|
(features/use-feature "render-wasm/v1")
|
||||||
|
|
||||||
|
cap-stops?
|
||||||
|
(or ^boolean render-wasm?
|
||||||
|
^boolean (contains? cfg/flags :frontend-binary-fills))
|
||||||
|
|
||||||
tabs
|
tabs
|
||||||
#js [#js {:aria-label (tr "workspace.libraries.colors.rgba")
|
(mf/with-memo []
|
||||||
|
[{:aria-label (tr "workspace.libraries.colors.rgba")
|
||||||
:icon ic/rgba
|
:icon ic/rgba
|
||||||
:id "ramp"
|
:id "ramp"}
|
||||||
:content (mf/html (if picking-color?
|
{:aria-label "Harmony"
|
||||||
[:div {:class (stl/css :picker-detail-wrapper)}
|
|
||||||
[:div {:class (stl/css :center-circle)}]
|
|
||||||
[:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]]
|
|
||||||
[:> ramp-selector*
|
|
||||||
{:color current-color
|
|
||||||
:disable-opacity disable-opacity
|
|
||||||
:on-change handle-change-color
|
|
||||||
:on-start-drag on-start-drag
|
|
||||||
:on-finish-drag on-finish-drag}]))}
|
|
||||||
|
|
||||||
#js {:aria-label "Harmony"
|
|
||||||
:icon ic/rgba-complementary
|
:icon ic/rgba-complementary
|
||||||
:id "harmony"
|
:id "harmony"}
|
||||||
:content (mf/html (if picking-color?
|
{:aria-label "HSVA"
|
||||||
[:div {:class (stl/css :picker-detail-wrapper)}
|
|
||||||
[:div {:class (stl/css :center-circle)}]
|
|
||||||
[:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]]
|
|
||||||
[:& harmony-selector
|
|
||||||
{:color current-color
|
|
||||||
:disable-opacity disable-opacity
|
|
||||||
:on-change handle-change-color
|
|
||||||
:on-start-drag on-start-drag
|
|
||||||
:on-finish-drag on-finish-drag}]))}
|
|
||||||
|
|
||||||
#js {:aria-label "HSVA"
|
|
||||||
:icon ic/hsva
|
:icon ic/hsva
|
||||||
:id "hsva"
|
:id "hsva"}])]
|
||||||
:content (mf/html (if picking-color?
|
|
||||||
[:div {:class (stl/css :picker-detail-wrapper)}
|
|
||||||
[:div {:class (stl/css :center-circle)}]
|
|
||||||
[:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]]
|
|
||||||
[:& hsva-selector
|
|
||||||
{:color current-color
|
|
||||||
:disable-opacity disable-opacity
|
|
||||||
:on-change handle-change-color
|
|
||||||
:on-start-drag on-start-drag
|
|
||||||
:on-finish-drag on-finish-drag}]))}]]
|
|
||||||
|
|
||||||
;; Initialize colorpicker state
|
;; Initialize colorpicker state
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
|
@ -486,11 +459,41 @@
|
||||||
:multi false
|
:multi false
|
||||||
:ref fill-image-ref
|
:ref fill-image-ref
|
||||||
:on-selected on-fill-image-selected}]]])
|
:on-selected on-fill-image-selected}]]])
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:div {:class (stl/css :colorpicker-tabs)}
|
[:div {:class (stl/css :colorpicker-tabs)}
|
||||||
[:> tab-switcher* {:tabs tabs
|
[:> tab-switcher* {:tabs tabs
|
||||||
:default-selected "ramp"
|
:selected active-color-tab
|
||||||
:on-change-tab on-change-tab}]]
|
:on-change on-change-tab}
|
||||||
|
(if picking-color?
|
||||||
|
[:div {:class (stl/css :picker-detail-wrapper)}
|
||||||
|
[:div {:class (stl/css :center-circle)}]
|
||||||
|
[:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]]
|
||||||
|
|
||||||
|
|
||||||
|
(case active-color-tab
|
||||||
|
"ramp"
|
||||||
|
[:> ramp-selector*
|
||||||
|
{:color current-color
|
||||||
|
:disable-opacity disable-opacity
|
||||||
|
:on-change handle-change-color
|
||||||
|
:on-start-drag on-start-drag
|
||||||
|
:on-finish-drag on-finish-drag}]
|
||||||
|
|
||||||
|
"harmony"
|
||||||
|
[:& harmony-selector
|
||||||
|
{:color current-color
|
||||||
|
:disable-opacity disable-opacity
|
||||||
|
:on-change handle-change-color
|
||||||
|
:on-start-drag on-start-drag}]
|
||||||
|
|
||||||
|
"hsva"
|
||||||
|
[:& hsva-selector
|
||||||
|
{:color current-color
|
||||||
|
:disable-opacity disable-opacity
|
||||||
|
:on-change handle-change-color
|
||||||
|
:on-start-drag on-start-drag
|
||||||
|
:on-finish-drag on-finish-drag}]))]]
|
||||||
|
|
||||||
[:& color-inputs
|
[:& color-inputs
|
||||||
{:type type
|
{:type type
|
||||||
|
|
|
@ -26,8 +26,7 @@
|
||||||
|
|
||||||
;; --- Header Component
|
;; --- Header Component
|
||||||
|
|
||||||
(mf/defc left-header
|
(mf/defc left-header*
|
||||||
{::mf/props :obj}
|
|
||||||
[{:keys [file layout project page-id class]}]
|
[{:keys [file layout project page-id class]}]
|
||||||
(let [profile (mf/deref refs/profile)
|
(let [profile (mf/deref refs/profile)
|
||||||
file-id (:id file)
|
file-id (:id file)
|
||||||
|
|
|
@ -565,7 +565,7 @@
|
||||||
(mf/defc libraries-dialog
|
(mf/defc libraries-dialog
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :libraries-dialog}
|
::mf/register-as :libraries-dialog}
|
||||||
[{:keys [starting-tab file-id] :as props :or {starting-tab :libraries}}]
|
[{:keys [starting-tab file-id]}]
|
||||||
(let [files (mf/deref refs/files)
|
(let [files (mf/deref refs/files)
|
||||||
file (get files file-id)
|
file (get files file-id)
|
||||||
shared? (:is-shared file)
|
shared? (:is-shared file)
|
||||||
|
@ -596,24 +596,21 @@
|
||||||
(modal/hide!)
|
(modal/hide!)
|
||||||
(modal/disallow-click-outside!)))
|
(modal/disallow-click-outside!)))
|
||||||
|
|
||||||
libraries-tab
|
selected-tab*
|
||||||
(mf/html [:> libraries-tab*
|
(mf/use-state #(d/nilv starting-tab "libraries"))
|
||||||
{:is-shared shared?
|
|
||||||
:linked-libraries linked-libraries
|
|
||||||
:shared-libraries shared-libraries}])
|
|
||||||
|
|
||||||
updates-tab
|
selected-tab
|
||||||
(mf/html [:> updates-tab*
|
(deref selected-tab*)
|
||||||
{:file-id file-id
|
|
||||||
:libraries linked-libraries}])
|
on-change-tab
|
||||||
|
(mf/use-fn #(reset! selected-tab* %))
|
||||||
|
|
||||||
tabs
|
tabs
|
||||||
#js [#js {:label (tr "workspace.libraries.libraries")
|
(mf/with-memo []
|
||||||
:id "libraries"
|
[{:label (tr "workspace.libraries.libraries")
|
||||||
:content libraries-tab}
|
:id "libraries"}
|
||||||
#js {:label (tr "workspace.libraries.updates")
|
{:label (tr "workspace.libraries.updates")
|
||||||
:id "updates"
|
:id "updates"}])]
|
||||||
:content updates-tab}]]
|
|
||||||
|
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
(st/emit! (dtm/fetch-shared-files)))
|
(st/emit! (dtm/fetch-shared-files)))
|
||||||
|
@ -631,7 +628,19 @@
|
||||||
(tr "workspace.libraries.libraries")]
|
(tr "workspace.libraries.libraries")]
|
||||||
|
|
||||||
[:> tab-switcher* {:tabs tabs
|
[:> tab-switcher* {:tabs tabs
|
||||||
:default-selected (dm/str starting-tab)}]]]))
|
:selected selected-tab
|
||||||
|
:on-change on-change-tab}
|
||||||
|
(case selected-tab
|
||||||
|
"libraries"
|
||||||
|
[:> libraries-tab*
|
||||||
|
{:is-shared shared?
|
||||||
|
:linked-libraries linked-libraries
|
||||||
|
:shared-libraries shared-libraries}]
|
||||||
|
|
||||||
|
"updates"
|
||||||
|
[:> updates-tab*
|
||||||
|
{:file-id file-id
|
||||||
|
:libraries linked-libraries}])]]]))
|
||||||
|
|
||||||
(mf/defc v2-info-dialog
|
(mf/defc v2-info-dialog
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
|
|
|
@ -19,18 +19,19 @@
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
||||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||||
|
[app.main.ui.hooks :as hooks]
|
||||||
[app.main.ui.hooks.resize :refer [use-resize-hook]]
|
[app.main.ui.hooks.resize :refer [use-resize-hook]]
|
||||||
[app.main.ui.workspace.comments :refer [comments-sidebar*]]
|
[app.main.ui.workspace.comments :refer [comments-sidebar*]]
|
||||||
[app.main.ui.workspace.left-header :refer [left-header]]
|
[app.main.ui.workspace.left-header :refer [left-header*]]
|
||||||
[app.main.ui.workspace.right-header :refer [right-header*]]
|
[app.main.ui.workspace.right-header :refer [right-header*]]
|
||||||
[app.main.ui.workspace.sidebar.assets :refer [assets-toolbox]]
|
[app.main.ui.workspace.sidebar.assets :refer [assets-toolbox*]]
|
||||||
[app.main.ui.workspace.sidebar.debug :refer [debug-panel]]
|
[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.debug-shape-info :refer [debug-shape-info*]]
|
||||||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
|
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
|
||||||
[app.main.ui.workspace.sidebar.layers :refer [layers-toolbox]]
|
[app.main.ui.workspace.sidebar.layers :refer [layers-toolbox*]]
|
||||||
[app.main.ui.workspace.sidebar.options :refer [options-toolbox*]]
|
[app.main.ui.workspace.sidebar.options :refer [options-toolbox*]]
|
||||||
[app.main.ui.workspace.sidebar.shortcuts :refer [shortcuts-container]]
|
[app.main.ui.workspace.sidebar.shortcuts :refer [shortcuts-container*]]
|
||||||
[app.main.ui.workspace.sidebar.sitemap :refer [sitemap]]
|
[app.main.ui.workspace.sidebar.sitemap :refer [sitemap*]]
|
||||||
[app.main.ui.workspace.sidebar.versions :refer [versions-toolbox*]]
|
[app.main.ui.workspace.sidebar.versions :refer [versions-toolbox*]]
|
||||||
[app.main.ui.workspace.tokens.sidebar :refer [tokens-sidebar-tab*]]
|
[app.main.ui.workspace.tokens.sidebar :refer [tokens-sidebar-tab*]]
|
||||||
[app.util.debug :as dbg]
|
[app.util.debug :as dbg]
|
||||||
|
@ -40,20 +41,61 @@
|
||||||
|
|
||||||
;; --- Left Sidebar (Component)
|
;; --- Left Sidebar (Component)
|
||||||
|
|
||||||
(mf/defc collapse-button
|
(defn- on-collapse-left-sidebar
|
||||||
{::mf/wrap [mf/memo]
|
[]
|
||||||
::mf/wrap-props false}
|
(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
|
||||||
[{:keys [on-click] :as props}]
|
|
||||||
|
(mf/defc collapse-button*
|
||||||
|
[]
|
||||||
;; NOTE: This custom button may be replace by an action button when this variant is designed
|
;; NOTE: This custom button may be replace by an action button when this variant is designed
|
||||||
[:button {:class (stl/css :collapse-sidebar-button)
|
[:button {:class (stl/css :collapse-sidebar-button)
|
||||||
:on-click on-click}
|
:on-click on-collapse-left-sidebar}
|
||||||
[:> icon* {:icon-id "arrow"
|
[:> icon* {:icon-id "arrow"
|
||||||
:size "s"
|
:size "s"
|
||||||
:aria-label (tr "workspace.sidebar.collapse")}]])
|
:aria-label (tr "workspace.sidebar.collapse")}]])
|
||||||
|
|
||||||
|
(mf/defc layers-content*
|
||||||
|
{::mf/private true
|
||||||
|
::mf/memo true}
|
||||||
|
[{:keys [width layout]}]
|
||||||
|
(let [{on-pointer-down :on-pointer-down
|
||||||
|
on-lost-pointer-capture :on-lost-pointer-capture
|
||||||
|
on-pointer-move :on-pointer-move
|
||||||
|
height :size}
|
||||||
|
(use-resize-hook :sitemap 200 38 "0.6" :y false nil)
|
||||||
|
|
||||||
|
sitemap-collapsed*
|
||||||
|
(hooks/use-persisted-state ::sitemap-collapsed false)
|
||||||
|
|
||||||
|
sitemap-collapsed?
|
||||||
|
(deref sitemap-collapsed*)
|
||||||
|
|
||||||
|
on-toggle-sitemap-collapsed
|
||||||
|
(mf/use-fn #(reset! sitemap-collapsed* not))
|
||||||
|
|
||||||
|
sitemap-height
|
||||||
|
(if sitemap-collapsed? 32 height)]
|
||||||
|
|
||||||
|
[:article {:class (stl/css :layers-tab)
|
||||||
|
:style {:--height (dm/str height "px")}}
|
||||||
|
|
||||||
|
[:> sitemap* {:layout layout
|
||||||
|
:height sitemap-height
|
||||||
|
:collapsed sitemap-collapsed?
|
||||||
|
:on-toggle-collapsed on-toggle-sitemap-collapsed}]
|
||||||
|
|
||||||
|
(when-not ^boolean sitemap-collapsed?
|
||||||
|
[:div {:class (stl/css :resize-area-horiz)
|
||||||
|
:on-pointer-down on-pointer-down
|
||||||
|
:on-lost-pointer-capture on-lost-pointer-capture
|
||||||
|
:on-pointer-move on-pointer-move}
|
||||||
|
|
||||||
|
[:div {:class (stl/css :resize-handle-horiz)}]])
|
||||||
|
|
||||||
|
[:> layers-toolbox* {:size-parent width}]]))
|
||||||
|
|
||||||
(mf/defc left-sidebar*
|
(mf/defc left-sidebar*
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/memo true}
|
||||||
::mf/props :obj}
|
|
||||||
[{:keys [layout file page-id] :as props}]
|
[{:keys [layout file page-id] :as props}]
|
||||||
(let [options-mode (mf/deref refs/options-mode-global)
|
(let [options-mode (mf/deref refs/options-mode-global)
|
||||||
project (mf/deref refs/project)
|
project (mf/deref refs/project)
|
||||||
|
@ -73,93 +115,53 @@
|
||||||
on-lost-pointer-capture :on-lost-pointer-capture
|
on-lost-pointer-capture :on-lost-pointer-capture
|
||||||
on-pointer-move :on-pointer-move
|
on-pointer-move :on-pointer-move
|
||||||
parent-ref :parent-ref
|
parent-ref :parent-ref
|
||||||
size :size}
|
width :size}
|
||||||
(use-resize-hook :left-sidebar 318 318 500 :x false :left)
|
(use-resize-hook :left-sidebar 318 318 500 :x false :left)
|
||||||
|
|
||||||
{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 :sitemap 200 38 "0.6" :y false nil)
|
|
||||||
|
|
||||||
show-pages? (mf/use-state true)
|
|
||||||
toggle-pages (mf/use-fn #(reset! show-pages? not))
|
|
||||||
size-pages (mf/with-memo [show-pages? size-pages-opened]
|
|
||||||
(if @show-pages? size-pages-opened 32))
|
|
||||||
|
|
||||||
handle-collapse
|
|
||||||
(mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
|
|
||||||
|
|
||||||
on-tab-change
|
on-tab-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [id]
|
(fn [id]
|
||||||
|
(st/emit! (dcm/go-to-workspace :layout (keyword id)))
|
||||||
(when (= id "tokens")
|
(when (= id "tokens")
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "open-tokens-tab"})))
|
(st/emit! (ptk/event ::ev/event {::ev/name "open-tokens-tab"})))))
|
||||||
(st/emit! (dcm/go-to-workspace :layout (keyword id)))))
|
|
||||||
|
|
||||||
layers-tab
|
|
||||||
(mf/html
|
|
||||||
[:article {:class (stl/css :layers-tab)
|
|
||||||
:style #js {"--height" (str size-pages "px")}}
|
|
||||||
|
|
||||||
[:& sitemap {:layout layout
|
|
||||||
:toggle-pages toggle-pages
|
|
||||||
:show-pages? @show-pages?
|
|
||||||
:size size-pages}]
|
|
||||||
|
|
||||||
(when @show-pages?
|
|
||||||
[:div {:class (stl/css :resize-area-horiz)
|
|
||||||
:on-pointer-down on-pointer-down-pages
|
|
||||||
:on-lost-pointer-capture on-lost-pointer-capture-pages
|
|
||||||
:on-pointer-move on-pointer-move-pages}
|
|
||||||
|
|
||||||
[:div {:class (stl/css :resize-handle-horiz)}]])
|
|
||||||
|
|
||||||
[:& layers-toolbox {:size-parent size
|
|
||||||
:size size-pages}]])
|
|
||||||
|
|
||||||
|
|
||||||
assets-tab
|
|
||||||
(mf/html [:& assets-toolbox {:size (- size 58) :file-id file-id}])
|
|
||||||
|
|
||||||
tokens-tab
|
|
||||||
(when design-tokens?
|
|
||||||
(mf/html [:> tokens-sidebar-tab*]))
|
|
||||||
|
|
||||||
tabs
|
tabs
|
||||||
|
(mf/with-memo [mode-inspect? design-tokens?]
|
||||||
(if ^boolean mode-inspect?
|
(if ^boolean mode-inspect?
|
||||||
#js [#js {:label (tr "workspace.sidebar.layers")
|
[{:label (tr "workspace.sidebar.layers")
|
||||||
:id "layers"
|
:id "layers"}]
|
||||||
:content layers-tab}]
|
|
||||||
(if ^boolean design-tokens?
|
(if ^boolean design-tokens?
|
||||||
#js [#js {:label (tr "workspace.sidebar.layers")
|
[{:label (tr "workspace.sidebar.layers")
|
||||||
:id "layers"
|
:id "layers"}
|
||||||
:content layers-tab}
|
{:label (tr "workspace.toolbar.assets")
|
||||||
#js {:label (tr "workspace.toolbar.assets")
|
:id "assets"}
|
||||||
:id "assets"
|
{:label "Tokens"
|
||||||
:content assets-tab}
|
:id "tokens"}]
|
||||||
#js {:label "Tokens"
|
[{:label (tr "workspace.sidebar.layers")
|
||||||
:id "tokens"
|
:id "layers"}
|
||||||
:content tokens-tab}]
|
{:label (tr "workspace.toolbar.assets")
|
||||||
#js [#js {:label (tr "workspace.sidebar.layers")
|
:id "assets"}])))
|
||||||
:id "layers"
|
|
||||||
:content layers-tab}
|
|
||||||
#js {:label (tr "workspace.toolbar.assets")
|
|
||||||
:id "assets"
|
|
||||||
:content assets-tab}]))]
|
|
||||||
|
|
||||||
[:& (mf/provider muc/sidebar) {:value :left}
|
aside-class
|
||||||
|
(stl/css-case
|
||||||
|
:left-settings-bar true
|
||||||
|
:global/two-row (<= width 300)
|
||||||
|
:global/three-row (and (> width 300) (<= width 400))
|
||||||
|
:global/four-row (> width 400))
|
||||||
|
|
||||||
|
tabs-action-button
|
||||||
|
(mf/with-memo []
|
||||||
|
(mf/html [:> collapse-button* {}]))]
|
||||||
|
|
||||||
|
[:> (mf/provider muc/sidebar) {:value :left}
|
||||||
[:aside {:ref parent-ref
|
[:aside {:ref parent-ref
|
||||||
:id "left-sidebar-aside"
|
:id "left-sidebar-aside"
|
||||||
:data-testid "left-sidebar"
|
:data-testid "left-sidebar"
|
||||||
:data-size (str size)
|
:data-size (str width)
|
||||||
:class (stl/css-case :left-settings-bar true
|
:class aside-class
|
||||||
:global/two-row (<= size 300)
|
:style {:--width (dm/str width "px")}}
|
||||||
:global/three-row (and (> size 300) (<= size 400))
|
|
||||||
:global/four-row (> size 400))
|
|
||||||
:style #js {"--width" (dm/str size "px")}}
|
|
||||||
|
|
||||||
[:& left-header
|
[:> left-header*
|
||||||
{:file file
|
{:file file
|
||||||
:layout layout
|
:layout layout
|
||||||
:project project
|
:project project
|
||||||
|
@ -170,31 +172,92 @@
|
||||||
:on-lost-pointer-capture on-lost-pointer-capture
|
:on-lost-pointer-capture on-lost-pointer-capture
|
||||||
:on-pointer-move on-pointer-move
|
:on-pointer-move on-pointer-move
|
||||||
:class (stl/css :resize-area)}]
|
:class (stl/css :resize-area)}]
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(true? shortcuts?)
|
(true? shortcuts?)
|
||||||
[:& shortcuts-container {:class (stl/css :settings-bar-content)}]
|
[:> shortcuts-container* {:class (stl/css :settings-bar-content)}]
|
||||||
|
|
||||||
(true? show-debug?)
|
(true? show-debug?)
|
||||||
[:& debug-panel {:class (stl/css :settings-bar-content)}]
|
[:> debug-panel* {:class (stl/css :settings-bar-content)}]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
[:div {:class (stl/css :settings-bar-content)}
|
[:div {:class (stl/css :settings-bar-content)}
|
||||||
[:> tab-switcher* {:tabs tabs
|
[:> tab-switcher* {:tabs tabs
|
||||||
:default-selected "layers"
|
:default "layers"
|
||||||
:selected (name section)
|
:selected (name section)
|
||||||
:on-change-tab on-tab-change
|
:on-change on-tab-change
|
||||||
:class (stl/css :left-sidebar-tabs)
|
:class (stl/css :left-sidebar-tabs)
|
||||||
:action-button-position "start"
|
:action-button-position "start"
|
||||||
:action-button (mf/html [:& collapse-button {:on-click handle-collapse}])}]])]]))
|
:action-button tabs-action-button}
|
||||||
|
|
||||||
|
(case section
|
||||||
|
:assets
|
||||||
|
[:> assets-toolbox*
|
||||||
|
{:size (- width 58)
|
||||||
|
:file-id file-id}]
|
||||||
|
|
||||||
|
:tokens
|
||||||
|
[:> tokens-sidebar-tab*]
|
||||||
|
|
||||||
|
:layers
|
||||||
|
[:> layers-content*
|
||||||
|
{:layout layout
|
||||||
|
:width width}])]])]]))
|
||||||
|
|
||||||
;; --- Right Sidebar (Component)
|
;; --- Right Sidebar (Component)
|
||||||
|
|
||||||
(mf/defc right-sidebar*
|
(defn- on-close-document-history
|
||||||
{::mf/wrap [mf/memo]}
|
[]
|
||||||
[{:keys [layout section file page-id] :as props}]
|
(st/emit! (dw/remove-layout-flag :document-history)))
|
||||||
(let [drawing-tool (:tool (mf/deref refs/workspace-drawing))
|
|
||||||
|
|
||||||
is-comments? (= drawing-tool :comments)
|
(mf/defc history-content*
|
||||||
|
{::mf/private true
|
||||||
|
::mf/memo true}
|
||||||
|
[]
|
||||||
|
(let [selected*
|
||||||
|
(hooks/use-persisted-state ::history-sidebar "history")
|
||||||
|
|
||||||
|
selected
|
||||||
|
(deref selected*)
|
||||||
|
|
||||||
|
on-change-tab
|
||||||
|
(mf/use-fn #(reset! selected* %))
|
||||||
|
|
||||||
|
tabs
|
||||||
|
(mf/with-memo []
|
||||||
|
[{:label (tr "workspace.versions.tab.history")
|
||||||
|
:id "history"}
|
||||||
|
{:label (tr "workspace.versions.tab.actions")
|
||||||
|
:id "actions"}])
|
||||||
|
|
||||||
|
button
|
||||||
|
(mf/with-memo []
|
||||||
|
(mf/html
|
||||||
|
[:> icon-button* {:variant "ghost"
|
||||||
|
:aria-label (tr "labels.close")
|
||||||
|
:on-click on-close-document-history
|
||||||
|
:icon "close"}]))]
|
||||||
|
|
||||||
|
[:> tab-switcher* {:tabs tabs
|
||||||
|
:selected selected
|
||||||
|
:on-change on-change-tab
|
||||||
|
:class (stl/css :left-sidebar-tabs)
|
||||||
|
:action-button-position "end"
|
||||||
|
:action-button button}
|
||||||
|
|
||||||
|
(case selected
|
||||||
|
"history"
|
||||||
|
[:article {:class (stl/css :history-tab)}
|
||||||
|
[:> versions-toolbox* {}]]
|
||||||
|
|
||||||
|
"actions"
|
||||||
|
[:article {:class (stl/css :versions-tab)}
|
||||||
|
[:> history-toolbox*]])]))
|
||||||
|
|
||||||
|
(mf/defc right-sidebar*
|
||||||
|
{::mf/memo true}
|
||||||
|
[{:keys [layout section file page-id drawing-tool] :as props}]
|
||||||
|
(let [is-comments? (= drawing-tool :comments)
|
||||||
is-history? (contains? layout :document-history)
|
is-history? (contains? layout :document-history)
|
||||||
is-inspect? (= section :inspect)
|
is-inspect? (= section :inspect)
|
||||||
|
|
||||||
|
@ -210,38 +273,36 @@
|
||||||
is-inspect?
|
is-inspect?
|
||||||
(= current-section :code)))
|
(= current-section :code)))
|
||||||
|
|
||||||
{:keys [on-pointer-down on-lost-pointer-capture on-pointer-move set-size size]}
|
{on-pointer-down :on-pointer-down
|
||||||
|
on-lost-pointer-capture :on-lost-pointer-capture
|
||||||
|
on-pointer-move :on-pointer-move
|
||||||
|
set-width :set-size
|
||||||
|
width :size}
|
||||||
(use-resize-hook :code sidebar-default-width sidebar-default-width sidebar-default-max-width :x true :right)
|
(use-resize-hook :code sidebar-default-width sidebar-default-width sidebar-default-max-width :x true :right)
|
||||||
|
|
||||||
on-change-section
|
on-change-section
|
||||||
(mf/use-fn
|
(mf/use-fn #(reset! current-section* %))
|
||||||
(fn [section]
|
|
||||||
(reset! current-section* section)))
|
|
||||||
|
|
||||||
on-close-history
|
|
||||||
(mf/use-fn #(st/emit! (dw/remove-layout-flag :document-history)))
|
|
||||||
|
|
||||||
on-expand
|
on-expand
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps size)
|
(mf/deps width set-width)
|
||||||
(fn []
|
(fn []
|
||||||
(set-size (if (> size sidebar-default-width) sidebar-default-width sidebar-default-max-width))))
|
(set-width (if (> width sidebar-default-width)
|
||||||
|
sidebar-default-width
|
||||||
props
|
sidebar-default-max-width))))]
|
||||||
(mf/spread-props props
|
|
||||||
{:on-change-section on-change-section
|
|
||||||
:on-expand on-expand})]
|
|
||||||
|
|
||||||
[:> (mf/provider muc/sidebar) {:value :right}
|
[:> (mf/provider muc/sidebar) {:value :right}
|
||||||
[:aside
|
[:aside
|
||||||
{:class (stl/css-case :right-settings-bar true
|
{:class (stl/css-case :right-settings-bar true
|
||||||
:not-expand (not can-be-expanded?)
|
:not-expand (not can-be-expanded?)
|
||||||
:expanded (> size sidebar-default-width))
|
:expanded (> width sidebar-default-width))
|
||||||
|
|
||||||
:id "right-sidebar-aside"
|
:id "right-sidebar-aside"
|
||||||
:data-testid "right-sidebar"
|
:data-testid "right-sidebar"
|
||||||
:data-size (str size)
|
:data-size (str width)
|
||||||
:style {"--width" (if can-be-expanded? (dm/str size "px") (dm/str sidebar-default-width "px"))}}
|
:style {:--width (if can-be-expanded?
|
||||||
|
(dm/str width "px")
|
||||||
|
(dm/str sidebar-default-width "px"))}}
|
||||||
|
|
||||||
(when can-be-expanded?
|
(when can-be-expanded?
|
||||||
[:div {:class (stl/css :resize-area)
|
[:div {:class (stl/css :resize-area)
|
||||||
|
@ -257,42 +318,16 @@
|
||||||
[:div {:class (stl/css :settings-bar-inside)}
|
[:div {:class (stl/css :settings-bar-inside)}
|
||||||
(cond
|
(cond
|
||||||
dbg-shape-panel?
|
dbg-shape-panel?
|
||||||
[:& debug-shape-info]
|
[:> debug-shape-info*]
|
||||||
|
|
||||||
is-comments?
|
is-comments?
|
||||||
[:> comments-sidebar* {}]
|
[:> comments-sidebar* {}]
|
||||||
|
|
||||||
is-history?
|
is-history?
|
||||||
(let [history-tab
|
[:> history-content* {}]
|
||||||
(mf/html
|
|
||||||
[:article {:class (stl/css :history-tab)}
|
|
||||||
[:> history-toolbox*]])
|
|
||||||
|
|
||||||
versions-tab
|
|
||||||
(mf/html
|
|
||||||
[:article {:class (stl/css :versions-tab)}
|
|
||||||
[:> versions-toolbox*]])
|
|
||||||
|
|
||||||
button
|
|
||||||
(mf/html
|
|
||||||
[:> icon-button* {:variant "ghost"
|
|
||||||
:aria-label (tr "labels.close")
|
|
||||||
:on-click on-close-history
|
|
||||||
:icon "close"}])
|
|
||||||
tabs (mf/object
|
|
||||||
[{:label (tr "workspace.versions.tab.history")
|
|
||||||
:id "history"
|
|
||||||
:content versions-tab}
|
|
||||||
{:label (tr "workspace.versions.tab.actions")
|
|
||||||
:id "actions"
|
|
||||||
:content history-tab}])]
|
|
||||||
|
|
||||||
[:> tab-switcher*
|
|
||||||
{:tabs tabs
|
|
||||||
:default-selected "history"
|
|
||||||
:class (stl/css :left-sidebar-tabs)
|
|
||||||
:action-button-position "end"
|
|
||||||
:action-button button}])
|
|
||||||
|
|
||||||
:else
|
:else
|
||||||
[:> options-toolbox* props])]]]))
|
(let [props (mf/spread-props props
|
||||||
|
{:on-change-section on-change-section
|
||||||
|
:on-expand on-expand})]
|
||||||
|
[:> options-toolbox* props]))]]]))
|
||||||
|
|
|
@ -71,9 +71,8 @@
|
||||||
[v [a b]]
|
[v [a b]]
|
||||||
(if (= v a) b a))
|
(if (= v a) b a))
|
||||||
|
|
||||||
(mf/defc assets-toolbox
|
(mf/defc assets-toolbox*
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]}
|
||||||
::mf/wrap-props false}
|
|
||||||
[{:keys [size file-id]}]
|
[{:keys [size file-id]}]
|
||||||
(let [read-only? (mf/use-ctx ctx/workspace-read-only?)
|
(let [read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
filters* (mf/use-state
|
filters* (mf/use-state
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(mf/defc debug-panel
|
(mf/defc debug-panel*
|
||||||
[{:keys [class] :as props}]
|
[{:keys [class]}]
|
||||||
(let [on-toggle-enabled
|
(let [on-toggle-enabled
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [event option]
|
(fn [event option]
|
||||||
|
|
|
@ -118,7 +118,7 @@
|
||||||
|
|
||||||
[:div {:class (stl/css :attrs-container-value)} (str value)]))
|
[:div {:class (stl/css :attrs-container-value)} (str value)]))
|
||||||
|
|
||||||
(mf/defc debug-shape-info
|
(mf/defc debug-shape-info*
|
||||||
[]
|
[]
|
||||||
(let [objects (mf/deref refs/workspace-page-objects)
|
(let [objects (mf/deref refs/workspace-page-objects)
|
||||||
selected (->> (mf/deref refs/selected-shapes)
|
selected (->> (mf/deref refs/selected-shapes)
|
||||||
|
|
|
@ -475,9 +475,8 @@
|
||||||
(dom/add-class! last-hidden-frame "sticky"))))))
|
(dom/add-class! last-hidden-frame "sticky"))))))
|
||||||
|
|
||||||
|
|
||||||
(mf/defc layers-toolbox
|
(mf/defc layers-toolbox*
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]}
|
||||||
::mf/wrap-props false}
|
|
||||||
[{:keys [size-parent]}]
|
[{:keys [size-parent]}]
|
||||||
(let [page (mf/deref refs/workspace-page)
|
(let [page (mf/deref refs/workspace-page)
|
||||||
focus (mf/deref refs/workspace-focus-selected)
|
focus (mf/deref refs/workspace-focus-selected)
|
||||||
|
|
|
@ -134,6 +134,7 @@
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:libraries libraries}])]))
|
:libraries libraries}])]))
|
||||||
|
|
||||||
|
;; FIXME: need optimizations
|
||||||
(mf/defc options-content*
|
(mf/defc options-content*
|
||||||
{::mf/memo true
|
{::mf/memo true
|
||||||
::mf/private true}
|
::mf/private true}
|
||||||
|
@ -155,17 +156,28 @@
|
||||||
(st/emit! :interrupt (dwc/set-workspace-read-only true))
|
(st/emit! :interrupt (dwc/set-workspace-read-only true))
|
||||||
(st/emit! :interrupt (dwc/set-workspace-read-only false)))))
|
(st/emit! :interrupt (dwc/set-workspace-read-only false)))))
|
||||||
|
|
||||||
design-content
|
tabs
|
||||||
(mf/html [:> design-menu*
|
(mf/with-memo []
|
||||||
{:selected selected
|
[{:label (tr "workspace.options.design")
|
||||||
:objects objects
|
:id "design"}
|
||||||
:page-id page-id
|
{:label (tr "workspace.options.prototype")
|
||||||
:file-id file-id
|
:id "prototype"}
|
||||||
:selected-shapes selected-shapes
|
{:label (tr "workspace.options.inspect")
|
||||||
:shapes-with-children shapes-with-children}])
|
:id "inspect"}])]
|
||||||
|
|
||||||
inspect-content
|
[:div {:class (stl/css :tool-window)}
|
||||||
(mf/html [:div {:class (stl/css :element-options :inspect-options)}
|
(if (:can-edit permissions)
|
||||||
|
[:> tab-switcher* {:tabs tabs
|
||||||
|
:on-change on-change-tab
|
||||||
|
:selected (name options-mode)
|
||||||
|
:class (stl/css :options-tab-switcher)}
|
||||||
|
(case options-mode
|
||||||
|
:prototype
|
||||||
|
[:div {:class (stl/css :element-options :interaction-options)}
|
||||||
|
[:& interactions-menu {:shape (first shapes)}]]
|
||||||
|
|
||||||
|
:inspect
|
||||||
|
[:div {:class (stl/css :element-options :inspect-options)}
|
||||||
[:& hrs/right-sidebar {:page-id page-id
|
[:& hrs/right-sidebar {:page-id page-id
|
||||||
:objects objects
|
:objects objects
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
|
@ -173,41 +185,18 @@
|
||||||
:shapes selected-shapes
|
:shapes selected-shapes
|
||||||
:on-change-section on-change-section
|
:on-change-section on-change-section
|
||||||
:on-expand on-expand
|
:on-expand on-expand
|
||||||
:from :workspace}]])
|
:from :workspace}]]
|
||||||
|
|
||||||
interactions-content
|
:design
|
||||||
(mf/html [:div {:class (stl/css :element-options :interaction-options)}
|
[:> design-menu* {:selected selected
|
||||||
[:& interactions-menu {:shape (first shapes)}]])
|
:objects objects
|
||||||
|
:page-id page-id
|
||||||
|
:file-id file-id
|
||||||
|
:selected-shapes selected-shapes
|
||||||
|
:shapes-with-children shapes-with-children}])]
|
||||||
|
|
||||||
|
;; FIXME: Reuse tab???
|
||||||
tabs
|
[:div {:class (stl/css :element-options :inspect-options :read-only)}
|
||||||
(if (:can-edit permissions)
|
|
||||||
#js [#js {:label (tr "workspace.options.design")
|
|
||||||
:id "design"
|
|
||||||
:content design-content}
|
|
||||||
|
|
||||||
#js {:label (tr "workspace.options.prototype")
|
|
||||||
:id "prototype"
|
|
||||||
:content interactions-content}
|
|
||||||
|
|
||||||
#js {:label (tr "workspace.options.inspect")
|
|
||||||
:id "inspect"
|
|
||||||
:content inspect-content}]
|
|
||||||
#js [#js {:label (tr "workspace.options.inspect")
|
|
||||||
:id "inspect"
|
|
||||||
:content inspect-content}])]
|
|
||||||
|
|
||||||
[:div {:class (stl/css :tool-window)}
|
|
||||||
(if (:can-edit permissions)
|
|
||||||
[:> tab-switcher* {:tabs tabs
|
|
||||||
:default-selected "info"
|
|
||||||
:on-change-tab on-change-tab
|
|
||||||
:selected (name options-mode)
|
|
||||||
:class (stl/css :options-tab-switcher)}]
|
|
||||||
|
|
||||||
[:div {:class (stl/css-case :element-options true
|
|
||||||
:inspect-options true
|
|
||||||
:read-only true)}
|
|
||||||
[:& hrs/right-sidebar {:page-id page-id
|
[:& hrs/right-sidebar {:page-id page-id
|
||||||
:objects objects
|
:objects objects
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
|
|
|
@ -364,8 +364,8 @@
|
||||||
:match-section? match-section?
|
:match-section? match-section?
|
||||||
:filter-term filter-term}]]])))
|
:filter-term filter-term}]]])))
|
||||||
|
|
||||||
(mf/defc shortcuts-container
|
(mf/defc shortcuts-container*
|
||||||
[{:keys [class] :as props}]
|
[{:keys [class]}]
|
||||||
(let [workspace-shortcuts app.main.data.workspace.shortcuts/shortcuts
|
(let [workspace-shortcuts app.main.data.workspace.shortcuts/shortcuts
|
||||||
path-shortcuts app.main.data.workspace.path.shortcuts/shortcuts
|
path-shortcuts app.main.data.workspace.path.shortcuts/shortcuts
|
||||||
all-workspace-shortcuts (->> (d/deep-merge path-shortcuts workspace-shortcuts)
|
all-workspace-shortcuts (->> (d/deep-merge path-shortcuts workspace-shortcuts)
|
||||||
|
|
|
@ -193,8 +193,8 @@
|
||||||
|
|
||||||
;; --- Pages List
|
;; --- Pages List
|
||||||
|
|
||||||
(mf/defc pages-list
|
(mf/defc pages-list*
|
||||||
{::mf/wrap-props false}
|
{::mf/private true}
|
||||||
[{:keys [file]}]
|
[{:keys [file]}]
|
||||||
(let [pages (:pages file)
|
(let [pages (:pages file)
|
||||||
deletable? (> (count pages) 1)
|
deletable? (> (count pages) 1)
|
||||||
|
@ -213,9 +213,8 @@
|
||||||
|
|
||||||
;; --- Sitemap Toolbox
|
;; --- Sitemap Toolbox
|
||||||
|
|
||||||
(mf/defc sitemap
|
(mf/defc sitemap*
|
||||||
{::mf/wrap-props false}
|
[{:keys [height collapsed on-toggle-collapsed]}]
|
||||||
[{:keys [size show-pages? toggle-pages]}]
|
|
||||||
(let [file (mf/deref ref:file-with-pages)
|
(let [file (mf/deref ref:file-with-pages)
|
||||||
file-id (get file :id)
|
file-id (get file :id)
|
||||||
project-id (get file :project-id)
|
project-id (get file :project-id)
|
||||||
|
@ -230,11 +229,11 @@
|
||||||
permissions (mf/use-ctx ctx/permissions)]
|
permissions (mf/use-ctx ctx/permissions)]
|
||||||
|
|
||||||
[:div {:class (stl/css :sitemap)
|
[:div {:class (stl/css :sitemap)
|
||||||
:style #js {"--height" (str size "px")}}
|
:style {:--height (dm/str height "px")}}
|
||||||
|
|
||||||
[:& title-bar {:collapsable true
|
[:& title-bar {:collapsable true
|
||||||
:collapsed (not show-pages?)
|
:collapsed collapsed
|
||||||
:on-collapsed toggle-pages
|
:on-collapsed on-toggle-collapsed
|
||||||
:all-clickable true
|
:all-clickable true
|
||||||
:title (tr "workspace.sidebar.sitemap")
|
:title (tr "workspace.sidebar.sitemap")
|
||||||
:class (stl/css :title-spacing-sitemap)}
|
:class (stl/css :title-spacing-sitemap)}
|
||||||
|
@ -250,5 +249,7 @@
|
||||||
:on-click on-create
|
:on-click on-create
|
||||||
:icon "add"}])]
|
:icon "add"}])]
|
||||||
|
|
||||||
|
(when-not ^boolean collapsed
|
||||||
[:div {:class (stl/css :tool-window-content)}
|
[:div {:class (stl/css :tool-window-content)}
|
||||||
[:& pages-list {:file file :key (:id file)}]]]))
|
[:> pages-list* {:file file :key (dm/str (:id file))}]])]))
|
||||||
|
|
||||||
|
|
|
@ -105,31 +105,31 @@
|
||||||
(mf/defc export-modal-body*
|
(mf/defc export-modal-body*
|
||||||
{::mf/private true}
|
{::mf/private true}
|
||||||
[]
|
[]
|
||||||
(let [selected-tab (mf/use-state "single-file")
|
(let [selected-tab* (mf/use-state "single")
|
||||||
|
selected-tab (deref selected-tab*)
|
||||||
|
|
||||||
on-change-tab
|
on-change-tab
|
||||||
(mf/use-fn
|
(mf/use-fn #(reset! selected-tab* %))
|
||||||
(fn [tab-id]
|
|
||||||
(reset! selected-tab tab-id)))
|
|
||||||
|
|
||||||
single-file-content
|
tabs
|
||||||
(mf/html [:> single-file-tab*])
|
(mf/with-memo []
|
||||||
|
[{:label (tr "workspace.tokens.export.single-file")
|
||||||
multiple-files-content
|
:id "single"}
|
||||||
(mf/html [:> multi-file-tab*])
|
{:label (tr "workspace.tokens.export.multiple-files")
|
||||||
|
:id "multiple"}])]
|
||||||
tabs #js [#js {:label (tr "workspace.tokens.export.single-file")
|
|
||||||
:id "single-file"
|
|
||||||
:content single-file-content}
|
|
||||||
#js {:label (tr "workspace.tokens.export.multiple-files")
|
|
||||||
:id "multiple-files"
|
|
||||||
:content multiple-files-content}]]
|
|
||||||
|
|
||||||
[:div {:class (stl/css :export-modal-wrapper)}
|
[:div {:class (stl/css :export-modal-wrapper)}
|
||||||
[:> heading* {:level 2 :typography "headline-medium" :class (stl/css :export-modal-title)}
|
[:> heading* {:level 2
|
||||||
|
:typography "headline-medium"
|
||||||
|
:class (stl/css :export-modal-title)}
|
||||||
(tr "workspace.tokens.export-tokens")]
|
(tr "workspace.tokens.export-tokens")]
|
||||||
|
|
||||||
[:> tab-switcher*
|
[:> tab-switcher* {:tabs tabs
|
||||||
{:tabs tabs
|
:selected selected-tab
|
||||||
:selected @selected-tab
|
:on-change on-change-tab}
|
||||||
:on-change-tab on-change-tab}]]))
|
(case selected-tab
|
||||||
|
"single"
|
||||||
|
[:> single-file-tab* {}]
|
||||||
|
|
||||||
|
"multiple"
|
||||||
|
[:> multi-file-tab* {}])]]))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue