From 3ca5b13e277d9842b3f2834715920cf4649a3258 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 21 May 2024 15:00:35 +0200 Subject: [PATCH] :sparkles: New apis for plugins --- .../src/app/main/ui/workspace/plugins.cljs | 1 + frontend/src/app/plugins/api.cljs | 2 +- frontend/src/app/plugins/flex.cljs | 282 ++++++++++++++++++ frontend/src/app/plugins/grid.cljs | 92 +++++- frontend/src/app/plugins/library.cljs | 167 +++++++---- frontend/src/app/plugins/shape.cljs | 66 +++- frontend/src/app/plugins/utils.cljs | 95 ++++-- 7 files changed, 613 insertions(+), 92 deletions(-) create mode 100644 frontend/src/app/plugins/flex.cljs diff --git a/frontend/src/app/main/ui/workspace/plugins.cljs b/frontend/src/app/main/ui/workspace/plugins.cljs index 13a69be15..63696b7d7 100644 --- a/frontend/src/app/main/ui/workspace/plugins.cljs +++ b/frontend/src/app/main/ui/workspace/plugins.cljs @@ -101,6 +101,7 @@ (fn [] (->> (http/send! {:method :get :uri plugin-url + :omit-default-headers true :response-type :json}) (rx/map :body) (rx/subs! diff --git a/frontend/src/app/plugins/api.cljs b/frontend/src/app/plugins/api.cljs index 83e38f642..b56b4c568 100644 --- a/frontend/src/app/plugins/api.cljs +++ b/frontend/src/app/plugins/api.cljs @@ -154,4 +154,4 @@ {:name "currentPage" :get #(.getPage ^js %)} {:name "selection" :get #(.getSelectedShapes ^js %)} {:name "viewport" :get #(.getViewport ^js %)} - {:name "library" :get (fn [_] (library/create-library-subcontext))})) + {:name "library" :get (fn [_] (library/library-subcontext))})) diff --git a/frontend/src/app/plugins/flex.cljs b/frontend/src/app/plugins/flex.cljs new file mode 100644 index 000000000..e75b2a849 --- /dev/null +++ b/frontend/src/app/plugins/flex.cljs @@ -0,0 +1,282 @@ +;; 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.plugins.flex + (:require + [app.common.data :as d] + [app.common.record :as crc] + [app.common.spec :as us] + [app.common.types.shape.layout :as ctl] + [app.main.data.workspace.shape-layout :as dwsl] + [app.main.data.workspace.transforms :as dwt] + [app.main.store :as st] + [app.plugins.utils :as utils :refer [proxy->shape]] + [app.util.object :as obj] + [potok.v2.core :as ptk])) + +(deftype FlexLayout [$file $page $id] + Object + (remove + [_] + (st/emit! (dwsl/remove-layout #{$id}))) + + (appendChild + [_ child] + (let [child-id (obj/get child "$id")] + (st/emit! (dwt/move-shapes-to-frame #{child-id} $id nil nil) + (ptk/data-event :layout/update {:ids [$id]}))))) + +(defn flex-layout-proxy + [file-id page-id id] + (-> (FlexLayout. file-id page-id id) + (crc/add-properties! + {:name "$id" :enumerable false} + {:name "$file" :enumerable false} + {:name "$page" :enumerable false} + + {:name "dir" + :get #(-> % proxy->shape :layout-flex-dir d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (when (contains? ctl/flex-direction-types value) + (st/emit! (dwsl/update-layout #{id} {:layout-flex-dir value})))))} + + {:name "alignItems" + :get #(-> % proxy->shape :layout-align-items d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (when (contains? ctl/align-items-types value) + (st/emit! (dwsl/update-layout #{id} {:layout-align-items value})))))} + + {:name "alignContent" + :get #(-> % proxy->shape :layout-align-content d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (when (contains? ctl/align-content-types value) + (st/emit! (dwsl/update-layout #{id} {:layout-align-content value})))))} + + {:name "justifyItems" + :get #(-> % proxy->shape :layout-justify-items d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (when (contains? ctl/justify-items-types value) + (st/emit! (dwsl/update-layout #{id} {:layout-justify-items value})))))} + + {:name "justifyContent" + :get #(-> % proxy->shape :layout-justify-content d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (when (contains? ctl/justify-content-types value) + (st/emit! (dwsl/update-layout #{id} {:layout-justify-content value})))))} + + {:name "rowGap" + :get #(-> % proxy->shape :layout-gap :row-gap) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-int? value) + (st/emit! (dwsl/update-layout #{id} {:layout-gap {:row-gap value}})))))} + + {:name "columnGap" + :get #(-> % proxy->shape :layout-gap :column-gap) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-int? value) + (st/emit! (dwsl/update-layout #{id} {:layout-gap {:column-gap value}})))))} + + {:name "verticalPadding" + :get #(-> % proxy->shape :layout-padding :p1) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-int? value) + (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value :p3 value}})))))} + + {:name "horizontalPadding" + :get #(-> % proxy->shape :layout-padding :p2) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-int? value) + (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}})))))} + + + {:name "topPadding" + :get #(-> % proxy->shape :layout-padding :p1) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-int? value) + (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value}})))))} + + {:name "rightPadding" + :get #(-> % proxy->shape :layout-padding :p2) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-int? value) + (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value}})))))} + + {:name "bottomPadding" + :get #(-> % proxy->shape :layout-padding :p3) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-int? value) + (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p3 value}})))))} + + {:name "leftPadding" + :get #(-> % proxy->shape :layout-padding :p4) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-int? value) + (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}})))))}))) + + +(deftype LayoutChildProxy [$file $page $id]) + +(defn layout-child-proxy + [file-id page-id id] + (-> (LayoutChildProxy. file-id page-id id) + (crc/add-properties! + {:name "$id" :enumerable false} + {:name "$file" :enumerable false} + {:name "$page" :enumerable false} + + {:name "absolute" + :get #(-> % proxy->shape :layout-item-absolute boolean) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (boolean? value) + (st/emit! (dwsl/update-layout #{id} {:layout-item-absolute value})))))} + + {:name "zIndex" + :get #(-> % proxy->shape :layout-item-z-index (d/nilv 0)) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-int? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-z-index value})))))} + + {:name "horizontalSizing" + :get #(-> % proxy->shape :layout-item-h-sizing (d/nilv :fix) d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (when (contains? ctl/item-h-sizing-types value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-h-sizing value})))))} + + {:name "verticalSizing" + :get #(-> % proxy->shape :layout-item-v-sizing (d/nilv :fix) d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (when (contains? ctl/item-v-sizing-types value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-v-sizing value})))))} + + {:name "alignSelf" + :get #(-> % proxy->shape :layout-item-align-self (d/nilv :auto) d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (when (contains? ctl/item-align-self-types value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-align-self value})))))} + + {:name "verticalMargin" + :get #(-> % proxy->shape :layout-item-margin :m1 (d/nilv 0)) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-number? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m1 value :m3 value}})))))} + + {:name "horizontalMargin" + :get #(-> % proxy->shape :layout-item-margin :m2 (d/nilv 0)) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-number? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m2 value :m4 value}})))))} + + {:name "topMargin" + :get #(-> % proxy->shape :layout-item-margin :m1 (d/nilv 0)) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-number? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m1 value}})))))} + + {:name "rightMargin" + :get #(-> % proxy->shape :layout-item-margin :m2 (d/nilv 0)) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-number? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m2 value}})))))} + + {:name "bottomMargin" + :get #(-> % proxy->shape :layout-item-margin :m3 (d/nilv 0)) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-number? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m3 value}})))))} + + {:name "leftMargin" + :get #(-> % proxy->shape :layout-item-margin :m4 (d/nilv 0)) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-number? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m4 value}})))))} + + {:name "maxWidth" + :get #(-> % proxy->shape :layout-item-max-w) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-number? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-max-w value})))))} + + {:name "minWidth" + :get #(-> % proxy->shape :layout-item-min-w) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-number? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-min-w value})))))} + + {:name "maxHeight" + :get #(-> % proxy->shape :layout-item-max-h) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-number? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-max-h value})))))} + + {:name "minHeight" + :get #(-> % proxy->shape :layout-item-min-h) + :set + (fn [self value] + (let [id (obj/get self "$id")] + (when (us/safe-number? value) + (st/emit! (dwsl/update-layout-child #{id} {:layout-item-min-h value})))))}))) diff --git a/frontend/src/app/plugins/grid.cljs b/frontend/src/app/plugins/grid.cljs index 4f9ac4979..179bbb10f 100644 --- a/frontend/src/app/plugins/grid.cljs +++ b/frontend/src/app/plugins/grid.cljs @@ -13,7 +13,7 @@ [app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.transforms :as dwt] [app.main.store :as st] - [app.plugins.utils :as utils :refer [proxy->shape]] + [app.plugins.utils :as utils :refer [proxy->shape locate-shape]] [app.util.object :as obj] [potok.v2.core :as ptk])) @@ -196,3 +196,93 @@ (let [id (obj/get self "$id")] (when (us/safe-int? value) (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}})))))}))) + +(deftype GridCellProxy [$file $page $id]) + +(defn layout-cell-proxy + [file-id page-id id] + (letfn [(locate-cell [_] + (let [shape (locate-shape file-id page-id id) + parent (locate-shape file-id page-id (:parent-id shape))] + (ctl/get-cell-by-shape-id parent id)))] + + (-> (GridCellProxy. file-id page-id id) + (crc/add-properties! + {:name "$id" :enumerable false} + {:name "$file" :enumerable false} + {:name "$page" :enumerable false} + + {:name "row" + :get #(-> % locate-cell :row) + :set + (fn [self value] + (let [shape (proxy->shape self) + cell (locate-cell self)] + (when (us/safe-int? value) + (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:row value})))))} + + {:name "rowSpan" + :get #(-> % locate-cell :row-span) + :set + (fn [self value] + (let [shape (proxy->shape self) + cell (locate-cell self)] + (when (us/safe-int? value) + (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:row-span value})))))} + + {:name "column" + :get #(-> % locate-cell :column) + :set + (fn [self value] + (let [shape (proxy->shape self) + cell (locate-cell self)] + (when (us/safe-int? value) + (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:column value})))))} + + {:name "columnSpan" + :get #(-> % locate-cell :column-span) + :set + (fn [self value] + (let [shape (proxy->shape self) + cell (locate-cell self)] + (when (us/safe-int? value) + (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:column-span value})))))} + + {:name "areaName" + :get #(-> % locate-cell :area-name) + :set + (fn [self value] + (let [shape (proxy->shape self) + cell (locate-cell self)] + (when (string? value) + (st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:area-name value})))))} + + {:name "position" + :get #(-> % locate-cell :position d/name) + :set + (fn [self value] + (let [shape (proxy->shape self) + cell (locate-cell self) + value (keyword value)] + (when (contains? ctl/grid-position-types value) + (st/emit! (dwsl/change-cells-mode (:parent-id shape) #{(:id cell)} value)))))} + + {:name "alignSelf" + :get #(-> % locate-cell :align-self d/name) + :set + (fn [self value] + (let [shape (proxy->shape self) + value (keyword value) + cell (locate-cell self)] + (when (contains? ctl/grid-cell-align-self-types value) + (st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:align-self value})))))} + + {:name "justifySelf" + :get #(-> % locate-cell :justify-self d/name) + :set + (fn [self value] + (let [shape (proxy->shape self) + value (keyword value) + cell (locate-cell self)] + (when (contains? ctl/grid-cell-justify-self-types value) + (st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:justify-self value})))))})))) diff --git a/frontend/src/app/plugins/library.cljs b/frontend/src/app/plugins/library.cljs index cefed442c..aeb029705 100644 --- a/frontend/src/app/plugins/library.cljs +++ b/frontend/src/app/plugins/library.cljs @@ -7,71 +7,134 @@ (ns app.plugins.library "RPC for plugins runtime." (:require + [app.common.data :as d] [app.common.data.macros :as dm] [app.common.record :as cr] [app.main.store :as st] - [app.plugins.utils :as utils :refer [get-data]] - [app.util.object :as obj])) + [app.plugins.utils :as u])) -(defn get-library-info - ([self attr] - (let [lib-id (get-data self :id) - current-file-id (:current-file-id @st/state)] - (if (= lib-id current-file-id) - (dm/get-in @st/state [:workspace-file attr]) - (dm/get-in @st/state [:workspace-libraries lib-id attr])))) +(deftype LibraryColorProxy [$file $id] + Object - ([self attr mapfn] - (-> (get-library-info self attr) - (mapfn)))) + (asFill [_] + (let [color (u/locate-library-color $file $id)] + (u/to-js + (d/without-nils + {:fill-color (:color color) + :fill-opacity (:opacity color) + :fill-color-gradient (:gradient color) + :fill-color-ref-file $file + :fill-color-ref-id $id + :fill-image (:image color)})))) -(defn get-library-data - ([self attr] - (let [lib-id (get-data self :id) - current-file-id (:current-file-id @st/state)] - (if (= lib-id current-file-id) - (dm/get-in @st/state [:workspace-data attr]) - (dm/get-in @st/state [:workspace-libraries lib-id :data attr])))) + (asStroke [_] + (let [color (u/locate-library-color $file $id)] + (u/to-js + (d/without-nils + {:stroke-color (:color color) + :stroke-opacity (:opacity color) + :stroke-color-gradient (:gradient color) + :stroke-color-ref-file $file + :stroke-color-ref-id $id + :stroke-image (:image color) + :stroke-style :solid + :stroke-alignment :inner}))))) - ([self attr mapfn] - (-> (get-library-data self attr) - (mapfn)))) +(defn lib-color-proxy + [file-id id] + (assert (uuid? file-id)) + (assert (uuid? id)) -(defn- array-to-js - [value] - (.freeze - js/Object - (apply array (->> value (map utils/to-js))))) - -(deftype Library [_data] - Object) - -(defn create-library - [data] (cr/add-properties! - (Library. data) - {:name "_data" - :enumerable false} - - {:name "id" - :get (fn [self] - (str (:id (obj/get self "_data"))))} + (LibraryColorProxy. file-id id) + {:name "$file" :enumerable false} + {:name "$id" :enumerable false} + {:name "id" :get (fn [_] (dm/str id))} {:name "name" - :get (fn [self] - (get-library-info self :name))} + :get #(-> % u/proxy->library-color :name)} + + {:name "color" + :get #(-> % u/proxy->library-color :color)} + + {:name "opacity" + :get #(-> % u/proxy->library-color :opacity)} + + {:name "gradient" + :get #(-> % u/proxy->library-color :gradient u/to-js)} + + {:name "image" + :get #(-> % u/proxy->library-color :image u/to-js)})) + +(deftype LibraryTypographyProxy [$file $id] + Object) + +(defn lib-typography-proxy + [file-id id] + (assert (uuid? file-id)) + (assert (uuid? id)) + + (cr/add-properties! + (LibraryTypographyProxy. file-id id) + {:name "$file" :enumerable false} + {:name "$id" :enumerable false} + {:name "id" :get (fn [_] (dm/str id))} + {:name "name" + :get #(-> % u/proxy->library-typography :name)})) + +(deftype LibraryComponentProxy [$file $id] + Object) + +(defn lib-component-proxy + [file-id id] + (assert (uuid? file-id)) + (assert (uuid? id)) + + (cr/add-properties! + (LibraryComponentProxy. file-id id) + {:name "$file" :enumerable false} + {:name "$id" :enumerable false} + {:name "id" :get (fn [_] (dm/str id))} + {:name "name" + :get #(-> % u/proxy->library-component :name)})) + +(deftype Library [$id] + Object) + +(defn library-proxy + [file-id] + (assert (uuid? file-id) "File id not valid") + + (cr/add-properties! + (Library. file-id) + {:name "$file" :enumerable false} + + {:name "id" + :get #(-> % u/proxy->file :id str)} + + {:name "name" + :get #(-> % u/proxy->file :name)} {:name "colors" - :get (fn [self] - (array-to-js (get-library-data self :colors vals)))} + :get + (fn [_] + (let [file (u/locate-file file-id) + colors (->> file :data :colors keys (map #(lib-color-proxy file-id %)))] + (apply array colors)))} {:name "typographies" - :get (fn [self] - (array-to-js (get-library-data self :typographies vals)))} + :get + (fn [_] + (let [file (u/locate-file file-id) + typographies (->> file :data :typographies keys (map #(lib-typography-proxy file-id %)))] + (apply array typographies)))} {:name "components" - :get (fn [self] - (array-to-js (get-library-data self :components vals)))})) + :get + (fn [_] + (let [file (u/locate-file file-id) + components (->> file :data :componentes keys (map #(lib-component-proxy file-id %)))] + (apply array components)))})) (deftype PenpotLibrarySubcontext [] Object @@ -80,17 +143,15 @@ (find [_])) -(defn create-library-subcontext +(defn library-subcontext [] (cr/add-properties! (PenpotLibrarySubcontext.) {:name "local" :get (fn [_] - (let [file (get @st/state :workspace-file) - data (get @st/state :workspace-data)] - (create-library (assoc file :data data))))} + (library-proxy (:current-file-id @st/state)))} {:name "connected" :get (fn [_] (let [libraries (get @st/state :workspace-libraries)] - (apply array (->> libraries vals (map create-library)))))})) + (apply array (->> libraries vals (map library-proxy)))))})) diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs index 79931491f..423f1eaf7 100644 --- a/frontend/src/app/plugins/shape.cljs +++ b/frontend/src/app/plugins/shape.cljs @@ -13,14 +13,16 @@ [app.common.spec :as us] [app.common.text :as txt] [app.common.types.shape :as cts] + [app.common.types.shape.layout :as ctl] [app.main.data.workspace :as udw] [app.main.data.workspace.changes :as dwc] [app.main.data.workspace.selection :as dws] [app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.shapes :as dwsh] [app.main.store :as st] + [app.plugins.flex :as flex] [app.plugins.grid :as grid] - [app.plugins.utils :as utils :refer [locate-shape proxy->shape array-to-js]] + [app.plugins.utils :as utils :refer [locate-objects locate-shape proxy->shape array-to-js]] [app.util.object :as obj])) (declare shape-proxy) @@ -62,7 +64,8 @@ ;; Only for frames (addFlexLayout [_] - (st/emit! (dwsl/create-layout-from-id $id :flex :from-frame? true :calculate-params? false))) + (st/emit! (dwsl/create-layout-from-id $id :flex :from-frame? true :calculate-params? false)) + (grid/grid-layout-proxy $file $page $id)) (addGridLayout [_] @@ -309,7 +312,27 @@ :set (fn [self value] (let [id (obj/get self "$id") value (mapv #(utils/from-js %) value)] - (st/emit! (dwc/update-shapes [id] #(assoc % :strokes value)))))}) + (st/emit! (dwc/update-shapes [id] #(assoc % :strokes value)))))} + + {:name "layoutChild" + :get + (fn [self] + (let [file-id (obj/get self "$file") + page-id (obj/get self "$page") + id (obj/get self "$id") + objects (locate-objects file-id page-id)] + (when (ctl/any-layout-immediate-child-id? objects id) + (flex/layout-child-proxy file-id page-id id))))} + + {:name "layoutCell" + :get + (fn [self] + (let [file-id (obj/get self "$file") + page-id (obj/get self "$page") + id (obj/get self "$id") + objects (locate-objects file-id page-id)] + (when (ctl/grid-layout-immediate-child-id? objects id) + (grid/layout-cell-proxy file-id page-id id))))}) (cond-> (or (cfh/frame-shape? data) (cfh/group-shape? data) (cfh/svg-raw-shape? data) (cfh/bool-shape? data)) (crc/add-properties! @@ -334,21 +357,40 @@ (when (= :grid layout) (grid/grid-layout-proxy file-id page-id id))))} + {:name "flex" + :get + (fn [self] + (let [layout (-> self proxy->shape :layout) + file-id (obj/get self "$file") + page-id (obj/get self "$page") + id (obj/get self "$id")] + (when (= :flex layout) + (flex/flex-layout-proxy file-id page-id id))))} + {:name "guides" :get #(-> % proxy->shape :grids array-to-js) :set (fn [self value] (let [id (obj/get self "$id") value (mapv #(utils/from-js %) value)] - (st/emit! (dwc/update-shapes [id] #(assoc % :grids value)))))}) + (st/emit! (dwc/update-shapes [id] #(assoc % :grids value)))))} - ;; TODO: Flex properties - #_(crc/add-properties! - {:name "flex" - :get - (fn [self] - (let [layout (-> self proxy->shape :layout)] - (when (= :flex layout) - (flex-layout-proxy (proxy->shape self)))))}))) + {:name "horizontalSizing" + :get #(-> % proxy->shape :layout-item-h-sizing (d/nilv :fix) d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (when (contains? #{:fix :auto} value) + (st/emit! (dwsl/update-layout #{id} {:layout-item-h-sizing value})))))} + + {:name "verticalSizing" + :get #(-> % proxy->shape :layout-item-v-sizing (d/nilv :fix) d/name) + :set + (fn [self value] + (let [id (obj/get self "$id") + value (keyword value)] + (when (contains? #{:fix :auto} value) + (st/emit! (dwsl/update-layout #{id} {:layout-item-v-sizing value})))))}))) (cond-> (not (cfh/frame-shape? data)) (-> (obj/unset! "addGridLayout") diff --git a/frontend/src/app/plugins/utils.cljs b/frontend/src/app/plugins/utils.cljs index fb3de2f60..9d7e9aa55 100644 --- a/frontend/src/app/plugins/utils.cljs +++ b/frontend/src/app/plugins/utils.cljs @@ -29,11 +29,30 @@ (assert (uuid? id) "Page not valid uuid") (dm/get-in (locate-file file-id) [:data :pages-index id])) +(defn locate-objects + [file-id page-id] + (:objects (locate-page file-id page-id))) + (defn locate-shape [file-id page-id id] (assert (uuid? id) "Shape not valid uuid") (dm/get-in (locate-page file-id page-id) [:objects id])) +(defn locate-library-color + [file-id id] + (assert (uuid? id) "Color not valid uuid") + (dm/get-in (locate-file file-id) [:data :colors id])) + +(defn locate-library-typography + [file-id id] + (assert (uuid? id) "Typography not valid uuid") + (dm/get-in (locate-file file-id) [:data :typographies id])) + +(defn locate-library-component + [file-id id] + (assert (uuid? id) "Component not valid uuid") + (dm/get-in (locate-file file-id) [:data :components id])) + (defn proxy->file [proxy] (let [id (obj/get proxy "$id")] @@ -52,6 +71,24 @@ id (obj/get proxy "$id")] (locate-shape file-id page-id id))) +(defn proxy->library-color + [proxy] + (let [file-id (obj/get proxy "$file") + id (obj/get proxy "$id")] + (locate-library-color file-id id))) + +(defn proxy->library-typography + [proxy] + (let [file-id (obj/get proxy "$file") + id (obj/get proxy "$id")] + (locate-library-color file-id id))) + +(defn proxy->library-component + [proxy] + (let [file-id (obj/get proxy "$file") + id (obj/get proxy "$id")] + (locate-library-color file-id id))) + (defn get-data ([self attr] (-> (obj/get self "_data") @@ -81,37 +118,45 @@ (defn from-js "Converts the object back to js" - ([obj] - (from-js obj identity)) - ([obj vfn] - (let [ret (js->clj obj {:keyword-fn (fn [k] (str/camel (name k)))})] - (reduce-kv - (fn [m k v] - (let [k (keyword (str/kebab k)) - v (cond (map? v) - (from-js v) + [obj] + (when (some? obj) + (let [process-node + (fn process-node [node] + (reduce-kv + (fn [m k v] + (let [k (keyword (str/kebab k)) + v (cond (map? v) + (process-node v) - (and (string? v) (re-matches us/uuid-rx v)) - (uuid/uuid v) + (vector? v) + (mapv process-node v) - :else (vfn k v))] - (assoc m k v))) - {} - ret)))) + (and (string? v) (re-matches us/uuid-rx v)) + (uuid/uuid v) + + (= k :type) + (keyword v) + + :else v)] + (assoc m k v))) + {} + node))] + (process-node (js->clj obj))))) (defn to-js "Converts to javascript an camelize the keys" [obj] - (let [result - (reduce-kv - (fn [m k v] - (let [v (cond (object? v) (to-js v) - (uuid? v) (dm/str v) - :else v)] - (assoc m (str/camel (name k)) v))) - {} - obj)] - (clj->js result))) + (when (some? obj) + (let [result + (reduce-kv + (fn [m k v] + (let [v (cond (object? v) (to-js v) + (uuid? v) (dm/str v) + :else v)] + (assoc m (str/camel (name k)) v))) + {} + obj)] + (clj->js result)))) (defn array-to-js [value]