mirror of
https://github.com/penpot/penpot.git
synced 2026-09-12 15:09:38 +00:00
🎉 Make tokens library readonly when it's in an external file
This commit is contained in:
parent
c63bf0a5e0
commit
1f793e9c15
@ -1682,10 +1682,10 @@
|
|||||||
(conj $ library-id)
|
(conj $ library-id)
|
||||||
(map #(load-library-file file-id %) $))))
|
(map #(load-library-file file-id %) $))))
|
||||||
(rx/catch (fn [cause]
|
(rx/catch (fn [cause]
|
||||||
(let [error (ex-data cause)]
|
(let [error (ex-data cause)]
|
||||||
(if (= (:code error) :circular-library-reference)
|
(if (= (:code error) :circular-library-reference)
|
||||||
(rx/of (ntf/error (tr "errors.circular-library-reference")))
|
(rx/of (ntf/error (tr "errors.circular-library-reference")))
|
||||||
(rx/throw cause))))))
|
(rx/throw cause))))))
|
||||||
(rx/of (ptk/reify ::link-file-to-library-finished))
|
(rx/of (ptk/reify ::link-file-to-library-finished))
|
||||||
(when (pos? variants-count)
|
(when (pos? variants-count)
|
||||||
(->> (rp/cmd! :get-library-usage {:file-id library-id})
|
(->> (rp/cmd! :get-library-usage {:file-id library-id})
|
||||||
|
|||||||
@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
(def permissions (mf/create-context nil))
|
(def permissions (mf/create-context nil))
|
||||||
(def can-edit? (mf/create-context nil))
|
(def can-edit? (mf/create-context nil))
|
||||||
|
(def can-edit-tokens? (mf/create-context nil))
|
||||||
|
|
||||||
(def active-tokens-by-type
|
(def active-tokens-by-type
|
||||||
"Active tokens by type, used mainly for provide tokens data to the
|
"Active tokens by type, used mainly for provide tokens data to the
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||||
|
[app.main.ui.context :as ctx]
|
||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
[app.util.clipboard :as clipboard]
|
[app.util.clipboard :as clipboard]
|
||||||
@ -346,31 +347,39 @@
|
|||||||
(defn default-actions
|
(defn default-actions
|
||||||
[{:keys [token selected-token-set-id on-delete-token errors]}]
|
[{:keys [token selected-token-set-id on-delete-token errors]}]
|
||||||
(let [{:keys [modal]} (dwta/get-token-properties token)
|
(let [{:keys [modal]} (dwta/get-token-properties token)
|
||||||
|
|
||||||
|
can-edit-tokens?
|
||||||
|
(mf/use-ctx ctx/can-edit-tokens?)
|
||||||
|
|
||||||
on-copy-name #(clipboard/to-clipboard (:name token))
|
on-copy-name #(clipboard/to-clipboard (:name token))
|
||||||
on-duplicate-token #(st/emit! (dwtl/duplicate-token (:id token)))]
|
on-duplicate-token #(st/emit! (dwtl/duplicate-token (:id token)))]
|
||||||
[{:title (tr "workspace.tokens.edit")
|
(concat
|
||||||
:no-selectable true
|
[]
|
||||||
:action (fn [event]
|
(when can-edit-tokens?
|
||||||
(let [{:keys [key fields]} modal]
|
[{:title (tr "workspace.tokens.edit")
|
||||||
(dom/stop-propagation event)
|
:no-selectable true
|
||||||
(st/emit! (dwtl/assign-token-context-menu nil)
|
:action (fn [event]
|
||||||
(modal/show key {:x (.-clientX ^js event)
|
(let [{:keys [key fields]} modal]
|
||||||
:y (.-clientY ^js event)
|
(dom/stop-propagation event)
|
||||||
:position :right
|
(st/emit! (dwtl/assign-token-context-menu nil)
|
||||||
:fields fields
|
(modal/show key {:x (.-clientX ^js event)
|
||||||
:initial-errors errors
|
:y (.-clientY ^js event)
|
||||||
:action "edit"
|
:position :right
|
||||||
:selected-token-set-id selected-token-set-id
|
:fields fields
|
||||||
:token token}))))}
|
:initial-errors errors
|
||||||
{:title (tr "workspace.tokens.duplicate")
|
:action "edit"
|
||||||
:no-selectable true
|
:selected-token-set-id selected-token-set-id
|
||||||
:action on-duplicate-token}
|
:token token}))))}
|
||||||
{:title (tr "workspace.tokens.copy-name")
|
{:title (tr "workspace.tokens.duplicate")
|
||||||
:no-selectable true
|
:no-selectable true
|
||||||
:action on-copy-name}
|
:action on-duplicate-token}])
|
||||||
{:title (tr "workspace.tokens.delete")
|
[{:title (tr "workspace.tokens.copy-name")
|
||||||
:no-selectable true
|
:no-selectable true
|
||||||
:action #(on-delete-token token)}]))
|
:action on-copy-name}]
|
||||||
|
(when can-edit-tokens?
|
||||||
|
[{:title (tr "workspace.tokens.delete")
|
||||||
|
:no-selectable true
|
||||||
|
:action #(on-delete-token token)}]))))
|
||||||
|
|
||||||
(defn- allowed-shape-attributes
|
(defn- allowed-shape-attributes
|
||||||
[shapes]
|
[shapes]
|
||||||
|
|||||||
@ -92,8 +92,8 @@
|
|||||||
(not (and (some? edition)
|
(not (and (some? edition)
|
||||||
(= :text (:type (get objects edition))))))
|
(= :text (:type (get objects edition))))))
|
||||||
|
|
||||||
can-edit?
|
can-edit-tokens?
|
||||||
(mf/use-ctx ctx/can-edit?)
|
(mf/use-ctx ctx/can-edit-tokens?)
|
||||||
|
|
||||||
is-selected-inside-layout (d/nilv is-selected-inside-layout false)
|
is-selected-inside-layout (d/nilv is-selected-inside-layout false)
|
||||||
|
|
||||||
@ -177,7 +177,7 @@
|
|||||||
:aria-controls (dm/str "token-tree-" (name type))
|
:aria-controls (dm/str "token-tree-" (name type))
|
||||||
:on-toggle-expand on-toggle-open-click
|
:on-toggle-expand on-toggle-open-click
|
||||||
:icon (token-section-icon type)}
|
:icon (token-section-icon type)}
|
||||||
(when can-edit?
|
(when can-edit-tokens?
|
||||||
[:> icon-button* {:id (str "add-token-button-" title)
|
[:> icon-button* {:id (str "add-token-button-" title)
|
||||||
:icon "add"
|
:icon "add"
|
||||||
:aria-label (tr "workspace.tokens.add-token" title)
|
:aria-label (tr "workspace.tokens.add-token" title)
|
||||||
|
|||||||
@ -140,14 +140,17 @@
|
|||||||
on-pill-context-menu
|
on-pill-context-menu
|
||||||
on-node-context-menu]}]
|
on-node-context-menu]}]
|
||||||
(let [separator "."
|
(let [separator "."
|
||||||
raw-tree (mf/with-memo [tokens]
|
raw-tree
|
||||||
(cpn/build-tree-root tokens separator))
|
(mf/with-memo [tokens]
|
||||||
permissions (mf/use-ctx ctx/permissions)
|
(cpn/build-tree-root tokens separator))
|
||||||
can-edit? (:can-edit permissions)
|
|
||||||
|
can-edit-file?
|
||||||
|
(mf/use-ctx ctx/can-edit?)
|
||||||
|
|
||||||
on-node-context-menu (mf/use-fn
|
on-node-context-menu (mf/use-fn
|
||||||
(mf/deps can-edit? on-node-context-menu)
|
(mf/deps can-edit-file? on-node-context-menu)
|
||||||
(fn [event node]
|
(fn [event node]
|
||||||
(when can-edit?
|
(when can-edit-file?
|
||||||
(on-node-context-menu event node))))
|
(on-node-context-menu event node))))
|
||||||
|
|
||||||
ordered-nodes (mf/with-memo [raw-tree]
|
ordered-nodes (mf/with-memo [raw-tree]
|
||||||
|
|||||||
@ -38,8 +38,8 @@
|
|||||||
token-sets
|
token-sets
|
||||||
(some-> tokens-lib (ctob/get-set-tree))
|
(some-> tokens-lib (ctob/get-set-tree))
|
||||||
|
|
||||||
can-edit?
|
can-edit-tokens?
|
||||||
(mf/use-ctx ctx/can-edit?)
|
(mf/use-ctx ctx/can-edit-tokens?)
|
||||||
|
|
||||||
token-set-active?
|
token-set-active?
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -55,17 +55,17 @@
|
|||||||
|
|
||||||
on-reset-edition
|
on-reset-edition
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps can-edit?)
|
(mf/deps can-edit-tokens?)
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(when can-edit?
|
(when can-edit-tokens?
|
||||||
(st/emit! (dwtl/clear-token-set-edition)
|
(st/emit! (dwtl/clear-token-set-edition)
|
||||||
(dwtl/clear-token-set-creation)))))
|
(dwtl/clear-token-set-creation)))))
|
||||||
|
|
||||||
on-start-edition
|
on-start-edition
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps can-edit?)
|
(mf/deps can-edit-tokens?)
|
||||||
(fn [id]
|
(fn [id]
|
||||||
(when can-edit?
|
(when can-edit-tokens?
|
||||||
(st/emit! (dwtl/start-token-set-edition id)))))]
|
(st/emit! (dwtl/start-token-set-edition id)))))]
|
||||||
|
|
||||||
[:> controlled-sets-list*
|
[:> controlled-sets-list*
|
||||||
@ -81,7 +81,6 @@
|
|||||||
:edition-id edition-id
|
:edition-id edition-id
|
||||||
|
|
||||||
:origin "set-panel"
|
:origin "set-panel"
|
||||||
:can-edit can-edit?
|
|
||||||
:on-start-edition on-start-edition
|
:on-start-edition on-start-edition
|
||||||
:on-reset-edition on-reset-edition
|
:on-reset-edition on-reset-edition
|
||||||
|
|
||||||
|
|||||||
@ -86,8 +86,8 @@
|
|||||||
|
|
||||||
(mf/defc inline-add-button*
|
(mf/defc inline-add-button*
|
||||||
[]
|
[]
|
||||||
(let [can-edit? (mf/use-ctx ctx/can-edit?)]
|
(let [can-edit-tokens? (mf/use-ctx ctx/can-edit-tokens?)]
|
||||||
(if can-edit?
|
(if can-edit-tokens?
|
||||||
[:div {:class (stl/css :empty-sets-wrapper)}
|
[:div {:class (stl/css :empty-sets-wrapper)}
|
||||||
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message)}
|
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message)}
|
||||||
(tr "workspace.tokens.no-sets-yet")]
|
(tr "workspace.tokens.no-sets-yet")]
|
||||||
@ -110,7 +110,10 @@
|
|||||||
[{:keys [id label is-editing is-active is-selected is-draggable is-collapsed path depth index
|
[{:keys [id label is-editing is-active is-selected is-draggable is-collapsed path depth index
|
||||||
on-toggle on-drop on-start-edition on-reset-edition on-edit-submit on-toggle-collapse]}]
|
on-toggle on-drop on-start-edition on-reset-edition on-edit-submit on-toggle-collapse]}]
|
||||||
|
|
||||||
(let [can-edit?
|
(let [can-edit-tokens?
|
||||||
|
(mf/use-ctx ctx/can-edit-tokens?)
|
||||||
|
|
||||||
|
can-edit-file?
|
||||||
(mf/use-ctx ctx/can-edit?)
|
(mf/use-ctx ctx/can-edit?)
|
||||||
|
|
||||||
label-id
|
label-id
|
||||||
@ -118,11 +121,11 @@
|
|||||||
|
|
||||||
on-context-menu
|
on-context-menu
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps is-editing id path can-edit?)
|
(mf/deps is-editing id path can-edit-tokens?)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(when (and can-edit? (not is-editing))
|
(when (and can-edit-tokens? (not is-editing))
|
||||||
(st/emit! (dwtl/assign-token-set-context-menu
|
(st/emit! (dwtl/assign-token-set-context-menu
|
||||||
{:position (dom/get-client-position event)
|
{:position (dom/get-client-position event)
|
||||||
:is-group true
|
:is-group true
|
||||||
@ -141,12 +144,12 @@
|
|||||||
|
|
||||||
on-checkbox-click
|
on-checkbox-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps on-toggle path can-edit?)
|
(mf/deps on-toggle path can-edit-file?)
|
||||||
#(on-toggle path))
|
#(on-toggle path))
|
||||||
|
|
||||||
on-edit-submit'
|
on-edit-submit'
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps path on-edit-submit can-edit?)
|
(mf/deps path on-edit-submit can-edit-tokens?)
|
||||||
#(on-edit-submit path %))
|
#(on-edit-submit path %))
|
||||||
|
|
||||||
on-drop
|
on-drop
|
||||||
@ -196,7 +199,7 @@
|
|||||||
label]
|
label]
|
||||||
[:> checkbox*
|
[:> checkbox*
|
||||||
{:on-click on-checkbox-click
|
{:on-click on-checkbox-click
|
||||||
:disabled (not can-edit?)
|
:disabled (not can-edit-file?)
|
||||||
:checked (case is-active
|
:checked (case is-active
|
||||||
:all true
|
:all true
|
||||||
:partial "mixed"
|
:partial "mixed"
|
||||||
@ -207,7 +210,11 @@
|
|||||||
[{:keys [id set label is-editing is-active is-selected is-draggable is-new path depth index
|
[{:keys [id set label is-editing is-active is-selected is-draggable is-new path depth index
|
||||||
on-select on-toggle on-drop on-start-edition on-reset-edition on-edit-submit]}]
|
on-select on-toggle on-drop on-start-edition on-reset-edition on-edit-submit]}]
|
||||||
|
|
||||||
(let [can-edit? (mf/use-ctx ctx/can-edit?)
|
(let [can-edit-tokens?
|
||||||
|
(mf/use-ctx ctx/can-edit-tokens?)
|
||||||
|
|
||||||
|
can-edit-file?
|
||||||
|
(mf/use-ctx ctx/can-edit?)
|
||||||
|
|
||||||
on-click
|
on-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -220,11 +227,11 @@
|
|||||||
|
|
||||||
on-context-menu
|
on-context-menu
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps is-editing id path can-edit?)
|
(mf/deps is-editing id path can-edit-tokens?)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(when (and can-edit? (not is-editing))
|
(when (and can-edit-tokens? (not is-editing))
|
||||||
(st/emit! (dwtl/assign-token-set-context-menu
|
(st/emit! (dwtl/assign-token-set-context-menu
|
||||||
{:position (dom/get-client-position event)
|
{:position (dom/get-client-position event)
|
||||||
:is-group false
|
:is-group false
|
||||||
@ -305,7 +312,7 @@
|
|||||||
label]
|
label]
|
||||||
[:> checkbox*
|
[:> checkbox*
|
||||||
{:on-click on-checkbox-click
|
{:on-click on-checkbox-click
|
||||||
:disabled (not can-edit?)
|
:disabled (not can-edit-file?)
|
||||||
:arial-label (tr "workspace.tokens.select-set")
|
:arial-label (tr "workspace.tokens.select-set")
|
||||||
:checked is-active}]])]))
|
:checked is-active}]])]))
|
||||||
|
|
||||||
@ -455,12 +462,12 @@
|
|||||||
(assert (fn? is-token-set-active) "expected a function for `is-token-set-active` prop")
|
(assert (fn? is-token-set-active) "expected a function for `is-token-set-active` prop")
|
||||||
(assert (fn? is-token-set-group-active) "expected a function for `is-token-set-group-active` prop")
|
(assert (fn? is-token-set-group-active) "expected a function for `is-token-set-group-active` prop")
|
||||||
|
|
||||||
(let [theme-modal? (= origin "theme-modal")
|
(let [theme-modal? (= origin "theme-modal")
|
||||||
can-edit? (mf/use-ctx ctx/can-edit?)
|
can-edit-tokens? (mf/use-ctx ctx/can-edit-tokens?)
|
||||||
draggable? (and (not theme-modal?) can-edit?)
|
draggable? (and (not theme-modal?) can-edit-tokens?)
|
||||||
empty-state? (and theme-modal?
|
empty-state? (and theme-modal?
|
||||||
(empty? token-sets)
|
(empty? token-sets)
|
||||||
(not new-path))
|
(not new-path))
|
||||||
|
|
||||||
;; NOTE: on-reset-edition and on-start-edition function can
|
;; NOTE: on-reset-edition and on-start-edition function can
|
||||||
;; come as nil, in this case we need to provide a safe
|
;; come as nil, in this case we need to provide a safe
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
(ns app.main.ui.workspace.tokens.sidebar
|
(ns app.main.ui.workspace.tokens.sidebar
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.files.tokens :as cfo]
|
||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
@ -62,9 +63,8 @@
|
|||||||
{::mf/private true}
|
{::mf/private true}
|
||||||
[{:keys [resize-height] :as props}]
|
[{:keys [resize-height] :as props}]
|
||||||
|
|
||||||
(let [can-edit?
|
(let [can-edit-tokens?
|
||||||
(mf/use-ctx ctx/can-edit?)]
|
(mf/use-ctx ctx/can-edit-tokens?)]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:> token-set-context-menu*]
|
[:> token-set-context-menu*]
|
||||||
[:section {:data-testid "token-management-sidebar"
|
[:section {:data-testid "token-management-sidebar"
|
||||||
@ -73,7 +73,7 @@
|
|||||||
[:> themes-header*]
|
[:> themes-header*]
|
||||||
[:div {:class (stl/css :sidebar-header)}
|
[:div {:class (stl/css :sidebar-header)}
|
||||||
[:> title-bar* {:title (tr "labels.sets")}
|
[:> title-bar* {:title (tr "labels.sets")}
|
||||||
(when can-edit?
|
(when can-edit-tokens?
|
||||||
[:> tsetslist/add-button*])]]
|
[:> tsetslist/add-button*])]]
|
||||||
|
|
||||||
[:> token-sets-list* props]]]))
|
[:> token-sets-list* props]]]))
|
||||||
@ -83,8 +83,8 @@
|
|||||||
(let [show-menu* (mf/use-state false)
|
(let [show-menu* (mf/use-state false)
|
||||||
show-menu? (deref show-menu*)
|
show-menu? (deref show-menu*)
|
||||||
|
|
||||||
can-edit?
|
can-edit-tokens?
|
||||||
(mf/use-ctx ctx/can-edit?)
|
(mf/use-ctx ctx/can-edit-tokens?)
|
||||||
|
|
||||||
open-menu
|
open-menu
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -124,7 +124,7 @@
|
|||||||
:on-close close-menu
|
:on-close close-menu
|
||||||
:id "tokens-menu"
|
:id "tokens-menu"
|
||||||
:class (stl/css :import-export-menu)}
|
:class (stl/css :import-export-menu)}
|
||||||
(when can-edit?
|
(when can-edit-tokens?
|
||||||
[:> dropdown-menu-item* {:class (stl/css :import-export-menu-item)
|
[:> dropdown-menu-item* {:class (stl/css :import-export-menu-item)
|
||||||
:on-click on-modal-show}
|
:on-click on-modal-show}
|
||||||
[:div {:class (stl/css :import-menu-item)}
|
[:div {:class (stl/css :import-menu-item)}
|
||||||
@ -133,8 +133,7 @@
|
|||||||
:on-click on-export}
|
:on-click on-export}
|
||||||
(tr "labels.export")]]
|
(tr "labels.export")]]
|
||||||
|
|
||||||
|
(when (and can-edit-tokens? (contains? cf/flags :token-base-font-size))
|
||||||
(when (and can-edit? (contains? cf/flags :token-base-font-size))
|
|
||||||
[:> icon-button* {:variant "secondary"
|
[:> icon-button* {:variant "secondary"
|
||||||
:icon i/settings
|
:icon i/settings
|
||||||
:aria-label "Settings"
|
:aria-label "Settings"
|
||||||
@ -146,18 +145,30 @@
|
|||||||
on-lost-pointer-capture-pages :on-lost-pointer-capture
|
on-lost-pointer-capture-pages :on-lost-pointer-capture
|
||||||
on-pointer-move-pages :on-pointer-move
|
on-pointer-move-pages :on-pointer-move
|
||||||
size-pages-opened :size}
|
size-pages-opened :size}
|
||||||
(use-resize-hook :tokens 200 38 "0.6" :y false nil)]
|
(use-resize-hook :tokens 200 38 "0.6" :y false nil)
|
||||||
|
|
||||||
[:div {:class (stl/css :sidebar-wrapper)}
|
current-file-data
|
||||||
[:> token-management-section*
|
(mf/deref refs/workspace-data)
|
||||||
{:resize-height size-pages-opened
|
|
||||||
:tokens-lib tokens-lib}]
|
can-edit-file?
|
||||||
[:article {:class (stl/css :tokens-section-wrapper)
|
(mf/use-ctx ctx/can-edit?)
|
||||||
:data-testid "tokens-sidebar"}
|
|
||||||
[:div {:class (stl/css :resize-area-horiz)
|
can-edit-tokens?
|
||||||
:on-pointer-down on-pointer-down-pages
|
(mf/with-memo [can-edit-file? current-file-data]
|
||||||
:on-lost-pointer-capture on-lost-pointer-capture-pages
|
(and can-edit-file?
|
||||||
:on-pointer-move on-pointer-move-pages}
|
(cfo/editable-tokens? current-file-data)))]
|
||||||
[:div {:class (stl/css :resize-handle-horiz)}]]
|
|
||||||
[:> tokens-section* props]]
|
[:> (mf/provider ctx/can-edit-tokens?) {:value can-edit-tokens?}
|
||||||
[:> import-export-button*]]))
|
[:div {:class (stl/css :sidebar-wrapper)}
|
||||||
|
[:> token-management-section*
|
||||||
|
{:resize-height size-pages-opened
|
||||||
|
:tokens-lib tokens-lib}]
|
||||||
|
[:article {:class (stl/css :tokens-section-wrapper)
|
||||||
|
:data-testid "tokens-sidebar"}
|
||||||
|
[: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)}]]
|
||||||
|
[:> tokens-section* props]]
|
||||||
|
[:> import-export-button*]]]))
|
||||||
|
|||||||
@ -23,8 +23,8 @@
|
|||||||
(let [ordered-themes
|
(let [ordered-themes
|
||||||
(mf/deref refs/workspace-token-themes-no-hidden)
|
(mf/deref refs/workspace-token-themes-no-hidden)
|
||||||
|
|
||||||
can-edit?
|
can-edit-tokens?
|
||||||
(mf/use-ctx ctx/can-edit?)
|
(mf/use-ctx ctx/can-edit-tokens?)
|
||||||
|
|
||||||
open-modal
|
open-modal
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -38,11 +38,11 @@
|
|||||||
[:div {:class (stl/css :empty-theme-wrapper)}
|
[:div {:class (stl/css :empty-theme-wrapper)}
|
||||||
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message)}
|
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message)}
|
||||||
(tr "workspace.tokens.no-themes")]
|
(tr "workspace.tokens.no-themes")]
|
||||||
(when can-edit?
|
(when can-edit-tokens?
|
||||||
[:button {:on-click open-modal
|
[:button {:on-click open-modal
|
||||||
:class (stl/css :create-theme-button)}
|
:class (stl/css :create-theme-button)}
|
||||||
(tr "workspace.tokens.create-one")])]
|
(tr "workspace.tokens.create-one")])]
|
||||||
(if can-edit?
|
(if can-edit-tokens?
|
||||||
[:div {:class (stl/css :theme-selector-wrapper)}
|
[:div {:class (stl/css :theme-selector-wrapper)}
|
||||||
[:> theme-selector*]
|
[:> theme-selector*]
|
||||||
[:> button* {:variant "secondary"
|
[:> button* {:variant "secondary"
|
||||||
@ -50,6 +50,6 @@
|
|||||||
:class (stl/css :edit-theme-button)
|
:class (stl/css :edit-theme-button)
|
||||||
:on-click open-modal}
|
:on-click open-modal}
|
||||||
(tr "labels.edit")]]
|
(tr "labels.edit")]]
|
||||||
[:div {:title (when-not can-edit?
|
[:div {:title (when-not can-edit-tokens?
|
||||||
(tr "workspace.tokens.no-permission-themes"))}
|
(tr "workspace.tokens.no-permission-themes"))}
|
||||||
[:> theme-selector*]]))]))
|
[:> theme-selector*]]))]))
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
[app.common.files.tokens :as cfo]
|
[app.common.files.tokens :as cfo]
|
||||||
[app.common.json :as json]
|
[app.common.json :as json]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
|
[app.common.types.file :as ctf]
|
||||||
[app.common.types.token :as cto]
|
[app.common.types.token :as cto]
|
||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
[app.common.types.tokens-status :as ctos]
|
[app.common.types.tokens-status :as ctos]
|
||||||
@ -217,8 +218,10 @@
|
|||||||
(u/not-valid plugin-id :name "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :name "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/emit! (-> (dwtl/update-token set-id id {:name value})
|
(do
|
||||||
(se/add-event plugin-id)))))}
|
(u/check-editable-tokens file-id)
|
||||||
|
(st/emit! (-> (dwtl/update-token set-id id {:name value})
|
||||||
|
(se/add-event plugin-id))))))}
|
||||||
|
|
||||||
:type
|
:type
|
||||||
{:this true
|
{:this true
|
||||||
@ -248,11 +251,13 @@
|
|||||||
(u/not-valid plugin-id :value "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :value "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [token (u/locate-token file-id set-id id)
|
(do
|
||||||
value (cond-> value
|
(u/check-editable-tokens file-id)
|
||||||
(= :font-family (:type token))
|
(let [token (u/locate-token file-id set-id id)
|
||||||
(ctob/convert-dtcg-font-family))]
|
value (cond-> value
|
||||||
(st/emit! (dwtl/update-token set-id id {:value value})))))}
|
(= :font-family (:type token))
|
||||||
|
(ctob/convert-dtcg-font-family))]
|
||||||
|
(st/emit! (dwtl/update-token set-id id {:value value}))))))}
|
||||||
|
|
||||||
:resolvedValue
|
:resolvedValue
|
||||||
{:this true
|
{:this true
|
||||||
@ -290,8 +295,10 @@
|
|||||||
(u/not-valid plugin-id :description "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :description "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/emit! (-> (dwtl/update-token set-id id {:description value})
|
(do
|
||||||
(se/add-event plugin-id)))))}
|
(u/check-editable-tokens file-id)
|
||||||
|
(st/emit! (-> (dwtl/update-token set-id id {:description value})
|
||||||
|
(se/add-event plugin-id))))))}
|
||||||
|
|
||||||
:duplicate
|
:duplicate
|
||||||
(fn []
|
(fn []
|
||||||
@ -305,13 +312,15 @@
|
|||||||
;; - use this function in dwtl/duplicate-token
|
;; - use this function in dwtl/duplicate-token
|
||||||
;; - return the new token proxy using the locally forced id
|
;; - return the new token proxy using the locally forced id
|
||||||
;; - do the same with sets and themes
|
;; - do the same with sets and themes
|
||||||
(let [token (u/locate-token file-id set-id id)
|
(do
|
||||||
token' (ctob/make-token (-> (datafy token)
|
(u/check-editable-tokens file-id)
|
||||||
(dissoc :id
|
(let [token (u/locate-token file-id set-id id)
|
||||||
:modified-at)))]
|
token' (ctob/make-token (-> (datafy token)
|
||||||
(st/emit! (-> (dwtl/create-token set-id token')
|
(dissoc :id
|
||||||
(se/add-event plugin-id)))
|
:modified-at)))]
|
||||||
(token-proxy plugin-id file-id set-id (:id token')))))
|
(st/emit! (-> (dwtl/create-token set-id token')
|
||||||
|
(se/add-event plugin-id)))
|
||||||
|
(token-proxy plugin-id file-id set-id (:id token'))))))
|
||||||
|
|
||||||
:remove
|
:remove
|
||||||
(fn []
|
(fn []
|
||||||
@ -320,8 +329,10 @@
|
|||||||
(u/not-valid plugin-id :remove "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :remove "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/emit! (-> (dwtl/delete-token set-id id)
|
(do
|
||||||
(se/add-event plugin-id)))))
|
(u/check-editable-tokens file-id)
|
||||||
|
(st/emit! (-> (dwtl/delete-token set-id id)
|
||||||
|
(se/add-event plugin-id))))))
|
||||||
|
|
||||||
:applyToShapes
|
:applyToShapes
|
||||||
{:enumerable false
|
{:enumerable false
|
||||||
@ -377,8 +388,10 @@
|
|||||||
(u/not-valid plugin-id :name "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :name "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [set (u/locate-token-set file-id id)]
|
(do
|
||||||
(st/emit! (dwtl/rename-token-set set name)))))}
|
(u/check-editable-tokens file-id)
|
||||||
|
(let [set (u/locate-token-set file-id id)]
|
||||||
|
(st/emit! (dwtl/rename-token-set set name))))))}
|
||||||
|
|
||||||
:active
|
:active
|
||||||
{:this true
|
{:this true
|
||||||
@ -395,7 +408,7 @@
|
|||||||
(u/not-valid plugin-id :active "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :active "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/emit! (dwtl/set-enabled-token-set id value))))}
|
(st/emit! (dwtl/set-enabled-token-set id value))))} ;; This can be done even with tokens in an external library
|
||||||
|
|
||||||
:toggleActive
|
:toggleActive
|
||||||
(fn []
|
(fn []
|
||||||
@ -468,28 +481,30 @@
|
|||||||
(u/not-valid plugin-id :addToken "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :addToken "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [tokens-lib (u/locate-tokens-lib file-id)
|
(do
|
||||||
token (ctob/make-token attrs)
|
(u/check-editable-tokens file-id)
|
||||||
;; Resolve against all tokens in the library (including those
|
(let [tokens-lib (u/locate-tokens-lib file-id)
|
||||||
;; in inactive sets) so that references to structurally
|
token (ctob/make-token attrs)
|
||||||
;; existing tokens resolve even if their set is not active.
|
;; Resolve against all tokens in the library (including those
|
||||||
;; The target set's tokens take precedence over equally named
|
;; in inactive sets) so that references to structurally
|
||||||
;; tokens in other sets, and the new token takes precedence
|
;; existing tokens resolve even if their set is not active.
|
||||||
;; over all.
|
;; The target set's tokens take precedence over equally named
|
||||||
tokens-tree (-> (merge (ctob/get-all-tokens-map tokens-lib)
|
;; tokens in other sets, and the new token takes precedence
|
||||||
(ctob/get-tokens tokens-lib id))
|
;; over all.
|
||||||
(assoc (:name token) token))
|
tokens-tree (-> (merge (ctob/get-all-tokens-map tokens-lib)
|
||||||
resolved-tokens (ts/resolve-tokens tokens-tree)
|
(ctob/get-tokens tokens-lib id))
|
||||||
|
(assoc (:name token) token))
|
||||||
|
resolved-tokens (ts/resolve-tokens tokens-tree)
|
||||||
|
|
||||||
{:keys [errors resolved-value] :as resolved-token}
|
{:keys [errors resolved-value] :as resolved-token}
|
||||||
(get resolved-tokens (:name token))]
|
(get resolved-tokens (:name token))]
|
||||||
|
|
||||||
(if resolved-value
|
(if resolved-value
|
||||||
(do (st/emit! (-> (dwtl/create-token id token)
|
(do (st/emit! (-> (dwtl/create-token id token)
|
||||||
(se/add-event plugin-id)))
|
(se/add-event plugin-id)))
|
||||||
(token-proxy plugin-id file-id id (:id token)))
|
(token-proxy plugin-id file-id id (:id token)))
|
||||||
(do (u/not-valid plugin-id :addToken (str errors))
|
(do (u/not-valid plugin-id :addToken (str errors))
|
||||||
nil)))))}
|
nil))))))}
|
||||||
|
|
||||||
:duplicate
|
:duplicate
|
||||||
(fn []
|
(fn []
|
||||||
@ -498,10 +513,12 @@
|
|||||||
(u/not-valid plugin-id :duplicate "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :duplicate "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [id-ref (atom nil)]
|
(do
|
||||||
(st/emit! (dwtl/duplicate-token-set id {:id-ref id-ref}))
|
(u/check-editable-tokens file-id)
|
||||||
(when (some? @id-ref)
|
(let [id-ref (atom nil)]
|
||||||
(token-set-proxy plugin-id file-id @id-ref)))))
|
(st/emit! (dwtl/duplicate-token-set id {:id-ref id-ref}))
|
||||||
|
(when (some? @id-ref)
|
||||||
|
(token-set-proxy plugin-id file-id @id-ref))))))
|
||||||
|
|
||||||
:remove
|
:remove
|
||||||
(fn []
|
(fn []
|
||||||
@ -510,7 +527,9 @@
|
|||||||
(u/not-valid plugin-id :remove "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :remove "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/emit! (dwtl/delete-token-set id)))))))
|
(do
|
||||||
|
(u/check-editable-tokens file-id)
|
||||||
|
(st/emit! (dwtl/delete-token-set id))))))))
|
||||||
|
|
||||||
(defn token-theme-proxy? [p]
|
(defn token-theme-proxy? [p]
|
||||||
(obj/type-of? p "TokenThemeProxy"))
|
(obj/type-of? p "TokenThemeProxy"))
|
||||||
@ -568,8 +587,10 @@
|
|||||||
(u/not-valid plugin-id :group "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :group "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [theme (u/locate-token-theme file-id id)]
|
(do
|
||||||
(st/emit! (dwtl/update-token-theme id (assoc theme :group group))))))}
|
(u/check-editable-tokens file-id)
|
||||||
|
(let [theme (u/locate-token-theme file-id id)]
|
||||||
|
(st/emit! (dwtl/update-token-theme id (assoc theme :group group)))))))}
|
||||||
|
|
||||||
:name
|
:name
|
||||||
{:this true
|
{:this true
|
||||||
@ -589,9 +610,11 @@
|
|||||||
(u/not-valid plugin-id :name "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :name "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [theme (u/locate-token-theme file-id id)]
|
(do
|
||||||
(when name
|
(u/check-editable-tokens file-id)
|
||||||
(st/emit! (dwtl/update-token-theme id (assoc theme :name name)))))))}
|
(let [theme (u/locate-token-theme file-id id)]
|
||||||
|
(when name
|
||||||
|
(st/emit! (dwtl/update-token-theme id (assoc theme :name name))))))))}
|
||||||
|
|
||||||
:active
|
:active
|
||||||
{:this true
|
{:this true
|
||||||
@ -641,10 +664,12 @@
|
|||||||
(u/not-valid plugin-id :addSet "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :addSet "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [set-name (token-set-name (resolve-token-set file-id set-arg))
|
(do
|
||||||
theme (u/locate-token-theme file-id id)]
|
(u/check-editable-tokens file-id)
|
||||||
(when (and set-name theme)
|
(let [set-name (token-set-name (resolve-token-set file-id set-arg))
|
||||||
(st/emit! (dwtl/update-token-theme id (ctob/enable-set theme set-name)))))))}
|
theme (u/locate-token-theme file-id id)]
|
||||||
|
(when (and set-name theme)
|
||||||
|
(st/emit! (dwtl/update-token-theme id (ctob/enable-set theme set-name))))))))}
|
||||||
|
|
||||||
:removeSet
|
:removeSet
|
||||||
{:enumerable false
|
{:enumerable false
|
||||||
@ -655,10 +680,12 @@
|
|||||||
(u/not-valid plugin-id :removeSet "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :removeSet "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [set-name (token-set-name (resolve-token-set file-id set-arg))
|
(do
|
||||||
theme (u/locate-token-theme file-id id)]
|
(u/check-editable-tokens file-id)
|
||||||
(when (and set-name theme)
|
(let [set-name (token-set-name (resolve-token-set file-id set-arg))
|
||||||
(st/emit! (dwtl/update-token-theme id (ctob/disable-set theme set-name)))))))}
|
theme (u/locate-token-theme file-id id)]
|
||||||
|
(when (and set-name theme)
|
||||||
|
(st/emit! (dwtl/update-token-theme id (ctob/disable-set theme set-name))))))))}
|
||||||
|
|
||||||
:duplicate
|
:duplicate
|
||||||
(fn []
|
(fn []
|
||||||
@ -667,12 +694,14 @@
|
|||||||
(u/not-valid plugin-id :duplicate "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :duplicate "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [theme (u/locate-token-theme file-id id)
|
(do
|
||||||
theme' (ctob/make-token-theme (-> (datafy theme)
|
(u/check-editable-tokens file-id)
|
||||||
(dissoc :id
|
(let [theme (u/locate-token-theme file-id id)
|
||||||
:modified-at)))]
|
theme' (ctob/make-token-theme (-> (datafy theme)
|
||||||
(st/emit! (dwtl/create-token-theme theme'))
|
(dissoc :id
|
||||||
(token-theme-proxy plugin-id file-id (:id theme')))))
|
:modified-at)))]
|
||||||
|
(st/emit! (dwtl/create-token-theme theme'))
|
||||||
|
(token-theme-proxy plugin-id file-id (:id theme'))))))
|
||||||
|
|
||||||
:remove
|
:remove
|
||||||
(fn []
|
(fn []
|
||||||
@ -681,7 +710,9 @@
|
|||||||
(u/not-valid plugin-id :remove "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :remove "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/emit! (dwtl/delete-token-theme id))))))
|
(do
|
||||||
|
(u/check-editable-tokens file-id)
|
||||||
|
(st/emit! (dwtl/delete-token-theme id)))))))
|
||||||
|
|
||||||
(defn tokens-catalog
|
(defn tokens-catalog
|
||||||
[plugin-id file-id]
|
[plugin-id file-id]
|
||||||
@ -690,6 +721,14 @@
|
|||||||
:$plugin {:enumerable false :get (constantly plugin-id)}
|
:$plugin {:enumerable false :get (constantly plugin-id)}
|
||||||
:$id {:enumerable false :get (constantly file-id)}
|
:$id {:enumerable false :get (constantly file-id)}
|
||||||
|
|
||||||
|
:isEditableTokens
|
||||||
|
{:this false
|
||||||
|
:enumerable false
|
||||||
|
:get
|
||||||
|
(fn []
|
||||||
|
(let [file (u/locate-file file-id)]
|
||||||
|
(cfo/editable-tokens? (ctf/file-data file))))}
|
||||||
|
|
||||||
:themes
|
:themes
|
||||||
{:this true
|
{:this true
|
||||||
:enumerable false
|
:enumerable false
|
||||||
@ -726,9 +765,11 @@
|
|||||||
(u/not-valid plugin-id :addTheme "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :addTheme "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [theme (ctob/make-token-theme attrs)]
|
(do
|
||||||
(st/emit! (dwtl/create-token-theme theme))
|
(u/check-editable-tokens file-id)
|
||||||
(token-theme-proxy plugin-id file-id (:id theme)))))}
|
(let [theme (ctob/make-token-theme attrs)]
|
||||||
|
(st/emit! (dwtl/create-token-theme theme))
|
||||||
|
(token-theme-proxy plugin-id file-id (:id theme))))))}
|
||||||
|
|
||||||
:addSet
|
:addSet
|
||||||
{:enumerable false
|
{:enumerable false
|
||||||
@ -750,21 +791,23 @@
|
|||||||
(u/not-valid plugin-id :addSet "Plugin doesn't have 'content:write' permission")
|
(u/not-valid plugin-id :addSet "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [active? (boolean (:active attrs))
|
(do
|
||||||
attrs (-> attrs
|
(u/check-editable-tokens file-id)
|
||||||
(dissoc :active)
|
(let [active? (boolean (:active attrs))
|
||||||
(update :name ctob/normalize-set-name))
|
attrs (-> attrs
|
||||||
set (ctob/make-token-set attrs)]
|
(dissoc :active)
|
||||||
(st/emit! (dwtl/create-token-set set))
|
(update :name ctob/normalize-set-name))
|
||||||
;; Newly created sets are inactive by default; activate it when
|
set (ctob/make-token-set attrs)]
|
||||||
;; requested. Enabling only adds the set name to the hidden theme,
|
(st/emit! (dwtl/create-token-set set))
|
||||||
;; so it does not depend on the create event having propagated yet.
|
;; Newly created sets are inactive by default; activate it when
|
||||||
(when active?
|
;; requested. Enabling only adds the set name to the hidden theme,
|
||||||
(st/emit! (dwtl/set-enabled-token-set (ctob/get-name set) true)))
|
;; so it does not depend on the create event having propagated yet.
|
||||||
;; Pass the set name as `initial-name` so the proxy can resolve
|
(when active?
|
||||||
;; it immediately, before the async `st/emit!` above propagates
|
(st/emit! (dwtl/set-enabled-token-set (ctob/get-name set) true)))
|
||||||
;; the new set into `@st/state`.
|
;; Pass the set name as `initial-name` so the proxy can resolve
|
||||||
(token-set-proxy plugin-id file-id (ctob/get-id set) (ctob/get-name set)))))}
|
;; it immediately, before the async `st/emit!` above propagates
|
||||||
|
;; the new set into `@st/state`.
|
||||||
|
(token-set-proxy plugin-id file-id (ctob/get-id set) (ctob/get-name set))))))}
|
||||||
|
|
||||||
:getThemeById
|
:getThemeById
|
||||||
{:enumerable false
|
{:enumerable false
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.files.tokens :as cfo]
|
||||||
[app.common.i18n :as i18n :refer [tr]]
|
[app.common.i18n :as i18n :refer [tr]]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.schema.messages :as csm]
|
[app.common.schema.messages :as csm]
|
||||||
@ -67,13 +68,18 @@
|
|||||||
|
|
||||||
(defn locate-tokens-lib
|
(defn locate-tokens-lib
|
||||||
[file-id]
|
[file-id]
|
||||||
(let [file (locate-file file-id)]
|
(let [file (locate-file file-id)
|
||||||
(->> file :data :tokens-lib)))
|
file-data (ctf/file-data file)
|
||||||
|
tokens-source-id (cfo/get-tokens-source file-data)
|
||||||
|
tokens-file (locate-file tokens-source-id)
|
||||||
|
tokens-file-data (ctf/file-data tokens-file)]
|
||||||
|
(cfo/get-tokens-lib tokens-file-data)))
|
||||||
|
|
||||||
(defn locate-tokens-status
|
(defn locate-tokens-status
|
||||||
[file-id]
|
[file-id]
|
||||||
(let [file (locate-file file-id)]
|
(let [file (locate-file file-id)
|
||||||
(->> file :data :tokens-status)))
|
file-data (ctf/file-data file)]
|
||||||
|
(cfo/get-tokens-status file-data)))
|
||||||
|
|
||||||
(defn locate-token-theme
|
(defn locate-token-theme
|
||||||
[file-id id]
|
[file-id id]
|
||||||
@ -271,6 +277,12 @@
|
|||||||
(boolean
|
(boolean
|
||||||
(dm/get-in @st/state [:plugins :flags plugin-id :natural-child-ordering])))
|
(dm/get-in @st/state [:plugins :flags plugin-id :natural-child-ordering])))
|
||||||
|
|
||||||
|
(defn check-editable-tokens
|
||||||
|
[file-id]
|
||||||
|
(let [file (locate-file file-id)]
|
||||||
|
(when-not (cfo/editable-tokens? (ctf/file-data file))
|
||||||
|
(throw (js/Error. (dm/str "[PENPOT PLUGIN] Cannot modify tokens in an external library"))))))
|
||||||
|
|
||||||
(defn throw-validation-errors?
|
(defn throw-validation-errors?
|
||||||
[plugin-id]
|
[plugin-id]
|
||||||
(boolean
|
(boolean
|
||||||
|
|||||||
@ -6,13 +6,15 @@
|
|||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<p class="headline-m">THEMES</p>
|
<p class="headline-m">THEMES</p>
|
||||||
<button
|
@if (isEditableTokens) {
|
||||||
type="button"
|
<button
|
||||||
data-appearance="secondary"
|
type="button"
|
||||||
(click)="addTheme()"
|
data-appearance="secondary"
|
||||||
>
|
(click)="addTheme()"
|
||||||
+
|
>
|
||||||
</button>
|
+
|
||||||
|
</button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul data-handler="themes-list">
|
<ul data-handler="themes-list">
|
||||||
@ -24,20 +26,22 @@
|
|||||||
}
|
}
|
||||||
{{ theme.name }}
|
{{ theme.name }}
|
||||||
</span>
|
</span>
|
||||||
<button
|
@if (isEditableTokens) {
|
||||||
type="button"
|
<button
|
||||||
data-appearance="secondary"
|
type="button"
|
||||||
(click)="renameTheme(theme.id, theme.name)"
|
data-appearance="secondary"
|
||||||
>
|
(click)="renameTheme(theme.id, theme.name)"
|
||||||
🖊️
|
>
|
||||||
</button>
|
🖊️
|
||||||
<button
|
</button>
|
||||||
type="button"
|
<button
|
||||||
data-appearance="secondary"
|
type="button"
|
||||||
(click)="deleteTheme(theme.id)"
|
data-appearance="secondary"
|
||||||
>
|
(click)="deleteTheme(theme.id)"
|
||||||
❌
|
>
|
||||||
</button>
|
❌
|
||||||
|
</button>
|
||||||
|
}
|
||||||
<div class="checkbox-container">
|
<div class="checkbox-container">
|
||||||
<input
|
<input
|
||||||
class="checkbox-input"
|
class="checkbox-input"
|
||||||
@ -55,9 +59,11 @@
|
|||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<p class="headline-m">SETS</p>
|
<p class="headline-m">SETS</p>
|
||||||
<button type="button" data-appearance="secondary" (click)="addSet()">
|
@if (isEditableTokens) {
|
||||||
+
|
<button type="button" data-appearance="secondary" (click)="addSet()">
|
||||||
</button>
|
+
|
||||||
|
</button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul data-handler="sets-list">
|
<ul data-handler="sets-list">
|
||||||
@ -69,20 +75,22 @@
|
|||||||
<span (click)="loadTokens(set.id)">
|
<span (click)="loadTokens(set.id)">
|
||||||
{{ set.name }}
|
{{ set.name }}
|
||||||
</span>
|
</span>
|
||||||
<button
|
@if (isEditableTokens) {
|
||||||
type="button"
|
<button
|
||||||
data-appearance="secondary"
|
type="button"
|
||||||
(click)="renameSet(set.id, set.name)"
|
data-appearance="secondary"
|
||||||
>
|
(click)="renameSet(set.id, set.name)"
|
||||||
🖊️
|
>
|
||||||
</button>
|
🖊️
|
||||||
<button
|
</button>
|
||||||
type="button"
|
<button
|
||||||
data-appearance="secondary"
|
type="button"
|
||||||
(click)="deleteSet(set.id)"
|
data-appearance="secondary"
|
||||||
>
|
(click)="deleteSet(set.id)"
|
||||||
❌
|
>
|
||||||
</button>
|
❌
|
||||||
|
</button>
|
||||||
|
}
|
||||||
<div class="checkbox-container">
|
<div class="checkbox-container">
|
||||||
<input
|
<input
|
||||||
class="checkbox-input"
|
class="checkbox-input"
|
||||||
@ -105,13 +113,15 @@
|
|||||||
@for (group of tokenGroups; track group[0]) {
|
@for (group of tokenGroups; track group[0]) {
|
||||||
<li class="body-m token-group">
|
<li class="body-m token-group">
|
||||||
<span>{{ group[0] }}</span>
|
<span>{{ group[0] }}</span>
|
||||||
<button
|
@if (isEditableTokens) {
|
||||||
type="button"
|
<button
|
||||||
data-appearance="secondary"
|
type="button"
|
||||||
(click)="addToken(group[0])"
|
data-appearance="secondary"
|
||||||
>
|
(click)="addToken(group[0])"
|
||||||
+
|
>
|
||||||
</button>
|
+
|
||||||
|
</button>
|
||||||
|
}
|
||||||
</li>
|
</li>
|
||||||
@for (token of group[1]; track token.id) {
|
@for (token of group[1]; track token.id) {
|
||||||
<li
|
<li
|
||||||
@ -125,20 +135,22 @@
|
|||||||
>
|
>
|
||||||
{{ token.name }}
|
{{ token.name }}
|
||||||
</span>
|
</span>
|
||||||
<button
|
@if (isEditableTokens) {
|
||||||
type="button"
|
<button
|
||||||
data-appearance="secondary"
|
type="button"
|
||||||
(click)="renameToken(token.id, token.name)"
|
data-appearance="secondary"
|
||||||
>
|
(click)="renameToken(token.id, token.name)"
|
||||||
🖊️
|
>
|
||||||
</button>
|
🖊️
|
||||||
<button
|
</button>
|
||||||
type="button"
|
<button
|
||||||
data-appearance="secondary"
|
type="button"
|
||||||
(click)="deleteToken(token.id)"
|
data-appearance="secondary"
|
||||||
>
|
(click)="deleteToken(token.id)"
|
||||||
❌
|
>
|
||||||
</button>
|
❌
|
||||||
|
</button>
|
||||||
|
}
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,6 +59,7 @@ export class AppComponent {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public isEditableTokens: boolean = false;
|
||||||
public themes: TokenTheme[] = [];
|
public themes: TokenTheme[] = [];
|
||||||
public sets: TokenSet[] = [];
|
public sets: TokenSet[] = [];
|
||||||
public tokenGroups: TokensGroup[] = [];
|
public tokenGroups: TokensGroup[] = [];
|
||||||
@ -72,6 +73,8 @@ export class AppComponent {
|
|||||||
this.#setSets(event.data.setsData);
|
this.#setSets(event.data.setsData);
|
||||||
} else if (event.data.type === 'set-tokens') {
|
} else if (event.data.type === 'set-tokens') {
|
||||||
this.#setTokens(event.data.tokenGroupsData);
|
this.#setTokens(event.data.tokenGroupsData);
|
||||||
|
} else if (event.data.type === 'set-is-editable-tokens') {
|
||||||
|
this.#setIsEditableTokens(event.data.isEditableTokens);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -268,6 +271,10 @@ export class AppComponent {
|
|||||||
parent.postMessage(message, '*');
|
parent.postMessage(message, '*');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#setIsEditableTokens(isEditableTokens: boolean) {
|
||||||
|
this.isEditableTokens = isEditableTokens;
|
||||||
|
}
|
||||||
|
|
||||||
#setThemes(themes: TokenTheme[]) {
|
#setThemes(themes: TokenTheme[]) {
|
||||||
this.themes = themes;
|
this.themes = themes;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,6 +58,14 @@ function sendMessage(message: PluginMessageEvent) {
|
|||||||
function loadLibrary() {
|
function loadLibrary() {
|
||||||
const tokensCatalog = penpot.library.local.tokens;
|
const tokensCatalog = penpot.library.local.tokens;
|
||||||
|
|
||||||
|
const isEditableTokens = tokensCatalog.isEditableTokens;
|
||||||
|
|
||||||
|
penpot.ui.sendMessage({
|
||||||
|
source: 'penpot',
|
||||||
|
type: 'set-is-editable-tokens',
|
||||||
|
isEditableTokens,
|
||||||
|
});
|
||||||
|
|
||||||
const themes = tokensCatalog.themes;
|
const themes = tokensCatalog.themes;
|
||||||
|
|
||||||
const themesData = themes.map((theme) => {
|
const themesData = themes.map((theme) => {
|
||||||
|
|||||||
8
plugins/libs/plugin-types/index.d.ts
vendored
8
plugins/libs/plugin-types/index.d.ts
vendored
@ -5220,6 +5220,14 @@ export type Token =
|
|||||||
* Themes.
|
* Themes.
|
||||||
*/
|
*/
|
||||||
export interface TokenCatalog {
|
export interface TokenCatalog {
|
||||||
|
/**
|
||||||
|
* Returns true if the tokens can be edited (it can't
|
||||||
|
* if the tokens of the file are in an external library).
|
||||||
|
* Note that even in this case, Themes and Sets status still
|
||||||
|
* can be changed and tokens can be applied to shapes.
|
||||||
|
*/
|
||||||
|
readonly isEditableTokens: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of themes in this catalog, in creation order.
|
* The list of themes in this catalog, in creation order.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user