mirror of
https://github.com/penpot/penpot.git
synced 2025-02-08 08:09:14 -05:00
Start tokens studio plugin base
This commit is contained in:
parent
d1a8427563
commit
e5c5640413
19 changed files with 880 additions and 3 deletions
|
@ -23,6 +23,8 @@
|
||||||
[app.common.types.pages-list :as ctpl]
|
[app.common.types.pages-list :as ctpl]
|
||||||
[app.common.types.shape :as cts]
|
[app.common.types.shape :as cts]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
|
[app.common.types.token :as cto]
|
||||||
|
[app.common.types.tokens-list :as ctol]
|
||||||
[app.common.types.typographies-list :as ctyl]
|
[app.common.types.typographies-list :as ctyl]
|
||||||
[app.common.types.typography :as ctt]
|
[app.common.types.typography :as ctt]
|
||||||
[clojure.set :as set]))
|
[clojure.set :as set]))
|
||||||
|
@ -232,6 +234,22 @@
|
||||||
[:del-typography
|
[:del-typography
|
||||||
[:map {:title "DelTypogrphyChange"}
|
[:map {:title "DelTypogrphyChange"}
|
||||||
[:type [:= :del-typography]]
|
[:type [:= :del-typography]]
|
||||||
|
[:id ::sm/uuid]]]
|
||||||
|
|
||||||
|
[:add-token
|
||||||
|
[:map {:title "AddTokenChange"}
|
||||||
|
[:type [:= :add-token]]
|
||||||
|
[:token ::cto/token]]]
|
||||||
|
|
||||||
|
[:mod-token
|
||||||
|
[:map {:title "ModTokenChange"}
|
||||||
|
[:type [:= :mod-token]]
|
||||||
|
[:id ::sm/uuid]
|
||||||
|
[:token ::cto/token]]]
|
||||||
|
|
||||||
|
[:del-token
|
||||||
|
[:map {:title "DelTokenChange"}
|
||||||
|
[:type [:= :del-token]]
|
||||||
[:id ::sm/uuid]]]]])
|
[:id ::sm/uuid]]]]])
|
||||||
|
|
||||||
(sm/define! ::changes
|
(sm/define! ::changes
|
||||||
|
@ -669,6 +687,20 @@
|
||||||
[data {:keys [id]}]
|
[data {:keys [id]}]
|
||||||
(ctyl/delete-typography data id))
|
(ctyl/delete-typography data id))
|
||||||
|
|
||||||
|
;; -- Tokens
|
||||||
|
|
||||||
|
(defmethod process-change :add-token
|
||||||
|
[data {:keys [token]}]
|
||||||
|
(ctol/add-token data token))
|
||||||
|
|
||||||
|
(defmethod process-change :mod-token
|
||||||
|
[data {:keys [id token]}]
|
||||||
|
(ctol/update-token data id merge token))
|
||||||
|
|
||||||
|
(defmethod process-change :del-token
|
||||||
|
[data {:keys [id]}]
|
||||||
|
(ctol/delete-token data id))
|
||||||
|
|
||||||
;; === Operations
|
;; === Operations
|
||||||
|
|
||||||
(defmethod process-operation :set
|
(defmethod process-operation :set
|
||||||
|
|
|
@ -664,6 +664,30 @@
|
||||||
(update :undo-changes conj {:type :add-typography :typography prev-typography})
|
(update :undo-changes conj {:type :add-typography :typography prev-typography})
|
||||||
(apply-changes-local))))
|
(apply-changes-local))))
|
||||||
|
|
||||||
|
(defn add-token
|
||||||
|
[changes token]
|
||||||
|
(-> changes
|
||||||
|
(update :redo-changes conj {:type :add-token :token token})
|
||||||
|
(update :undo-changes conj {:type :del-token :id (:id token)})
|
||||||
|
(apply-changes-local)))
|
||||||
|
|
||||||
|
(defn update-token
|
||||||
|
[changes token]
|
||||||
|
(let [token-id (:id token)]
|
||||||
|
(-> changes
|
||||||
|
(update :redo-changes conj {:type :mod-token :id token-id :token token})
|
||||||
|
(apply-changes-local))))
|
||||||
|
|
||||||
|
(defn delete-token
|
||||||
|
[changes token-id]
|
||||||
|
(assert-library! changes)
|
||||||
|
(let [library-data (::library-data (meta changes))
|
||||||
|
prev-token (get-in library-data [:tokens token-id])]
|
||||||
|
(-> changes
|
||||||
|
(update :redo-changes conj {:type :del-token :id token-id})
|
||||||
|
(update :undo-changes conj {:type :add-token :token prev-token})
|
||||||
|
(apply-changes-local))))
|
||||||
|
|
||||||
(defn add-component
|
(defn add-component
|
||||||
([changes id path name new-shapes updated-shapes main-instance-id main-instance-page]
|
([changes id path name new-shapes updated-shapes main-instance-id main-instance-page]
|
||||||
(add-component changes id path name new-shapes updated-shapes main-instance-id main-instance-page nil))
|
(add-component changes id path name new-shapes updated-shapes main-instance-id main-instance-page nil))
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
[app.common.types.pages-list :as ctpl]
|
[app.common.types.pages-list :as ctpl]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
|
[app.common.types.token :as cto]
|
||||||
[app.common.types.typographies-list :as ctyl]
|
[app.common.types.typographies-list :as ctyl]
|
||||||
[app.common.types.typography :as cty]
|
[app.common.types.typography :as cty]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
|
@ -55,6 +56,8 @@
|
||||||
[:vector {:gen/max 3} ::ctc/recent-color]]
|
[:vector {:gen/max 3} ::ctc/recent-color]]
|
||||||
[:typographies {:optional true}
|
[:typographies {:optional true}
|
||||||
[:map-of {:gen/max 2} ::sm/uuid ::cty/typography]]
|
[:map-of {:gen/max 2} ::sm/uuid ::cty/typography]]
|
||||||
|
[:tokens {:optional true}
|
||||||
|
[:map-of {:gen/max 100} ::sm/uuid ::cto/token]]
|
||||||
[:media {:optional true}
|
[:media {:optional true}
|
||||||
[:map-of {:gen/max 5} ::sm/uuid ::media-object]]])
|
[:map-of {:gen/max 5} ::sm/uuid ::media-object]]])
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
[app.common.types.shape.path :as ctsp]
|
[app.common.types.shape.path :as ctsp]
|
||||||
[app.common.types.shape.shadow :as ctss]
|
[app.common.types.shape.shadow :as ctss]
|
||||||
[app.common.types.shape.text :as ctsx]
|
[app.common.types.shape.text :as ctsx]
|
||||||
|
[app.common.types.token :as cto]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[clojure.set :as set]))
|
[clojure.set :as set]))
|
||||||
|
|
||||||
|
@ -180,7 +181,8 @@
|
||||||
[:vector {:gen/max 1} ::ctss/shadow]]
|
[:vector {:gen/max 1} ::ctss/shadow]]
|
||||||
[:blur {:optional true} ::ctsb/blur]
|
[:blur {:optional true} ::ctsb/blur]
|
||||||
[:grow-type {:optional true}
|
[:grow-type {:optional true}
|
||||||
[::sm/one-of #{:auto-width :auto-height :fixed}]]])
|
[::sm/one-of #{:auto-width :auto-height :fixed}]]
|
||||||
|
[:applied-tokens {:optional true} ::cto/applied-tokens]])
|
||||||
|
|
||||||
(sm/define! ::group-attrs
|
(sm/define! ::group-attrs
|
||||||
[:map {:title "GroupAttrs"}
|
[:map {:title "GroupAttrs"}
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
:show-content
|
:show-content
|
||||||
:hide-in-viewer
|
:hide-in-viewer
|
||||||
|
|
||||||
|
:applied-tokens
|
||||||
|
|
||||||
:opacity
|
:opacity
|
||||||
:blend-mode
|
:blend-mode
|
||||||
:blocked
|
:blocked
|
||||||
|
@ -95,6 +97,8 @@
|
||||||
:parent-id
|
:parent-id
|
||||||
:frame-id
|
:frame-id
|
||||||
|
|
||||||
|
:applied-tokens
|
||||||
|
|
||||||
:opacity
|
:opacity
|
||||||
:blend-mode
|
:blend-mode
|
||||||
:blocked
|
:blocked
|
||||||
|
|
80
common/src/app/common/types/token.cljc
Normal file
80
common/src/app/common/types/token.cljc
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.common.types.token
|
||||||
|
(:require
|
||||||
|
[app.common.schema :as sm]
|
||||||
|
[app.common.schema.registry :as sr]))
|
||||||
|
|
||||||
|
(defn merge-schemas [& schema-keys]
|
||||||
|
(let [schemas (map #(get @sr/registry %) schema-keys)]
|
||||||
|
(reduce sm/merge schemas)))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; SCHEMA
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(def token-types
|
||||||
|
#{:boolean
|
||||||
|
:border-radius
|
||||||
|
:box-shadow
|
||||||
|
:dimension
|
||||||
|
:numeric
|
||||||
|
:opacity
|
||||||
|
:other
|
||||||
|
:rotation
|
||||||
|
:sizing
|
||||||
|
:spacing
|
||||||
|
:string
|
||||||
|
:typography})
|
||||||
|
|
||||||
|
(sm/def! ::token
|
||||||
|
[:map {:title "Token"}
|
||||||
|
[:id ::sm/uuid]
|
||||||
|
[:name :string]
|
||||||
|
[:type [::sm/one-of token-types]]
|
||||||
|
[:value :any]
|
||||||
|
[:description {:optional true} :string]
|
||||||
|
[:modified-at {:optional true} ::sm/inst]])
|
||||||
|
|
||||||
|
(sm/def! ::border-radius
|
||||||
|
[:map
|
||||||
|
[:rx {:optional true} ::sm/uuid]
|
||||||
|
[:ry {:optional true} ::sm/uuid]
|
||||||
|
[:r1 {:optional true} ::sm/uuid]
|
||||||
|
[:r2 {:optional true} ::sm/uuid]
|
||||||
|
[:r3 {:optional true} ::sm/uuid]
|
||||||
|
[:r4 {:optional true} ::sm/uuid]])
|
||||||
|
|
||||||
|
(sm/def! ::dimensions
|
||||||
|
[:map
|
||||||
|
[:width {:optional true} ::sm/uuid]
|
||||||
|
[:height {:optional true} ::sm/uuid]
|
||||||
|
[:min-height {:optional true} ::sm/uuid]
|
||||||
|
[:max-height {:optional true} ::sm/uuid]
|
||||||
|
[:min-width {:optional true} ::sm/uuid]
|
||||||
|
[:max-width {:optional true} ::sm/uuid]])
|
||||||
|
|
||||||
|
(sm/def! ::spacing
|
||||||
|
[:map
|
||||||
|
[:spacing-column {:optional true} ::sm/uuid]
|
||||||
|
[:spacing-row {:optional true} ::sm/uuid]
|
||||||
|
[:padding-p1 {:optional true} ::sm/uuid]
|
||||||
|
[:padding-p2 {:optional true} ::sm/uuid]
|
||||||
|
[:padding-p3 {:optional true} ::sm/uuid]
|
||||||
|
[:padding-p4 {:optional true} ::sm/uuid]
|
||||||
|
[:padding-all {:optional true} ::sm/uuid]
|
||||||
|
[:position-x {:optional true} ::sm/uuid]
|
||||||
|
[:position-y {:optional true} ::sm/uuid]])
|
||||||
|
|
||||||
|
(sm/def! ::tokens
|
||||||
|
[:map {:title "Applied Tokens"}])
|
||||||
|
|
||||||
|
(sm/def! ::applied-tokens
|
||||||
|
(merge-schemas ::tokens
|
||||||
|
::border-radius
|
||||||
|
::dimensions
|
||||||
|
::spacing))
|
45
common/src/app/common/types/tokens_list.cljc
Normal file
45
common/src/app/common/types/tokens_list.cljc
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.common.types.tokens-list
|
||||||
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.common.time :as dt]))
|
||||||
|
|
||||||
|
(defn tokens-seq
|
||||||
|
"Returns a sequence of all tokens within the file data."
|
||||||
|
[file-data]
|
||||||
|
(vals (:tokens file-data)))
|
||||||
|
|
||||||
|
(defn- touch
|
||||||
|
"Updates the `modified-at` timestamp of a token."
|
||||||
|
[token]
|
||||||
|
(assoc token :modified-at (dt/now)))
|
||||||
|
|
||||||
|
(defn add-token
|
||||||
|
"Adds a new token to the file data, setting its `modified-at` timestamp."
|
||||||
|
[file-data token]
|
||||||
|
(update file-data :tokens assoc (:id token) (touch token)))
|
||||||
|
|
||||||
|
(defn get-token
|
||||||
|
"Retrieves a token by its ID from the file data."
|
||||||
|
[file-data token-id]
|
||||||
|
(get-in file-data [:tokens token-id]))
|
||||||
|
|
||||||
|
(defn set-token
|
||||||
|
"Sets or updates a token in the file data, updating its `modified-at` timestamp."
|
||||||
|
[file-data token]
|
||||||
|
(d/assoc-in-when file-data [:tokens (:id token)] (touch token)))
|
||||||
|
|
||||||
|
(defn update-token
|
||||||
|
"Applies a function to update a token in the file data, then touches it."
|
||||||
|
[file-data token-id f & args]
|
||||||
|
(d/update-in-when file-data [:tokens token-id] #(-> (apply f % args) (touch))))
|
||||||
|
|
||||||
|
(defn delete-token
|
||||||
|
"Removes a token from the file data by its ID."
|
||||||
|
[file-data token-id]
|
||||||
|
(update file-data :tokens dissoc token-id))
|
110
frontend/src/app/main/data/tokens.cljs
Normal file
110
frontend/src/app/main/data/tokens.cljs
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.data.tokens
|
||||||
|
(:require
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.files.changes-builder :as pcb]
|
||||||
|
[app.common.types.shape :as cts]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
|
[app.main.data.workspace.changes :as dch]
|
||||||
|
[app.main.ui.workspace.tokens.common :refer [workspace-shapes]]
|
||||||
|
[beicon.v2.core :as rx]
|
||||||
|
[clojure.data :as data]
|
||||||
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Helpers
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; TODO HYMA: Copied over from workspace.cljs
|
||||||
|
(defn update-shape
|
||||||
|
[id attrs]
|
||||||
|
(dm/assert!
|
||||||
|
"expected valid parameters"
|
||||||
|
(and (cts/check-shape-attrs! attrs)
|
||||||
|
(uuid? id)))
|
||||||
|
|
||||||
|
(ptk/reify ::update-shape
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ _ _]
|
||||||
|
(rx/of (dch/update-shapes [id] #(merge % attrs))))))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; TOKENS Actions
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn toggle-or-apply-token
|
||||||
|
"Remove any shape attributes from token if they exists.
|
||||||
|
Othewise apply token attributes."
|
||||||
|
[shape token]
|
||||||
|
(let [[shape-leftover token-leftover _matching] (data/diff (:applied-tokens shape) token)]
|
||||||
|
(merge {} shape-leftover token-leftover)))
|
||||||
|
|
||||||
|
(defn get-shape-from-state [shape-id state]
|
||||||
|
(let [current-page-id (get state :current-page-id)
|
||||||
|
shape (-> (workspace-shapes (:workspace-data state) current-page-id #{shape-id})
|
||||||
|
(first))]
|
||||||
|
shape))
|
||||||
|
|
||||||
|
(defn token-from-attributes [token-id attributes]
|
||||||
|
(->> (map (fn [attr] [attr token-id]) attributes)
|
||||||
|
(into {})))
|
||||||
|
|
||||||
|
(defn update-token-from-attributes
|
||||||
|
[{:keys [token-id shape-id attributes]}]
|
||||||
|
(ptk/reify ::update-token-from-attributes
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [shape (get-shape-from-state shape-id state)
|
||||||
|
token (token-from-attributes token-id attributes)
|
||||||
|
next-applied-tokens (toggle-or-apply-token shape token)]
|
||||||
|
(rx/of (update-shape shape-id {:applied-tokens next-applied-tokens}))))))
|
||||||
|
|
||||||
|
(defn add-token
|
||||||
|
[token]
|
||||||
|
(let [token (update token :id #(or % (uuid/next)))]
|
||||||
|
(ptk/reify ::add-token
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [it _ _]
|
||||||
|
(let [changes (-> (pcb/empty-changes it)
|
||||||
|
(pcb/add-token token))]
|
||||||
|
(rx/of (dch/commit-changes changes)))))))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; TEMP (Move to test)
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(def shape-1 {:r3 3})
|
||||||
|
|
||||||
|
(def token-1 {:rx 1
|
||||||
|
:ry 1})
|
||||||
|
|
||||||
|
|
||||||
|
(def shape-after-token-1-is-applied {:rx 1
|
||||||
|
:ry 1
|
||||||
|
:r3 3})
|
||||||
|
|
||||||
|
(def token-2 {:r3 1})
|
||||||
|
|
||||||
|
|
||||||
|
(def shape-after-token-2-is-applied {:rx 1
|
||||||
|
:ry 1
|
||||||
|
:r3 1})
|
||||||
|
|
||||||
|
(def token-3 {:r3 1})
|
||||||
|
|
||||||
|
(def shape-after-token-3-is-applied {:rx 1
|
||||||
|
:ry 1})
|
||||||
|
|
||||||
|
(= (toggle-or-apply-token shape-1 token-1)
|
||||||
|
shape-after-token-1-is-applied)
|
||||||
|
(= (toggle-or-apply-token shape-after-token-1-is-applied token-2)
|
||||||
|
shape-after-token-2-is-applied)
|
||||||
|
(= (toggle-or-apply-token shape-after-token-2-is-applied token-3)
|
||||||
|
shape-after-token-3-is-applied)
|
||||||
|
nil)
|
|
@ -43,7 +43,11 @@
|
||||||
|
|
||||||
:layers
|
:layers
|
||||||
{:del #{:document-history :assets}
|
{:del #{:document-history :assets}
|
||||||
:add #{:sitemap :layers}}})
|
:add #{:sitemap :layers}}
|
||||||
|
|
||||||
|
:tokens
|
||||||
|
{:del #{:sitemap :layers :document-history :assets}
|
||||||
|
:add #{:tokens}}})
|
||||||
|
|
||||||
(def valid-options-mode
|
(def valid-options-mode
|
||||||
#{:design :prototype :inspect})
|
#{:design :prototype :inspect})
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
[app.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]]
|
[app.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]]
|
||||||
[app.main.ui.workspace.sidebar.collapsable-button :refer [collapsed-button]]
|
[app.main.ui.workspace.sidebar.collapsable-button :refer [collapsed-button]]
|
||||||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox]]
|
[app.main.ui.workspace.sidebar.history :refer [history-toolbox]]
|
||||||
|
[app.main.ui.workspace.tokens.modals]
|
||||||
[app.main.ui.workspace.viewport :refer [viewport]]
|
[app.main.ui.workspace.viewport :refer [viewport]]
|
||||||
[app.util.debug :as dbg]
|
[app.util.debug :as dbg]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
[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.tokens.sidebar :refer [tokens-sidebar-tab]]
|
||||||
[app.util.debug :as dbg]
|
[app.util.debug :as dbg]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
@ -42,6 +43,7 @@
|
||||||
toggle-pages (mf/use-callback #(reset! show-pages? not))
|
toggle-pages (mf/use-callback #(reset! show-pages? not))
|
||||||
|
|
||||||
section (cond (or mode-inspect? (contains? layout :layers)) :layers
|
section (cond (or mode-inspect? (contains? layout :layers)) :layers
|
||||||
|
(contains? layout :tokens) :tokens
|
||||||
(contains? layout :assets) :assets)
|
(contains? layout :assets) :assets)
|
||||||
|
|
||||||
shortcuts? (contains? layout :shortcuts)
|
shortcuts? (contains? layout :shortcuts)
|
||||||
|
@ -115,7 +117,11 @@
|
||||||
(when-not ^boolean mode-inspect?
|
(when-not ^boolean mode-inspect?
|
||||||
[:& tab-element {:id :assets
|
[:& tab-element {:id :assets
|
||||||
:title (tr "workspace.toolbar.assets")}
|
:title (tr "workspace.toolbar.assets")}
|
||||||
[:& assets-toolbox {:size (- size 58)}]])]])]]))
|
[:& assets-toolbox {:size (- size 58)}]])
|
||||||
|
|
||||||
|
[:& tab-element {:id :tokens
|
||||||
|
:title "Tokens"}
|
||||||
|
[:& tokens-sidebar-tab]]]])]]))
|
||||||
|
|
||||||
;; --- Right Sidebar (Component)
|
;; --- Right Sidebar (Component)
|
||||||
|
|
||||||
|
|
41
frontend/src/app/main/ui/workspace/tokens/common.cljs
Normal file
41
frontend/src/app/main/ui/workspace/tokens/common.cljs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.ui.workspace.tokens.common
|
||||||
|
(:require-macros [app.main.style :as stl])
|
||||||
|
(:require
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
;; Helpers ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(defn workspace-shapes [workspace page-id shape-ids]
|
||||||
|
(-> (get-in workspace [:pages-index page-id :objects])
|
||||||
|
(keep shape-ids)))
|
||||||
|
|
||||||
|
(defn vec-remove
|
||||||
|
"remove elem in coll"
|
||||||
|
[pos coll]
|
||||||
|
(into (subvec coll 0 pos) (subvec coll (inc pos))))
|
||||||
|
|
||||||
|
;; Components ------------------------------------------------------------------
|
||||||
|
|
||||||
|
(mf/defc input
|
||||||
|
{::mf/wrap-props false}
|
||||||
|
[{:keys [type placeholder]
|
||||||
|
:or {type "text"}}]
|
||||||
|
[:input {:type type
|
||||||
|
:class (stl/css :input)
|
||||||
|
:placeholder placeholder}])
|
||||||
|
|
||||||
|
(mf/defc labeled-input
|
||||||
|
{::mf/wrap-props false}
|
||||||
|
[{:keys [input-ref label default-value on-change auto-focus?]}]
|
||||||
|
[:label {:class (stl/css :labeled-input)}
|
||||||
|
[:span {:class (stl/css :label)} label]
|
||||||
|
[:input {:ref input-ref
|
||||||
|
:default-value default-value
|
||||||
|
:autoFocus auto-focus?
|
||||||
|
:on-change on-change}]])
|
32
frontend/src/app/main/ui/workspace/tokens/common.scss
Normal file
32
frontend/src/app/main/ui/workspace/tokens/common.scss
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@import "refactor/common-refactor.scss";
|
||||||
|
|
||||||
|
.input {
|
||||||
|
@extend .input-element;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labeled-input {
|
||||||
|
@extend .input-element;
|
||||||
|
.label {
|
||||||
|
width: auto;
|
||||||
|
text-wrap: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
@extend .button-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-button {
|
||||||
|
@extend .button-tertiary;
|
||||||
|
height: $s-32;
|
||||||
|
width: $s-28;
|
||||||
|
svg {
|
||||||
|
@extend .button-icon;
|
||||||
|
}
|
||||||
|
}
|
112
frontend/src/app/main/ui/workspace/tokens/core.cljs
Normal file
112
frontend/src/app/main/ui/workspace/tokens/core.cljs
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.ui.workspace.tokens.core
|
||||||
|
(:require
|
||||||
|
[app.common.data :as d :refer [ordered-map]]
|
||||||
|
[app.common.types.shape.radius :as ctsr]
|
||||||
|
[app.main.data.tokens :as dt]
|
||||||
|
[app.main.data.workspace.changes :as dch]))
|
||||||
|
|
||||||
|
;; Helpers ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(defn token-applied?
|
||||||
|
"Test if `token` is applied to a `shape` with the given `token-attributes`."
|
||||||
|
[token shape token-attributes]
|
||||||
|
(let [{:keys [id]} token
|
||||||
|
applied-tokens (get shape :applied-tokens {})]
|
||||||
|
(some (fn [attr]
|
||||||
|
(= (get applied-tokens attr) id))
|
||||||
|
token-attributes)))
|
||||||
|
|
||||||
|
(defn tokens-applied?
|
||||||
|
"Test if `token` is applied to to any of `shapes` with the given `token-attributes`."
|
||||||
|
[token shapes token-attributes]
|
||||||
|
(some #(token-applied? token % token-attributes) shapes))
|
||||||
|
|
||||||
|
;; Update functions ------------------------------------------------------------
|
||||||
|
|
||||||
|
(defn update-shape-radius [value shape-ids]
|
||||||
|
(let [parsed-value (d/parse-integer value)]
|
||||||
|
(dch/update-shapes shape-ids
|
||||||
|
(fn [shape]
|
||||||
|
(when (ctsr/has-radius? shape)
|
||||||
|
(ctsr/set-radius-1 shape parsed-value)))
|
||||||
|
{:reg-objects? true
|
||||||
|
:attrs [:rx :ry :r1 :r2 :r3 :r4]})))
|
||||||
|
|
||||||
|
;; Token types -----------------------------------------------------------------
|
||||||
|
|
||||||
|
(def token-types
|
||||||
|
(ordered-map
|
||||||
|
[:boolean {:title "Boolean"
|
||||||
|
:modal {:key :tokens/boolean
|
||||||
|
:fields [{:label "Boolean"}]}}]
|
||||||
|
[:border-radius {:title "Border Radius"
|
||||||
|
:attributes #{:rx :ry :r1 :r2 :r3 :r4}
|
||||||
|
:on-apply dt/update-token-from-attributes
|
||||||
|
:modal {:key :tokens/border-radius
|
||||||
|
:fields [{:label "Border Radius"
|
||||||
|
:key :border-radius}]}
|
||||||
|
:on-update-shape update-shape-radius}]
|
||||||
|
[:box-shadow
|
||||||
|
{:title "Box Shadow"
|
||||||
|
:modal {:key :tokens/box-shadow
|
||||||
|
:fields [{:label "Box shadows"
|
||||||
|
:key :box-shadow
|
||||||
|
:type :box-shadow}]}}]
|
||||||
|
[:sizing
|
||||||
|
{:title "Sizing"
|
||||||
|
:modal {:key :tokens/sizing
|
||||||
|
:fields [{:label "Sizing"
|
||||||
|
:key :sizing}]}}]
|
||||||
|
[:dimension
|
||||||
|
{:title "Dimension"
|
||||||
|
:modal {:key :tokens/dimensions
|
||||||
|
:fields [{:label "Dimensions"
|
||||||
|
:key :dimensions}]}}]
|
||||||
|
[:numeric
|
||||||
|
{:title "Numeric"
|
||||||
|
:modal {:key :tokens/numeric
|
||||||
|
:fields [{:label "Numeric"
|
||||||
|
:key :numeric}]}}]
|
||||||
|
[:opacity
|
||||||
|
{:title "Opacity"
|
||||||
|
:modal {:key :tokens/opacity
|
||||||
|
:fields [{:label "Opacity"
|
||||||
|
:key :opacity}]}}]
|
||||||
|
[:other
|
||||||
|
{:title "Other"
|
||||||
|
:modal {:key :tokens/other
|
||||||
|
:fields [{:label "Other"
|
||||||
|
:key :other}]}}]
|
||||||
|
[:rotation
|
||||||
|
{:title "Rotation"
|
||||||
|
:modal {:key :tokens/rotation
|
||||||
|
:fields [{:label "Rotation"
|
||||||
|
:key :rotation}]}}]
|
||||||
|
[:spacing
|
||||||
|
{:title "Spacing"
|
||||||
|
:modal {:key :tokens/spacing
|
||||||
|
:fields [{:label "Spacing"
|
||||||
|
:key :spacing}]}}]
|
||||||
|
[:string
|
||||||
|
{:title "String"
|
||||||
|
:modal {:key :tokens/string
|
||||||
|
:fields [{:label "String"
|
||||||
|
:key :string}]}}]
|
||||||
|
[:typography
|
||||||
|
{:title "Typography"
|
||||||
|
:modal {:key :tokens/typography
|
||||||
|
:fields [{:label "Font" :key :font-family}
|
||||||
|
{:label "Weight" :key :weight}
|
||||||
|
{:label "Font Size" :key :font-size}
|
||||||
|
{:label "Line Height" :key :line-height}
|
||||||
|
{:label "Letter Spacing" :key :letter-spacing}
|
||||||
|
{:label "Paragraph Spacing" :key :paragraph-spacing}
|
||||||
|
{:label "Paragraph Indent" :key :paragraph-indent}
|
||||||
|
{:label "Text Decoration" :key :text-decoration}
|
||||||
|
{:label "Text Case" :key :text-case}]}}]))
|
96
frontend/src/app/main/ui/workspace/tokens/modal.cljs
Normal file
96
frontend/src/app/main/ui/workspace/tokens/modal.cljs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.ui.workspace.tokens.modal
|
||||||
|
(:require-macros [app.main.style :as stl])
|
||||||
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.main.data.tokens :as dt]
|
||||||
|
[app.main.refs :as refs]
|
||||||
|
[app.main.store :as st]
|
||||||
|
[app.main.ui.workspace.tokens.common :as tokens.common]
|
||||||
|
[app.util.dom :as dom]
|
||||||
|
[okulary.core :as l]
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(defn calculate-position
|
||||||
|
"Calculates the style properties for the given coordinates and position"
|
||||||
|
[{vh :height} position x y]
|
||||||
|
(let [;; picker height in pixels
|
||||||
|
h 510
|
||||||
|
;; Checks for overflow outside the viewport height
|
||||||
|
overflow-fix (max 0 (+ y (- 50) h (- vh)))
|
||||||
|
|
||||||
|
x-pos 325]
|
||||||
|
(cond
|
||||||
|
(or (nil? x) (nil? y)) {:left "auto" :right "16rem" :top "4rem"}
|
||||||
|
(= position :left) {:left (str (- x x-pos) "px")
|
||||||
|
:top (str (- y 50 overflow-fix) "px")}
|
||||||
|
:else {:left (str (+ x 80) "px")
|
||||||
|
:top (str (- y 70 overflow-fix) "px")})))
|
||||||
|
|
||||||
|
(def viewport
|
||||||
|
(l/derived :vport refs/workspace-local))
|
||||||
|
|
||||||
|
(defn fields->map [fields]
|
||||||
|
(->> (map (fn [{:keys [key] :as field}]
|
||||||
|
[key (:value field)]) fields)
|
||||||
|
(into {})))
|
||||||
|
|
||||||
|
(mf/defc tokens-properties-form
|
||||||
|
{::mf/wrap-props false}
|
||||||
|
[{:keys [token-type x y position fields]}]
|
||||||
|
(let [vport (mf/deref viewport)
|
||||||
|
style (calculate-position vport position x y)
|
||||||
|
|
||||||
|
name (mf/use-var nil)
|
||||||
|
on-update-name #(reset! name (dom/get-target-val %))
|
||||||
|
name-ref (mf/use-ref)
|
||||||
|
|
||||||
|
description (mf/use-var nil)
|
||||||
|
on-update-description #(reset! description (dom/get-target-val %))
|
||||||
|
|
||||||
|
state (mf/use-state fields)
|
||||||
|
on-update-state-field (fn [idx e]
|
||||||
|
(->> (dom/get-target-val e)
|
||||||
|
(assoc-in @state [idx :value])
|
||||||
|
(reset! state)))
|
||||||
|
|
||||||
|
on-submit (fn [e]
|
||||||
|
(dom/prevent-default e)
|
||||||
|
(let [token-value (-> (fields->map @state)
|
||||||
|
(first)
|
||||||
|
(val))
|
||||||
|
token (cond-> {:name @name
|
||||||
|
:type token-type
|
||||||
|
:value token-value}
|
||||||
|
@description (assoc :description @description))]
|
||||||
|
(st/emit! (dt/add-token token))))]
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
(fn []
|
||||||
|
(dom/focus! (mf/ref-val name-ref))))
|
||||||
|
|
||||||
|
[:form
|
||||||
|
{:class (stl/css :shadow)
|
||||||
|
:style (clj->js style)
|
||||||
|
:on-submit on-submit}
|
||||||
|
[:div {:class (stl/css :token-rows)}
|
||||||
|
[:& tokens.common/labeled-input {:label "Name"
|
||||||
|
:on-change on-update-name
|
||||||
|
:input-ref name-ref}]
|
||||||
|
(for [[idx {:keys [type label]}] (d/enumerate @state)]
|
||||||
|
[:* {:key (str "form-field-" idx)}
|
||||||
|
(case type
|
||||||
|
:box-shadow [:p "TODO BOX SHADOW"]
|
||||||
|
[:& tokens.common/labeled-input {:label label
|
||||||
|
:on-change #(on-update-state-field idx %)}])])
|
||||||
|
[:& tokens.common/labeled-input {:label "Description"
|
||||||
|
:on-change #(on-update-description %)}]
|
||||||
|
[:div {:class (stl/css :button-row)}
|
||||||
|
[:button {:class (stl/css :button)
|
||||||
|
:type "submit"}
|
||||||
|
"Save"]]]]))
|
66
frontend/src/app/main/ui/workspace/tokens/modal.scss
Normal file
66
frontend/src/app/main/ui/workspace/tokens/modal.scss
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@import "refactor/common-refactor.scss";
|
||||||
|
@import "./common.scss";
|
||||||
|
|
||||||
|
.button-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: $s-16;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token-rows {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $s-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow {
|
||||||
|
@extend .modal-container-base;
|
||||||
|
@include menuShadow;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 11;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
|
&-select-wrapper {
|
||||||
|
display: flex;
|
||||||
|
grid-gap: $s-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-properties {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
grid-gap: $s-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputs-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-areas:
|
||||||
|
"x blur blur spread spread"
|
||||||
|
"y color color color color";
|
||||||
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
grid-template-rows: repeat(2, 1fr);
|
||||||
|
grid-gap: $s-4;
|
||||||
|
|
||||||
|
label:nth-child(1) {
|
||||||
|
grid-area: x;
|
||||||
|
}
|
||||||
|
label:nth-child(2) {
|
||||||
|
grid-area: y;
|
||||||
|
}
|
||||||
|
label:nth-child(3) {
|
||||||
|
grid-area: blur;
|
||||||
|
}
|
||||||
|
label:nth-child(4) {
|
||||||
|
grid-area: spread;
|
||||||
|
}
|
||||||
|
label:nth-child(5) {
|
||||||
|
grid-area: color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
83
frontend/src/app/main/ui/workspace/tokens/modals.cljs
Normal file
83
frontend/src/app/main/ui/workspace/tokens/modals.cljs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.ui.workspace.tokens.modals
|
||||||
|
(:require
|
||||||
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.ui.workspace.tokens.modal :refer [tokens-properties-form]]
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(mf/defc boolean-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/boolean}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc border-radius-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/border-radius}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc box-shadow-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/box-shadow}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc sizing-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/sizing}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc dimensions-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/dimensions}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc numeric-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/numeric}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc opacity-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/opacity}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc other-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/other}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc rotation-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/rotation}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc spacing-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/spacing}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc string-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/string}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
||||||
|
|
||||||
|
(mf/defc typography-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/typography}
|
||||||
|
[properties]
|
||||||
|
[:& tokens-properties-form properties])
|
106
frontend/src/app/main/ui/workspace/tokens/sidebar.cljs
Normal file
106
frontend/src/app/main/ui/workspace/tokens/sidebar.cljs
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.ui.workspace.tokens.sidebar
|
||||||
|
(:require-macros [app.main.style :as stl])
|
||||||
|
(:require
|
||||||
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.refs :as refs]
|
||||||
|
[app.main.store :as st]
|
||||||
|
[app.main.ui.components.search-bar :refer [search-bar]]
|
||||||
|
[app.main.ui.icons :as i]
|
||||||
|
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||||
|
[app.main.ui.workspace.tokens.common :refer [workspace-shapes]]
|
||||||
|
[app.main.ui.workspace.tokens.core :refer [token-types tokens-applied?]]
|
||||||
|
[app.util.dom :as dom]
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(mf/defc token-pill
|
||||||
|
{::mf/wrap-props false}
|
||||||
|
[{:keys [on-click token highlighted?]}]
|
||||||
|
(let [{:keys [name value]} token]
|
||||||
|
[:div {:class (stl/css-case :token-pill true
|
||||||
|
:token-pill-highlighted highlighted?)
|
||||||
|
:title (str "Token value: " value)
|
||||||
|
:on-click on-click}
|
||||||
|
name]))
|
||||||
|
|
||||||
|
(defn- on-apply-token [token attributes selected-shapes on-apply on-update-shape event]
|
||||||
|
(let [shapes-to-apply-token (filter #(not (tokens-applied? token % attributes)) selected-shapes)
|
||||||
|
shapes-to-apply-token-ids (map #(:id %) shapes-to-apply-token)]
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(doseq [shape selected-shapes]
|
||||||
|
(st/emit! (on-apply {:token-id (:id token)
|
||||||
|
:shape-id (:id shape)
|
||||||
|
:attributes attributes}))
|
||||||
|
(st/emit! (on-update-shape (:value token) shapes-to-apply-token-ids)))))
|
||||||
|
|
||||||
|
(mf/defc token-component
|
||||||
|
[{:keys [type file tokens selected-shapes token-type-props]}]
|
||||||
|
(let [open? (mf/use-state false)
|
||||||
|
{:keys [modal attributes title on-apply on-update-shape]} token-type-props
|
||||||
|
on-toggle-open-click (mf/use-fn
|
||||||
|
(mf/deps open? tokens)
|
||||||
|
#(when (seq tokens)
|
||||||
|
(swap! open? not)))
|
||||||
|
on-popover-open-click (mf/use-fn
|
||||||
|
(fn [event]
|
||||||
|
(let [{:keys [key fields]} modal]
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(modal/show! key {:x (.-clientX ^js event)
|
||||||
|
:y (.-clientY ^js event)
|
||||||
|
:position :right
|
||||||
|
:fields fields
|
||||||
|
:token-type type}))))
|
||||||
|
tokens-count (count tokens)]
|
||||||
|
[:div {:on-click on-toggle-open-click}
|
||||||
|
[:& cmm/asset-section {:file-id (:id file)
|
||||||
|
:title title
|
||||||
|
:assets-count tokens-count
|
||||||
|
:open? @open?}
|
||||||
|
[:& cmm/asset-section-block {:role :title-button}
|
||||||
|
[:button {:class (stl/css :action-button)
|
||||||
|
:on-click on-popover-open-click}
|
||||||
|
i/add]]
|
||||||
|
(when open?
|
||||||
|
[:& cmm/asset-section-block {:role :content}
|
||||||
|
[:div {:class (stl/css :token-pills-wrapper)}
|
||||||
|
(for [token tokens]
|
||||||
|
[:& token-pill {:key (:id token)
|
||||||
|
:token token
|
||||||
|
:highlighted? (tokens-applied? token selected-shapes attributes)
|
||||||
|
:on-click #(on-apply-token token attributes selected-shapes on-apply on-update-shape %1)}])]])]]))
|
||||||
|
|
||||||
|
(mf/defc tokens-explorer
|
||||||
|
[_props]
|
||||||
|
(let [file (mf/deref refs/workspace-file)
|
||||||
|
current-page-id (:current-page-id @st/state)
|
||||||
|
workspace-data (mf/deref refs/workspace-data)
|
||||||
|
tokens (get workspace-data :tokens)
|
||||||
|
tokens-by-group (->> (vals tokens)
|
||||||
|
(group-by :type))
|
||||||
|
selected-shape-ids (mf/deref refs/selected-shapes)
|
||||||
|
selected-shapes (workspace-shapes workspace-data current-page-id selected-shape-ids)]
|
||||||
|
(js/console.log "tokens" tokens)
|
||||||
|
[:article
|
||||||
|
[:& search-bar {:placeholder "Filter"
|
||||||
|
:on-change js/console.log}]
|
||||||
|
[:div.assets-bar
|
||||||
|
(for [[token-key token-type-props] token-types
|
||||||
|
:let [tokens (or (get tokens-by-group token-key) [])]]
|
||||||
|
[:& token-component {:key token-key
|
||||||
|
:type token-key
|
||||||
|
:file file
|
||||||
|
:selected-shapes selected-shapes
|
||||||
|
:tokens tokens
|
||||||
|
:token-type-props token-type-props}])]]))
|
||||||
|
|
||||||
|
(mf/defc tokens-sidebar-tab
|
||||||
|
{::mf/wrap [mf/memo]
|
||||||
|
::mf/wrap-props false}
|
||||||
|
[_props]
|
||||||
|
[:div {:class (stl/css :sidebar-tab-wrapper)}
|
||||||
|
[:& tokens-explorer]])
|
30
frontend/src/app/main/ui/workspace/tokens/sidebar.scss
Normal file
30
frontend/src/app/main/ui/workspace/tokens/sidebar.scss
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@import "refactor/common-refactor.scss";
|
||||||
|
|
||||||
|
@import "./common.scss";
|
||||||
|
|
||||||
|
.sidebar-tab-wrapper {
|
||||||
|
padding: $s-12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token-pills-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: $s-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token-pill {
|
||||||
|
@extend .button-secondary;
|
||||||
|
padding: $s-4 $s-8;
|
||||||
|
border-radius: $br-6;
|
||||||
|
font-size: $fs-14;
|
||||||
|
|
||||||
|
&.token-pill-highlighted {
|
||||||
|
color: var(--button-primary-foreground-color-rest);
|
||||||
|
background: var(--button-primary-background-color-rest);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue