0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -05:00

Merge branch 'main' into develop

This commit is contained in:
Andrey Antukh 2021-12-03 15:51:44 +01:00
commit 7a97c94f2b
16 changed files with 273 additions and 175 deletions

View file

@ -9,7 +9,7 @@
[app.common.colors :as clr] [app.common.colors :as clr]
[app.common.uuid :as uuid])) [app.common.uuid :as uuid]))
(def file-version 11) (def file-version 12)
(def default-color clr/gray-20) (def default-color clr/gray-20)
(def root uuid/zero) (def root uuid/zero)

View file

@ -217,16 +217,11 @@
(defn insert-at-index (defn insert-at-index
[objects index ids] [objects index ids]
(let [[before after] (split-at index objects) (let [[before after] (split-at index objects)
p? (complement (set ids)) p? (set ids)]
before' (filterv p? before) (d/concat-vec []
after' (filterv p? after)] (remove p? before)
ids
(if (and (not= (count before) (count before')) (remove p? after))))
(pos? (count after')))
(let [before' (conj before' (first after'))
after' (into [] (rest after'))]
(d/concat-vec before' ids after'))
(d/concat-vec before' ids after'))))
(defn append-at-the-end (defn append-at-the-end
[prev-ids ids] [prev-ids ids]

View file

@ -268,3 +268,16 @@
(update page :objects #(d/mapm (partial update-object %) %)))] (update page :objects #(d/mapm (partial update-object %) %)))]
(update data :pages-index #(d/mapm update-page %)))) (update data :pages-index #(d/mapm update-page %))))
(defmethod migrate 12
[data]
(letfn [(update-grid [_key grid]
(cond-> grid
(= :auto (:size grid))
(assoc :size nil)))
(update-page [_id page]
(d/update-in-when page [:options :saved-grids] #(d/mapm update-grid %)))]
(update data :pages-index #(d/mapm update-page %))))

View file

@ -15,11 +15,12 @@
(s/def :artboard-grid.color/color ::us/string) (s/def :artboard-grid.color/color ::us/string)
(s/def :artboard-grid.color/opacity ::us/safe-number) (s/def :artboard-grid.color/opacity ::us/safe-number)
(s/def :artboard-grid/size ::us/safe-integer) (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 (s/def :artboard-grid/color (s/keys :req-un [:artboard-grid.color/color
:artboard-grid.color/opacity])) :artboard-grid.color/opacity]))
(s/def :artboard-grid/type #{:stretch :left :center :right}) (s/def :artboard-grid/type #{:stretch :left :center :right})
(s/def :artboard-grid/item-length (s/nilable ::us/safe-integer))
(s/def :artboard-grid/gutter (s/nilable ::us/safe-integer)) (s/def :artboard-grid/gutter (s/nilable ::us/safe-integer))
(s/def :artboard-grid/margin (s/nilable ::us/safe-integer)) (s/def :artboard-grid/margin (s/nilable ::us/safe-integer))

View file

@ -0,0 +1,58 @@
;; 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.data-test
(:require
[app.common.data :as d]
[clojure.test :as t]))
(t/deftest concat-vec
(t/is (= [1 2 3]
(d/concat-vec [1] #{2} [3])))
(t/is (= [1 2]
(d/concat-vec '(1) [2])))
(t/is (= [1]
(d/concat-vec [1])))
(t/is (= [] (d/concat-vec))))
(t/deftest concat-set
(t/is (= #{} (d/concat-set)))
(t/is (= #{1 2}
(d/concat-set [1] [2]))))
(t/deftest remove-at-index
(t/is (= [1 2 3 4]
(d/remove-at-index [1 2 3 4 5] 4)))
(t/is (= [1 2 3 4]
(d/remove-at-index [5 1 2 3 4] 0)))
(t/is (= [1 2 3 4]
(d/remove-at-index [1 5 2 3 4] 1)))
)
(t/deftest with-next
(t/is (= [[0 1] [1 2] [2 3] [3 4] [4 nil]]
(d/with-next (range 5)))))
(t/deftest with-prev
(t/is (= [[0 nil] [1 0] [2 1] [3 2] [4 3]]
(d/with-prev (range 5)))))
(t/deftest with-prev-next
(t/is (= [[0 nil 1] [1 0 2] [2 1 3] [3 2 4] [4 3 nil]]
(d/with-prev-next (range 5)))))
(t/deftest join
(t/is (= [[1 :a] [1 :b] [2 :a] [2 :b] [3 :a] [3 :b]]
(d/join [1 2 3] [:a :b])))
(t/is (= [1 10 100 2 20 200 3 30 300]
(d/join [1 2 3] [1 10 100] *))))

View file

@ -407,7 +407,7 @@
border: 1px solid transparent; border: 1px solid transparent;
position: relative; position: relative;
height: 38px; height: 38px;
margin-right: $size-2; // margin-left: $size-2;
max-height: 30px; max-height: 30px;
position: relative; position: relative;
width: 60%; width: 60%;
@ -495,12 +495,10 @@
.editable-select svg { .editable-select svg {
fill: $color-gray-40; fill: $color-gray-40;
} }
.dropdown-button {
top: 4px;
}
.editable-select.input-option .input-text { .editable-select.input-option .input-text {
padding: 0; padding: 0;
padding-top: 0.18rem; padding-top: 0.18rem;
padding-left: 0.25rem;
} }
.input-element { .input-element {

View file

@ -1112,7 +1112,7 @@
(defn relocate-page (defn relocate-page
[id index] [id index]
(ptk/reify ::relocate-pages (ptk/reify ::relocate-page
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(let [prev-index (-> (get-in state [:workspace-data :pages]) (let [prev-index (-> (get-in state [:workspace-data :pages])

View file

@ -16,7 +16,8 @@
[app.util.timers :as timers] [app.util.timers :as timers]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
(mf/defc editable-select [{:keys [value type options class on-change placeholder on-blur] :as params}] (mf/defc editable-select
[{:keys [value type options class on-change placeholder on-blur] :as params}]
(let [state (mf/use-state {:id (uuid/next) (let [state (mf/use-state {:id (uuid/next)
:is-open? false :is-open? false
:current-value value :current-value value
@ -42,20 +43,23 @@
(when on-blur (on-blur)))) (when on-blur (on-blur))))
as-key-value (fn [item] (if (map? item) [(:value item) (:label item)] [item item])) as-key-value (fn [item] (if (map? item) [(:value item) (:label item)] [item item]))
labels-map (into {} (map as-key-value) options)
labels-map (into {} (->> options (map as-key-value)))
value->label (fn [value] (get labels-map value value)) value->label (fn [value] (get labels-map value value))
set-value (fn [value] set-value
(swap! state assoc :current-value value) (fn [value]
(when on-change (on-change value))) (swap! state assoc :current-value value)
(when on-change (on-change value)))
handle-change-input (fn [event] ;; TODO: why this method supposes that all editable select
(let [value (-> event dom/get-target dom/get-value) ;; works with numbers?
value (-> (or (d/parse-double value) value)
(math/precision 2))] handle-change-input
(set-value value))) (fn [event]
(let [value (-> event dom/get-target dom/get-value)
value (-> (or (d/parse-double value) value)
(math/precision 2))]
(set-value value)))
on-node-load on-node-load
(fn [node] (fn [node]
@ -133,7 +137,7 @@
[:div.editable-select {:class class [:div.editable-select {:class class
:ref on-node-load} :ref on-node-load}
[:input.input-text {:value (or (-> @state :current-value value->label) "") [:input.input-text {:value (or (some-> @state :current-value value->label) "")
:on-change handle-change-input :on-change handle-change-input
:on-key-down handle-key-down :on-key-down handle-key-down
:on-focus handle-focus :on-focus handle-focus
@ -149,12 +153,12 @@
:left (:left @state) :left (:left @state)
:bottom (:bottom @state)}} :bottom (:bottom @state)}}
(for [[index item] (map-indexed vector options)] (for [[index item] (map-indexed vector options)]
(cond (if (= :separator item)
(= :separator item) [:hr {:key (str (:id @state) "-" index)}] [:hr {:key (str (:id @state) "-" index)}]
:else (let [[value label] (as-key-value item)] (let [[value label] (as-key-value item)]
[:li.checked-element [:li.checked-element
{:key (str (:id @state) "-" index) {:key (str (:id @state) "-" index)
:class (when (= value (-> @state :current-value)) "is-selected") :class (when (= value (-> @state :current-value)) "is-selected")
:on-click (select-item value)} :on-click (select-item value)}
[:span.check-icon i/tick] [:span.check-icon i/tick]
[:span label]])))]]])) [:span label]])))]]]))

View file

@ -15,6 +15,11 @@
[app.util.simple-math :as sm] [app.util.simple-math :as sm]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
(defn num? [val]
(and (number? val)
(not (math/nan? val))
(math/finite? val)))
(mf/defc numeric-input (mf/defc numeric-input
{::mf/wrap-props false {::mf/wrap-props false
::mf/forward-ref true} ::mf/forward-ref true}
@ -25,32 +30,31 @@
wrap-value? (obj/get props "data-wrap") wrap-value? (obj/get props "data-wrap")
on-change (obj/get props "onChange") on-change (obj/get props "onChange")
title (obj/get props "title") title (obj/get props "title")
default-val (obj/get props "default" 0)
;; We need a ref pointing to the input dom element, but the user ;; We need a ref pointing to the input dom element, but the user
;; of this component may provide one (that is forwarded here). ;; of this component may provide one (that is forwarded here).
;; So we use the external ref if provided, and the local one if not. ;; So we use the external ref if provided, and the local one if not.
local-ref (mf/use-ref) local-ref (mf/use-ref)
ref (or external-ref local-ref) ref (or external-ref local-ref)
value (d/parse-integer value-str 0) ;; This `value` represents the previous value and is used as
;; initil value for the simple math expression evaluation.
value (d/parse-integer value-str default-val)
min-val (cond min-val (cond
(number? min-val-str) (number? min-val-str)
min-val-str min-val-str
(string? min-val-str) (string? min-val-str)
(d/parse-integer min-val-str)) (d/parse-integer min-val-str))
max-val (cond max-val (cond
(number? max-val-str) (number? max-val-str)
max-val-str max-val-str
(string? max-val-str) (string? max-val-str)
(d/parse-integer max-val-str)) (d/parse-integer max-val-str))
num? (fn [val] (and (number? val)
(not (math/nan? val))
(math/finite? val)))
parse-value parse-value
(mf/use-callback (mf/use-callback
@ -82,10 +86,9 @@
(mf/use-callback (mf/use-callback
(mf/deps on-change update-input value) (mf/deps on-change update-input value)
(fn [new-value] (fn [new-value]
(when (and (some? new-value) (not= new-value value) (some? on-change)) (when (and (not= new-value value) (some? on-change))
(on-change new-value)) (on-change new-value))
(when (some? new-value) (update-input new-value)))
(update-input new-value))))
set-delta set-delta
(mf/use-callback (mf/use-callback
@ -143,10 +146,10 @@
(mf/use-callback (mf/use-callback
(mf/deps parse-value apply-value update-input) (mf/deps parse-value apply-value update-input)
(fn [_] (fn [_]
(let [new-value (parse-value)] (let [new-value (or (parse-value) default-val)]
(if new-value (if new-value
(apply-value new-value) (apply-value new-value)
(update-input value-str))))) (update-input new-value)))))
props (-> props props (-> props
(obj/without ["value" "onChange"]) (obj/without ["value" "onChange"])
@ -159,12 +162,5 @@
(obj/set! "onKeyDown" handle-key-down) (obj/set! "onKeyDown" handle-key-down)
(obj/set! "onBlur" handle-blur))] (obj/set! "onBlur" handle-blur))]
(mf/use-effect
(mf/deps value-str)
(fn []
(when-let [input-node (mf/ref-val ref)]
(when-not (dom/active? input-node)
(dom/set-value! input-node value-str)))))
[:> :input props])) [:> :input props]))

View file

@ -16,8 +16,7 @@
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]] [app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]] [app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
[app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]] [app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row input-row-v2]]
[app.util.data :as d]
[app.util.geom.grid :as gg] [app.util.geom.grid :as gg]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[okulary.core :as l] [okulary.core :as l]
@ -27,90 +26,101 @@
(l/derived :saved-grids refs/workspace-page-options)) (l/derived :saved-grids refs/workspace-page-options))
(defn- get-size-options [] (defn- get-size-options []
[{:value :auto :label (tr "workspace.options.grid.auto")} [{:value nil :label (tr "workspace.options.grid.auto")}
:separator :separator
18 12 10 8 6 4 3 2]) 18 12 10 8 6 4 3 2])
(mf/defc grid-options (mf/defc grid-options
[{:keys [grid frame default-grid-params on-change on-remove on-save-grid]}] {::mf/wrap [mf/memo]}
(let [size-options (get-size-options) [{:keys [shape-id index grid frame-width frame-height default-grid-params]}]
state (mf/use-state {:show-advanced-options false}) (let [on-change (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/set-frame-grid shape-id index %)))
on-remove (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/remove-frame-grid shape-id index)))
on-save-default (mf/use-fn #(st/emit! (dw/set-default-grid (:type %) (:params %))))
size-options (mf/use-memo get-size-options)
state (mf/use-state {:show-advanced-options false})
{:keys [type display params]} grid {:keys [type display params]} grid
toggle-advanced-options toggle-advanced-options
#(swap! state update :show-advanced-options not) (mf/use-fn #(swap! state update :show-advanced-options not))
handle-toggle-visibility handle-toggle-visibility
(fn [_] (mf/use-fn
(when on-change (mf/deps grid)
(on-change (update grid :display #(if (nil? %) false (not %)))))) (fn [_]
(on-change (update grid :display #(if (nil? %) false (not %))))))
handle-remove-grid
(fn [_]
(when on-remove (on-remove)))
handle-change-type handle-change-type
(fn [grid-type] (mf/use-fn
(let [defaults (grid-type default-grid-params)] (mf/deps grid)
(when on-change (fn [grid-type]
(on-change (assoc grid (let [defaults (grid-type default-grid-params)]
:type grid-type (on-change (assoc grid
:params defaults))))) :type grid-type
:params defaults)))))
handle-change handle-change
(fn [& keys] (fn [& keys-path]
(fn [value] (fn [value]
(when on-change (on-change (assoc-in grid keys-path value))))
(on-change (assoc-in grid keys value)))))
;; TODO: remove references to :auto
handle-change-size handle-change-size
(fn [size] (mf/use-fn
(let [{:keys [margin gutter item-length]} (:params grid) (mf/deps grid)
frame-length (if (= :column (:type grid)) (:width frame) (:height frame)) (fn [size]
item-length (if (or (nil? size) (= :auto size)) (let [{:keys [margin gutter item-length]} (:params grid)
(-> (gg/calculate-default-item-length frame-length margin gutter) frame-length (if (= :column (:type grid)) frame-width frame-height)
(mth/precision 2)) item-length (if (nil? size)
item-length)] (-> (gg/calculate-default-item-length frame-length margin gutter)
(when on-change (mth/precision 2))
(on-change (-> grid item-length)]
(assoc-in [:params :size] size)
(assoc-in [:params :item-length] item-length)))))) (-> grid
(update :params assoc :size size :item-length item-length)
(on-change)))))
handle-change-item-length handle-change-item-length
(fn [item-length] (mf/use-fn
(let [size (get-in grid [:params :size]) (mf/deps grid)
size (if (and (nil? item-length) (or (nil? size) (= :auto size))) 12 size)] (fn [item-length]
(when on-change (let [item-length (if (zero? item-length) nil item-length)
(on-change (-> grid size (get-in grid [:params :size])
(assoc-in [:params :size] size) size (if (and (nil? item-length) (nil? size)) 12 size)]
(assoc-in [:params :item-length] item-length)))))) (-> grid
(update :params assoc :size size :item-length item-length)
(on-change)))))
handle-change-color handle-change-color
(fn [color] (mf/use-fn
(when on-change (mf/deps grid)
(on-change (assoc-in grid [:params :color] color)))) (fn [color]
(-> grid
(update :params assoc :color color)
(on-change))))
handle-detach-color handle-detach-color
(fn [] (mf/use-fn
(when on-change (mf/deps grid)
(on-change (-> grid (fn []
(d/dissoc-in [:params :color :id]) (-> grid
(d/dissoc-in [:params :color :file-id]))))) (update-in [:params :color] dissoc :id :file-id)
(on-change))))
handle-use-default handle-use-default
(fn [] (mf/use-fn
(let [params ((:type grid) default-grid-params) (mf/deps grid)
color (or (get-in params [:color :value]) (get-in params [:color :color])) (fn []
params (-> params (let [params ((:type grid) default-grid-params)
(assoc-in [:color :color] color) color (or (get-in params [:color :value]) (get-in params [:color :color]))
(update :color dissoc :value))] params (-> params
(when on-change (assoc-in [:color :color] color)
(on-change (assoc grid :params params))))) (update :color dissoc :value))]
(when on-change
(on-change (assoc grid :params params))))))
handle-set-as-default handle-set-as-default
(fn [] (mf/use-fn (mf/deps grid) #(on-save-default grid))
(when on-save-grid
(on-save-grid grid)))
is-default (= (->> grid :params) is-default (= (->> grid :params)
(->> grid :type default-grid-params)) (->> grid :type default-grid-params))
@ -122,21 +132,23 @@
[:button.custom-button {:class (when open? "is-active") [:button.custom-button {:class (when open? "is-active")
:on-click toggle-advanced-options} i/actions] :on-click toggle-advanced-options} i/actions]
[:& select {:class "flex-grow" [:& select
:default-value type {:class "flex-grow"
:options [{:value :square :label (tr "workspace.options.grid.square")} :default-value type
{:value :column :label (tr "workspace.options.grid.column")} :options [{:value :square :label (tr "workspace.options.grid.square")}
{:value :row :label (tr "workspace.options.grid.row")}] {:value :column :label (tr "workspace.options.grid.column")}
:on-change handle-change-type}] {:value :row :label (tr "workspace.options.grid.row")}]
:on-change handle-change-type}]
(if (= type :square) (if (= type :square)
[:div.input-element.pixels {:title (tr "workspace.options.size")} [:div.input-element.pixels {:title (tr "workspace.options.size")}
[:> numeric-input {:min 1 [:> numeric-input {:min 1
:value (or (:size params) "")
:no-validate true :no-validate true
:value (:size params)
:on-change (handle-change :params :size)}]] :on-change (handle-change :params :size)}]]
[:& editable-select {:value (:size params) [:& editable-select {:value (:size params)
:type (when (number? (:size params)) "number" ) :type "number"
:class "input-option" :class "input-option"
:min 1 :min 1
:options size-options :options size-options
@ -145,10 +157,9 @@
[:div.grid-option-main-actions [:div.grid-option-main-actions
[:button.custom-button {:on-click handle-toggle-visibility} (if display i/eye i/eye-closed)] [:button.custom-button {:on-click handle-toggle-visibility} (if display i/eye i/eye-closed)]
[:button.custom-button {:on-click handle-remove-grid} i/minus]]] [:button.custom-button {:on-click on-remove} i/minus]]]
[:& advanced-options {:visible? open? [:& advanced-options {:visible? open? :on-close toggle-advanced-options}
:on-close toggle-advanced-options}
[:button.custom-button {:on-click toggle-advanced-options} i/actions] [:button.custom-button {:on-click toggle-advanced-options} i/actions]
(when (= :square type) (when (= :square type)
[:& input-row {:label (tr "workspace.options.grid.params.size") [:& input-row {:label (tr "workspace.options.grid.params.size")
@ -190,13 +201,16 @@
:on-change (handle-change :params :type)}]) :on-change (handle-change :params :type)}])
(when (#{:row :column} type) (when (#{:row :column} type)
[:& input-row {:label (if (= :row type) [:& input-row-v2
(tr "workspace.options.grid.params.height") {:class "pixels"
(tr "workspace.options.grid.params.width")) :label (if (= :row type)
:class "pixels" (tr "workspace.options.grid.params.height")
:placeholder "Auto" (tr "workspace.options.grid.params.width"))}
:value (or (:item-length params) "") [:> numeric-input
:on-change handle-change-item-length}]) {:placeholder "Auto"
:value (or (:item-length params) "")
:default nil
:on-change handle-change-item-length}]])
(when (#{:row :column} type) (when (#{:row :column} type)
[:* [:*
@ -226,11 +240,9 @@
(mf/defc frame-grid [{:keys [shape]}] (mf/defc frame-grid [{:keys [shape]}]
(let [id (:id shape) (let [id (:id shape)
default-grid-params (merge dw/default-grid-params (mf/deref workspace-saved-grids)) saved-grids (mf/deref workspace-saved-grids)
handle-create-grid #(st/emit! (dw/add-frame-grid id)) default-grid-params (mf/use-memo (mf/deps saved-grids) #(merge dw/default-grid-params saved-grids))
handle-remove-grid (fn [index] #(st/emit! (dw/remove-frame-grid id index))) handle-create-grid (mf/use-fn (mf/deps id) #(st/emit! (dw/add-frame-grid id)))]
handle-edit-grid (fn [index] #(st/emit! (dw/set-frame-grid id index %)))
handle-save-grid (fn [grid] (st/emit! (dw/set-default-grid (:type grid) (:params grid))))]
[:div.element-set [:div.element-set
[:div.element-set-title [:div.element-set-title
[:span (tr "workspace.options.grid.title")] [:span (tr "workspace.options.grid.title")]
@ -239,12 +251,13 @@
(when (seq (:grids shape)) (when (seq (:grids shape))
[:div.element-set-content [:div.element-set-content
(for [[index grid] (map-indexed vector (:grids shape))] (for [[index grid] (map-indexed vector (:grids shape))]
[:& grid-options {:key (str (:id shape) "-" index) [:& grid-options {:key (str id "-" index)
:grid grid :shape-id id
:default-grid-params default-grid-params :grid grid
:frame shape :index index
:on-change (handle-edit-grid index) :frame-width (:width shape)
:on-remove (handle-remove-grid index) :frame-height (:height shape)
:on-save-grid handle-save-grid}])])])) :default-grid-params default-grid-params
}])])]))

View file

@ -278,7 +278,7 @@
text-transform-attrs))) text-transform-attrs)))
typography (merge txt/default-typography set-values) typography (merge txt/default-typography set-values)
typography (generate-typography-name typography) typography (generate-typography-name typography)
id (uuid/next)] id (uuid/next)]
(st/emit! (dwl/add-typography (assoc typography :id id) false)) (st/emit! (dwl/add-typography (assoc typography :id id) false))
(run! #(emit-update! % {:typography-ref-id id (run! #(emit-update! % {:typography-ref-id id
:typography-ref-file file-id}) ids))) :typography-ref-file file-id}) ids)))

View file

@ -9,6 +9,7 @@
[app.main.ui.components.editable-select :refer [editable-select]] [app.main.ui.components.editable-select :refer [editable-select]]
[app.main.ui.components.numeric-input :refer [numeric-input]] [app.main.ui.components.numeric-input :refer [numeric-input]]
[app.main.ui.components.select :refer [select]] [app.main.ui.components.select :refer [select]]
[app.util.object :as obj]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
(mf/defc input-row [{:keys [label options value class min max on-change type placeholder]}] (mf/defc input-row [{:keys [label options value class min max on-change type placeholder]}]
@ -27,7 +28,7 @@
[:& editable-select {:value value [:& editable-select {:value value
:class "input-option" :class "input-option"
:options options :options options
:type (when (number? value) "number") :type "number"
:min min :min min
:max max :max max
:placeholder placeholder :placeholder placeholder
@ -38,9 +39,28 @@
:class "input-text" :class "input-text"
:on-change on-change} ] :on-change on-change} ]
[:> numeric-input {:placeholder placeholder [:> numeric-input
:min min {:placeholder placeholder
:max max :min min
:on-change on-change :max max
:value (or value "")}])]]) :on-change on-change
:value (or value "")}])]])
;; NOTE: (by niwinz) this is a new version of input-row, I didn't
;; touched the original one because it is used in many sites and I
;; don't have intention to refactor all the code right now. We should
;; consider to use the new one and once we have migrated all to the
;; new component, we can proceed to rename it and delete the old one.
(mf/defc input-row-v2
{::mf/wrap-props false}
[props]
(let [label (obj/get props "label")
class (obj/get props "class")
children (obj/get props "children")]
[:div.row-flex.input-row
[:span.element-set-subtitle label]
[:div.input-element {:class class}
children]]))

View file

@ -184,7 +184,7 @@
(attrs/get-attrs-multi (txt/node-seq content) attrs))))] (attrs/get-attrs-multi (txt/node-seq content) attrs))))]
:children (let [children (->> (:shapes shape []) (map #(get objects %))) :children (let [children (->> (:shapes shape []) (map #(get objects %)))
[new-ids new-values] (get-attrs* children objects attr-type)] [new-ids new-values] (get-attrs* children objects attr-type)]
[(into ids new-ids) (merge-attrs values new-values)]) [(d/concat-vec ids new-ids) (merge-attrs values new-values)])
[])))] [])))]
(reduce extract-attrs [[] []] shapes))) (reduce extract-attrs [[] []] shapes)))

View file

@ -83,8 +83,9 @@
on-drop on-drop
(mf/use-callback (mf/use-callback
(mf/deps id index) (mf/deps id index)
(fn [_side {:keys [id] :as data}] (fn [side {:keys [id] :as data}]
(st/emit! (dw/relocate-page id index)))) (let [index (if (= :bot side) (inc index) index)]
(st/emit! (dw/relocate-page id index)))))
on-duplicate on-duplicate
(fn [_] (fn [_]

View file

@ -28,9 +28,8 @@
(let [token (first tree) (let [token (first tree)
args (rest tree)] args (rest tree)]
(case token (case token
:opt-expr :opt-expr
(if (empty? args) 0 (interpret (first args) init-value)) (if (empty? args) nil (interpret (first args) init-value))
:expr :expr
(if (index-of "+-*/" (first args)) (if (index-of "+-*/" (first args))
@ -87,8 +86,9 @@
(defn expr-eval (defn expr-eval
[expr init-value] [expr init-value]
(s/assert string? expr) (s/assert string? expr)
(s/assert number? init-value) (let [result (parser expr)
(let [result (parser expr)] init-value (or init-value 0)]
(s/assert number? init-value)
(if-not (insta/failure? result) (if-not (insta/failure? result)
(interpret result init-value) (interpret result init-value)
(let [text (:text result) (let [text (:text result)

View file

@ -79,7 +79,6 @@
(defn- update-index (defn- update-index
[{index :index z-index :z-index :as data} old-objects new-objects] [{index :index z-index :z-index :as data} old-objects new-objects]
(let [changes? (fn [id] (let [changes? (fn [id]
(not= (get old-objects id) (not= (get old-objects id)
(get new-objects id))) (get new-objects id)))