mirror of
https://github.com/penpot/penpot.git
synced 2026-02-12 22:53:02 +00:00
✨ Add variants to plugins API
This commit is contained in:
5975
backend/hs_err_pid595.log
Normal file
5975
backend/hs_err_pid595.log
Normal file
File diff suppressed because one or more lines are too long
10795
backend/replay_pid595.log
Normal file
10795
backend/replay_pid595.log
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,16 +10,23 @@
|
||||
[app.common.types.components-list :as ctcl]
|
||||
[app.common.types.variant :as ctv]))
|
||||
|
||||
|
||||
(defn find-variant-components
|
||||
"Find a list of the components thet belongs to this variant-id"
|
||||
[data objects variant-id]
|
||||
;; We can't simply filter components, because we need to maintain the order
|
||||
(->> (dm/get-in objects [variant-id :shapes])
|
||||
(map #(dm/get-in objects [% :component-id]))
|
||||
(map #(ctcl/get-component data % true))
|
||||
reverse))
|
||||
|
||||
([data variant-id]
|
||||
(let [page-id (->> data
|
||||
:components
|
||||
vals
|
||||
(filter #(= (:variant-id %) variant-id))
|
||||
first
|
||||
:main-instance-page)
|
||||
objects (dm/get-in data [:pages-index page-id :objects])]
|
||||
(find-variant-components data objects variant-id)))
|
||||
([data objects variant-id]
|
||||
;; We can't simply filter components, because we need to maintain the order
|
||||
(->> (dm/get-in objects [variant-id :shapes])
|
||||
(map #(dm/get-in objects [% :component-id]))
|
||||
(map #(ctcl/get-component data % true))
|
||||
reverse)))
|
||||
|
||||
(defn extract-properties-names
|
||||
[shape data]
|
||||
@@ -28,7 +35,6 @@
|
||||
:variant-properties
|
||||
(map :name)))
|
||||
|
||||
|
||||
(defn extract-properties-values
|
||||
"Get a map of properties associated to their possible values"
|
||||
[data objects variant-id]
|
||||
@@ -50,7 +56,6 @@
|
||||
(get :objects))]
|
||||
(dm/get-in objects [variant-id :shapes]))))
|
||||
|
||||
|
||||
(defn is-secondary-variant?
|
||||
[component data]
|
||||
(let [shapes (get-variant-mains component data)]
|
||||
|
||||
@@ -42,18 +42,21 @@
|
||||
[changes variant-id pos]
|
||||
(let [data (pcb/get-library-data changes)
|
||||
objects (pcb/get-objects changes)
|
||||
related-components (cfv/find-variant-components data objects variant-id)]
|
||||
(reduce (fn [changes component]
|
||||
(let [props (:variant-properties component)
|
||||
props (d/remove-at-index props pos)
|
||||
main-id (:main-instance-id component)
|
||||
name (ctv/properties-to-name props)]
|
||||
(-> changes
|
||||
(pcb/update-component (:id component) #(assoc % :variant-properties props)
|
||||
{:apply-changes-local-library? true})
|
||||
(pcb/update-shapes [main-id] #(assoc % :variant-name name)))))
|
||||
changes
|
||||
related-components)))
|
||||
related-components (cfv/find-variant-components data objects variant-id)
|
||||
props (-> related-components first :variant-properties)]
|
||||
(if (and (seq props) (<= 0 pos) (< pos (count props)))
|
||||
(reduce (fn [changes component]
|
||||
(let [props (:variant-properties component)
|
||||
props (d/remove-at-index props pos)
|
||||
main-id (:main-instance-id component)
|
||||
name (ctv/properties-to-name props)]
|
||||
(-> changes
|
||||
(pcb/update-component (:id component) #(assoc % :variant-properties props)
|
||||
{:apply-changes-local-library? true})
|
||||
(pcb/update-shapes [main-id] #(assoc % :variant-name name)))))
|
||||
changes
|
||||
related-components)
|
||||
changes)))
|
||||
|
||||
|
||||
(defn generate-update-property-value
|
||||
|
||||
@@ -670,7 +670,8 @@
|
||||
(ctkl/components-seq current-lib-data))
|
||||
(update-vals count)))
|
||||
|
||||
components (->> (get-in libraries [current-library-id :data :components])
|
||||
components (->> current-lib-data
|
||||
:components
|
||||
vals
|
||||
(remove #(true? (:deleted %)))
|
||||
(remove #(cfv/is-secondary-variant? % current-lib-data))
|
||||
|
||||
@@ -5,16 +5,18 @@
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.plugins.library
|
||||
"RPC for plugins runtime."
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.variant :as cfv]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.types.color :as clr]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.typography :as ctt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.plugins :as dp]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
@@ -612,6 +614,85 @@
|
||||
(let [typography (u/locate-library-typography file-id id)]
|
||||
(apply array (keys (dm/get-in typography [:plugin-data (keyword "shared" namespace)]))))))))
|
||||
|
||||
(defn get-variant-components
|
||||
[file-id variant-id]
|
||||
(cfv/find-variant-components (-> file-id u/locate-file :data) variant-id))
|
||||
|
||||
(declare lib-component-proxy)
|
||||
|
||||
(defn variant-proxy
|
||||
[plugin-id file-id id]
|
||||
|
||||
(obj/reify {:name "VariantProxy"}
|
||||
:$plugin {:enumerable false :get (constantly plugin-id)}
|
||||
:$file {:enumerable false :get (constantly file-id)}
|
||||
:$id {:enumerable false :get (constantly id)}
|
||||
|
||||
:id {:get (fn [_] (dm/str id))}
|
||||
:libraryId {:get (fn [_] (dm/str file-id))}
|
||||
|
||||
:properties
|
||||
{:this true
|
||||
:get (fn [_]
|
||||
(->> (get-variant-components file-id id)
|
||||
(mapcat :variant-properties)
|
||||
(keep :name)
|
||||
(set)
|
||||
(apply array)))}
|
||||
|
||||
:currentValues
|
||||
(fn [property]
|
||||
(->> (get-variant-components file-id id)
|
||||
(map
|
||||
(fn [{:keys [variant-properties]}]
|
||||
(->> variant-properties
|
||||
(d/seek #(= (:name %) property)))))
|
||||
(keep :value)
|
||||
(set)
|
||||
(apply array)))
|
||||
|
||||
:variantComponents
|
||||
(fn []
|
||||
(->> (get-variant-components file-id id)
|
||||
(map :id)
|
||||
(map #(lib-component-proxy plugin-id file-id %))
|
||||
(apply array)))
|
||||
|
||||
:addVariant
|
||||
(fn []
|
||||
(st/emit!
|
||||
(ev/event {::ev/name "add-new-variant" ::ev/origin "plugin:add-variant"})
|
||||
(dwv/add-new-variant id)))
|
||||
|
||||
:addProperty
|
||||
(fn []
|
||||
(st/emit!
|
||||
(ev/event {::ev/name "add-new-property" ::ev/origin "plugin:add-property"})
|
||||
(dwv/add-new-property id {:property-value "Value 1"})))
|
||||
|
||||
:removeProperty
|
||||
(fn [pos]
|
||||
(if (not (nat-int? pos))
|
||||
(u/display-not-valid :pos pos)
|
||||
(st/emit!
|
||||
(ev/event {::ev/name "remove-property" ::ev/origin "plugin:remove-property"})
|
||||
(dwv/remove-property id pos))))
|
||||
|
||||
:renameProperty
|
||||
(fn [pos name]
|
||||
(cond
|
||||
(not (nat-int? pos))
|
||||
(u/display-not-valid :pos pos)
|
||||
|
||||
(not (string? name))
|
||||
(u/display-not-valid :name name)
|
||||
|
||||
:else
|
||||
(st/emit!
|
||||
(dwv/update-property-name id pos name {:trigger "plugin:rename-property"}))))))
|
||||
|
||||
(set! shape/variant-proxy variant-proxy)
|
||||
|
||||
(defn lib-component-proxy? [p]
|
||||
(obj/type-of? p "LibraryComponentProxy"))
|
||||
|
||||
@@ -763,7 +844,71 @@
|
||||
component (u/locate-library-component file-id id)
|
||||
root (ctf/get-component-root (:data file) component)]
|
||||
(when (some? root)
|
||||
(shape/shape-proxy plugin-id file-id (:main-instance-page component) (:id root)))))))
|
||||
(shape/shape-proxy plugin-id file-id (:main-instance-page component) (:id root)))))
|
||||
|
||||
:isVariant
|
||||
(fn []
|
||||
(let [component (u/locate-library-component file-id id)]
|
||||
(ctk/is-variant? component)))
|
||||
|
||||
:variants
|
||||
{:enumerable false
|
||||
:get
|
||||
(fn []
|
||||
(let [component (u/locate-library-component file-id id)]
|
||||
(when (ctk/is-variant? component)
|
||||
(variant-proxy plugin-id file-id (:variant-id component)))))}
|
||||
|
||||
:variantProps
|
||||
{:get
|
||||
(fn []
|
||||
(let [component (u/locate-library-component file-id id)]
|
||||
(when (ctk/is-variant? component)
|
||||
(->> (:variant-properties component)
|
||||
(reduce
|
||||
(fn [acc {:keys [name value]}]
|
||||
(obj/set! acc name value))
|
||||
#js {})))))}
|
||||
|
||||
:variantError
|
||||
{:get (fn []
|
||||
(let [file (u/locate-file file-id)
|
||||
component (u/locate-library-component file-id id)
|
||||
root (ctf/get-component-root (:data file) component)]
|
||||
(when (ctk/is-variant? component)
|
||||
(:variant-error root))))}
|
||||
|
||||
:transformInVariant
|
||||
(fn []
|
||||
(let [component (u/locate-library-component file-id id)]
|
||||
(when (and component
|
||||
(not (ctk/is-variant? component)))
|
||||
(st/emit!
|
||||
(ev/event {::ev/name "transform-in-variant" ::ev/origin "plugin:transform-in-variant"})
|
||||
(dwv/transform-in-variant (:main-instance-id component))))))
|
||||
|
||||
:addVariant
|
||||
(fn []
|
||||
(let [component (u/locate-library-component file-id id)]
|
||||
(when (and component
|
||||
(ctk/is-variant? component))
|
||||
(st/emit!
|
||||
(ev/event {::ev/name "add-new-variant" ::ev/origin "plugin:add-variant-from-component"})
|
||||
(dwv/add-new-variant (:main-instance-id component))))))
|
||||
|
||||
:setVariantProperty
|
||||
(fn [pos value]
|
||||
(cond
|
||||
(not (nat-int? pos))
|
||||
(u/display-not-valid :pos pos)
|
||||
|
||||
(not (string? name))
|
||||
(u/display-not-valid :name name)
|
||||
|
||||
:else
|
||||
(st/emit!
|
||||
(ev/event {::ev/name "variant-edit-property-value" ::ev/origin "plugin:edit-property-value"})
|
||||
(dwv/update-property-value id pos value))))))
|
||||
|
||||
(defn library-proxy? [p]
|
||||
(obj/type-of? p "LibraryProxy"))
|
||||
@@ -804,11 +949,12 @@
|
||||
{:this true
|
||||
:get
|
||||
(fn [_]
|
||||
(let [file (u/locate-file file-id)
|
||||
components (->> file
|
||||
:data
|
||||
(let [file (u/locate-file file-id)
|
||||
data (:data file)
|
||||
components (->> data
|
||||
:components
|
||||
(remove (comp :deleted second))
|
||||
(remove (comp #(cfv/is-secondary-variant? % data) second))
|
||||
(map first)
|
||||
(map #(lib-component-proxy plugin-id file-id %)))]
|
||||
(apply array components)))}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.data.workspace.variants :as dwv]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.plugins.flex :as flex]
|
||||
@@ -58,6 +59,8 @@
|
||||
|
||||
(declare shape-proxy)
|
||||
(declare shape-proxy?)
|
||||
;; This is injected from plugin/librraies
|
||||
(def variant-proxy nil)
|
||||
|
||||
(defn interaction-proxy? [p]
|
||||
(obj/type-of? p "InteractionProxy"))
|
||||
@@ -771,9 +774,7 @@
|
||||
#(interaction-proxy plugin-id file-id page-id id %)
|
||||
(range 0 (count interactions)))))}
|
||||
|
||||
|
||||
;; Methods
|
||||
|
||||
:resize
|
||||
(fn [width height]
|
||||
(cond
|
||||
@@ -1221,7 +1222,46 @@
|
||||
|
||||
:else
|
||||
(let [guide (u/proxy->ruler-guide value)]
|
||||
(st/emit! (dwgu/remove-guide guide))))))
|
||||
(st/emit! (dwgu/remove-guide guide)))))
|
||||
|
||||
:isVariantHead
|
||||
(fn []
|
||||
(let [shape (u/locate-shape file-id page-id id)
|
||||
component (u/locate-library-component file-id (:component-id shape))]
|
||||
(and (ctk/instance-head? shape) (ctk/is-variant? component))))
|
||||
|
||||
:isVariantContainer
|
||||
(fn []
|
||||
(let [shape (u/locate-shape file-id page-id id)]
|
||||
(ctk/is-variant-container? shape)))
|
||||
|
||||
:switchVariant
|
||||
(fn [pos value]
|
||||
(cond
|
||||
(not (nat-int? pos))
|
||||
(u/display-not-valid :pos pos)
|
||||
|
||||
(not (string? value))
|
||||
(u/display-not-valid :value value)
|
||||
|
||||
:else
|
||||
(let [shape (u/locate-shape file-id page-id id)
|
||||
component (u/locate-library-component file-id (:component-id shape))]
|
||||
(when (and component (ctk/is-variant? component))
|
||||
(st/emit! (dwv/variants-switch {:shapes [shape] :pos pos :val value}))))))
|
||||
|
||||
:combineAsVariants
|
||||
(fn [ids]
|
||||
(if (or (not (seq ids)) (not (every? uuid/parse* ids)))
|
||||
(u/display-not-valid :ids ids)
|
||||
(let [shape (u/locate-shape file-id page-id id)
|
||||
component (u/locate-library-component file-id (:component-id shape))
|
||||
ids (->> ids
|
||||
(map uuid/uuid)
|
||||
(into #{id}))]
|
||||
(when (and component (not (ctk/is-variant? component)))
|
||||
(st/emit!
|
||||
(dwv/combine-as-variants ids {:trigger "plugin:combine-as-variants"})))))))
|
||||
|
||||
(cond-> (or (cfh/frame-shape? data) (cfh/group-shape? data) (cfh/svg-raw-shape? data) (cfh/bool-shape? data))
|
||||
(crc/add-properties!
|
||||
@@ -1338,7 +1378,15 @@
|
||||
(u/display-not-valid :verticalSizing "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(st/emit! (dwsl/update-layout #{id} {:layout-item-v-sizing value})))))})))
|
||||
(st/emit! (dwsl/update-layout #{id} {:layout-item-v-sizing value})))))}
|
||||
|
||||
{:name "variants"
|
||||
:enumerable false
|
||||
:get
|
||||
(fn [self]
|
||||
(let [shape (-> self u/proxy->shape)]
|
||||
(when (ctk/is-variant-container? shape)
|
||||
(variant-proxy plugin-id file-id (:id shape)))))})))
|
||||
|
||||
(cond-> (cfh/text-shape? data) (text/add-text-props plugin-id))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user