Merge remote-tracking branch 'origin/token-studio-develop' into florian/rename-set-groups

This commit is contained in:
Florian Schroedl 2024-12-10 17:31:38 +01:00
commit 78d743406b
25 changed files with 886 additions and 173 deletions

View file

@ -6,7 +6,6 @@
(ns app.main.data.tokens
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.changes-builder :as pcb]
[app.common.geom.point :as gpt]
@ -15,11 +14,9 @@
[app.main.data.changes :as dch]
[app.main.data.workspace.shapes :as dwsh]
[app.main.refs :as refs]
[app.main.ui.workspace.tokens.token :as wtt]
[app.main.ui.workspace.tokens.token-set :as wtts]
[app.main.ui.workspace.tokens.update :as wtu]
[beicon.v2.core :as rx]
[clojure.data :as data]
[cuerdas.core :as str]
[potok.v2.core :as ptk]))
@ -51,38 +48,6 @@
;; 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 token-from-attributes [token attributes]
(->> (map (fn [attr] [attr (wtt/token-identifier token)]) attributes)
(into {})))
(defn unapply-token-id [shape attributes]
(update shape :applied-tokens d/without-keys attributes))
(defn apply-token-to-attributes [{:keys [shape token attributes]}]
(let [token (token-from-attributes token attributes)]
(toggle-or-apply-token shape token)))
(defn apply-token-to-shape
[{:keys [shape token attributes] :as _props}]
(let [applied-tokens (apply-token-to-attributes {:shape shape
:token token
:attributes attributes})]
(update shape :applied-tokens #(merge % applied-tokens))))
(defn maybe-apply-token-to-shape
"When the passed `:token` is non-nil apply it to the `:applied-tokens` on a shape."
[{:keys [shape token _attributes] :as props}]
(if token
(apply-token-to-shape props)
shape))
(defn get-token-data-from-token-id
[id]
(let [workspace-data (deref refs/workspace-data)]

View file

@ -82,7 +82,7 @@
(assoc-in [:workspace-global :picked-shift?] shift?)))))
(defn transform-fill
[state ids color transform]
[state ids color transform & options]
(let [objects (wsh/lookup-page-objects state)
is-text? #(= :text (:type (get objects %)))
@ -118,8 +118,8 @@
(rx/concat
(rx/of (dwu/start-undo-transaction undo-id))
(rx/from (map #(dwt/update-text-with-function % transform-attrs) text-ids))
(rx/of (dwsh/update-shapes shape-ids transform-attrs))
(rx/from (map #(apply dwt/update-text-with-function % transform-attrs options) text-ids))
(rx/of (dwsh/update-shapes shape-ids transform-attrs options))
(rx/of (dwu/commit-undo-transaction undo-id)))))
(defn swap-attrs [shape attr index new-index]
@ -146,7 +146,7 @@
(rx/of (dwsh/update-shapes shape-ids transform-attrs)))))))
(defn change-fill
[ids color position]
[ids color position & options]
(ptk/reify ::change-fill
ptk/WatchEvent
(watch [_ state _]
@ -155,18 +155,18 @@
(cond-> (not (contains? shape :fills))
(assoc :fills []))
(assoc-in [:fills position] (into {} attrs))))]
(transform-fill state ids color change-fn)))))
(apply transform-fill state ids color change-fn options)))))
(defn change-fill-and-clear
[ids color]
[ids color & options]
(ptk/reify ::change-fill-and-clear
ptk/WatchEvent
(watch [_ state _]
(let [set (fn [shape attrs] (assoc shape :fills [attrs]))]
(transform-fill state ids color set)))))
(apply transform-fill state ids color set options)))))
(defn add-fill
[ids color]
[ids color & options]
(dm/assert!
"expected a valid color struct"
@ -182,10 +182,10 @@
(let [add (fn [shape attrs]
(-> shape
(update :fills #(into [attrs] %))))]
(transform-fill state ids color add)))))
(apply transform-fill state ids color add options)))))
(defn remove-fill
[ids color position]
[ids color position & options]
(dm/assert!
"expected a valid color struct"
@ -203,10 +203,10 @@
(mapv second)))
remove (fn [shape _] (update shape :fills remove-fill-by-index position))]
(transform-fill state ids color remove)))))
(apply transform-fill state ids color remove options)))))
(defn remove-all-fills
[ids color]
[ids color & options]
(dm/assert!
"expected a valid color struct"
@ -220,7 +220,7 @@
ptk/WatchEvent
(watch [_ state _]
(let [remove-all (fn [shape _] (assoc shape :fills []))]
(transform-fill state ids color remove-all)))))
(apply transform-fill state ids color remove-all options)))))
(defn change-hide-fill-on-export
[ids hide-fill-on-export]
@ -237,7 +237,7 @@
(d/merge shape attrs)
shape))))))))
(defn change-stroke
[ids attrs index]
[ids attrs index & options]
(ptk/reify ::change-stroke
ptk/WatchEvent
(watch [_ _ _]
@ -286,7 +286,8 @@
(assoc :strokes [])
:always
(assoc-in [:strokes index] new-attrs))))))))))
(assoc-in [:strokes index] new-attrs))))
options))))))
(defn change-shadow
[ids attrs index]

View file

@ -786,7 +786,6 @@
(rx/map #(reset-component %) (rx/from ids))
(rx/of (dwu/commit-undo-transaction undo-id)))))))
(defn update-component
"Modify the component linked to the shape with the given id, in the
current page, so that all attributes of its shapes are equal to the

View file

@ -465,8 +465,10 @@
([]
(apply-modifiers nil))
([{:keys [modifiers undo-transation? stack-undo? ignore-constraints ignore-snap-pixel undo-group]
:or {undo-transation? true stack-undo? false ignore-constraints false ignore-snap-pixel false}}]
([{:keys [modifiers undo-transation? stack-undo? ignore-constraints
ignore-snap-pixel ignore-touched undo-group]
:or {undo-transation? true stack-undo? false ignore-constraints false
ignore-snap-pixel false ignore-touched false}}]
(ptk/reify ::apply-modifiers
ptk/WatchEvent
(watch [_ state _]
@ -515,6 +517,7 @@
{:reg-objects? true
:stack-undo? stack-undo?
:ignore-tree ignore-tree
:ignore-touched ignore-touched
:undo-group undo-group
;; Attributes that can change in the transform. This way we don't have to check
;; all the attributes

View file

@ -260,13 +260,13 @@
(rx/of (with-meta event (meta it)))))))))
(defn update-layout
[ids changes]
[ids changes & options]
(ptk/reify ::update-layout
ptk/WatchEvent
(watch [_ _ _]
(let [undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
(dwsh/update-shapes ids (d/patch-object changes))
(dwsh/update-shapes ids (d/patch-object changes) options)
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id))))))
@ -516,7 +516,7 @@
(assoc :layout-item-v-sizing :fix))))
(defn update-layout-child
[ids changes]
[ids changes & options]
(ptk/reify ::update-layout-child
ptk/WatchEvent
(watch [_ state _]
@ -525,8 +525,8 @@
parent-ids (->> ids (map #(cfh/get-parent-id objects %)))
undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
(dwsh/update-shapes ids (d/patch-object changes))
(dwsh/update-shapes children-ids (partial fix-child-sizing objects changes))
(dwsh/update-shapes ids (d/patch-object changes) options)
(dwsh/update-shapes children-ids (partial fix-child-sizing objects changes) options)
(dwsh/update-shapes
parent-ids
(fn [parent objects]
@ -534,7 +534,7 @@
(fix-parent-sizing objects (set ids) changes)
(cond-> (ctl/grid-layout? parent)
(ctl/assign-cells objects))))
{:with-objects? true})
(merge options {:with-objects? true}))
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id))))))

View file

@ -432,7 +432,7 @@
(txt/transform-nodes (some-fn txt/is-text-node? txt/is-paragraph-node?) migrate-node content))
(defn update-text-with-function
[id update-node-fn]
[id update-node-fn & options]
(ptk/reify ::update-text-with-function
ptk/UpdateEvent
(update [_ state]
@ -464,7 +464,7 @@
(-> shape
(dissoc :fills)
(d/update-when :content update-content)))]
(rx/of (dwsh/update-shapes shape-ids update-shape)))))
(rx/of (dwsh/update-shapes shape-ids update-shape options)))))
ptk/EffectEvent
(effect [_ state _]

View file

@ -301,7 +301,7 @@
(defn update-dimensions
"Change size of shapes, from the sideber options form.
Will ignore pixel snap used in the options side panel"
[ids attr value]
[ids attr value & options]
(dm/assert! (number? value))
(dm/assert!
"expected valid coll of uuids"
@ -324,7 +324,7 @@
ptk/WatchEvent
(watch [_ _ _]
(rx/of (dwm/apply-modifiers)))))
(rx/of (dwm/apply-modifiers options)))))
(defn change-orientation
"Change orientation of shapes, from the sidebar options form.
@ -402,7 +402,7 @@
"Rotate shapes a fixed angle, from a keyboard action."
([ids rotation]
(increase-rotation ids rotation nil))
([ids rotation params]
([ids rotation params & options]
(ptk/reify ::increase-rotation
ptk/WatchEvent
(watch [_ state _]
@ -411,7 +411,7 @@
shapes (->> ids (map #(get objects %)))]
(rx/concat
(rx/of (dwm/set-delta-rotation-modifiers rotation shapes params))
(rx/of (dwm/apply-modifiers))))))))
(rx/of (dwm/apply-modifiers options))))))))
;; -- Move ----------------------------------------------------------

View file

@ -502,6 +502,14 @@
(def workspace-active-theme-paths
(l/derived (d/nilf ctob/get-active-theme-paths) tokens-lib))
(defn token-sets-at-path-all-active?
[prefixed-path]
(l/derived
(fn [lib]
(when lib
(ctob/sets-at-path-all-active? lib prefixed-path)))
tokens-lib))
(def workspace-active-theme-paths-no-hidden
(l/derived #(disj % ctob/hidden-token-theme-path) workspace-active-theme-paths))

View file

@ -13,9 +13,9 @@
[app.common.types.shape :as cts]
[app.common.types.shape.layout :as ctl]
[app.common.types.shape.radius :as ctsr]
[app.common.types.token :as cto]
[app.common.types.tokens-lib :as ctob]
[app.main.constants :refer [size-presets]]
[app.main.data.tokens :as dt]
[app.main.data.workspace :as udw]
[app.main.data.workspace.interactions :as dwi]
[app.main.data.workspace.shapes :as dwsh]
@ -342,7 +342,7 @@
(let [token-value (wtc/maybe-resolve-token-value token)]
(st/emit!
(change-radius (fn [shape]
(-> (dt/unapply-token-id shape (wtty/token-attributes :border-radius))
(-> (cto/unapply-token-id shape (wtty/token-attributes :border-radius))
(ctsr/set-radius-1 token-value))))))))
on-radius-1-change
@ -352,9 +352,9 @@
(let [token-value (wtc/maybe-resolve-token-value value)]
(st/emit!
(change-radius (fn [shape]
(-> (dt/maybe-apply-token-to-shape {:token (when token-value value)
:shape shape
:attributes (wtty/token-attributes :border-radius)})
(-> (cto/maybe-apply-token-to-shape {:token (when token-value value)
:shape shape
:attributes (wtty/token-attributes :border-radius)})
(ctsr/set-radius-1 (or token-value value)))))))))
on-radius-multi-change

View file

@ -95,20 +95,9 @@
(when (ctsr/has-radius? shape)
(ctsr/set-radius-1 shape value)))
{:reg-objects? true
:ignore-touched true
:attrs ctt/border-radius-keys}))
(defn update-opacity [value shape-ids]
(when (<= 0 value 1)
(dwsh/update-shapes shape-ids #(assoc % :opacity value))))
(defn update-rotation [value shape-ids]
(ptk/reify ::update-shape-rotation
ptk/WatchEvent
(watch [_ _ _]
(rx/of
(udw/trigger-bounding-box-cloaking shape-ids)
(udw/increase-rotation shape-ids value)))))
(defn update-shape-radius-single-corner [value shape-ids attributes]
(dwsh/update-shapes shape-ids
(fn [shape]
@ -117,8 +106,23 @@
(:rx shape) (ctsr/switch-to-radius-4)
:always (ctsr/set-radius-4 (first attributes) value))))
{:reg-objects? true
:ignore-touched true
:attrs [:rx :ry :r1 :r2 :r3 :r4]}))
(defn update-opacity [value shape-ids]
(when (<= 0 value 1)
(dwsh/update-shapes shape-ids
#(assoc % :opacity value)
{:ignore-touched true})))
(defn update-rotation [value shape-ids]
(ptk/reify ::update-shape-rotation
ptk/WatchEvent
(watch [_ _ _]
(rx/of
(udw/trigger-bounding-box-cloaking shape-ids)
(udw/increase-rotation shape-ids value nil :ignore-touched true)))))
(defn update-stroke-width
[value shape-ids]
(dwsh/update-shapes shape-ids
@ -126,6 +130,7 @@
(when (seq (:strokes shape))
(assoc-in shape [:strokes 0 :stroke-width] value)))
{:reg-objects? true
:ignore-touched true
:attrs [:strokes]}))
(defn update-color [f value shape-ids]
@ -133,7 +138,7 @@
(tinycolor/valid-color)
(tinycolor/->hex)
(str "#"))]
(f shape-ids {:color color} 0)))
(apply f shape-ids {:color color} 0 [:ignore-touched true])))
(defn update-fill
[value shape-ids]
@ -156,8 +161,8 @@
ptk/WatchEvent
(watch [_ _ _]
(rx/of
(when (:width attributes) (dwt/update-dimensions shape-ids :width value))
(when (:height attributes) (dwt/update-dimensions shape-ids :height value))))))
(when (:width attributes) (dwt/update-dimensions shape-ids :width value :ignore-touched true))
(when (:height attributes) (dwt/update-dimensions shape-ids :height value :ignore-touched true))))))
(defn- attributes->layout-gap [attributes value]
(let [layout-gap (-> (set/intersection attributes #{:column-gap :row-gap})
@ -165,7 +170,9 @@
{:layout-gap layout-gap}))
(defn update-layout-padding [value shape-ids attrs]
(dwsl/update-layout shape-ids {:layout-padding (zipmap attrs (repeat value))}))
(dwsl/update-layout shape-ids
{:layout-padding (zipmap attrs (repeat value))}
:ignore-touched true))
(defn update-layout-spacing [value shape-ids attributes]
(ptk/reify ::update-layout-spacing
@ -177,7 +184,9 @@
(map :id)))
layout-attributes (attributes->layout-gap attributes value)]
(rx/of
(dwsl/update-layout layout-shape-ids layout-attributes))))))
(dwsl/update-layout layout-shape-ids
layout-attributes
:ignore-touched true))))))
(defn update-shape-position [value shape-ids attributes]
(ptk/reify ::update-shape-position
@ -195,4 +204,4 @@
:layout-item-max-w value
:layout-item-max-h value}
(select-keys attributes))]
(dwsl/update-layout-child shape-ids props)))))
(dwsl/update-layout-child shape-ids props :ignore-touched true)))))

View file

@ -254,41 +254,41 @@
[{:keys [state set-state]}]
(let [{:keys [theme-path]} @state
[_ theme-group theme-name] theme-path
ordered-token-sets (mf/deref refs/workspace-ordered-token-sets)
token-sets (mf/deref refs/workspace-token-sets-tree)
theme (mf/deref (refs/workspace-token-theme theme-group theme-name))
theme-state (mf/use-state theme)
lib (-> (ctob/make-tokens-lib)
(ctob/add-theme @theme-state)
(ctob/add-sets ordered-token-sets)
(ctob/activate-theme (:group @theme-state) (:name @theme-state)))
;; Form / Modal handlers
on-back #(set-state (constantly {:type :themes-overview}))
on-submit #(st/emit! (wdt/update-token-theme [(:group theme) (:name theme)] %))
{:keys [dropdown-open? _on-open-dropdown on-close-dropdown on-toggle-dropdown]} (wtco/use-dropdown-open-state)
theme-state (mf/use-state theme)
disabled? (-> (:name @theme-state)
(str/trim)
(str/empty?))
token-set-active? (mf/use-callback
(mf/deps theme-state)
(fn [set-name]
(get-in @theme-state [:sets set-name])))
on-toggle-token-set (mf/use-callback
(mf/deps theme-state)
(fn [set-name]
(swap! theme-state #(ctob/toggle-set % set-name))))
on-click-token-set (mf/use-callback
(mf/deps on-toggle-token-set)
(fn [prefixed-set-path-str]
(let [set-name (ctob/prefixed-set-path-string->set-name-string prefixed-set-path-str)]
(on-toggle-token-set set-name))))
on-change-field (fn [field value]
(swap! theme-state #(assoc % field value)))
on-save-form (mf/use-callback
(mf/deps theme-state on-submit)
(fn [e]
(dom/prevent-default e)
(let [theme (-> @theme-state
(update :name str/trim)
(update :group str/trim)
(update :description str/trim))]
(when-not (str/empty? (:name theme))
(on-submit theme)))
(on-back)))
on-change-field
(mf/use-fn
(fn [field value]
(swap! theme-state #(assoc % field value))))
on-save-form
(mf/use-callback
(mf/deps theme-state on-submit)
(fn [e]
(dom/prevent-default e)
(let [theme (-> @theme-state
(update :name str/trim)
(update :group str/trim)
(update :description str/trim))]
(when-not (str/empty? (:name theme))
(on-submit theme)))
(on-back)))
close-modal
(mf/use-fn
(fn [e]
@ -300,7 +300,33 @@
(mf/deps theme on-back)
(fn []
(st/emit! (wdt/delete-token-theme (:group theme) (:name theme)))
(on-back)))]
(on-back)))
;; Sets tree handlers
token-set-group-active?
(mf/use-callback
(mf/deps theme-state)
(fn [prefixed-path]
(ctob/sets-at-path-all-active? lib prefixed-path)))
token-set-active?
(mf/use-callback
(mf/deps theme-state)
(fn [set-name]
(get-in @theme-state [:sets set-name])))
on-toggle-token-set
(mf/use-callback
(mf/deps theme-state)
(fn [set-name]
(swap! theme-state #(ctob/toggle-set % set-name))))
on-click-token-set
(mf/use-callback
(mf/deps on-toggle-token-set)
(fn [prefixed-set-path-str]
(let [set-name (ctob/prefixed-set-path-string->set-name-string prefixed-set-path-str)]
(on-toggle-token-set set-name))))]
[:div {:class (stl/css :themes-modal-wrapper)}
[:> heading* {:level 2 :typography "headline-medium" :class (stl/css :themes-modal-title)}
@ -327,6 +353,7 @@
{:token-sets token-sets
:token-set-selected? (constantly false)
:token-set-active? token-set-active?
:token-set-group-active? token-set-group-active?
:on-select on-click-token-set
:on-toggle-token-set on-toggle-token-set
:origin "theme-modal"

View file

@ -7,6 +7,7 @@
(ns app.main.ui.workspace.tokens.sets
(:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
[app.common.types.tokens-lib :as ctob]
[app.main.data.tokens :as wdt]
[app.main.refs :as refs]
@ -68,9 +69,28 @@
:auto-focus true
:default-value default-value}]))
(mf/defc checkbox
[{:keys [checked aria-label on-click]}]
(let [all? (true? checked)
mixed? (= checked "mixed")
checked? (or all? mixed?)]
[:div {:role "checkbox"
:aria-checked (dm/str checked)
:tabindex 0
:class (stl/css-case :checkbox-style true
:checkbox-checked-style checked?)
:on-click on-click}
(when checked?
[:> icon*
{:aria-label aria-label
:class (stl/css :check-icon)
:size "s"
:id (if mixed? ic/remove ic/tick)}])]))
(mf/defc sets-tree-set-group
[{:keys [label tree-depth tree-path selected? collapsed? editing? on-edit on-edit-reset on-edit-submit]}]
[{:keys [label tree-depth tree-path active? selected? collapsed? editing? on-edit on-edit-reset on-edit-submit]}]
(let [editing?' (editing? tree-path)
active?' (active? tree-path)
on-context-menu
(mf/use-fn
(mf/deps editing? tree-path)
@ -114,9 +134,16 @@
:on-cancel on-edit-reset
:on-create on-edit-reset
:on-submit on-edit-submit'}]
[:div {:class (stl/css :set-name)
:on-double-click on-double-click}
label])]))
[:*
[:div {:class (stl/css :set-name)
:on-double-click on-double-click}
label]
[:& checkbox
{:checked (case active?'
:all true
:partial "mixed"
:none false)
:arial-label (tr "workspace.token.select-set")}]])]))
(mf/defc sets-tree-set
[{:keys [set label tree-depth tree-path selected? on-select active? on-toggle editing? on-edit on-edit-reset on-edit-submit]}]
@ -173,18 +200,14 @@
[:div {:class (stl/css :set-name)
:on-double-click on-double-click}
label]
[:button {:type "button"
:on-click on-checkbox-click
:class (stl/css-case :checkbox-style true
:checkbox-checked-style active?')}
(when active?'
[:> icon* {:aria-label (tr "workspace.token.select-set")
:class (stl/css :check-icon)
:size "s"
:id ic/tick}])]])]))
[:& checkbox
{:on-click on-checkbox-click
:arial-label (tr "workspace.token.select-set")
:checked active?'}]])]))
(mf/defc sets-tree
[{:keys [active?
group-active?
editing?
on-edit
on-edit-reset
@ -227,6 +250,7 @@
set-group?
[:& sets-tree-set-group
{:selected? (selected? tree-path)
:active? group-active?
:on-select on-select
:label set-fname
:collapsed? collapsed?
@ -249,6 +273,7 @@
:selected? selected?
:on-toggle on-toggle
:active? active?
:group-active? group-active?
:editing? editing?
:on-edit on-edit
:on-edit-reset on-edit-reset
@ -261,6 +286,7 @@
on-update-token-set-group
token-set-selected?
token-set-active?
token-set-group-active?
on-create-token-set
on-toggle-token-set
origin
@ -268,10 +294,9 @@
context]
:as _props}]
(let [{:keys [editing? new? on-edit on-reset] :as ctx} (or context (sets-context/use-context))]
[:ul {:class (stl/css :sets-list)}
(if (and
(= origin "theme-modal")
(empty? token-sets))
[:fieldset {:class (stl/css :sets-list)}
(if (and (= origin "theme-modal")
(empty? token-sets))
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message-sets)}
(tr "workspace.token.no-sets-create")]
(if (and (= origin "theme-modal")
@ -284,6 +309,7 @@
:selected? token-set-selected?
:on-select on-select
:active? token-set-active?
:group-active? token-set-group-active?
:on-toggle on-toggle-token-set
:editing? editing?
:on-edit on-edit
@ -314,11 +340,15 @@
token-set-active? (mf/use-fn
(mf/deps active-token-set-names)
(fn [set-name]
(get active-token-set-names set-name)))]
(get active-token-set-names set-name)))
token-set-group-active? (mf/use-fn
(fn [prefixed-path]
@(refs/token-sets-at-path-all-active? prefixed-path)))]
[:& controlled-sets-list
{:token-sets token-sets
:token-set-selected? token-set-selected?
:token-set-active? token-set-active?
:token-set-group-active? token-set-group-active?
:on-select on-select-token-set-click
:origin "set-panel"
:on-toggle-token-set on-toggle-token-set-click

View file

@ -2,8 +2,8 @@
(:require
[app.common.types.token :as ctt]
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
[app.main.refs :as refs]
[app.main.ui.workspace.tokens.changes :as wtch]
[app.main.ui.workspace.tokens.style-dictionary :as wtsd]
[app.main.ui.workspace.tokens.token-set :as wtts]
@ -112,8 +112,8 @@
update-infos)))
shapes-update-info))
(defn update-tokens [resolved-tokens]
(->> @refs/workspace-page-objects
(defn update-tokens [state resolved-tokens]
(->> (wsh/lookup-page-objects state)
(collect-shapes-update-info resolved-tokens)
(actionize-shapes-update-info)))
@ -131,5 +131,5 @@
(let [undo-id (js/Symbol)]
(rx/concat
(rx/of (dwu/start-undo-transaction undo-id))
(update-tokens sd-tokens)
(update-tokens state sd-tokens)
(rx/of (dwu/commit-undo-transaction undo-id))))))))))

View file

@ -57,7 +57,7 @@
(fn [cause]
(js/console.log "[error]:" cause))
(fn [_]
(js/console.log "[complete]"))))
#_(js/console.debug "[complete]"))))
(doseq [event events]
(ptk/emit! store event))

View file

@ -0,0 +1,397 @@
;; 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 frontend-tests.logic.components-and-tokens
(:require
[app.common.geom.point :as geom]
[app.common.math :as mth]
[app.common.test-helpers.components :as cthc]
[app.common.test-helpers.compositions :as ctho]
[app.common.test-helpers.files :as cthf]
[app.common.test-helpers.ids-map :as cthi]
[app.common.test-helpers.shapes :as cths]
[app.common.test-helpers.tokens :as ctht]
[app.common.types.tokens-lib :as ctob]
[app.main.data.tokens :as dt]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.ui.workspace.tokens.changes :as wtch]
[app.main.ui.workspace.tokens.update :as wtu]
[cljs.test :as t :include-macros true]
[frontend-tests.helpers.pages :as thp]
[frontend-tests.helpers.state :as ths]
[frontend-tests.tokens.helpers.state :as tohs]
[frontend-tests.tokens.helpers.tokens :as toht]))
(t/use-fixtures :each
{:before thp/reset-idmap!})
(defn- setup-base-file
[]
(-> (cthf/sample-file :file1)
(ctht/add-tokens-lib)
(ctht/update-tokens-lib #(-> %
(ctob/add-set (ctob/make-token-set :name "test-token-set"))
(ctob/add-theme (ctob/make-token-theme :name "test-theme"
:sets #{"test-token-set"}))
(ctob/set-active-themes #{"/test-theme"})
(ctob/add-token-in-set "test-token-set"
(ctob/make-token :name "test-token-1"
:type :border-radius
:value 25))
(ctob/add-token-in-set "test-token-set"
(ctob/make-token :name "test-token-2"
:type :border-radius
:value 50))
(ctob/add-token-in-set "test-token-set"
(ctob/make-token :name "test-token-3"
:type :border-radius
:value 75))))
(ctho/add-frame :frame1)
(ctht/apply-token-to-shape :frame1 "test-token-1" [:rx :ry] [:rx :ry] 25)))
(defn- setup-file-with-main
[]
(-> (setup-base-file)
(cthc/make-component :component1 :frame1)))
(defn- setup-file-with-copy
[]
(-> (setup-file-with-main)
(cthc/instantiate-component :component1 :c-frame1)))
(t/deftest create-component-with-token
(t/async
done
(let [;; ==== Setup
file (setup-base-file)
store (ths/setup-store file)
;; ==== Action
events
[(dws/select-shape (cthi/id :frame1))
(dwl/add-component)]]
(ths/run-store
store done events
(fn [new-state]
(let [;; ==== Get
file' (ths/get-file-from-store new-state)
frame1' (cths/get-shape file' :frame1)
tokens-frame1' (:applied-tokens frame1')]
;; ==== Check
(t/is (= (count tokens-frame1') 2))
(t/is (= (get tokens-frame1' :rx) "test-token-1"))
(t/is (= (get tokens-frame1' :ry) "test-token-1"))
(t/is (= (get frame1' :rx) 25))
(t/is (= (get frame1' :ry) 25))))))))
(t/deftest create-copy-with-token
(t/async
done
(let [;; ==== Setup
file (setup-file-with-main)
store (ths/setup-store file)
;; ==== Action
events
[(dwl/instantiate-component (:id file)
(cthi/id :component1)
(geom/point 0 0))]]
(ths/run-store
store done events
(fn [new-state]
(let [;; ==== Get
selected (wsh/lookup-selected new-state)
c-frame1' (wsh/lookup-shape new-state (first selected))
tokens-frame1' (:applied-tokens c-frame1')]
;; ==== Check
(t/is (= (count tokens-frame1') 2))
(t/is (= (get tokens-frame1' :rx) "test-token-1"))
(t/is (= (get tokens-frame1' :ry) "test-token-1"))
(t/is (= (get c-frame1' :rx) 25))
(t/is (= (get c-frame1' :ry) 25))))))))
(t/deftest change-token-in-main
(t/async
done
(let [;; ==== Setup
file (setup-file-with-copy)
store (ths/setup-store file)
;; ==== Action
events [(wtch/apply-token {:shape-ids [(cthi/id :frame1)]
:attributes #{:rx :ry}
:token (toht/get-token file "test-token-2")
:on-update-shape wtch/update-shape-radius-all})]
step2 (fn [_]
(let [events2 [(dwl/sync-file (:id file) (:id file))]]
(ths/run-store
store done events2
(fn [new-state]
(let [;; ==== Get
file' (ths/get-file-from-store new-state)
c-frame1' (cths/get-shape file' :c-frame1)
tokens-frame1' (:applied-tokens c-frame1')]
;; ==== Check
(t/is (= (count tokens-frame1') 2))
(t/is (= (get tokens-frame1' :rx) "test-token-2"))
(t/is (= (get tokens-frame1' :ry) "test-token-2"))
(t/is (= (get c-frame1' :rx) 50))
(t/is (= (get c-frame1' :ry) 50)))))))]
(tohs/run-store-async
store step2 events identity))))
(t/deftest remove-token-in-main
(t/async
done
(let [;; ==== Setup
file (setup-file-with-copy)
store (ths/setup-store file)
;; ==== Action
events [(wtch/unapply-token {:shape-ids [(cthi/id :frame1)]
:attributes #{:rx :ry}
:token (toht/get-token file "test-token-1")})]
step2 (fn [_]
(let [events2 [(dwl/sync-file (:id file) (:id file))]]
(ths/run-store
store done events2
(fn [new-state]
(let [;; ==== Get
file' (ths/get-file-from-store new-state)
c-frame1' (cths/get-shape file' :c-frame1)
tokens-frame1' (:applied-tokens c-frame1')]
;; ==== Check
(t/is (= (count tokens-frame1') 0))
(t/is (= (get c-frame1' :rx) 25))
(t/is (= (get c-frame1' :ry) 25)))))))]
(tohs/run-store-async
store step2 events identity))))
(t/deftest modify-token
(t/async
done
(let [;; ==== Setup
file (setup-file-with-copy)
store (ths/setup-store file)
;; ==== Action
events [(dt/update-create-token {:token (ctob/make-token :name "test-token-1"
:type :border-radius
:value 66)
:prev-token-name "test-token-1"})]
step2 (fn [_]
(let [events2 [(wtu/update-workspace-tokens)
(dwl/sync-file (:id file) (:id file))]]
(tohs/run-store-async
store done events2
(fn [new-state]
(let [;; ==== Get
file' (ths/get-file-from-store new-state)
c-frame1' (cths/get-shape file' :c-frame1)
tokens-frame1' (:applied-tokens c-frame1')]
;; ==== Check
(t/is (= (count tokens-frame1') 2))
(t/is (= (get tokens-frame1' :rx) "test-token-1"))
(t/is (= (get tokens-frame1' :ry) "test-token-1"))
(t/is (= (get c-frame1' :rx) 66))
(t/is (= (get c-frame1' :ry) 66)))))))]
(tohs/run-store-async
store step2 events identity))))
(t/deftest change-token-in-copy-then-change-main
(t/async
done
(let [;; ==== Setup
file (setup-file-with-copy)
store (ths/setup-store file)
;; ==== Action
events [(wtch/apply-token {:shape-ids [(cthi/id :c-frame1)]
:attributes #{:rx :ry}
:token (toht/get-token file "test-token-2")
:on-update-shape wtch/update-shape-radius-all})
(wtch/apply-token {:shape-ids [(cthi/id :frame1)]
:attributes #{:rx :ry}
:token (toht/get-token file "test-token-3")
:on-update-shape wtch/update-shape-radius-all})]
step2 (fn [_]
(let [events2 [(dwl/sync-file (:id file) (:id file))]]
(ths/run-store
store done events2
(fn [new-state]
(let [;; ==== Get
file' (ths/get-file-from-store new-state)
c-frame1' (cths/get-shape file' :c-frame1)
tokens-frame1' (:applied-tokens c-frame1')]
;; ==== Check
(t/is (= (count tokens-frame1') 2))
(t/is (= (get tokens-frame1' :rx) "test-token-2"))
(t/is (= (get tokens-frame1' :ry) "test-token-2"))
(t/is (= (get c-frame1' :rx) 50))
(t/is (= (get c-frame1' :ry) 50)))))))]
(tohs/run-store-async
store step2 events identity))))
(t/deftest remove-token-in-copy-then-change-main
(t/async
done
(let [;; ==== Setup
file (setup-file-with-copy)
store (ths/setup-store file)
;; ==== Action
events [(wtch/unapply-token {:shape-ids [(cthi/id :c-frame1)]
:attributes #{:rx :ry}
:token (toht/get-token file "test-token-1")})
(wtch/apply-token {:shape-ids [(cthi/id :frame1)]
:attributes #{:rx :ry}
:token (toht/get-token file "test-token-3")
:on-update-shape wtch/update-shape-radius-all})]
step2 (fn [_]
(let [events2 [(dwl/sync-file (:id file) (:id file))]]
(ths/run-store
store done events2
(fn [new-state]
(let [;; ==== Get
file' (ths/get-file-from-store new-state)
c-frame1' (cths/get-shape file' :c-frame1)
tokens-frame1' (:applied-tokens c-frame1')]
;; ==== Check
(t/is (= (count tokens-frame1') 0))
(t/is (= (get c-frame1' :rx) 25))
(t/is (= (get c-frame1' :ry) 25)))))))]
(tohs/run-store-async
store step2 events identity))))
(t/deftest modify-token-all-types
(t/async
done
(let [;; ==== Setup
file (-> (cthf/sample-file :file1)
(ctht/add-tokens-lib)
(ctht/update-tokens-lib #(-> %
(ctob/add-set (ctob/make-token-set :name "test-token-set"))
(ctob/add-theme (ctob/make-token-theme :name "test-theme"
:sets #{"test-token-set"}))
(ctob/set-active-themes #{"/test-theme"})
(ctob/add-token-in-set "token-radius"
(ctob/make-token :name "token-radius"
:type :border-radius
:value 10))
(ctob/add-token-in-set "token-rotation"
(ctob/make-token :name "token-rotation"
:type :rotation
:value 30))
(ctob/add-token-in-set "token-opacity"
(ctob/make-token :name "token-opacity"
:type :opacity
:value 0.7))
(ctob/add-token-in-set "token-stroke-width"
(ctob/make-token :name "token-stroke-width"
:type :stroke-width
:value 2))
(ctob/add-token-in-set "token-color"
(ctob/make-token :name "token-color"
:type :color
:value "#00ff00"))
(ctob/add-token-in-set "token-dimensions"
(ctob/make-token :name "token-dimensions"
:type :dimensions
:value 100))))
(ctho/add-frame :frame1)
(ctht/apply-token-to-shape :frame1 "token-radius" [:rx :ry] [:rx :ry] 10)
(ctht/apply-token-to-shape :frame1 "token-rotation" [:rotation] [:rotation] 30)
(ctht/apply-token-to-shape :frame1 "token-opacity" [:opacity] [:opacity] 0.7)
(ctht/apply-token-to-shape :frame1 "token-stroke-width" [:stroke-width] [:stroke-width] 2)
(ctht/apply-token-to-shape :frame1 "token-color" [:stroke-color] [:stroke-color] "#00ff00")
(ctht/apply-token-to-shape :frame1 "token-color" [:fill] [:fill] "#00ff00")
(ctht/apply-token-to-shape :frame1 "token-dimensions" [:width :height] [:width :height] 100)
(cthc/make-component :component1 :frame1)
(cthc/instantiate-component :component1 :c-frame1))
store (ths/setup-store file)
;; ==== Action
events [(dt/update-create-token {:token (ctob/make-token :name "token-radius"
:type :border-radius
:value 30)
:prev-token-name "token-radius"})
(dt/update-create-token {:token (ctob/make-token :name "token-rotation"
:type :rotation
:value 45)
:prev-token-name "token-rotation"})
(dt/update-create-token {:token (ctob/make-token :name "token-opacity"
:type :opacity
:value 0.9)
:prev-token-name "token-opacity"})
(dt/update-create-token {:token (ctob/make-token :name "token-stroke-width"
:type :stroke-width
:value 8)
:prev-token-name "token-stroke-width"})
(dt/update-create-token {:token (ctob/make-token :name "token-color"
:type :color
:value "#ff0000")
:prev-token-name "token-color"})
(dt/update-create-token {:token (ctob/make-token :name "token-dimensions"
:type :dimensions
:value 200)
:prev-token-name "token-dimensions"})]
step2 (fn [_]
(let [events2 [(wtu/update-workspace-tokens)
(dwl/sync-file (:id file) (:id file))]]
(tohs/run-store-async
store done events2
(fn [new-state]
(let [;; ==== Get
file' (ths/get-file-from-store new-state)
c-frame1' (cths/get-shape file' :c-frame1)
tokens-frame1' (:applied-tokens c-frame1')]
;; ==== Check
(t/is (= (count tokens-frame1') 9))
(t/is (= (get tokens-frame1' :rx) "token-radius"))
(t/is (= (get tokens-frame1' :ry) "token-radius"))
(t/is (= (get tokens-frame1' :rotation) "token-rotation"))
(t/is (= (get tokens-frame1' :opacity) "token-opacity"))
(t/is (= (get tokens-frame1' :stroke-width) "token-stroke-width"))
(t/is (= (get tokens-frame1' :stroke-color) "token-color"))
(t/is (= (get tokens-frame1' :fill) "token-color"))
(t/is (= (get tokens-frame1' :width) "token-dimensions"))
(t/is (= (get tokens-frame1' :height) "token-dimensions"))
(t/is (= (get c-frame1' :rx) 30))
(t/is (= (get c-frame1' :ry) 30))
(t/is (= (get c-frame1' :rotation) 45))
(t/is (= (get c-frame1' :opacity) 0.9))
(t/is (= (get-in c-frame1' [:strokes 0 :stroke-width]) 8))
(t/is (= (get-in c-frame1' [:strokes 0 :stroke-color]) "#ff0000"))
(t/is (= (get-in c-frame1' [:fills 0 :fill-color]) "#ff0000"))
(t/is (mth/close? (get c-frame1' :width) 200))
(t/is (mth/close? (get c-frame1' :height) 200))
(t/is (empty? (:touched c-frame1'))))))))]
(tohs/run-store-async
store step2 events identity))))

View file

@ -4,6 +4,7 @@
[frontend-tests.basic-shapes-test]
[frontend-tests.helpers-shapes-test]
[frontend-tests.logic.comp-remove-swap-slots-test]
[frontend-tests.logic.components-and-tokens]
[frontend-tests.logic.copying-and-duplicating-test]
[frontend-tests.logic.frame-guides-test]
[frontend-tests.logic.groups-test]
@ -28,6 +29,7 @@
(t/run-tests
'frontend-tests.helpers-shapes-test
'frontend-tests.logic.comp-remove-swap-slots-test
'frontend-tests.logic.components-and-tokens
'frontend-tests.logic.copying-and-duplicating-test
'frontend-tests.logic.frame-guides-test
'frontend-tests.logic.groups-test