mirror of
https://github.com/penpot/penpot.git
synced 2025-08-04 16:58:20 +02:00
♻️ Refactor and modularize all specs.
This commit is contained in:
parent
b1d55348dc
commit
04f7169aef
48 changed files with 1112 additions and 1031 deletions
|
@ -13,6 +13,7 @@
|
|||
[app.common.pages.changes :as ch]
|
||||
[app.common.pages.init :as init]
|
||||
[app.common.spec :as us]
|
||||
[app.common.spec.change :as spec.change]
|
||||
[app.common.uuid :as uuid]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
|
@ -38,9 +39,9 @@
|
|||
:frame-id (:current-frame-id file)))]
|
||||
|
||||
(when fail-on-spec?
|
||||
(us/verify :app.common.pages.spec/change change))
|
||||
(us/verify ::spec.change/change change))
|
||||
|
||||
(let [valid? (us/valid? :app.common.pages.spec/change change)]
|
||||
(let [valid? (us/valid? ::spec.change/change change)]
|
||||
#?(:cljs
|
||||
(when-not valid? (.warn js/console "Invalid shape" (clj->js change))))
|
||||
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
:clj [clojure.pprint :as pp])
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.math :as mth]))
|
||||
[app.common.math :as mth]
|
||||
[app.common.spec :as us]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;; --- Matrix Impl
|
||||
|
||||
|
@ -24,6 +26,21 @@
|
|||
(toString [_]
|
||||
(str "matrix(" a "," b "," c "," d "," e "," f ")")))
|
||||
|
||||
(defn ^boolean matrix?
|
||||
"Return true if `v` is Matrix instance."
|
||||
[v]
|
||||
(instance? Matrix v))
|
||||
|
||||
(s/def ::a ::us/safe-number)
|
||||
(s/def ::b ::us/safe-number)
|
||||
(s/def ::c ::us/safe-number)
|
||||
(s/def ::d ::us/safe-number)
|
||||
(s/def ::e ::us/safe-number)
|
||||
(s/def ::f ::us/safe-number)
|
||||
|
||||
(s/def ::matrix
|
||||
(s/and (s/keys :req-un [::a ::b ::c ::d ::e ::f]) matrix?))
|
||||
|
||||
(defn matrix
|
||||
"Create a new matrix instance."
|
||||
([]
|
||||
|
@ -84,11 +101,6 @@
|
|||
(- m1a m2a) (- m1b m2b) (- m1c m2c)
|
||||
(- m1d m2d) (- m1e m2e) (- m1f m2f)))
|
||||
|
||||
(defn ^boolean matrix?
|
||||
"Return true if `v` is Matrix instance."
|
||||
[v]
|
||||
(instance? Matrix v))
|
||||
|
||||
(def base (matrix))
|
||||
|
||||
(defn base?
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
:clj [clojure.pprint :as pp])
|
||||
#?(:cljs [cljs.core :as c]
|
||||
:clj [clojure.core :as c])
|
||||
[app.common.math :as mth]))
|
||||
[app.common.math :as mth]
|
||||
[app.common.spec :as us]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;; --- Point Impl
|
||||
|
||||
|
@ -25,6 +27,13 @@
|
|||
(or (instance? Point v)
|
||||
(and (map? v) (contains? v :x) (contains? v :y))))
|
||||
|
||||
(s/def ::x ::us/safe-number)
|
||||
(s/def ::y ::us/safe-number)
|
||||
|
||||
(s/def ::point
|
||||
(s/and (s/keys :req-un [::x ::y]) point?))
|
||||
|
||||
|
||||
(defn ^boolean point-like?
|
||||
[{:keys [x y] :as v}]
|
||||
(and (map? v)
|
||||
|
|
|
@ -185,3 +185,7 @@
|
|||
;; Bool
|
||||
(d/export gsb/update-bool-selrect)
|
||||
(d/export gsb/calc-bool-content)
|
||||
|
||||
;; Constraints
|
||||
(d/export gct/default-constraints-h)
|
||||
(d/export gct/default-constraints-v)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[app.common.geom.shapes.common :as gco]
|
||||
[app.common.geom.shapes.transforms :as gtr]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.spec :as spec]))
|
||||
[app.common.uuid :as uuid]))
|
||||
|
||||
;; Auxiliary methods to work in an specifica axis
|
||||
(defn get-delta-start [axis rect tr-rect]
|
||||
|
@ -117,7 +117,7 @@
|
|||
(not (mth/close? (:y resize-vector-2) 1)))
|
||||
(assoc :resize-origin (:resize-origin-2 modifiers)
|
||||
:resize-vector (gpt/point 1 (:y resize-vector-2)))
|
||||
|
||||
|
||||
(some? displacement)
|
||||
(assoc :displacement
|
||||
(get-displacement axis (-> (gpt/point 0 0)
|
||||
|
@ -138,16 +138,32 @@
|
|||
:center :center
|
||||
:scale :scale})
|
||||
|
||||
(defn default-constraints-h
|
||||
[shape]
|
||||
(if (= (:parent-id shape) uuid/zero)
|
||||
nil
|
||||
(if (= (:parent-id shape) (:frame-id shape))
|
||||
:left
|
||||
:scale)))
|
||||
|
||||
(defn default-constraints-v
|
||||
[shape]
|
||||
(if (= (:parent-id shape) uuid/zero)
|
||||
nil
|
||||
(if (= (:parent-id shape) (:frame-id shape))
|
||||
:top
|
||||
:scale)))
|
||||
|
||||
(defn calc-child-modifiers
|
||||
[parent child modifiers ignore-constraints transformed-parent-rect]
|
||||
(let [constraints-h
|
||||
(if-not ignore-constraints
|
||||
(:constraints-h child (spec/default-constraints-h child))
|
||||
(:constraints-h child (default-constraints-h child))
|
||||
:scale)
|
||||
|
||||
constraints-v
|
||||
(if-not ignore-constraints
|
||||
(:constraints-v child (spec/default-constraints-v child))
|
||||
(:constraints-v child (default-constraints-v child))
|
||||
:scale)
|
||||
|
||||
modifiers-h (constraint-modifier (constraints-h const->type+axis) :x parent child modifiers transformed-parent-rect)
|
||||
|
|
|
@ -12,9 +12,7 @@
|
|||
[app.common.pages.common :as common]
|
||||
[app.common.pages.helpers :as helpers]
|
||||
[app.common.pages.indices :as indices]
|
||||
[app.common.pages.init :as init]
|
||||
[app.common.pages.spec :as spec]
|
||||
[clojure.spec.alpha :as s]))
|
||||
[app.common.pages.init :as init]))
|
||||
|
||||
;; Common
|
||||
(d/export common/root)
|
||||
|
@ -88,15 +86,3 @@
|
|||
(d/export init/make-minimal-shape)
|
||||
(d/export init/make-minimal-group)
|
||||
(d/export init/empty-file-data)
|
||||
|
||||
;; Specs
|
||||
|
||||
(s/def ::changes ::spec/changes)
|
||||
(s/def ::color ::spec/color)
|
||||
(s/def ::data ::spec/data)
|
||||
(s/def ::media-object ::spec/media-object)
|
||||
(s/def ::page ::spec/page)
|
||||
(s/def ::recent-color ::spec/recent-color)
|
||||
(s/def ::shape-attrs ::spec/shape-attrs)
|
||||
(s/def ::typography ::spec/typography)
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.common.pages.changes
|
||||
#_:clj-kondo/ignore
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.exceptions :as ex]
|
||||
|
@ -13,9 +14,9 @@
|
|||
[app.common.pages.common :refer [component-sync-attrs]]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.pages.init :as init]
|
||||
[app.common.pages.spec :as spec]
|
||||
[app.common.spec :as us]))
|
||||
|
||||
[app.common.spec :as us]
|
||||
[app.common.spec.change :as spec.change]
|
||||
[app.common.spec.shape :as spec.shape]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Specific helpers
|
||||
|
@ -47,7 +48,7 @@
|
|||
;; When verify? false we spec the schema validation. Currently used to make just
|
||||
;; 1 validation even if the changes are applied twice
|
||||
(when verify?
|
||||
(us/assert ::spec/changes items))
|
||||
(us/assert ::spec.change/changes items))
|
||||
|
||||
(let [result (reduce #(or (process-change %1 %2) %1) data items)]
|
||||
;; Validate result shapes (only on the backend)
|
||||
|
@ -57,7 +58,7 @@
|
|||
(doseq [[id shape] (:objects page)]
|
||||
(when-not (= shape (get-in data [:pages-index page-id :objects id]))
|
||||
;; If object has change verify is correct
|
||||
(us/verify ::spec/shape shape))))))
|
||||
(us/verify ::spec.shape/shape shape))))))
|
||||
|
||||
result)))
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.interactions :as cti]
|
||||
[app.common.spec.interactions :as cti]
|
||||
[app.common.uuid :as uuid]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
|
@ -464,3 +464,4 @@
|
|||
(tree-seq #(d/not-empty? (get shape :shapes))
|
||||
#(->> (get % :shapes) (map getter))
|
||||
shape)))
|
||||
|
||||
|
|
|
@ -1,623 +0,0 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.pages.spec
|
||||
(:require
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.interactions :as cti]
|
||||
[app.common.types.page-options :as cto]
|
||||
[app.common.types.radius :as ctr]
|
||||
[app.common.uuid :as uuid]
|
||||
[clojure.set :as set]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;; --- Specs
|
||||
|
||||
(s/def ::frame-id uuid?)
|
||||
(s/def ::id uuid?)
|
||||
(s/def ::name string?)
|
||||
(s/def ::path (s/nilable string?))
|
||||
(s/def ::page-id uuid?)
|
||||
(s/def ::parent-id uuid?)
|
||||
(s/def ::string string?)
|
||||
(s/def ::type keyword?)
|
||||
(s/def ::uuid uuid?)
|
||||
|
||||
(s/def ::component-id uuid?)
|
||||
(s/def ::component-file uuid?)
|
||||
(s/def ::component-root? boolean?)
|
||||
(s/def ::shape-ref uuid?)
|
||||
|
||||
(s/def :internal.matrix/a ::us/safe-number)
|
||||
(s/def :internal.matrix/b ::us/safe-number)
|
||||
(s/def :internal.matrix/c ::us/safe-number)
|
||||
(s/def :internal.matrix/d ::us/safe-number)
|
||||
(s/def :internal.matrix/e ::us/safe-number)
|
||||
(s/def :internal.matrix/f ::us/safe-number)
|
||||
|
||||
(s/def ::matrix
|
||||
(s/and (s/keys :req-un [:internal.matrix/a
|
||||
:internal.matrix/b
|
||||
:internal.matrix/c
|
||||
:internal.matrix/d
|
||||
:internal.matrix/e
|
||||
:internal.matrix/f])
|
||||
gmt/matrix?))
|
||||
|
||||
|
||||
(s/def :internal.point/x ::us/safe-number)
|
||||
(s/def :internal.point/y ::us/safe-number)
|
||||
|
||||
(s/def ::point
|
||||
(s/and (s/keys :req-un [:internal.point/x
|
||||
:internal.point/y])
|
||||
gpt/point?))
|
||||
|
||||
;; GRADIENTS
|
||||
|
||||
(s/def :internal.gradient.stop/color ::string)
|
||||
(s/def :internal.gradient.stop/opacity ::us/safe-number)
|
||||
(s/def :internal.gradient.stop/offset ::us/safe-number)
|
||||
|
||||
(s/def :internal.gradient/type #{:linear :radial})
|
||||
(s/def :internal.gradient/start-x ::us/safe-number)
|
||||
(s/def :internal.gradient/start-y ::us/safe-number)
|
||||
(s/def :internal.gradient/end-x ::us/safe-number)
|
||||
(s/def :internal.gradient/end-y ::us/safe-number)
|
||||
(s/def :internal.gradient/width ::us/safe-number)
|
||||
|
||||
(s/def :internal.gradient/stop
|
||||
(s/keys :req-un [:internal.gradient.stop/color
|
||||
:internal.gradient.stop/opacity
|
||||
:internal.gradient.stop/offset]))
|
||||
|
||||
(s/def :internal.gradient/stops
|
||||
(s/coll-of :internal.gradient/stop :kind vector?))
|
||||
|
||||
(s/def ::gradient
|
||||
(s/keys :req-un [:internal.gradient/type
|
||||
:internal.gradient/start-x
|
||||
:internal.gradient/start-y
|
||||
:internal.gradient/end-x
|
||||
:internal.gradient/end-y
|
||||
:internal.gradient/width
|
||||
:internal.gradient/stops]))
|
||||
|
||||
|
||||
;;; COLORS
|
||||
|
||||
(s/def :internal.color/name ::string)
|
||||
(s/def :internal.color/path (s/nilable ::string))
|
||||
(s/def :internal.color/value (s/nilable ::string))
|
||||
(s/def :internal.color/color (s/nilable ::string))
|
||||
(s/def :internal.color/opacity (s/nilable ::us/safe-number))
|
||||
(s/def :internal.color/gradient (s/nilable ::gradient))
|
||||
|
||||
(s/def ::color
|
||||
(s/keys :opt-un [::id
|
||||
:internal.color/name
|
||||
:internal.color/path
|
||||
:internal.color/value
|
||||
:internal.color/color
|
||||
:internal.color/opacity
|
||||
:internal.color/gradient]))
|
||||
|
||||
|
||||
;;; SHADOW EFFECT
|
||||
|
||||
(s/def :internal.shadow/id uuid?)
|
||||
(s/def :internal.shadow/style #{:drop-shadow :inner-shadow})
|
||||
(s/def :internal.shadow/color ::color)
|
||||
(s/def :internal.shadow/offset-x ::us/safe-number)
|
||||
(s/def :internal.shadow/offset-y ::us/safe-number)
|
||||
(s/def :internal.shadow/blur ::us/safe-number)
|
||||
(s/def :internal.shadow/spread ::us/safe-number)
|
||||
(s/def :internal.shadow/hidden boolean?)
|
||||
|
||||
(s/def :internal.shadow/shadow
|
||||
(s/keys :req-un [:internal.shadow/id
|
||||
:internal.shadow/style
|
||||
:internal.shadow/color
|
||||
:internal.shadow/offset-x
|
||||
:internal.shadow/offset-y
|
||||
:internal.shadow/blur
|
||||
:internal.shadow/spread
|
||||
:internal.shadow/hidden]))
|
||||
|
||||
(s/def ::shadow
|
||||
(s/coll-of :internal.shadow/shadow :kind vector?))
|
||||
|
||||
|
||||
;;; BLUR EFFECT
|
||||
|
||||
(s/def :internal.blur/id uuid?)
|
||||
(s/def :internal.blur/type #{:layer-blur})
|
||||
(s/def :internal.blur/value ::us/safe-number)
|
||||
(s/def :internal.blur/hidden boolean?)
|
||||
|
||||
(s/def ::blur
|
||||
(s/keys :req-un [:internal.blur/id
|
||||
:internal.blur/type
|
||||
:internal.blur/value
|
||||
:internal.blur/hidden]))
|
||||
|
||||
;; Size constraints
|
||||
|
||||
(s/def :internal.shape/constraints-h #{:left :right :leftright :center :scale})
|
||||
(s/def :internal.shape/constraints-v #{:top :bottom :topbottom :center :scale})
|
||||
(s/def :internal.shape/fixed-scroll boolean?)
|
||||
|
||||
; Shapes in the top frame have no constraints. Shapes directly below some
|
||||
; frame are left-top constrained. Else (shapes in a group) are scaled.
|
||||
(defn default-constraints-h
|
||||
[shape]
|
||||
(if (= (:parent-id shape) uuid/zero)
|
||||
nil
|
||||
(if (= (:parent-id shape) (:frame-id shape))
|
||||
:left
|
||||
:scale)))
|
||||
|
||||
(defn default-constraints-v
|
||||
[shape]
|
||||
(if (= (:parent-id shape) uuid/zero)
|
||||
nil
|
||||
(if (= (:parent-id shape) (:frame-id shape))
|
||||
:top
|
||||
:scale)))
|
||||
|
||||
;; Page Data related
|
||||
(s/def :internal.shape/blocked boolean?)
|
||||
(s/def :internal.shape/collapsed boolean?)
|
||||
|
||||
(s/def :internal.shape/fill-color string?)
|
||||
(s/def :internal.shape/fill-opacity ::us/safe-number)
|
||||
(s/def :internal.shape/fill-color-gradient (s/nilable ::gradient))
|
||||
(s/def :internal.shape/fill-color-ref-file (s/nilable uuid?))
|
||||
(s/def :internal.shape/fill-color-ref-id (s/nilable uuid?))
|
||||
(s/def :internal.shape/hide-fill-on-export boolean?)
|
||||
|
||||
(s/def :internal.shape/font-family string?)
|
||||
(s/def :internal.shape/font-size ::us/safe-integer)
|
||||
(s/def :internal.shape/font-style string?)
|
||||
(s/def :internal.shape/font-weight string?)
|
||||
(s/def :internal.shape/hidden boolean?)
|
||||
(s/def :internal.shape/letter-spacing ::us/safe-number)
|
||||
(s/def :internal.shape/line-height ::us/safe-number)
|
||||
(s/def :internal.shape/locked boolean?)
|
||||
(s/def :internal.shape/page-id uuid?)
|
||||
(s/def :internal.shape/proportion ::us/safe-number)
|
||||
(s/def :internal.shape/proportion-lock boolean?)
|
||||
(s/def :internal.shape/stroke-color string?)
|
||||
(s/def :internal.shape/stroke-color-gradient (s/nilable ::gradient))
|
||||
(s/def :internal.shape/stroke-color-ref-file (s/nilable uuid?))
|
||||
(s/def :internal.shape/stroke-color-ref-id (s/nilable uuid?))
|
||||
(s/def :internal.shape/stroke-opacity ::us/safe-number)
|
||||
(s/def :internal.shape/stroke-style #{:solid :dotted :dashed :mixed :none :svg})
|
||||
|
||||
(def stroke-caps-line #{:round :square})
|
||||
(def stroke-caps-marker #{:line-arrow :triangle-arrow :square-marker :circle-marker :diamond-marker})
|
||||
(def stroke-caps (set/union stroke-caps-line stroke-caps-marker))
|
||||
(s/def :internal.shape/stroke-cap-start stroke-caps)
|
||||
(s/def :internal.shape/stroke-cap-end stroke-caps)
|
||||
|
||||
(defn has-caps?
|
||||
[shape]
|
||||
(= (:type shape) :path))
|
||||
|
||||
(s/def :internal.shape/stroke-width ::us/safe-number)
|
||||
(s/def :internal.shape/stroke-alignment #{:center :inner :outer})
|
||||
(s/def :internal.shape/text-align #{"left" "right" "center" "justify"})
|
||||
(s/def :internal.shape/x ::us/safe-number)
|
||||
(s/def :internal.shape/y ::us/safe-number)
|
||||
(s/def :internal.shape/cx ::us/safe-number)
|
||||
(s/def :internal.shape/cy ::us/safe-number)
|
||||
(s/def :internal.shape/width ::us/safe-number)
|
||||
(s/def :internal.shape/height ::us/safe-number)
|
||||
(s/def :internal.shape/index integer?)
|
||||
(s/def :internal.shape/shadow ::shadow)
|
||||
(s/def :internal.shape/blur ::blur)
|
||||
|
||||
(s/def :internal.shape/x1 ::us/safe-number)
|
||||
(s/def :internal.shape/y1 ::us/safe-number)
|
||||
(s/def :internal.shape/x2 ::us/safe-number)
|
||||
(s/def :internal.shape/y2 ::us/safe-number)
|
||||
|
||||
(s/def :internal.shape.export/suffix string?)
|
||||
(s/def :internal.shape.export/scale ::us/safe-number)
|
||||
(s/def :internal.shape/export
|
||||
(s/keys :req-un [::type
|
||||
:internal.shape.export/suffix
|
||||
:internal.shape.export/scale]))
|
||||
|
||||
(s/def :internal.shape/exports
|
||||
(s/coll-of :internal.shape/export :kind vector?))
|
||||
|
||||
(s/def :internal.shape/selrect
|
||||
(s/keys :req-un [:internal.shape/x
|
||||
:internal.shape/y
|
||||
:internal.shape/x1
|
||||
:internal.shape/y1
|
||||
:internal.shape/x2
|
||||
:internal.shape/y2
|
||||
:internal.shape/width
|
||||
:internal.shape/height]))
|
||||
|
||||
(s/def :internal.shape/points
|
||||
(s/every ::point :kind vector?))
|
||||
|
||||
(s/def :internal.shape/shapes
|
||||
(s/every uuid? :kind vector?))
|
||||
|
||||
(s/def :internal.shape/transform ::matrix)
|
||||
(s/def :internal.shape/transform-inverse ::matrix)
|
||||
|
||||
(s/def :internal.shape/opacity ::us/safe-number)
|
||||
(s/def :internal.shape/blend-mode
|
||||
#{:normal
|
||||
:darken
|
||||
:multiply
|
||||
:color-burn
|
||||
:lighten
|
||||
:screen
|
||||
:color-dodge
|
||||
:overlay
|
||||
:soft-light
|
||||
:hard-light
|
||||
:difference
|
||||
:exclusion
|
||||
:hue
|
||||
:saturation
|
||||
:color
|
||||
:luminosity})
|
||||
|
||||
(s/def ::shape-attrs
|
||||
(s/keys :opt-un [::id
|
||||
::type
|
||||
::name
|
||||
::component-id
|
||||
::component-file
|
||||
::component-root?
|
||||
::shape-ref
|
||||
:internal.shape/selrect
|
||||
:internal.shape/points
|
||||
:internal.shape/blocked
|
||||
:internal.shape/collapsed
|
||||
:internal.shape/fill-color
|
||||
:internal.shape/fill-opacity
|
||||
:internal.shape/fill-color-gradient
|
||||
:internal.shape/fill-color-ref-file
|
||||
:internal.shape/fill-color-ref-id
|
||||
:internal.shape/font-family
|
||||
:internal.shape/font-size
|
||||
:internal.shape/font-style
|
||||
:internal.shape/font-weight
|
||||
:internal.shape/hidden
|
||||
:internal.shape/letter-spacing
|
||||
:internal.shape/line-height
|
||||
:internal.shape/locked
|
||||
:internal.shape/proportion
|
||||
:internal.shape/proportion-lock
|
||||
:internal.shape/constraints-h
|
||||
:internal.shape/constraints-v
|
||||
:internal.shape/fixed-scroll
|
||||
::ctr/rx
|
||||
::ctr/ry
|
||||
::ctr/r1
|
||||
::ctr/r2
|
||||
::ctr/r3
|
||||
::ctr/r4
|
||||
:internal.shape/x
|
||||
:internal.shape/y
|
||||
:internal.shape/exports
|
||||
:internal.shape/shapes
|
||||
:internal.shape/stroke-color
|
||||
:internal.shape/stroke-color-ref-file
|
||||
:internal.shape/stroke-color-ref-id
|
||||
:internal.shape/stroke-opacity
|
||||
:internal.shape/stroke-style
|
||||
:internal.shape/stroke-width
|
||||
:internal.shape/stroke-alignment
|
||||
:internal.shape/stroke-cap-start
|
||||
:internal.shape/stroke-cap-end
|
||||
:internal.shape/text-align
|
||||
:internal.shape/transform
|
||||
:internal.shape/transform-inverse
|
||||
:internal.shape/width
|
||||
:internal.shape/height
|
||||
::cti/interactions
|
||||
:internal.shape/masked-group?
|
||||
:internal.shape/shadow
|
||||
:internal.shape/blur
|
||||
:internal.shape/opacity
|
||||
:internal.shape/blend-mode]))
|
||||
|
||||
(s/def :internal.shape.text/type #{"root" "paragraph-set" "paragraph"})
|
||||
(s/def :internal.shape.text/children
|
||||
(s/coll-of :internal.shape.text/content
|
||||
:kind vector?
|
||||
:min-count 1))
|
||||
|
||||
(s/def :internal.shape.text/text string?)
|
||||
(s/def :internal.shape.text/key string?)
|
||||
|
||||
(s/def :internal.shape.text/content
|
||||
(s/nilable
|
||||
(s/or :text-container
|
||||
(s/keys :req-un [:internal.shape.text/type
|
||||
:internal.shape.text/children]
|
||||
:opt-un [:internal.shape.text/key])
|
||||
:text-content
|
||||
(s/keys :req-un [:internal.shape.text/text]))))
|
||||
|
||||
(s/def :internal.shape.path/command keyword?)
|
||||
(s/def :internal.shape.path/params
|
||||
(s/nilable (s/map-of keyword? any?)))
|
||||
|
||||
(s/def :internal.shape.path/command-item
|
||||
(s/keys :req-un [:internal.shape.path/command]
|
||||
:opt-un [:internal.shape.path/params]))
|
||||
|
||||
(s/def :internal.shape.path/content
|
||||
(s/coll-of :internal.shape.path/command-item :kind vector?))
|
||||
|
||||
(defmulti shape-spec :type)
|
||||
|
||||
(defmethod shape-spec :default [_]
|
||||
(s/spec ::shape-attrs))
|
||||
|
||||
(defmethod shape-spec :text [_]
|
||||
(s/and ::shape-attrs
|
||||
(s/keys :opt-un [:internal.shape.text/content])))
|
||||
|
||||
(defmethod shape-spec :path [_]
|
||||
(s/and ::shape-attrs
|
||||
(s/keys :opt-un [:internal.shape.path/content])))
|
||||
|
||||
(defmethod shape-spec :frame [_]
|
||||
(s/and ::shape-attrs
|
||||
(s/keys :opt-un [:internal.shape/hide-fill-on-export])))
|
||||
|
||||
(s/def ::shape
|
||||
(s/and (s/multi-spec shape-spec :type)
|
||||
#(contains? % :name)
|
||||
#(contains? % :type)))
|
||||
|
||||
(s/def :internal.page/objects (s/map-of uuid? ::shape))
|
||||
|
||||
(s/def ::page
|
||||
(s/keys :req-un [::id
|
||||
::name
|
||||
::cto/options
|
||||
:internal.page/objects]))
|
||||
|
||||
(s/def ::recent-color
|
||||
(s/keys :opt-un [:internal.color/value
|
||||
:internal.color/color
|
||||
:internal.color/opacity
|
||||
:internal.color/gradient]))
|
||||
|
||||
(s/def :internal.media-object/name ::string)
|
||||
(s/def :internal.media-object/width ::us/safe-integer)
|
||||
(s/def :internal.media-object/height ::us/safe-integer)
|
||||
(s/def :internal.media-object/mtype ::string)
|
||||
|
||||
(s/def ::media-object
|
||||
(s/keys :req-un [::id
|
||||
::name
|
||||
:internal.media-object/width
|
||||
:internal.media-object/height
|
||||
:internal.media-object/mtype]))
|
||||
|
||||
(s/def ::media-object-update
|
||||
(s/keys :req-un [::id]
|
||||
:opt-un [::name
|
||||
:internal.media-object/width
|
||||
:internal.media-object/height
|
||||
:internal.media-object/mtype]))
|
||||
|
||||
(s/def :internal.file/colors
|
||||
(s/map-of ::uuid ::color))
|
||||
|
||||
(s/def :internal.file/recent-colors
|
||||
(s/coll-of ::recent-color :kind vector?))
|
||||
|
||||
(s/def :internal.typography/id ::id)
|
||||
(s/def :internal.typography/name ::string)
|
||||
(s/def :internal.typography/path (s/nilable ::string))
|
||||
(s/def :internal.typography/font-id ::string)
|
||||
(s/def :internal.typography/font-family ::string)
|
||||
(s/def :internal.typography/font-variant-id ::string)
|
||||
(s/def :internal.typography/font-size ::string)
|
||||
(s/def :internal.typography/font-weight ::string)
|
||||
(s/def :internal.typography/font-style ::string)
|
||||
(s/def :internal.typography/line-height ::string)
|
||||
(s/def :internal.typography/letter-spacing ::string)
|
||||
(s/def :internal.typography/text-transform ::string)
|
||||
|
||||
(s/def ::typography
|
||||
(s/keys :req-un [:internal.typography/id
|
||||
:internal.typography/name
|
||||
:internal.typography/font-id
|
||||
:internal.typography/font-family
|
||||
:internal.typography/font-variant-id
|
||||
:internal.typography/font-size
|
||||
:internal.typography/font-weight
|
||||
:internal.typography/font-style
|
||||
:internal.typography/line-height
|
||||
:internal.typography/letter-spacing
|
||||
:internal.typography/text-transform]
|
||||
:opt-un [:internal.typography/path]))
|
||||
|
||||
(s/def :internal.file/pages
|
||||
(s/coll-of ::uuid :kind vector?))
|
||||
|
||||
(s/def :internal.file/media
|
||||
(s/map-of ::uuid ::media-object))
|
||||
|
||||
(s/def :internal.file/pages-index
|
||||
(s/map-of ::uuid ::page))
|
||||
|
||||
(s/def ::data
|
||||
(s/keys :req-un [:internal.file/pages-index
|
||||
:internal.file/pages]
|
||||
:opt-un [:internal.file/colors
|
||||
:internal.file/recent-colors
|
||||
:internal.file/media]))
|
||||
|
||||
(s/def :internal.container/type #{:page :component})
|
||||
|
||||
(s/def ::container
|
||||
(s/keys :req-un [:internal.container/type
|
||||
::id
|
||||
::name
|
||||
:internal.page/objects]))
|
||||
|
||||
(defmulti operation-spec :type)
|
||||
|
||||
(s/def :internal.operations.set/attr keyword?)
|
||||
(s/def :internal.operations.set/val any?)
|
||||
(s/def :internal.operations.set/touched
|
||||
(s/nilable (s/every keyword? :kind set?)))
|
||||
(s/def :internal.operations.set/remote-synced?
|
||||
(s/nilable boolean?))
|
||||
|
||||
(defmethod operation-spec :set [_]
|
||||
(s/keys :req-un [:internal.operations.set/attr
|
||||
:internal.operations.set/val]))
|
||||
|
||||
(defmethod operation-spec :set-touched [_]
|
||||
(s/keys :req-un [:internal.operations.set/touched]))
|
||||
|
||||
(defmethod operation-spec :set-remote-synced [_]
|
||||
(s/keys :req-un [:internal.operations.set/remote-synced?]))
|
||||
|
||||
(defmulti change-spec :type)
|
||||
|
||||
(s/def :internal.changes.set-option/option any?)
|
||||
(s/def :internal.changes.set-option/value any?)
|
||||
|
||||
(defmethod change-spec :set-option [_]
|
||||
(s/keys :req-un [:internal.changes.set-option/option
|
||||
:internal.changes.set-option/value]))
|
||||
|
||||
(s/def :internal.changes.add-obj/obj ::shape)
|
||||
|
||||
(defn- valid-container-id-frame?
|
||||
[o]
|
||||
(or (and (contains? o :page-id)
|
||||
(not (contains? o :component-id))
|
||||
(some? (:frame-id o)))
|
||||
(and (contains? o :component-id)
|
||||
(not (contains? o :page-id))
|
||||
(nil? (:frame-id o)))))
|
||||
|
||||
(defn- valid-container-id?
|
||||
[o]
|
||||
(or (and (contains? o :page-id)
|
||||
(not (contains? o :component-id)))
|
||||
(and (contains? o :component-id)
|
||||
(not (contains? o :page-id)))))
|
||||
|
||||
(defmethod change-spec :add-obj [_]
|
||||
(s/and (s/keys :req-un [::id :internal.changes.add-obj/obj]
|
||||
:opt-un [::page-id ::component-id ::parent-id ::frame-id])
|
||||
valid-container-id-frame?))
|
||||
|
||||
(s/def ::operation (s/multi-spec operation-spec :type))
|
||||
(s/def ::operations (s/coll-of ::operation))
|
||||
|
||||
(defmethod change-spec :mod-obj [_]
|
||||
(s/and (s/keys :req-un [::id ::operations]
|
||||
:opt-un [::page-id ::component-id])
|
||||
valid-container-id?))
|
||||
|
||||
(defmethod change-spec :del-obj [_]
|
||||
(s/and (s/keys :req-un [::id]
|
||||
:opt-un [::page-id ::component-id])
|
||||
valid-container-id?))
|
||||
|
||||
(s/def :internal.changes.reg-objects/shapes
|
||||
(s/coll-of uuid? :kind vector?))
|
||||
|
||||
(defmethod change-spec :reg-objects [_]
|
||||
(s/and (s/keys :req-un [:internal.changes.reg-objects/shapes]
|
||||
:opt-un [::page-id ::component-id])
|
||||
valid-container-id?))
|
||||
|
||||
(defmethod change-spec :mov-objects [_]
|
||||
(s/and (s/keys :req-un [::parent-id :internal.shape/shapes]
|
||||
:opt-un [::page-id ::component-id ::index])
|
||||
valid-container-id?))
|
||||
|
||||
(defmethod change-spec :add-page [_]
|
||||
(s/or :empty (s/keys :req-un [::id ::name])
|
||||
:complete (s/keys :req-un [::page])))
|
||||
|
||||
(defmethod change-spec :mod-page [_]
|
||||
(s/keys :req-un [::id ::name]))
|
||||
|
||||
(defmethod change-spec :del-page [_]
|
||||
(s/keys :req-un [::id]))
|
||||
|
||||
(defmethod change-spec :mov-page [_]
|
||||
(s/keys :req-un [::id ::index]))
|
||||
|
||||
(defmethod change-spec :add-color [_]
|
||||
(s/keys :req-un [::color]))
|
||||
|
||||
(defmethod change-spec :mod-color [_]
|
||||
(s/keys :req-un [::color]))
|
||||
|
||||
(defmethod change-spec :del-color [_]
|
||||
(s/keys :req-un [::id]))
|
||||
|
||||
(s/def :internal.changes.add-recent-color/color ::recent-color)
|
||||
|
||||
(defmethod change-spec :add-recent-color [_]
|
||||
(s/keys :req-un [:internal.changes.add-recent-color/color]))
|
||||
|
||||
(s/def :internal.changes.media/object ::media-object)
|
||||
|
||||
(defmethod change-spec :add-media [_]
|
||||
(s/keys :req-un [:internal.changes.media/object]))
|
||||
|
||||
(s/def :internal.changes.media.mod/object ::media-object-update)
|
||||
|
||||
(defmethod change-spec :mod-media [_]
|
||||
(s/keys :req-un [:internal.changes.media.mod/object]))
|
||||
|
||||
(defmethod change-spec :del-media [_]
|
||||
(s/keys :req-un [::id]))
|
||||
|
||||
(s/def :internal.changes.add-component/shapes
|
||||
(s/coll-of ::shape))
|
||||
|
||||
(defmethod change-spec :add-component [_]
|
||||
(s/keys :req-un [::id ::name :internal.changes.add-component/shapes]
|
||||
:opt-un [::path]))
|
||||
|
||||
(defmethod change-spec :mod-component [_]
|
||||
(s/keys :req-un [::id]
|
||||
:opt-un [::name :internal.changes.add-component/shapes]))
|
||||
|
||||
(defmethod change-spec :del-component [_]
|
||||
(s/keys :req-un [::id]))
|
||||
|
||||
(s/def :internal.changes.typography/typography ::typography)
|
||||
|
||||
(defmethod change-spec :add-typography [_]
|
||||
(s/keys :req-un [:internal.changes.typography/typography]))
|
||||
|
||||
(defmethod change-spec :mod-typography [_]
|
||||
(s/keys :req-un [:internal.changes.typography/typography]))
|
||||
|
||||
(defmethod change-spec :del-typography [_]
|
||||
(s/keys :req-un [:internal.typography/id]))
|
||||
|
||||
(s/def ::change (s/multi-spec change-spec :type))
|
||||
(s/def ::changes (s/coll-of ::change))
|
|
@ -16,7 +16,6 @@
|
|||
;; because of some strange interaction with cljs.spec.alpha and
|
||||
;; modules splitting.
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.uuid :as uuid]
|
||||
[cuerdas.core :as str]
|
||||
[expound.alpha]))
|
||||
|
@ -110,7 +109,6 @@
|
|||
(s/def ::not-empty-string (s/and string? #(not (str/empty? %))))
|
||||
(s/def ::url string?)
|
||||
(s/def ::fn fn?)
|
||||
(s/def ::point gpt/point?)
|
||||
(s/def ::id ::uuid)
|
||||
|
||||
(defn bytes?
|
||||
|
|
19
common/src/app/common/spec/blur.cljc
Normal file
19
common/src/app/common/spec/blur.cljc
Normal file
|
@ -0,0 +1,19 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.spec.blur
|
||||
(:require
|
||||
[app.common.spec :as us]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
(s/def ::id uuid?)
|
||||
(s/def ::type #{:layer-blur})
|
||||
(s/def ::value ::us/safe-number)
|
||||
(s/def ::hidden boolean?)
|
||||
|
||||
(s/def ::blur
|
||||
(s/keys :req-un [::id ::type ::value ::hidden]))
|
||||
|
165
common/src/app/common/spec/change.cljc
Normal file
165
common/src/app/common/spec/change.cljc
Normal file
|
@ -0,0 +1,165 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.spec.change
|
||||
(:require
|
||||
[app.common.spec.color :as color]
|
||||
[app.common.spec.file :as file]
|
||||
[app.common.spec.page :as page]
|
||||
[app.common.spec.shape :as shape]
|
||||
[app.common.spec.typography :as typg]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
(s/def ::index integer?)
|
||||
(s/def ::id uuid?)
|
||||
(s/def ::parent-id uuid?)
|
||||
(s/def ::frame-id uuid?)
|
||||
(s/def ::page-id uuid?)
|
||||
(s/def ::component-id uuid?)
|
||||
(s/def ::name string?)
|
||||
|
||||
(defmulti operation-spec :type)
|
||||
|
||||
(s/def :internal.operations.set/attr keyword?)
|
||||
(s/def :internal.operations.set/val any?)
|
||||
|
||||
(s/def :internal.operations.set/touched
|
||||
(s/nilable (s/every keyword? :kind set?)))
|
||||
|
||||
(s/def :internal.operations.set/remote-synced?
|
||||
(s/nilable boolean?))
|
||||
|
||||
(defmethod operation-spec :set [_]
|
||||
(s/keys :req-un [:internal.operations.set/attr
|
||||
:internal.operations.set/val]))
|
||||
|
||||
(defmethod operation-spec :set-touched [_]
|
||||
(s/keys :req-un [:internal.operations.set/touched]))
|
||||
|
||||
(defmethod operation-spec :set-remote-synced [_]
|
||||
(s/keys :req-un [:internal.operations.set/remote-synced?]))
|
||||
|
||||
(defmulti change-spec :type)
|
||||
|
||||
(s/def :internal.changes.set-option/option any?)
|
||||
(s/def :internal.changes.set-option/value any?)
|
||||
|
||||
(defmethod change-spec :set-option [_]
|
||||
(s/keys :req-un [:internal.changes.set-option/option
|
||||
:internal.changes.set-option/value]))
|
||||
|
||||
(s/def :internal.changes.add-obj/obj ::shape/shape)
|
||||
|
||||
(defn- valid-container-id-frame?
|
||||
[o]
|
||||
(or (and (contains? o :page-id)
|
||||
(not (contains? o :component-id))
|
||||
(some? (:frame-id o)))
|
||||
(and (contains? o :component-id)
|
||||
(not (contains? o :page-id))
|
||||
(nil? (:frame-id o)))))
|
||||
|
||||
(defn- valid-container-id?
|
||||
[o]
|
||||
(or (and (contains? o :page-id)
|
||||
(not (contains? o :component-id)))
|
||||
(and (contains? o :component-id)
|
||||
(not (contains? o :page-id)))))
|
||||
|
||||
(defmethod change-spec :add-obj [_]
|
||||
(s/and (s/keys :req-un [::id :internal.changes.add-obj/obj]
|
||||
:opt-un [::page-id ::component-id ::parent-id ::frame-id])
|
||||
valid-container-id-frame?))
|
||||
|
||||
(s/def ::operation (s/multi-spec operation-spec :type))
|
||||
(s/def ::operations (s/coll-of ::operation))
|
||||
|
||||
(defmethod change-spec :mod-obj [_]
|
||||
(s/and (s/keys :req-un [::id ::operations]
|
||||
:opt-un [::page-id ::component-id])
|
||||
valid-container-id?))
|
||||
|
||||
(defmethod change-spec :del-obj [_]
|
||||
(s/and (s/keys :req-un [::id]
|
||||
:opt-un [::page-id ::component-id])
|
||||
valid-container-id?))
|
||||
|
||||
(defmethod change-spec :reg-objects [_]
|
||||
(s/and (s/keys :req-un [::shape/shapes]
|
||||
:opt-un [::page-id ::component-id])
|
||||
valid-container-id?))
|
||||
|
||||
(defmethod change-spec :mov-objects [_]
|
||||
(s/and (s/keys :req-un [::parent-id ::shape/shapes]
|
||||
:opt-un [::page-id ::component-id ::index])
|
||||
valid-container-id?))
|
||||
|
||||
(defmethod change-spec :add-page [_]
|
||||
(s/or :empty (s/keys :req-un [::id ::name])
|
||||
:complete (s/keys :req-un [::page/page])))
|
||||
|
||||
(defmethod change-spec :mod-page [_]
|
||||
(s/keys :req-un [::id ::name]))
|
||||
|
||||
(defmethod change-spec :del-page [_]
|
||||
(s/keys :req-un [::id]))
|
||||
|
||||
(defmethod change-spec :mov-page [_]
|
||||
(s/keys :req-un [::id ::index]))
|
||||
|
||||
(defmethod change-spec :add-color [_]
|
||||
(s/keys :req-un [::color/color]))
|
||||
|
||||
(defmethod change-spec :mod-color [_]
|
||||
(s/keys :req-un [::color/color]))
|
||||
|
||||
(defmethod change-spec :del-color [_]
|
||||
(s/keys :req-un [::id]))
|
||||
|
||||
(s/def :internal.changes.add-recent-color/color ::color/recent-color)
|
||||
|
||||
(defmethod change-spec :add-recent-color [_]
|
||||
(s/keys :req-un [:internal.changes.add-recent-color/color]))
|
||||
|
||||
(s/def :internal.changes.media/object ::file/media-object)
|
||||
|
||||
(defmethod change-spec :add-media [_]
|
||||
(s/keys :req-un [:internal.changes.media/object]))
|
||||
|
||||
(s/def :internal.changes.media.mod/object
|
||||
(s/and ::file/media-object #(contains? % :id)))
|
||||
|
||||
(defmethod change-spec :mod-media [_]
|
||||
(s/keys :req-un [:internal.changes.media.mod/object]))
|
||||
|
||||
(defmethod change-spec :del-media [_]
|
||||
(s/keys :req-un [::id]))
|
||||
|
||||
(s/def :internal.changes.add-component/shapes
|
||||
(s/coll-of ::shape/shape))
|
||||
|
||||
(defmethod change-spec :add-component [_]
|
||||
(s/keys :req-un [::id ::name :internal.changes.add-component/shapes]
|
||||
:opt-un [::path]))
|
||||
|
||||
(defmethod change-spec :mod-component [_]
|
||||
(s/keys :req-un [::id]
|
||||
:opt-un [::name :internal.changes.add-component/shapes]))
|
||||
|
||||
(defmethod change-spec :del-component [_]
|
||||
(s/keys :req-un [::id]))
|
||||
|
||||
(defmethod change-spec :add-typography [_]
|
||||
(s/keys :req-un [::typg/typography]))
|
||||
|
||||
(defmethod change-spec :mod-typography [_]
|
||||
(s/keys :req-un [::typg/typography]))
|
||||
|
||||
(defmethod change-spec :del-typography [_]
|
||||
(s/keys :req-un [::typg/id]))
|
||||
|
||||
(s/def ::change (s/multi-spec change-spec :type))
|
||||
(s/def ::changes (s/coll-of ::change))
|
75
common/src/app/common/spec/color.cljc
Normal file
75
common/src/app/common/spec/color.cljc
Normal file
|
@ -0,0 +1,75 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.spec.color
|
||||
(:require
|
||||
[app.common.spec :as us]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;; TODO: waiting clojure 1.11 to rename this all :internal.stuff to a
|
||||
;; more consistent name.
|
||||
|
||||
;; TODO: maybe define ::color-hex-string with proper hex color spec?
|
||||
|
||||
;; --- GRADIENTS
|
||||
|
||||
(s/def ::id uuid?)
|
||||
|
||||
(s/def :internal.gradient.stop/color string?)
|
||||
(s/def :internal.gradient.stop/opacity ::us/safe-number)
|
||||
(s/def :internal.gradient.stop/offset ::us/safe-number)
|
||||
|
||||
(s/def :internal.gradient/type #{:linear :radial})
|
||||
(s/def :internal.gradient/start-x ::us/safe-number)
|
||||
(s/def :internal.gradient/start-y ::us/safe-number)
|
||||
(s/def :internal.gradient/end-x ::us/safe-number)
|
||||
(s/def :internal.gradient/end-y ::us/safe-number)
|
||||
(s/def :internal.gradient/width ::us/safe-number)
|
||||
|
||||
(s/def :internal.gradient/stop
|
||||
(s/keys :req-un [:internal.gradient.stop/color
|
||||
:internal.gradient.stop/opacity
|
||||
:internal.gradient.stop/offset]))
|
||||
|
||||
(s/def :internal.gradient/stops
|
||||
(s/coll-of :internal.gradient/stop :kind vector?))
|
||||
|
||||
(s/def ::gradient
|
||||
(s/keys :req-un [:internal.gradient/type
|
||||
:internal.gradient/start-x
|
||||
:internal.gradient/start-y
|
||||
:internal.gradient/end-x
|
||||
:internal.gradient/end-y
|
||||
:internal.gradient/width
|
||||
:internal.gradient/stops]))
|
||||
|
||||
;;; --- COLORS
|
||||
|
||||
(s/def :internal.color/name string?)
|
||||
(s/def :internal.color/path (s/nilable string?))
|
||||
(s/def :internal.color/value (s/nilable string?))
|
||||
(s/def :internal.color/color (s/nilable string?))
|
||||
(s/def :internal.color/opacity (s/nilable ::us/safe-number))
|
||||
(s/def :internal.color/gradient (s/nilable ::gradient))
|
||||
|
||||
(s/def ::color
|
||||
(s/keys :opt-un [::id
|
||||
:internal.color/name
|
||||
:internal.color/path
|
||||
:internal.color/value
|
||||
:internal.color/color
|
||||
:internal.color/opacity
|
||||
:internal.color/gradient]))
|
||||
|
||||
(s/def ::recent-color
|
||||
(s/keys :opt-un [:internal.color/value
|
||||
:internal.color/color
|
||||
:internal.color/opacity
|
||||
:internal.color/gradient]))
|
||||
|
||||
|
||||
|
||||
|
22
common/src/app/common/spec/export.cljc
Normal file
22
common/src/app/common/spec/export.cljc
Normal file
|
@ -0,0 +1,22 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.spec.export
|
||||
(:require
|
||||
[app.common.spec :as us]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
|
||||
(s/def ::suffix string?)
|
||||
(s/def ::scale ::us/safe-number)
|
||||
(s/def ::type keyword?)
|
||||
|
||||
(s/def ::export
|
||||
(s/keys :req-un [::type
|
||||
::suffix
|
||||
::scale]))
|
||||
|
||||
|
54
common/src/app/common/spec/file.cljc
Normal file
54
common/src/app/common/spec/file.cljc
Normal file
|
@ -0,0 +1,54 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.spec.file
|
||||
(:require
|
||||
[app.common.spec :as us]
|
||||
[app.common.spec.color :as color]
|
||||
[app.common.spec.page :as page]
|
||||
[app.common.spec.typography]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
(s/def :internal.media-object/name string?)
|
||||
(s/def :internal.media-object/width ::us/safe-integer)
|
||||
(s/def :internal.media-object/height ::us/safe-integer)
|
||||
(s/def :internal.media-object/mtype string?)
|
||||
|
||||
(s/def ::media-object
|
||||
(s/keys :req-un [::id
|
||||
::name
|
||||
:internal.media-object/width
|
||||
:internal.media-object/height
|
||||
:internal.media-object/mtype]))
|
||||
|
||||
(s/def ::colors
|
||||
(s/map-of uuid? ::color/color))
|
||||
|
||||
(s/def ::recent-colors
|
||||
(s/coll-of ::color/recent-color :kind vector?))
|
||||
|
||||
(s/def ::typographies
|
||||
(s/map-of uuid? :app.common.spec.typography/typography))
|
||||
|
||||
(s/def ::pages
|
||||
(s/coll-of uuid? :kind vector?))
|
||||
|
||||
(s/def ::media
|
||||
(s/map-of uuid? ::media-object))
|
||||
|
||||
(s/def ::pages-index
|
||||
(s/map-of uuid? ::page/page))
|
||||
|
||||
(s/def ::components
|
||||
(s/map-of uuid? ::page/container))
|
||||
|
||||
(s/def ::data
|
||||
(s/keys :req-un [::pages-index
|
||||
::pages]
|
||||
:opt-un [::colors
|
||||
::recent-colors
|
||||
::typographies
|
||||
::media]))
|
|
@ -4,7 +4,7 @@
|
|||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.common.types.interactions
|
||||
(ns app.common.spec.interactions
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
|
@ -100,7 +100,7 @@
|
|||
:bottom-left
|
||||
:bottom-right
|
||||
:bottom-center})
|
||||
(s/def ::overlay-position ::us/point)
|
||||
(s/def ::overlay-position ::gpt/point)
|
||||
(s/def ::url ::us/string)
|
||||
(s/def ::close-click-outside ::us/boolean)
|
||||
(s/def ::background-overlay ::us/boolean)
|
129
common/src/app/common/spec/page.cljc
Normal file
129
common/src/app/common/spec/page.cljc
Normal file
|
@ -0,0 +1,129 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.spec.page
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.spec :as us]
|
||||
[app.common.spec.shape :as shape]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
|
||||
;; --- Grid options
|
||||
|
||||
(s/def :internal.grid.color/color string?)
|
||||
(s/def :internal.grid.color/opacity ::us/safe-number)
|
||||
|
||||
(s/def :internal.grid/size (s/nilable ::us/safe-integer))
|
||||
(s/def :internal.grid/item-length (s/nilable ::us/safe-number))
|
||||
|
||||
(s/def :internal.grid/color (s/keys :req-un [:internal.grid.color/color
|
||||
:internal.grid.color/opacity]))
|
||||
(s/def :internal.grid/type #{:stretch :left :center :right})
|
||||
(s/def :internal.grid/gutter (s/nilable ::us/safe-integer))
|
||||
(s/def :internal.grid/margin (s/nilable ::us/safe-integer))
|
||||
|
||||
(s/def :internal.grid/square
|
||||
(s/keys :req-un [:internal.grid/size
|
||||
:internal.grid/color]))
|
||||
|
||||
(s/def :internal.grid/column
|
||||
(s/keys :req-un [:internal.grid/color]
|
||||
:opt-un [:internal.grid/size
|
||||
:internal.grid/type
|
||||
:internal.grid/item-length
|
||||
:internal.grid/margin
|
||||
:internal.grid/gutter]))
|
||||
|
||||
(s/def :internal.grid/row :internal.grid/column)
|
||||
|
||||
(s/def ::saved-grids
|
||||
(s/keys :opt-un [:internal.grid/square
|
||||
:internal.grid/row
|
||||
:internal.grid/column]))
|
||||
|
||||
;; --- Background options
|
||||
|
||||
(s/def ::background string?)
|
||||
|
||||
;; --- Flow options
|
||||
|
||||
(s/def :internal.flow/id uuid?)
|
||||
(s/def :internal.flow/name string?)
|
||||
(s/def :internal.flow/starting-frame uuid?)
|
||||
|
||||
(s/def ::flow
|
||||
(s/keys :req-un [:internal.flow/id
|
||||
:internal.flow/name
|
||||
:internal.flow/starting-frame]))
|
||||
|
||||
(s/def ::flows
|
||||
(s/coll-of ::flow :kind vector?))
|
||||
|
||||
;; --- Guides
|
||||
|
||||
(s/def :internal.guides/id uuid?)
|
||||
(s/def :internal.guides/axis #{:x :y})
|
||||
(s/def :internal.guides/position ::us/safe-number)
|
||||
(s/def :internal.guides/frame-id (s/nilable uuid?))
|
||||
|
||||
(s/def ::guide
|
||||
(s/keys :req-un [:internal.guides/id
|
||||
:internal.guides/axis
|
||||
:internal.guides/position]
|
||||
:opt-un [:internal.guides/frame-id]))
|
||||
|
||||
(s/def ::guides
|
||||
(s/map-of uuid? ::guide))
|
||||
|
||||
;; --- Page Options
|
||||
|
||||
(s/def ::options
|
||||
(s/keys :opt-un [::background
|
||||
::saved-grids
|
||||
::flows
|
||||
::guides]))
|
||||
|
||||
;; --- Page
|
||||
|
||||
(s/def ::id uuid?)
|
||||
(s/def ::name string?)
|
||||
(s/def ::objects (s/map-of uuid? ::shape/shape))
|
||||
|
||||
(s/def ::page
|
||||
(s/keys :req-un [::id ::name ::objects ::options]))
|
||||
|
||||
(s/def ::type #{:page :component})
|
||||
(s/def ::path (s/nilable string?))
|
||||
(s/def ::container
|
||||
(s/keys :req-un [::id ::name ::objects]
|
||||
:opt-un [::type ::path]))
|
||||
|
||||
;; --- Helpers for flow
|
||||
|
||||
(defn rename-flow
|
||||
[flow name]
|
||||
(assoc flow :name name))
|
||||
|
||||
(defn add-flow
|
||||
[flows flow]
|
||||
(conj (or flows []) flow))
|
||||
|
||||
(defn remove-flow
|
||||
[flows flow-id]
|
||||
(d/removev #(= (:id %) flow-id) flows))
|
||||
|
||||
(defn update-flow
|
||||
[flows flow-id update-fn]
|
||||
(let [index (d/index-of-pred flows #(= (:id %) flow-id))]
|
||||
(update flows index update-fn)))
|
||||
|
||||
(defn get-frame-flow
|
||||
[flows frame-id]
|
||||
(d/seek #(= (:starting-frame %) frame-id) flows))
|
||||
|
||||
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.common.types.radius
|
||||
(ns app.common.spec.radius
|
||||
(:require
|
||||
[app.common.spec :as us]
|
||||
[clojure.spec.alpha :as s]))
|
37
common/src/app/common/spec/shadow.cljc
Normal file
37
common/src/app/common/spec/shadow.cljc
Normal file
|
@ -0,0 +1,37 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.spec.shadow
|
||||
(:require
|
||||
[app.common.spec :as us]
|
||||
[app.common.spec.color :as color]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
|
||||
;;; SHADOW EFFECT
|
||||
|
||||
(s/def ::id uuid?)
|
||||
(s/def ::style #{:drop-shadow :inner-shadow})
|
||||
(s/def ::color ::color/color)
|
||||
(s/def ::offset-x ::us/safe-number)
|
||||
(s/def ::offset-y ::us/safe-number)
|
||||
(s/def ::blur ::us/safe-number)
|
||||
(s/def ::spread ::us/safe-number)
|
||||
(s/def ::hidden boolean?)
|
||||
|
||||
(s/def ::shadow-props
|
||||
(s/keys :req-un [:internal.shadow/id
|
||||
:internal.shadow/style
|
||||
:internal.shadow/color
|
||||
:internal.shadow/offset-x
|
||||
:internal.shadow/offset-y
|
||||
:internal.shadow/blur
|
||||
:internal.shadow/spread
|
||||
:internal.shadow/hidden]))
|
||||
|
||||
(s/def ::shadow
|
||||
(s/coll-of ::shadow-props :kind vector?))
|
||||
|
241
common/src/app/common/spec/shape.cljc
Normal file
241
common/src/app/common/spec/shape.cljc
Normal file
|
@ -0,0 +1,241 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.spec.shape
|
||||
(:require
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.spec :as us]
|
||||
[app.common.spec.blur :as blur]
|
||||
[app.common.spec.color :as color]
|
||||
[app.common.spec.export :as export]
|
||||
[app.common.spec.interactions :as cti]
|
||||
[app.common.spec.radius :as radius]
|
||||
[app.common.spec.shadow :as shadow]
|
||||
[clojure.set :as set]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;; --- Specs
|
||||
|
||||
(s/def ::frame-id uuid?)
|
||||
(s/def ::id uuid?)
|
||||
(s/def ::name string?)
|
||||
(s/def ::path (s/nilable string?))
|
||||
(s/def ::page-id uuid?)
|
||||
(s/def ::parent-id uuid?)
|
||||
(s/def ::string string?)
|
||||
(s/def ::type keyword?)
|
||||
(s/def ::uuid uuid?)
|
||||
|
||||
(s/def ::component-id uuid?)
|
||||
(s/def ::component-file uuid?)
|
||||
(s/def ::component-root? boolean?)
|
||||
(s/def ::shape-ref uuid?)
|
||||
|
||||
;; Size constraints
|
||||
|
||||
(s/def ::constraints-h #{:left :right :leftright :center :scale})
|
||||
(s/def ::constraints-v #{:top :bottom :topbottom :center :scale})
|
||||
(s/def ::fixed-scroll boolean?)
|
||||
|
||||
;; Page Data related
|
||||
(s/def ::blocked boolean?)
|
||||
(s/def ::collapsed boolean?)
|
||||
|
||||
(s/def ::fill-color string?)
|
||||
(s/def ::fill-opacity ::us/safe-number)
|
||||
(s/def ::fill-color-gradient (s/nilable ::color/gradient))
|
||||
(s/def ::fill-color-ref-file (s/nilable uuid?))
|
||||
(s/def ::fill-color-ref-id (s/nilable uuid?))
|
||||
|
||||
(s/def ::hide-fill-on-export boolean?)
|
||||
|
||||
(s/def ::masked-group? boolean?)
|
||||
(s/def ::font-family string?)
|
||||
(s/def ::font-size ::us/safe-integer)
|
||||
(s/def ::font-style string?)
|
||||
(s/def ::font-weight string?)
|
||||
(s/def ::hidden boolean?)
|
||||
(s/def ::letter-spacing ::us/safe-number)
|
||||
(s/def ::line-height ::us/safe-number)
|
||||
(s/def ::locked boolean?)
|
||||
(s/def ::page-id uuid?)
|
||||
(s/def ::proportion ::us/safe-number)
|
||||
(s/def ::proportion-lock boolean?)
|
||||
(s/def ::stroke-color string?)
|
||||
(s/def ::stroke-color-gradient (s/nilable ::color/gradient))
|
||||
(s/def ::stroke-color-ref-file (s/nilable uuid?))
|
||||
(s/def ::stroke-color-ref-id (s/nilable uuid?))
|
||||
(s/def ::stroke-opacity ::us/safe-number)
|
||||
(s/def ::stroke-style #{:solid :dotted :dashed :mixed :none :svg})
|
||||
|
||||
(def stroke-caps-line #{:round :square})
|
||||
(def stroke-caps-marker #{:line-arrow :triangle-arrow :square-marker :circle-marker :diamond-marker})
|
||||
(def stroke-caps (set/union stroke-caps-line stroke-caps-marker))
|
||||
|
||||
(s/def ::stroke-cap-start stroke-caps)
|
||||
(s/def ::stroke-cap-end stroke-caps)
|
||||
|
||||
(s/def ::stroke-width ::us/safe-number)
|
||||
(s/def ::stroke-alignment #{:center :inner :outer})
|
||||
(s/def ::text-align #{"left" "right" "center" "justify"})
|
||||
(s/def ::x ::us/safe-number)
|
||||
(s/def ::y ::us/safe-number)
|
||||
(s/def ::cx ::us/safe-number)
|
||||
(s/def ::cy ::us/safe-number)
|
||||
(s/def ::width ::us/safe-number)
|
||||
(s/def ::height ::us/safe-number)
|
||||
(s/def ::index integer?)
|
||||
|
||||
(s/def ::x1 ::us/safe-number)
|
||||
(s/def ::y1 ::us/safe-number)
|
||||
(s/def ::x2 ::us/safe-number)
|
||||
(s/def ::y2 ::us/safe-number)
|
||||
|
||||
(s/def ::selrect
|
||||
(s/keys :req-un [::x ::y ::x1 ::y1 ::x2 ::y2 ::width ::height]))
|
||||
|
||||
(s/def ::exports
|
||||
(s/coll-of ::export/export :kind vector?))
|
||||
|
||||
(s/def ::points
|
||||
(s/every ::gpt/point :kind vector?))
|
||||
|
||||
(s/def ::shapes
|
||||
(s/every uuid? :kind vector?))
|
||||
|
||||
(s/def ::transform ::gmt/matrix)
|
||||
(s/def ::transform-inverse ::gmt/matrix)
|
||||
(s/def ::opacity ::us/safe-number)
|
||||
(s/def ::blend-mode
|
||||
#{:normal
|
||||
:darken
|
||||
:multiply
|
||||
:color-burn
|
||||
:lighten
|
||||
:screen
|
||||
:color-dodge
|
||||
:overlay
|
||||
:soft-light
|
||||
:hard-light
|
||||
:difference
|
||||
:exclusion
|
||||
:hue
|
||||
:saturation
|
||||
:color
|
||||
:luminosity})
|
||||
|
||||
(s/def ::shape-attrs
|
||||
(s/keys :opt-un [::id
|
||||
::type
|
||||
::name
|
||||
::component-id
|
||||
::component-file
|
||||
::component-root?
|
||||
::shape-ref
|
||||
::selrect
|
||||
::points
|
||||
::blocked
|
||||
::collapsed
|
||||
::fill-color
|
||||
::fill-opacity
|
||||
::fill-color-gradient
|
||||
::fill-color-ref-file
|
||||
::fill-color-ref-id
|
||||
::font-family
|
||||
::font-size
|
||||
::font-style
|
||||
::font-weight
|
||||
::hidden
|
||||
::letter-spacing
|
||||
::line-height
|
||||
::locked
|
||||
::proportion
|
||||
::proportion-lock
|
||||
::constraints-h
|
||||
::constraints-v
|
||||
::fixed-scroll
|
||||
::radius/rx
|
||||
::radius/ry
|
||||
::radius/r1
|
||||
::radius/r2
|
||||
::radius/r3
|
||||
::radius/r4
|
||||
::x
|
||||
::y
|
||||
::exports
|
||||
::shapes
|
||||
::stroke-color
|
||||
::stroke-color-ref-file
|
||||
::stroke-color-ref-id
|
||||
::stroke-opacity
|
||||
::stroke-style
|
||||
::stroke-width
|
||||
::stroke-alignment
|
||||
::stroke-cap-start
|
||||
::stroke-cap-end
|
||||
::text-align
|
||||
::transform
|
||||
::transform-inverse
|
||||
::width
|
||||
::height
|
||||
::masked-group?
|
||||
::cti/interactions
|
||||
::shadow/shadow
|
||||
::blur/blur
|
||||
::opacity
|
||||
::blend-mode]))
|
||||
|
||||
(s/def :internal.shape.text/type #{"root" "paragraph-set" "paragraph"})
|
||||
(s/def :internal.shape.text/children
|
||||
(s/coll-of :internal.shape.text/content
|
||||
:kind vector?
|
||||
:min-count 1))
|
||||
|
||||
(s/def :internal.shape.text/text string?)
|
||||
(s/def :internal.shape.text/key string?)
|
||||
|
||||
(s/def :internal.shape.text/content
|
||||
(s/nilable
|
||||
(s/or :text-container
|
||||
(s/keys :req-un [:internal.shape.text/type
|
||||
:internal.shape.text/children]
|
||||
:opt-un [:internal.shape.text/key])
|
||||
:text-content
|
||||
(s/keys :req-un [:internal.shape.text/text]))))
|
||||
|
||||
(s/def :internal.shape.path/command keyword?)
|
||||
(s/def :internal.shape.path/params
|
||||
(s/nilable (s/map-of keyword? any?)))
|
||||
|
||||
(s/def :internal.shape.path/command-item
|
||||
(s/keys :req-un [:internal.shape.path/command]
|
||||
:opt-un [:internal.shape.path/params]))
|
||||
|
||||
(s/def :internal.shape.path/content
|
||||
(s/coll-of :internal.shape.path/command-item :kind vector?))
|
||||
|
||||
(defmulti shape-spec :type)
|
||||
|
||||
(defmethod shape-spec :default [_]
|
||||
(s/spec ::shape-attrs))
|
||||
|
||||
(defmethod shape-spec :text [_]
|
||||
(s/and ::shape-attrs
|
||||
(s/keys :opt-un [:internal.shape.text/content])))
|
||||
|
||||
(defmethod shape-spec :path [_]
|
||||
(s/and ::shape-attrs
|
||||
(s/keys :opt-un [:internal.shape.path/content])))
|
||||
|
||||
(defmethod shape-spec :frame [_]
|
||||
(s/and ::shape-attrs
|
||||
(s/keys :opt-un [::hide-fill-on-export])))
|
||||
|
||||
(s/def ::shape
|
||||
(s/and (s/multi-spec shape-spec :type)
|
||||
#(contains? % :type)
|
||||
#(contains? % :name)))
|
38
common/src/app/common/spec/typography.cljc
Normal file
38
common/src/app/common/spec/typography.cljc
Normal file
|
@ -0,0 +1,38 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.spec.typography
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
(s/def ::id uuid?)
|
||||
(s/def ::name string?)
|
||||
(s/def ::path (s/nilable string?))
|
||||
(s/def ::font-id string?)
|
||||
(s/def ::font-family string?)
|
||||
(s/def ::font-variant-id string?)
|
||||
(s/def ::font-size string?)
|
||||
(s/def ::font-weight string?)
|
||||
(s/def ::font-style string?)
|
||||
(s/def ::line-height string?)
|
||||
(s/def ::letter-spacing string?)
|
||||
(s/def ::text-transform string?)
|
||||
|
||||
(s/def ::typography
|
||||
(s/keys :req-un [::id
|
||||
::name
|
||||
::font-id
|
||||
::font-family
|
||||
::font-variant-id
|
||||
::font-size
|
||||
::font-weight
|
||||
::font-style
|
||||
::line-height
|
||||
::letter-spacing
|
||||
::text-transform]
|
||||
:opt-un [::path]))
|
||||
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.types.page-options
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.spec :as us]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;; --- Grid options
|
||||
|
||||
(s/def :artboard-grid.color/color ::us/string)
|
||||
(s/def :artboard-grid.color/opacity ::us/safe-number)
|
||||
|
||||
(s/def :artboard-grid/size (s/nilable ::us/safe-integer))
|
||||
(s/def :artboard-grid/item-length (s/nilable ::us/safe-number))
|
||||
|
||||
(s/def :artboard-grid/color (s/keys :req-un [:artboard-grid.color/color
|
||||
:artboard-grid.color/opacity]))
|
||||
(s/def :artboard-grid/type #{:stretch :left :center :right})
|
||||
(s/def :artboard-grid/gutter (s/nilable ::us/safe-integer))
|
||||
(s/def :artboard-grid/margin (s/nilable ::us/safe-integer))
|
||||
|
||||
(s/def :artboard-grid/square
|
||||
(s/keys :req-un [:artboard-grid/size
|
||||
:artboard-grid/color]))
|
||||
|
||||
(s/def :artboard-grid/column
|
||||
(s/keys :req-un [:artboard-grid/color]
|
||||
:opt-un [:artboard-grid/size
|
||||
:artboard-grid/type
|
||||
:artboard-grid/item-length
|
||||
:artboard-grid/margin
|
||||
:artboard-grid/gutter]))
|
||||
|
||||
(s/def :artboard-grid/row :artboard-grid/column)
|
||||
|
||||
(s/def ::saved-grids
|
||||
(s/keys :opt-un [:artboard-grid/square
|
||||
:artboard-grid/row
|
||||
:artboard-grid/column]))
|
||||
|
||||
;; --- Background options
|
||||
|
||||
(s/def ::background string?)
|
||||
|
||||
;; --- Flow options
|
||||
|
||||
(s/def :interactions-flow/id ::us/uuid)
|
||||
(s/def :interactions-flow/name ::us/string)
|
||||
(s/def :interactions-flow/starting-frame ::us/uuid)
|
||||
|
||||
(s/def ::flow
|
||||
(s/keys :req-un [:interactions-flow/id
|
||||
:interactions-flow/name
|
||||
:interactions-flow/starting-frame]))
|
||||
|
||||
(s/def ::flows
|
||||
(s/coll-of ::flow :kind vector?))
|
||||
|
||||
;; --- Guides
|
||||
|
||||
(s/def :guides/id ::us/uuid)
|
||||
(s/def :guides/axis #{:x :y})
|
||||
(s/def :guides/position ::us/safe-number)
|
||||
(s/def :guides/frame-id (s/nilable ::us/uuid))
|
||||
|
||||
(s/def ::guide
|
||||
(s/keys :req-un [:guides/id
|
||||
:guides/axis
|
||||
:guides/position]
|
||||
:opt-un [:guides/frame-id]))
|
||||
|
||||
(s/def ::guides
|
||||
(s/map-of uuid? ::guide))
|
||||
|
||||
;; --- Options
|
||||
|
||||
(s/def ::options
|
||||
(s/keys :opt-un [::background
|
||||
::saved-grids
|
||||
::flows
|
||||
::guides]))
|
||||
|
||||
;; --- Helpers for flow
|
||||
|
||||
(defn rename-flow
|
||||
[flow name]
|
||||
(assoc flow :name name))
|
||||
|
||||
;; --- Helpers for flows
|
||||
|
||||
(defn add-flow
|
||||
[flows flow]
|
||||
(conj (or flows []) flow))
|
||||
|
||||
(defn remove-flow
|
||||
[flows flow-id]
|
||||
(d/removev #(= (:id %) flow-id) flows))
|
||||
|
||||
(defn update-flow
|
||||
[flows flow-id update-fn]
|
||||
(let [index (d/index-of-pred flows #(= (:id %) flow-id))]
|
||||
(update flows index update-fn)))
|
||||
|
||||
(defn get-frame-flow
|
||||
[flows frame-id]
|
||||
(d/seek #(= (:starting-frame %) frame-id) flows))
|
||||
|
|
@ -4,68 +4,68 @@
|
|||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.common.types-interactions-test
|
||||
(ns app.common.spec-interactions-test
|
||||
(:require
|
||||
[clojure.test :as t]
|
||||
[clojure.pprint :refer [pprint]]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.pages.init :as cpi]
|
||||
[app.common.types.interactions :as cti]
|
||||
[app.common.spec.interactions :as csi]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.common.geom.point :as gpt]))
|
||||
|
||||
(t/deftest set-event-type
|
||||
(let [interaction cti/default-interaction
|
||||
(let [interaction csi/default-interaction
|
||||
shape (cpi/make-minimal-shape :rect)
|
||||
frame (cpi/make-minimal-shape :frame)]
|
||||
|
||||
(t/testing "Set event type unchanged"
|
||||
(let [new-interaction
|
||||
(cti/set-event-type interaction :click shape)]
|
||||
(csi/set-event-type interaction :click shape)]
|
||||
(t/is (= :click (:event-type new-interaction)))))
|
||||
|
||||
(t/testing "Set event type changed"
|
||||
(let [new-interaction
|
||||
(cti/set-event-type interaction :mouse-press shape)]
|
||||
(csi/set-event-type interaction :mouse-press shape)]
|
||||
(t/is (= :mouse-press (:event-type new-interaction)))))
|
||||
|
||||
(t/testing "Set after delay on non-frame"
|
||||
(let [result (ex/try
|
||||
(cti/set-event-type interaction :after-delay shape))]
|
||||
(csi/set-event-type interaction :after-delay shape))]
|
||||
(t/is (ex/exception? result))))
|
||||
|
||||
(t/testing "Set after delay on frame"
|
||||
(let [new-interaction
|
||||
(cti/set-event-type interaction :after-delay frame)]
|
||||
(csi/set-event-type interaction :after-delay frame)]
|
||||
(t/is (= :after-delay (:event-type new-interaction)))
|
||||
(t/is (= 600 (:delay new-interaction)))))
|
||||
|
||||
(t/testing "Set after delay with previous data"
|
||||
(let [interaction (assoc interaction :delay 300)
|
||||
new-interaction
|
||||
(cti/set-event-type interaction :after-delay frame)]
|
||||
(csi/set-event-type interaction :after-delay frame)]
|
||||
(t/is (= :after-delay (:event-type new-interaction)))
|
||||
(t/is (= 300 (:delay new-interaction)))))))
|
||||
|
||||
|
||||
(t/deftest set-action-type
|
||||
(let [interaction cti/default-interaction]
|
||||
(let [interaction csi/default-interaction]
|
||||
|
||||
(t/testing "Set action type unchanged"
|
||||
(let [new-interaction
|
||||
(cti/set-action-type interaction :navigate)]
|
||||
(csi/set-action-type interaction :navigate)]
|
||||
(t/is (= :navigate (:action-type new-interaction)))))
|
||||
|
||||
(t/testing "Set action type changed"
|
||||
(let [new-interaction
|
||||
(cti/set-action-type interaction :prev-screen)]
|
||||
(csi/set-action-type interaction :prev-screen)]
|
||||
(t/is (= :prev-screen (:action-type new-interaction)))))
|
||||
|
||||
(t/testing "Set action type navigate"
|
||||
(let [interaction {:event-type :click
|
||||
:action-type :prev-screen}
|
||||
new-interaction
|
||||
(cti/set-action-type interaction :navigate)]
|
||||
(csi/set-action-type interaction :navigate)]
|
||||
(t/is (= :navigate (:action-type new-interaction)))
|
||||
(t/is (nil? (:destination new-interaction)))
|
||||
(t/is (= false (:preserve-scroll new-interaction)))))
|
||||
|
@ -77,14 +77,14 @@
|
|||
:destination destination
|
||||
:preserve-scroll true}
|
||||
new-interaction
|
||||
(cti/set-action-type interaction :navigate)]
|
||||
(csi/set-action-type interaction :navigate)]
|
||||
(t/is (= :navigate (:action-type new-interaction)))
|
||||
(t/is (= destination (:destination new-interaction)))
|
||||
(t/is (= true (:preserve-scroll new-interaction)))))
|
||||
|
||||
(t/testing "Set action type open-overlay"
|
||||
(let [new-interaction
|
||||
(cti/set-action-type interaction :open-overlay)]
|
||||
(csi/set-action-type interaction :open-overlay)]
|
||||
(t/is (= :open-overlay (:action-type new-interaction)))
|
||||
(t/is (= :center (:overlay-pos-type new-interaction)))
|
||||
(t/is (= (gpt/point 0 0) (:overlay-position new-interaction)))))
|
||||
|
@ -93,14 +93,14 @@
|
|||
(let [interaction (assoc interaction :overlay-pos-type :top-left
|
||||
:overlay-position (gpt/point 100 200))
|
||||
new-interaction
|
||||
(cti/set-action-type interaction :open-overlay)]
|
||||
(csi/set-action-type interaction :open-overlay)]
|
||||
(t/is (= :open-overlay (:action-type new-interaction)))
|
||||
(t/is (= :top-left (:overlay-pos-type new-interaction)))
|
||||
(t/is (= (gpt/point 100 200) (:overlay-position new-interaction)))))
|
||||
|
||||
(t/testing "Set action type toggle-overlay"
|
||||
(let [new-interaction
|
||||
(cti/set-action-type interaction :toggle-overlay)]
|
||||
(csi/set-action-type interaction :toggle-overlay)]
|
||||
(t/is (= :toggle-overlay (:action-type new-interaction)))
|
||||
(t/is (= :center (:overlay-pos-type new-interaction)))
|
||||
(t/is (= (gpt/point 0 0) (:overlay-position new-interaction)))))
|
||||
|
@ -109,14 +109,14 @@
|
|||
(let [interaction (assoc interaction :overlay-pos-type :top-left
|
||||
:overlay-position (gpt/point 100 200))
|
||||
new-interaction
|
||||
(cti/set-action-type interaction :toggle-overlay)]
|
||||
(csi/set-action-type interaction :toggle-overlay)]
|
||||
(t/is (= :toggle-overlay (:action-type new-interaction)))
|
||||
(t/is (= :top-left (:overlay-pos-type new-interaction)))
|
||||
(t/is (= (gpt/point 100 200) (:overlay-position new-interaction)))))
|
||||
|
||||
(t/testing "Set action type close-overlay"
|
||||
(let [new-interaction
|
||||
(cti/set-action-type interaction :close-overlay)]
|
||||
(csi/set-action-type interaction :close-overlay)]
|
||||
(t/is (= :close-overlay (:action-type new-interaction)))
|
||||
(t/is (nil? (:destination new-interaction)))))
|
||||
|
||||
|
@ -124,89 +124,89 @@
|
|||
(let [destination (uuid/next)
|
||||
interaction (assoc interaction :destination destination)
|
||||
new-interaction
|
||||
(cti/set-action-type interaction :close-overlay)]
|
||||
(csi/set-action-type interaction :close-overlay)]
|
||||
(t/is (= :close-overlay (:action-type new-interaction)))
|
||||
(t/is (= destination (:destination new-interaction)))))
|
||||
|
||||
(t/testing "Set action type prev-screen"
|
||||
(let [new-interaction
|
||||
(cti/set-action-type interaction :prev-screen)]
|
||||
(csi/set-action-type interaction :prev-screen)]
|
||||
(t/is (= :prev-screen (:action-type new-interaction)))))
|
||||
|
||||
(t/testing "Set action type open-url"
|
||||
(let [new-interaction
|
||||
(cti/set-action-type interaction :open-url)]
|
||||
(csi/set-action-type interaction :open-url)]
|
||||
(t/is (= :open-url (:action-type new-interaction)))
|
||||
(t/is (= "" (:url new-interaction)))))
|
||||
|
||||
(t/testing "Set action type open-url with previous data"
|
||||
(let [interaction (assoc interaction :url "https://example.com")
|
||||
new-interaction
|
||||
(cti/set-action-type interaction :open-url)]
|
||||
(csi/set-action-type interaction :open-url)]
|
||||
(t/is (= :open-url (:action-type new-interaction)))
|
||||
(t/is (= "https://example.com" (:url new-interaction)))))))
|
||||
|
||||
|
||||
(t/deftest option-delay
|
||||
(let [frame (cpi/make-minimal-shape :frame)
|
||||
i1 cti/default-interaction
|
||||
i2 (cti/set-event-type i1 :after-delay frame)]
|
||||
i1 csi/default-interaction
|
||||
i2 (csi/set-event-type i1 :after-delay frame)]
|
||||
|
||||
(t/testing "Has delay"
|
||||
(t/is (not (cti/has-delay i1)))
|
||||
(t/is (cti/has-delay i2)))
|
||||
(t/is (not (csi/has-delay i1)))
|
||||
(t/is (csi/has-delay i2)))
|
||||
|
||||
(t/testing "Set delay"
|
||||
(let [new-interaction (cti/set-delay i2 1000)]
|
||||
(let [new-interaction (csi/set-delay i2 1000)]
|
||||
(t/is (= 1000 (:delay new-interaction)))))))
|
||||
|
||||
|
||||
(t/deftest option-destination
|
||||
(let [destination (uuid/next)
|
||||
i1 cti/default-interaction
|
||||
i2 (cti/set-action-type i1 :prev-screen)
|
||||
i3 (cti/set-action-type i1 :open-overlay)]
|
||||
i1 csi/default-interaction
|
||||
i2 (csi/set-action-type i1 :prev-screen)
|
||||
i3 (csi/set-action-type i1 :open-overlay)]
|
||||
|
||||
(t/testing "Has destination"
|
||||
(t/is (cti/has-destination i1))
|
||||
(t/is (not (cti/has-destination i2))))
|
||||
(t/is (csi/has-destination i1))
|
||||
(t/is (not (csi/has-destination i2))))
|
||||
|
||||
(t/testing "Set destination"
|
||||
(let [new-interaction (cti/set-destination i1 destination)]
|
||||
(let [new-interaction (csi/set-destination i1 destination)]
|
||||
(t/is (= destination (:destination new-interaction)))
|
||||
(t/is (nil? (:overlay-pos-type new-interaction)))
|
||||
(t/is (nil? (:overlay-position new-interaction)))))
|
||||
|
||||
(t/testing "Set destination of overlay"
|
||||
(let [new-interaction (cti/set-destination i3 destination)]
|
||||
(let [new-interaction (csi/set-destination i3 destination)]
|
||||
(t/is (= destination (:destination new-interaction)))
|
||||
(t/is (= :center (:overlay-pos-type new-interaction)))
|
||||
(t/is (= (gpt/point 0 0) (:overlay-position new-interaction)))))))
|
||||
|
||||
|
||||
(t/deftest option-preserve-scroll
|
||||
(let [i1 cti/default-interaction
|
||||
i2 (cti/set-action-type i1 :prev-screen)]
|
||||
(let [i1 csi/default-interaction
|
||||
i2 (csi/set-action-type i1 :prev-screen)]
|
||||
|
||||
(t/testing "Has preserve-scroll"
|
||||
(t/is (cti/has-preserve-scroll i1))
|
||||
(t/is (not (cti/has-preserve-scroll i2))))
|
||||
(t/is (csi/has-preserve-scroll i1))
|
||||
(t/is (not (csi/has-preserve-scroll i2))))
|
||||
|
||||
(t/testing "Set preserve-scroll"
|
||||
(let [new-interaction (cti/set-preserve-scroll i1 true)]
|
||||
(let [new-interaction (csi/set-preserve-scroll i1 true)]
|
||||
(t/is (= true (:preserve-scroll new-interaction)))))))
|
||||
|
||||
|
||||
(t/deftest option-url
|
||||
(let [i1 cti/default-interaction
|
||||
i2 (cti/set-action-type i1 :open-url)]
|
||||
(let [i1 csi/default-interaction
|
||||
i2 (csi/set-action-type i1 :open-url)]
|
||||
|
||||
(t/testing "Has url"
|
||||
(t/is (not (cti/has-url i1)))
|
||||
(t/is (cti/has-url i2)))
|
||||
(t/is (not (csi/has-url i1)))
|
||||
(t/is (csi/has-url i2)))
|
||||
|
||||
(t/testing "Set url"
|
||||
(let [new-interaction (cti/set-url i2 "https://example.com")]
|
||||
(let [new-interaction (csi/set-url i2 "https://example.com")]
|
||||
(t/is (= "https://example.com" (:url new-interaction)))))))
|
||||
|
||||
|
||||
|
@ -220,35 +220,35 @@
|
|||
objects {(:id base-frame) base-frame
|
||||
(:id overlay-frame) overlay-frame}
|
||||
|
||||
i1 cti/default-interaction
|
||||
i2 (cti/set-action-type i1 :open-overlay)
|
||||
i1 csi/default-interaction
|
||||
i2 (csi/set-action-type i1 :open-overlay)
|
||||
i3 (-> i1
|
||||
(cti/set-action-type :open-overlay)
|
||||
(cti/set-destination (:id overlay-frame)))]
|
||||
(csi/set-action-type :open-overlay)
|
||||
(csi/set-destination (:id overlay-frame)))]
|
||||
|
||||
(t/testing "Has overlay options"
|
||||
(t/is (not (cti/has-overlay-opts i1)))
|
||||
(t/is (cti/has-overlay-opts i2)))
|
||||
(t/is (not (csi/has-overlay-opts i1)))
|
||||
(t/is (csi/has-overlay-opts i2)))
|
||||
|
||||
(t/testing "Set overlay-pos-type without destination"
|
||||
(let [new-interaction (cti/set-overlay-pos-type i2 :top-right base-frame objects)]
|
||||
(let [new-interaction (csi/set-overlay-pos-type i2 :top-right base-frame objects)]
|
||||
(t/is (= :top-right (:overlay-pos-type new-interaction)))
|
||||
(t/is (= (gpt/point 0 0) (:overlay-position new-interaction)))))
|
||||
|
||||
(t/testing "Set overlay-pos-type with destination and auto"
|
||||
(let [new-interaction (cti/set-overlay-pos-type i3 :bottom-right base-frame objects)]
|
||||
(let [new-interaction (csi/set-overlay-pos-type i3 :bottom-right base-frame objects)]
|
||||
(t/is (= :bottom-right (:overlay-pos-type new-interaction)))
|
||||
(t/is (= (gpt/point 0 0) (:overlay-position new-interaction)))))
|
||||
|
||||
(t/testing "Set overlay-pos-type with destination and manual"
|
||||
(let [new-interaction (cti/set-overlay-pos-type i3 :manual base-frame objects)]
|
||||
(let [new-interaction (csi/set-overlay-pos-type i3 :manual base-frame objects)]
|
||||
(t/is (= :manual (:overlay-pos-type new-interaction)))
|
||||
(t/is (= (gpt/point 35 40) (:overlay-position new-interaction)))))
|
||||
|
||||
(t/testing "Toggle overlay-pos-type"
|
||||
(let [new-interaction (cti/toggle-overlay-pos-type i3 :center base-frame objects)
|
||||
new-interaction-2 (cti/toggle-overlay-pos-type new-interaction :center base-frame objects)
|
||||
new-interaction-3 (cti/toggle-overlay-pos-type new-interaction-2 :top-right base-frame objects)]
|
||||
(let [new-interaction (csi/toggle-overlay-pos-type i3 :center base-frame objects)
|
||||
new-interaction-2 (csi/toggle-overlay-pos-type new-interaction :center base-frame objects)
|
||||
new-interaction-3 (csi/toggle-overlay-pos-type new-interaction-2 :top-right base-frame objects)]
|
||||
(t/is (= :manual (:overlay-pos-type new-interaction)))
|
||||
(t/is (= (gpt/point 35 40) (:overlay-position new-interaction)))
|
||||
(t/is (= :center (:overlay-pos-type new-interaction-2)))
|
||||
|
@ -257,73 +257,73 @@
|
|||
(t/is (= (gpt/point 0 0) (:overlay-position new-interaction-3)))))
|
||||
|
||||
(t/testing "Set overlay-position"
|
||||
(let [new-interaction (cti/set-overlay-position i3 (gpt/point 50 60))]
|
||||
(let [new-interaction (csi/set-overlay-position i3 (gpt/point 50 60))]
|
||||
(t/is (= :manual (:overlay-pos-type new-interaction)))
|
||||
(t/is (= (gpt/point 50 60) (:overlay-position new-interaction)))))
|
||||
|
||||
(t/testing "Set close-click-outside"
|
||||
(let [new-interaction (cti/set-close-click-outside i3 true)]
|
||||
(let [new-interaction (csi/set-close-click-outside i3 true)]
|
||||
(t/is (not (:close-click-outside i3)))
|
||||
(t/is (:close-click-outside new-interaction))))
|
||||
|
||||
(t/testing "Set background-overlay"
|
||||
(let [new-interaction (cti/set-background-overlay i3 true)]
|
||||
(let [new-interaction (csi/set-background-overlay i3 true)]
|
||||
(t/is (not (:background-overlay i3)))
|
||||
(t/is (:background-overlay new-interaction))))))
|
||||
|
||||
|
||||
(t/deftest animation-checks
|
||||
(let [i1 cti/default-interaction
|
||||
i2 (cti/set-action-type i1 :open-overlay)
|
||||
i3 (cti/set-action-type i1 :toggle-overlay)
|
||||
i4 (cti/set-action-type i1 :close-overlay)
|
||||
i5 (cti/set-action-type i1 :prev-screen)
|
||||
i6 (cti/set-action-type i1 :open-url)]
|
||||
(let [i1 csi/default-interaction
|
||||
i2 (csi/set-action-type i1 :open-overlay)
|
||||
i3 (csi/set-action-type i1 :toggle-overlay)
|
||||
i4 (csi/set-action-type i1 :close-overlay)
|
||||
i5 (csi/set-action-type i1 :prev-screen)
|
||||
i6 (csi/set-action-type i1 :open-url)]
|
||||
|
||||
(t/testing "Has animation?"
|
||||
(t/is (cti/has-animation? i1))
|
||||
(t/is (cti/has-animation? i2))
|
||||
(t/is (cti/has-animation? i3))
|
||||
(t/is (cti/has-animation? i4))
|
||||
(t/is (not (cti/has-animation? i5)))
|
||||
(t/is (not (cti/has-animation? i6))))
|
||||
(t/is (csi/has-animation? i1))
|
||||
(t/is (csi/has-animation? i2))
|
||||
(t/is (csi/has-animation? i3))
|
||||
(t/is (csi/has-animation? i4))
|
||||
(t/is (not (csi/has-animation? i5)))
|
||||
(t/is (not (csi/has-animation? i6))))
|
||||
|
||||
(t/testing "Valid push?"
|
||||
(t/is (cti/allow-push? (:action-type i1)))
|
||||
(t/is (not (cti/allow-push? (:action-type i2))))
|
||||
(t/is (not (cti/allow-push? (:action-type i3))))
|
||||
(t/is (not (cti/allow-push? (:action-type i4))))
|
||||
(t/is (not (cti/allow-push? (:action-type i5))))
|
||||
(t/is (not (cti/allow-push? (:action-type i6)))))))
|
||||
(t/is (csi/allow-push? (:action-type i1)))
|
||||
(t/is (not (csi/allow-push? (:action-type i2))))
|
||||
(t/is (not (csi/allow-push? (:action-type i3))))
|
||||
(t/is (not (csi/allow-push? (:action-type i4))))
|
||||
(t/is (not (csi/allow-push? (:action-type i5))))
|
||||
(t/is (not (csi/allow-push? (:action-type i6)))))))
|
||||
|
||||
|
||||
(t/deftest set-animation-type
|
||||
(let [i1 cti/default-interaction
|
||||
i2 (cti/set-animation-type i1 :dissolve)]
|
||||
(let [i1 csi/default-interaction
|
||||
i2 (csi/set-animation-type i1 :dissolve)]
|
||||
|
||||
(t/testing "Set animation type nil"
|
||||
(let [new-interaction
|
||||
(cti/set-animation-type i1 nil)]
|
||||
(csi/set-animation-type i1 nil)]
|
||||
(t/is (nil? (-> new-interaction :animation :animation-type)))))
|
||||
|
||||
(t/testing "Set animation type unchanged"
|
||||
(let [new-interaction
|
||||
(cti/set-animation-type i2 :dissolve)]
|
||||
(csi/set-animation-type i2 :dissolve)]
|
||||
(t/is (= :dissolve (-> new-interaction :animation :animation-type)))))
|
||||
|
||||
(t/testing "Set animation type changed"
|
||||
(let [new-interaction
|
||||
(cti/set-animation-type i2 :slide)]
|
||||
(csi/set-animation-type i2 :slide)]
|
||||
(t/is (= :slide (-> new-interaction :animation :animation-type)))))
|
||||
|
||||
(t/testing "Set animation type reset"
|
||||
(let [new-interaction
|
||||
(cti/set-animation-type i2 nil)]
|
||||
(csi/set-animation-type i2 nil)]
|
||||
(t/is (nil? (-> new-interaction :animation)))))
|
||||
|
||||
(t/testing "Set animation type dissolve"
|
||||
(let [new-interaction
|
||||
(cti/set-animation-type i1 :dissolve)]
|
||||
(csi/set-animation-type i1 :dissolve)]
|
||||
(t/is (= :dissolve (-> new-interaction :animation :animation-type)))
|
||||
(t/is (= 300 (-> new-interaction :animation :duration)))
|
||||
(t/is (= :linear (-> new-interaction :animation :easing)))))
|
||||
|
@ -336,14 +336,14 @@
|
|||
:direction :left
|
||||
:offset-effect true})
|
||||
new-interaction
|
||||
(cti/set-animation-type interaction :dissolve)]
|
||||
(csi/set-animation-type interaction :dissolve)]
|
||||
(t/is (= :dissolve (-> new-interaction :animation :animation-type)))
|
||||
(t/is (= 1000 (-> new-interaction :animation :duration)))
|
||||
(t/is (= :ease-out (-> new-interaction :animation :easing)))))
|
||||
|
||||
(t/testing "Set animation type slide"
|
||||
(let [new-interaction
|
||||
(cti/set-animation-type i1 :slide)]
|
||||
(csi/set-animation-type i1 :slide)]
|
||||
(t/is (= :slide (-> new-interaction :animation :animation-type)))
|
||||
(t/is (= 300 (-> new-interaction :animation :duration)))
|
||||
(t/is (= :linear (-> new-interaction :animation :easing)))
|
||||
|
@ -359,7 +359,7 @@
|
|||
:direction :left
|
||||
:offset-effect true})
|
||||
new-interaction
|
||||
(cti/set-animation-type interaction :slide)]
|
||||
(csi/set-animation-type interaction :slide)]
|
||||
(t/is (= :slide (-> new-interaction :animation :animation-type)))
|
||||
(t/is (= 1000 (-> new-interaction :animation :duration)))
|
||||
(t/is (= :ease-out (-> new-interaction :animation :easing)))
|
||||
|
@ -369,7 +369,7 @@
|
|||
|
||||
(t/testing "Set animation type push"
|
||||
(let [new-interaction
|
||||
(cti/set-animation-type i1 :push)]
|
||||
(csi/set-animation-type i1 :push)]
|
||||
(t/is (= :push (-> new-interaction :animation :animation-type)))
|
||||
(t/is (= 300 (-> new-interaction :animation :duration)))
|
||||
(t/is (= :linear (-> new-interaction :animation :easing)))
|
||||
|
@ -383,7 +383,7 @@
|
|||
:direction :left
|
||||
:offset-effect true})
|
||||
new-interaction
|
||||
(cti/set-animation-type interaction :push)]
|
||||
(csi/set-animation-type interaction :push)]
|
||||
(t/is (= :push (-> new-interaction :animation :animation-type)))
|
||||
(t/is (= 1000 (-> new-interaction :animation :duration)))
|
||||
(t/is (= :ease-out (-> new-interaction :animation :easing)))
|
||||
|
@ -391,9 +391,9 @@
|
|||
|
||||
|
||||
(t/deftest allowed-animation
|
||||
(let [i1 (cti/set-action-type cti/default-interaction :open-overlay)
|
||||
i2 (cti/set-action-type cti/default-interaction :close-overlay)
|
||||
i3 (cti/set-action-type cti/default-interaction :toggle-overlay)]
|
||||
(let [i1 (csi/set-action-type csi/default-interaction :open-overlay)
|
||||
i2 (csi/set-action-type csi/default-interaction :close-overlay)
|
||||
i3 (csi/set-action-type csi/default-interaction :toggle-overlay)]
|
||||
|
||||
(t/testing "Cannot use animation push for an overlay action"
|
||||
(let [bad-interaction-1 (assoc i1 :animation {:animation-type :push
|
||||
|
@ -408,72 +408,72 @@
|
|||
:duration 1000
|
||||
:easing :ease-out
|
||||
:direction :left})]
|
||||
(t/is (not (cti/allowed-animation? (:action-type bad-interaction-1)
|
||||
(t/is (not (csi/allowed-animation? (:action-type bad-interaction-1)
|
||||
(-> bad-interaction-1 :animation :animation-type))))
|
||||
(t/is (not (cti/allowed-animation? (:action-type bad-interaction-2)
|
||||
(t/is (not (csi/allowed-animation? (:action-type bad-interaction-2)
|
||||
(-> bad-interaction-1 :animation :animation-type))))
|
||||
(t/is (not (cti/allowed-animation? (:action-type bad-interaction-3)
|
||||
(t/is (not (csi/allowed-animation? (:action-type bad-interaction-3)
|
||||
(-> bad-interaction-1 :animation :animation-type))))))
|
||||
|
||||
(t/testing "Remove animation if moving to an forbidden state"
|
||||
(let [interaction (cti/set-animation-type cti/default-interaction :push)
|
||||
new-interaction (cti/set-action-type interaction :open-overlay)]
|
||||
(let [interaction (csi/set-animation-type csi/default-interaction :push)
|
||||
new-interaction (csi/set-action-type interaction :open-overlay)]
|
||||
(t/is (nil? (:animation new-interaction)))))))
|
||||
|
||||
|
||||
(t/deftest option-duration
|
||||
(let [i1 cti/default-interaction
|
||||
i2 (cti/set-animation-type cti/default-interaction :dissolve)]
|
||||
(let [i1 csi/default-interaction
|
||||
i2 (csi/set-animation-type csi/default-interaction :dissolve)]
|
||||
|
||||
(t/testing "Has duration?"
|
||||
(t/is (not (cti/has-duration? i1)))
|
||||
(t/is (cti/has-duration? i2)))
|
||||
(t/is (not (csi/has-duration? i1)))
|
||||
(t/is (csi/has-duration? i2)))
|
||||
|
||||
(t/testing "Set duration"
|
||||
(let [new-interaction (cti/set-duration i2 1000)]
|
||||
(let [new-interaction (csi/set-duration i2 1000)]
|
||||
(t/is (= 1000 (-> new-interaction :animation :duration)))))))
|
||||
|
||||
|
||||
(t/deftest option-easing
|
||||
(let [i1 cti/default-interaction
|
||||
i2 (cti/set-animation-type cti/default-interaction :dissolve)]
|
||||
(let [i1 csi/default-interaction
|
||||
i2 (csi/set-animation-type csi/default-interaction :dissolve)]
|
||||
|
||||
(t/testing "Has easing?"
|
||||
(t/is (not (cti/has-easing? i1)))
|
||||
(t/is (cti/has-easing? i2)))
|
||||
(t/is (not (csi/has-easing? i1)))
|
||||
(t/is (csi/has-easing? i2)))
|
||||
|
||||
(t/testing "Set easing"
|
||||
(let [new-interaction (cti/set-easing i2 :ease-in)]
|
||||
(let [new-interaction (csi/set-easing i2 :ease-in)]
|
||||
(t/is (= :ease-in (-> new-interaction :animation :easing)))))))
|
||||
|
||||
|
||||
(t/deftest option-way
|
||||
(let [i1 cti/default-interaction
|
||||
i2 (cti/set-animation-type cti/default-interaction :slide)
|
||||
i3 (cti/set-action-type i2 :open-overlay)]
|
||||
(let [i1 csi/default-interaction
|
||||
i2 (csi/set-animation-type csi/default-interaction :slide)
|
||||
i3 (csi/set-action-type i2 :open-overlay)]
|
||||
|
||||
(t/testing "Has way?"
|
||||
(t/is (not (cti/has-way? i1)))
|
||||
(t/is (cti/has-way? i2))
|
||||
(t/is (not (cti/has-way? i3)))
|
||||
(t/is (not (csi/has-way? i1)))
|
||||
(t/is (csi/has-way? i2))
|
||||
(t/is (not (csi/has-way? i3)))
|
||||
(t/is (some? (-> i3 :animation :way)))) ; <- it exists but is ignored
|
||||
|
||||
(t/testing "Set way"
|
||||
(let [new-interaction (cti/set-way i2 :out)]
|
||||
(let [new-interaction (csi/set-way i2 :out)]
|
||||
(t/is (= :out (-> new-interaction :animation :way)))))))
|
||||
|
||||
|
||||
(t/deftest option-direction
|
||||
(let [i1 cti/default-interaction
|
||||
i2 (cti/set-animation-type cti/default-interaction :push)
|
||||
i3 (cti/set-animation-type cti/default-interaction :dissolve)]
|
||||
(let [i1 csi/default-interaction
|
||||
i2 (csi/set-animation-type csi/default-interaction :push)
|
||||
i3 (csi/set-animation-type csi/default-interaction :dissolve)]
|
||||
|
||||
(t/testing "Has direction?"
|
||||
(t/is (not (cti/has-direction? i1)))
|
||||
(t/is (cti/has-direction? i2)))
|
||||
(t/is (not (csi/has-direction? i1)))
|
||||
(t/is (csi/has-direction? i2)))
|
||||
|
||||
(t/testing "Set direction"
|
||||
(let [new-interaction (cti/set-direction i2 :left)]
|
||||
(let [new-interaction (csi/set-direction i2 :left)]
|
||||
(t/is (= :left (-> new-interaction :animation :direction)))))
|
||||
|
||||
(t/testing "Invert direction"
|
||||
|
@ -483,12 +483,12 @@
|
|||
a-up (assoc a-right :direction :up)
|
||||
a-down (assoc a-right :direction :down)
|
||||
|
||||
a-nil' (cti/invert-direction nil)
|
||||
a-none' (cti/invert-direction a-none)
|
||||
a-right' (cti/invert-direction a-right)
|
||||
a-left' (cti/invert-direction a-left)
|
||||
a-up' (cti/invert-direction a-up)
|
||||
a-down' (cti/invert-direction a-down)]
|
||||
a-nil' (csi/invert-direction nil)
|
||||
a-none' (csi/invert-direction a-none)
|
||||
a-right' (csi/invert-direction a-right)
|
||||
a-left' (csi/invert-direction a-left)
|
||||
a-up' (csi/invert-direction a-up)
|
||||
a-down' (csi/invert-direction a-down)]
|
||||
|
||||
(t/is (nil? a-nil'))
|
||||
(t/is (nil? (:direction a-none')))
|
||||
|
@ -499,44 +499,44 @@
|
|||
|
||||
|
||||
(t/deftest option-offset-effect
|
||||
(let [i1 cti/default-interaction
|
||||
i2 (cti/set-animation-type cti/default-interaction :slide)
|
||||
i3 (cti/set-action-type i2 :open-overlay)]
|
||||
(let [i1 csi/default-interaction
|
||||
i2 (csi/set-animation-type csi/default-interaction :slide)
|
||||
i3 (csi/set-action-type i2 :open-overlay)]
|
||||
|
||||
(t/testing "Has offset-effect"
|
||||
(t/is (not (cti/has-offset-effect? i1)))
|
||||
(t/is (cti/has-offset-effect? i2))
|
||||
(t/is (not (cti/has-offset-effect? i3)))
|
||||
(t/is (not (csi/has-offset-effect? i1)))
|
||||
(t/is (csi/has-offset-effect? i2))
|
||||
(t/is (not (csi/has-offset-effect? i3)))
|
||||
(t/is (some? (-> i3 :animation :offset-effect)))) ; <- it exists but is ignored
|
||||
|
||||
(t/testing "Set offset-effect"
|
||||
(let [new-interaction (cti/set-offset-effect i2 true)]
|
||||
(let [new-interaction (csi/set-offset-effect i2 true)]
|
||||
(t/is (= true (-> new-interaction :animation :offset-effect)))))))
|
||||
|
||||
|
||||
(t/deftest modify-interactions
|
||||
(let [i1 (cti/set-action-type cti/default-interaction :open-overlay)
|
||||
i2 (cti/set-action-type cti/default-interaction :close-overlay)
|
||||
i3 (cti/set-action-type cti/default-interaction :prev-screen)
|
||||
(let [i1 (csi/set-action-type csi/default-interaction :open-overlay)
|
||||
i2 (csi/set-action-type csi/default-interaction :close-overlay)
|
||||
i3 (csi/set-action-type csi/default-interaction :prev-screen)
|
||||
interactions [i1 i2]]
|
||||
|
||||
(t/testing "Add interaction to nil"
|
||||
(let [new-interactions (cti/add-interaction nil i3)]
|
||||
(let [new-interactions (csi/add-interaction nil i3)]
|
||||
(t/is (= (count new-interactions) 1))
|
||||
(t/is (= (:action-type (last new-interactions)) :prev-screen))))
|
||||
|
||||
(t/testing "Add interaction to normal"
|
||||
(let [new-interactions (cti/add-interaction interactions i3)]
|
||||
(let [new-interactions (csi/add-interaction interactions i3)]
|
||||
(t/is (= (count new-interactions) 3))
|
||||
(t/is (= (:action-type (last new-interactions)) :prev-screen))))
|
||||
|
||||
(t/testing "Remove interaction"
|
||||
(let [new-interactions (cti/remove-interaction interactions 0)]
|
||||
(let [new-interactions (csi/remove-interaction interactions 0)]
|
||||
(t/is (= (count new-interactions) 1))
|
||||
(t/is (= (:action-type (last new-interactions)) :close-overlay))))
|
||||
|
||||
(t/testing "Update interaction"
|
||||
(let [new-interactions (cti/update-interaction interactions 1 #(cti/set-action-type % :open-url))]
|
||||
(let [new-interactions (csi/update-interaction interactions 1 #(csi/set-action-type % :open-url))]
|
||||
(t/is (= (count new-interactions) 2))
|
||||
(t/is (= (:action-type (last new-interactions)) :open-url))))))
|
||||
|
||||
|
@ -556,16 +556,16 @@
|
|||
ids-map {(:id frame1) (:id frame4)
|
||||
(:id frame2) (:id frame5)}
|
||||
|
||||
i1 (cti/set-destination cti/default-interaction (:id frame1))
|
||||
i2 (cti/set-destination cti/default-interaction (:id frame2))
|
||||
i3 (cti/set-destination cti/default-interaction (:id frame3))
|
||||
i4 (cti/set-destination cti/default-interaction nil)
|
||||
i5 (cti/set-destination cti/default-interaction (:id frame6))
|
||||
i1 (csi/set-destination csi/default-interaction (:id frame1))
|
||||
i2 (csi/set-destination csi/default-interaction (:id frame2))
|
||||
i3 (csi/set-destination csi/default-interaction (:id frame3))
|
||||
i4 (csi/set-destination csi/default-interaction nil)
|
||||
i5 (csi/set-destination csi/default-interaction (:id frame6))
|
||||
|
||||
interactions [i1 i2 i3 i4 i5]]
|
||||
|
||||
(t/testing "Remap interactions"
|
||||
(let [new-interactions (cti/remap-interactions interactions ids-map objects)]
|
||||
(let [new-interactions (csi/remap-interactions interactions ids-map objects)]
|
||||
(t/is (= (count new-interactions) 4))
|
||||
(t/is (= (:id frame4) (:destination (get new-interactions 0))))
|
||||
(t/is (= (:id frame5) (:destination (get new-interactions 1))))
|
Loading…
Add table
Add a link
Reference in a new issue