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:
parent
6454e878dd
commit
2d25df33ce
8 changed files with 622 additions and 45 deletions
|
@ -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."
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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)))}))
|
||||
|
|
|
@ -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)))))
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -134,3 +134,4 @@
|
|||
(catch :default err
|
||||
(.error js/console err)
|
||||
nil)))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue