0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-23 23:18:48 -05:00

Add write methods to prototype API

This commit is contained in:
alonso.torres 2024-07-23 16:55:32 +02:00
parent 6454e878dd
commit 2d25df33ce
8 changed files with 622 additions and 45 deletions

View file

@ -28,29 +28,33 @@
;; --- Flows
(defn add-flow
[starting-frame]
([starting-frame]
(add-flow nil nil nil starting-frame))
(dm/assert!
"expect uuid"
(uuid? starting-frame))
([flow-id page-id name starting-frame]
(dm/assert!
"expect uuid"
(uuid? starting-frame))
(ptk/reify ::add-flow
ptk/WatchEvent
(watch [it state _]
(let [page (wsh/lookup-page state)
(ptk/reify ::add-flow
ptk/WatchEvent
(watch [it state _]
(let [page (if page-id
(wsh/lookup-page state page-id)
(wsh/lookup-page state))
flows (get-in page [:options :flows] [])
unames (cfh/get-used-names flows)
name (cfh/generate-unique-name unames "Flow 1")
flows (get-in page [:options :flows] [])
unames (cfh/get-used-names flows)
name (or name (cfh/generate-unique-name unames "Flow 1"))
new-flow {:id (uuid/next)
:name name
:starting-frame starting-frame}]
new-flow {:id (or flow-id (uuid/next))
:name name
:starting-frame starting-frame}]
(rx/of (dch/commit-changes
(-> (pcb/empty-changes it)
(pcb/with-page page)
(pcb/update-page-option :flows ctp/add-flow new-flow))))))))
(rx/of (dch/commit-changes
(-> (pcb/empty-changes it)
(pcb/with-page page)
(pcb/update-page-option :flows ctp/add-flow new-flow)))))))))
(defn add-flow-selected-frame
[]
@ -61,16 +65,35 @@
(rx/of (add-flow (first selected)))))))
(defn remove-flow
[flow-id]
([flow-id]
(remove-flow nil flow-id))
([page-id flow-id]
(dm/assert! (uuid? flow-id))
(ptk/reify ::remove-flow
ptk/WatchEvent
(watch [it state _]
(let [page (if page-id
(wsh/lookup-page state page-id)
(wsh/lookup-page state))]
(rx/of (dch/commit-changes
(-> (pcb/empty-changes it)
(pcb/with-page page)
(pcb/update-page-option :flows ctp/remove-flow flow-id)))))))))
(defn update-flow
[page-id flow-id update-fn]
(dm/assert! (uuid? flow-id))
(ptk/reify ::remove-flow
(ptk/reify ::update-flow
ptk/WatchEvent
(watch [it state _]
(let [page (wsh/lookup-page state)]
(let [page (if page-id
(wsh/lookup-page state page-id)
(wsh/lookup-page state))]
(rx/of (dch/commit-changes
(-> (pcb/empty-changes it)
(pcb/with-page page)
(pcb/update-page-option :flows ctp/remove-flow flow-id))))))))
(pcb/update-page-option :flows ctp/update-flow flow-id update-fn))))))))
(defn rename-flow
[flow-id name]
@ -111,6 +134,18 @@
(or (some ctsi/flow-origin? (map :interactions children))
(some #(ctsi/flow-to? % frame-id) (map :interactions (vals objects))))))
(defn add-interaction
[page-id shape-id interaction]
(ptk/reify ::add-interaction
ptk/WatchEvent
(watch [_ state _]
(let [page-id (or page-id (:current-page-id state))]
(rx/of (dwsh/update-shapes
[shape-id]
(fn [shape]
(cls/add-new-interaction shape interaction))
{:page-id page-id}))))))
(defn add-new-interaction
([shape] (add-new-interaction shape nil))
([shape destination]
@ -138,23 +173,29 @@
(rx/of (add-flow (:id frame))))))))))
(defn remove-interaction
[shape index]
(ptk/reify ::remove-interaction
ptk/WatchEvent
(watch [_ _ _]
(rx/of (dwsh/update-shapes [(:id shape)]
(fn [shape]
(update shape :interactions
ctsi/remove-interaction index)))))))
([shape index]
(remove-interaction nil shape index))
([page-id shape index]
(ptk/reify ::remove-interaction
ptk/WatchEvent
(watch [_ _ _]
(rx/of (dwsh/update-shapes [(:id shape)]
(fn [shape]
(update shape :interactions
ctsi/remove-interaction index))
{:page-id page-id}))))))
(defn update-interaction
[shape index update-fn]
(ptk/reify ::update-interaction
ptk/WatchEvent
(watch [_ _ _]
(rx/of (dwsh/update-shapes [(:id shape)]
(fn [shape]
(update shape :interactions
ctsi/update-interaction index update-fn)))))))
([shape index update-fn]
(update-interaction shape index update-fn nil))
([shape index update-fn options]
(ptk/reify ::update-interaction
ptk/WatchEvent
(watch [_ _ _]
(rx/of (dwsh/update-shapes [(:id shape)]
(fn [shape]
(update shape :interactions
ctsi/update-interaction index update-fn))
options))))))
(defn remove-all-interactions-nav-to
"Remove all interactions that navigate to the given frame."

View file

@ -352,7 +352,7 @@
(openViewer
[_]
(let [params {:page-id (:current-page-id @st/state)
(let [params {:page-id (:current-page-id @st/state)
:file-id (:current-file-id @st/state)
:section "interactions"}]
(st/emit! (dw/go-to-viewer params))))

View file

@ -10,6 +10,8 @@
[app.common.data.macros :as dm]
[app.util.object :as obj]))
(def shape-proxy nil)
(defn format-id
[id]
(when id (dm/str id)))
@ -422,3 +424,163 @@
[tracks]
(when (some? tracks)
(format-array format-track tracks)))
;; export interface PenpotDissolve {
;; type: 'dissolve';
;; duration: number;
;; easing?: 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out';
;; }
;;
;; export interface PenpotSlide {
;; type: 'slide';
;; way: 'in' | 'out';
;; direction?:
;; | 'right'
;; | 'left'
;; | 'up'
;; | 'down';
;; duration: number;
;; offsetEffect?: boolean;
;; easing?: 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out';
;; }
;;
;; export interface PenpotPush {
;; type: 'push';
;; direction?:
;; | 'right'
;; | 'left'
;; | 'up'
;; | 'down';
;;
;; duration: number;
;; easing?: 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out';
;; }
;;
;; export type PenpotAnimation = PenpotDissolve | PenpotSlide | PenpotPush;
(defn format-animation
[animation]
(when animation
(obj/clear-empty
(case (:animation-type animation)
:dissolve
#js {:type "dissolve"
:duration (:duration animation)
:easing (format-key (:easing animation))}
:slide
#js {:type "slide"
:way (format-key (:way animation))
:direction (format-key (:direction animation))
:duration (:duration animation)
:easing (format-key (:easing animation))
:offsetEffect (:offset-effect animation)}
:push
#js {:type "push"
:direction (format-key (:direction animation))
:duration (:duration animation)
:easing (format-key (:easing animation))}
nil))))
;;export type PenpotAction =
;; | PenpotNavigateTo
;; | PenpotOpenOverlay
;; | PenpotToggleOverlay
;; | PenpotCloseOverlay
;; | PenpotPreviousScreen
;; | PenpotOpenUrl;
;;
;;export interface PenpotNavigateTo {
;; type: 'navigate-to';
;; destination: PenpotFrame;
;; preserveScrollPosition?: boolean;
;; animation: PenpotAnimation;
;;}
;;
;;export interface PenpotOverlayAction {
;; destination: PenpotFrame;
;; relativeTo?: PenpotShape;
;; position?:
;; | 'manual'
;; | 'center'
;; | 'top-left'
;; | 'top-right'
;; | 'top-center'
;; | 'bottom-left'
;; | 'bottom-right'
;; | 'bottom-center';
;; manualPositionLocation?: PenpotPoint;
;; closeWhenClickOutside?: boolean;
;; addBackgroundOverlay?: boolean;
;; animation: PenpotAnimation;
;;}
;;
;;export interface PenpotOpenOverlay extends PenpotOverlayAction {
;; type: 'open-overlay';
;;}
;;
;;export interface PenpotToggleOverlay extends PenpotOverlayAction {
;; type: 'toggle-overlay';
;;}
;;
;;export interface PenpotCloseOverlay {
;; type: 'close-overlay';
;; destination?: PenpotFrame;
;; animation: PenpotAnimation;
;;}
;;
;;export interface PenpotPreviousScreen {
;; type: 'previous-screen';
;;}
;;
;;export interface PenpotOpenUrl {
;; type: 'open-url';
;; url: string;
;;}
(defn format-action
[interaction plugin file-id page-id]
(when interaction
(obj/clear-empty
(case (:action-type interaction)
:navigate
#js {:type "navigate-to"
:destination (when (:destination interaction) (shape-proxy plugin file-id page-id (:destination interaction)))
:preserveScrollPosition (:preserve-scroll interaction false)
:animation (format-animation (:animation interaction))}
:open-overlay
#js {:type "open-overlay"
:destination (when (:destination interaction) (shape-proxy plugin file-id page-id (:destination interaction)))
:relativeTo (when (:relative-to interaction) (shape-proxy plugin file-id page-id (:relative-to interaction)))
:position (format-key (:overlay-pos-type interaction))
:manualPositionLocation (format-point (:overlay-position interaction))
:closeWhenClickOutside (:close-click-outside interaction)
:addBackgroundOverlay (:background-overlay interaction)
:animation (format-animation (:animation interaction))}
:toggle-overlay
#js {:type "toggle-overlay"
:destination (when (:destination interaction) (shape-proxy plugin file-id page-id (:destination interaction)))
:relativeTo (when (:relative-to interaction) (shape-proxy plugin file-id page-id (:relative-to interaction)))
:position (format-key (:overlay-pos-type interaction))
:manualPositionLocation (format-point (:overlay-position interaction))
:closeWhenClickOutside (:close-click-outside interaction)
:addBackgroundOverlay (:background-overlay interaction)
:animation (format-animation (:animation interaction))}
:close-overlay
#js {:type "close-overlay"
:destination (when (:destination interaction) (shape-proxy plugin file-id page-id (:destination interaction)))
:animation (format-animation (:animation interaction))}
:prev-screen
#js {:type "previous-screen"}
:open-url
#js {:type "open-url"
:url (:url interaction)}
nil))))

View file

@ -8,11 +8,14 @@
"RPC for plugins runtime."
(:require
[app.common.colors :as cc]
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.record :as crc]
[app.common.uuid :as uuid]
[app.main.data.workspace :as dw]
[app.main.data.workspace.interactions :as dwi]
[app.main.store :as st]
[app.plugins.format :as format]
[app.plugins.parser :as parser]
[app.plugins.register :as r]
[app.plugins.shape :as shape]
@ -20,6 +23,49 @@
[app.util.object :as obj]
[cuerdas.core :as str]))
(deftype FlowProxy [$plugin $file $page $id]
Object
(remove [_]
(st/emit! (dwi/remove-flow $page $id))))
(defn flow-proxy? [p]
(instance? FlowProxy p))
(defn flow-proxy
[plugin-id file-id page-id id]
(crc/add-properties!
(FlowProxy. plugin-id file-id page-id id)
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$file" :enumerable false :get (constantly file-id)}
{:name "$page" :enumerable false :get (constantly page-id)}
{:name "$id" :enumerable false :get (constantly id)}
{:name "page" :enumerable false :get (fn [_] (u/locate-page file-id page-id))}
{:name "name"
:get #(-> % u/proxy->flow :name)
:set
(fn [_ value]
(cond
(or (not (string? value)) (empty? value))
(u/display-not-valid :name value)
:else
(st/emit! (dwi/update-flow page-id id #(assoc % :name value)))))}
{:name "startingFrame"
:get
(fn [self]
(let [frame (-> self u/proxy->flow :starting-frame)]
(u/locate-shape file-id page-id frame)))
:set
(fn [_ value]
(cond
(not (shape/shape-proxy? value))
(u/display-not-valid :startingFrame value)
:else
(st/emit! (dwi/update-flow page-id id #(assoc % :starting-frame (obj/get value "$id"))))))}))
(deftype PageProxy [$plugin $file $id]
Object
(getShapeById
@ -140,7 +186,30 @@
(u/display-not-valid :openPage "Plugin doesn't have 'content:read' permission")
:else
(st/emit! (dw/go-to-page $id)))))
(st/emit! (dw/go-to-page $id))))
(createFlow
[_ name frame]
(cond
(or (not (string? name)) (empty? name))
(u/display-not-valid :createFlow-name name)
(not (shape/shape-proxy? frame))
(u/display-not-valid :createFlow-frame frame)
:else
(let [flow-id (uuid/next)]
(st/emit! (dwi/add-flow flow-id $id name (obj/get frame "$id")))
(flow-proxy $plugin $file $id flow-id))))
(removeFlow
[_ flow]
(cond
(not (flow-proxy? flow))
(u/display-not-valid :removeFlow-flow flow)
:else
(st/emit! (dwi/remove-flow $id (obj/get flow "$id"))))))
(crc/define-properties!
PageProxy
@ -192,4 +261,10 @@
(u/display-not-valid :background "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dw/change-canvas-color id {:color value}))))}))
(st/emit! (dw/change-canvas-color id {:color value}))))}
{:name "flows"
:get
(fn [self]
(let [flows (d/nilv (-> (u/proxy->page self) :options :flows) [])]
(format/format-array #(flow-proxy plugin-id file-id id (:id %)) flows)))}))

View file

@ -23,6 +23,12 @@
[color]
(if (string? color) (-> color str/lower) color))
(defn parse-point
[^js point]
(when point
{:x (obj/get point "x")
:y (obj/get point "y")}))
;; {
;; name?: string;
;; nameLike?: string;
@ -394,3 +400,164 @@
[^js content]
(when (some? content)
(into [] (map parse-command) content)))
;; export interface PenpotDissolve {
;; type: 'dissolve';
;; duration: number;
;; easing?: 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out';
;; }
;;
;; export interface PenpotSlide {
;; type: 'slide';
;; way: 'in' | 'out';
;; direction?:
;; | 'right'
;; | 'left'
;; | 'up'
;; | 'down';
;; duration: number;
;; offsetEffect?: boolean;
;; easing?: 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out';
;; }
;;
;; export interface PenpotPush {
;; type: 'push';
;; direction?:
;; | 'right'
;; | 'left'
;; | 'up'
;; | 'down';
;;
;; duration: number;
;; easing?: 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out';
;; }
;;
;; export type PenpotAnimation = PenpotDissolve | PenpotSlide | PenpotPush;
(defn parse-animation
[^js animation]
(when animation
(let [animation-type (-> (obj/get animation "type") parse-keyword)]
(d/without-nils
(case animation-type
:dissolve
{:type animation-type
:duration (obj/get animation "duration")
:easing (-> (obj/get animation "easing") parse-keyword)}
:slide
{:type animation-type
:way (-> (obj/get animation "way") parse-keyword)
:direction (-> (obj/get animation "direction") parse-keyword)
:duration (obj/get animation "duration")
:easing (-> (obj/get animation "easing") parse-keyword)
:offset-effect (obj/get animation "offsetEffect")}
:push
{:type animation-type
:direction (-> (obj/get animation "direction") parse-keyword)
:duration (obj/get animation "duration")
:easing (-> (obj/get animation "easing") parse-keyword)}
nil)))))
;;export type PenpotAction =
;; | PenpotNavigateTo
;; | PenpotOpenOverlay
;; | PenpotToggleOverlay
;; | PenpotCloseOverlay
;; | PenpotPreviousScreen
;; | PenpotOpenUrl;
;;
;;export interface PenpotNavigateTo {
;; type: 'navigate-to';
;; destination: PenpotFrame;
;; preserveScrollPosition?: boolean;
;; animation: PenpotAnimation;
;;}
;;
;;export interface PenpotOverlayAction {
;; destination: PenpotFrame;
;; relativeTo?: PenpotShape;
;; position?:
;; | 'manual'
;; | 'center'
;; | 'top-left'
;; | 'top-right'
;; | 'top-center'
;; | 'bottom-left'
;; | 'bottom-right'
;; | 'bottom-center';
;; manualPositionLocation?: PenpotPoint;
;; closeWhenClickOutside?: boolean;
;; addBackgroundOverlay?: boolean;
;; animation: PenpotAnimation;
;;}
;;
;;export interface PenpotOpenOverlay extends PenpotOverlayAction {
;; type: 'open-overlay';
;;}
;;
;;export interface PenpotToggleOverlay extends PenpotOverlayAction {
;; type: 'toggle-overlay';
;;}
;;
;;export interface PenpotCloseOverlay {
;; type: 'close-overlay';
;; destination?: PenpotFrame;
;; animation: PenpotAnimation;
;;}
;;
;;export interface PenpotPreviousScreen {
;; type: 'previous-screen';
;;}
;;
;;export interface PenpotOpenUrl {
;; type: 'open-url';
;; url: string;
;;}
(defn parse-action
[action]
(when action
(let [action-type (-> (obj/get action "type") parse-keyword)]
(d/without-nils
(case action-type
:navigate-to
{:action-type :navigate
:destination (-> (obj/get action "destination") (obj/get "$id"))
:preserve-scroll (obj/get action "preserveScrollPosition")
:animation (-> (obj/get action "animation") parse-animation)}
(:open-overlay
:toggle-overlay)
{:action-type action-type
:destination (-> (obj/get action "destination") (obj/get "$id"))
:relative-to (-> (obj/get action "relativeTo") (obj/get "$id"))
:overlay-pos-type (-> (obj/get action "position") parse-keyword)
:overlay-position (-> (obj/get action "manualPositionLocation") parse-point)
:close-click-outside (obj/get action "closeWhenClickOutside")
:background-overlay (obj/get action "addBackgroundOverlay")
:animation (-> (obj/get action "animation") parse-animation)}
:close-overlay
{:action-type action-type
:destination (-> (obj/get action "destination") (obj/get "$id"))
:animation (-> (obj/get action "animation") parse-animation)}
:previous-screen
{:action-type :prev-screen}
:open-url
{:action-type action-type
:url (obj/get action "url")}
nil)))))
(defn parse-interaction
[^js interaction]
(when interaction
(let [trigger (-> (obj/get interaction "trigger") parse-keyword)
delay (obj/get interaction "trigger")
action (-> (obj/get interaction "action") parse-action)]
(d/without-nils
(d/patch-object {:event-type trigger :delay delay} action)))))

View file

@ -25,6 +25,7 @@
[app.common.types.shape :as cts]
[app.common.types.shape.blur :as ctsb]
[app.common.types.shape.export :as ctse]
[app.common.types.shape.interactions :as ctsi]
[app.common.types.shape.layout :as ctl]
[app.common.types.shape.path :as ctsp]
[app.common.types.shape.radius :as ctsr]
@ -32,6 +33,7 @@
[app.common.uuid :as uuid]
[app.main.data.workspace :as dw]
[app.main.data.workspace.groups :as dwg]
[app.main.data.workspace.interactions :as dwi]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.shape-layout :as dwsl]
@ -52,6 +54,81 @@
[cuerdas.core :as str]
[promesa.core :as p]))
(declare shape-proxy)
(declare shape-proxy?)
(deftype InteractionProxy [$plugin $file $page $shape $index]
Object
(remove [_]
(st/emit! (dwi/remove-interaction {:id $shape} $index))))
(defn interaction-proxy? [p]
(instance? InteractionProxy p))
(defn interaction-proxy
[plugin-id file-id page-id shape-id index]
(crc/add-properties!
(InteractionProxy. plugin-id file-id page-id shape-id index)
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$file" :enumerable false :get (constantly file-id)}
{:name "$page" :enumerable false :get (constantly page-id)}
{:name "$shape" :enumerable false :get (constantly shape-id)}
{:name "$index" :enumerable false :get (constantly index)}
;; Not enumerable so we don't have an infinite loop
{:name "shape" :enumerable false
:get (fn [_] (shape-proxy plugin-id file-id page-id shape-id))}
{:name "trigger"
:get #(-> % u/proxy->interaction :event-type format/format-key)
:set
(fn [_ value]
(let [value (parser/parse-keyword value)]
(cond
(not (contains? ctsi/event-types value))
(u/display-not-valid :trigger value)
:else
(st/emit! (dwi/update-interaction
{:id shape-id}
index
#(assoc % :event-type value)
{:page-id page-id})))))}
{:name "delay"
:get #(-> % u/proxy->interaction :delay)
:set
(fn [_ value]
(cond
(or (not (number? value)) (not (pos? value)))
(u/display-not-valid :delay value)
:else
(st/emit! (dwi/update-interaction
{:id shape-id}
index
#(assoc % :delay value)
{:page-id page-id}))))}
{:name "action"
:get #(-> % u/proxy->interaction (format/format-action plugin-id file-id page-id))
:set
(fn [self value]
(let [params (parser/parse-action value)
interaction
(-> (u/proxy->interaction self)
(d/patch-object params))]
(cond
(not (sm/validate ::ctsi/interaction interaction))
(u/display-not-valid :action interaction)
:else
(st/emit! (dwi/update-interaction
{:id shape-id}
index
#(d/patch-object % params)
{:page-id page-id})))))}))
(def lib-typography-proxy? nil)
(def lib-component-proxy nil)
@ -62,8 +139,6 @@
(dwt/current-paragraph-values {:shape shape :attrs txt/paragraph-attrs})
(dwt/current-text-values {:shape shape :attrs txt/text-node-attrs})))
(declare shape-proxy)
(declare shape-proxy?)
(defn- shadow-defaults
[shadow]
@ -446,6 +521,7 @@
[_]
(st/emit! (dwl/detach-component $id)))
;; Export
(export
[self value]
(let [value (parser/parse-export value)]
@ -471,7 +547,31 @@
(rx/mapcat #(rp/cmd! :export {:cmd :get-resource :wait true :id (:id %) :blob? true}))
(rx/mapcat #(.arrayBuffer %))
(rx/map #(js/Uint8Array. %))
(rx/subs! resolve reject)))))))))
(rx/subs! resolve reject))))))))
;; Interactions
(addInteraction
[self interaction]
(let [interaction
(-> ctsi/default-interaction
(d/patch-object (parser/parse-interaction interaction)))]
(cond
(not (sm/validate ::ctsi/interaction interaction))
(u/display-not-valid :addInteraction interaction)
:else
(let [index (-> (u/proxy->shape self) (:interactions []) count)]
(st/emit! (dwi/add-interaction $page $id interaction))
(interaction-proxy $plugin $file $page $id index)))))
(removeInteraction
[_ interaction]
(cond
(not (interaction-proxy? interaction))
(u/display-not-valid :removeInteraction interaction)
:else
(st/emit! (dwi/remove-interaction {:id $id} (obj/get interaction "$index"))))))
(defn shape-proxy? [p]
(instance? ShapeProxy p))
@ -480,6 +580,8 @@
(do (set! flex/shape-proxy? shape-proxy?)
(set! grid/shape-proxy? shape-proxy?))
(set! format/shape-proxy shape-proxy)
(crc/define-properties!
ShapeProxy
{:name js/Symbol.toStringTag
@ -1036,7 +1138,17 @@
id (obj/get self "$id")
objects (u/locate-objects file-id page-id)]
(when (ctl/grid-layout-immediate-child-id? objects id)
(grid/layout-cell-proxy plugin-id file-id page-id id))))})
(grid/layout-cell-proxy plugin-id file-id page-id id))))}
;; Interactions
{:name "interactions"
:get
(fn [self]
(let [interactions (-> self u/proxy->shape :interactions)]
(format/format-array
#(interaction-proxy plugin-id file-id page-id id %)
(range 0 (count interactions)))))})
(cond-> (or (cfh/frame-shape? data) (cfh/group-shape? data) (cfh/svg-raw-shape? data) (cfh/bool-shape? data))
(crc/add-properties!

View file

@ -113,6 +113,25 @@
(when (and (some? file-id) (some? id))
(locate-library-component file-id id))))
(defn proxy->flow
[proxy]
(let [file-id (obj/get proxy "$file")
page-id (obj/get proxy "$page")
flow-id (obj/get proxy "$id")
page (locate-page file-id page-id)]
(when (some? page)
(d/seek #(= (:id %) flow-id) (-> page :options :flows)))))
(defn proxy->interaction
[proxy]
(let [file-id (obj/get proxy "$file")
page-id (obj/get proxy "$page")
shape-id (obj/get proxy "$shape")
index (obj/get proxy "$index")
shape (locate-shape file-id page-id shape-id)]
(when (some? shape)
(get-in shape [:interactions index]))))
(defn get-data
([self attr]
(-> (obj/get self "_data")

View file

@ -134,3 +134,4 @@
(catch :default err
(.error js/console err)
nil)))