0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-24 13:41:39 -05:00

Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2024-02-29 12:53:08 +01:00
commit a109673654
86 changed files with 740 additions and 561 deletions

View file

@ -6,11 +6,11 @@
(ns user
(:require
[app.common.pprint :as pp]
[app.common.schema :as sm]
[app.common.schema.desc-js-like :as smdj]
[app.common.schema.desc-native :as smdn]
[app.common.schema.generators :as sg]
[app.common.pprint :as pp]
[clojure.java.io :as io]
[clojure.pprint :refer [pprint print-table]]
[clojure.repl :refer :all]

View file

@ -13,25 +13,22 @@
[cuerdas.core :as str]))
(def black "#000000")
(def canvas "#E8E9EA")
(def default-layout "#DE4762")
(def gray-10 "#E3E3E3")
(def gray-20 "#B1B2B5")
(def gray-30 "#7B7D85")
(def gray-40 "#64666A")
(def gray-50 "#303236")
(def info "#59B9E2")
(def test "#fabada")
(def white "#FFFFFF")
(def primary "#31EFB8")
(def danger "#E65244")
(def warning "#FC8802")
;; new-css-system colors
(def new-primary "#91fadb")
(def new-danger "#ff4986")
(def new-warning "#ff9b49")
(def canvas-background "#1d1f20")
(def new-primary "#7efff5")
(def new-danger "#ff3277")
(def new-warning "#fe4811")
(def new-primary-light "#6911d4")
(def background-quaternary "#2e3434")
(def background-quaternary-light "#eef0f2")
(def canvas "#E8E9EA")
(def names
{"aliceblue" "#f0f8ff"

View file

@ -749,21 +749,23 @@
(defmulti components-changed (fn [_ change] (:type change)))
(defmethod components-changed :mod-obj
[file-data {:keys [id page-id _component-id operations]}]
(when page-id
(let [page (ctpl/get-page file-data page-id)
shape-and-parents (map #(ctn/get-shape page %)
(cons id (cfh/get-parent-ids (:objects page) id)))
need-sync? (fn [operation]
; We need to trigger a sync if the shape has changed any
; attribute that participates in components synchronization.
(and (= (:type operation) :set)
(get ctk/sync-attrs (:attr operation))))
any-sync? (some need-sync? operations)]
(when any-sync?
(let [xform (comp (filter :main-instance) ; Select shapes that are main component instances
[file-data {:keys [id page-id component-id operations]}]
(let [need-sync? (fn [operation]
; We need to trigger a sync if the shape has changed any
; attribute that participates in components synchronization.
(and (= (:type operation) :set)
(get ctk/sync-attrs (:attr operation))))
any-sync? (some need-sync? operations)]
(when any-sync?
(if page-id
(let [page (ctpl/get-page file-data page-id)
shape-and-parents (map #(ctn/get-shape page %)
(cons id (cfh/get-parent-ids (:objects page) id)))
xform (comp (filter :main-instance) ; Select shapes that are main component instances
(map :component-id))]
(into #{} xform shape-and-parents))))))
(into #{} xform shape-and-parents))
(when component-id
#{component-id})))))
(defmethod components-changed :mov-objects
[file-data {:keys [page-id _component-id parent-id shapes] :as change}]

View file

@ -8,7 +8,8 @@
(:require
[app.common.geom.point :as gpt]
[app.common.geom.rect :as grc]
[app.common.geom.shapes :as gsh]))
[app.common.geom.shapes :as gsh]
[app.common.geom.shapes.points :as gpo]))
;; --- Alignment
@ -30,6 +31,23 @@
(- (:y align-pos) (:y wrapper-rect)))]
(gsh/move shape delta)))
(defn align-to-parent
"Does the same calc as align-to-rect but relative to a parent shape."
[shape parent axis]
(let [parent-bounds (:points parent)
wrapper-rect
(-> (gsh/transform-points (:points shape) (gsh/shape->center parent) (:transform-inverse parent))
(grc/points->rect))
align-pos (calc-align-pos wrapper-rect (:selrect parent) axis)
xv #(gpo/start-hv parent-bounds %)
yv #(gpo/start-vv parent-bounds %)
delta (-> (xv (- (:x align-pos) (:x wrapper-rect)))
(gpt/add (yv (- (:y align-pos) (:y wrapper-rect)))))]
(gsh/move shape delta)))
(defn calc-align-pos
[wrapper-rect rect axis]
(case axis

View file

@ -211,7 +211,7 @@
([{:keys [type metadata] :as shape} objects]
(assert (map? objects))
(case type
:group
(:group :frame)
(group-to-path shape objects)
:bool

View file

@ -103,6 +103,12 @@
(concat (map #(ctn/make-container % :page) (ctpl/pages-seq file-data))
(map #(ctn/make-container % :component) (ctkl/components-seq file-data))))
(defn object-containers-seq
"Generate a sequence of all pages and all deleted components (all those components that have :objects), wrapped as containers"
[file-data]
(concat (map #(ctn/make-container % :page) (ctpl/pages-seq file-data))
(map #(ctn/make-container % :component) (ctkl/deleted-components-seq file-data))))
(defn update-container
"Update a container inside the file, it can be a page or a component"
[file-data container f]

View file

@ -247,6 +247,16 @@ function templatePipeline(options) {
gulpSass.compiler = sass;
gulp.task("scss:clean", async function (next) {
try {
await rimraf("./resources/public/.tmp");
await rimraf("./resources/public/css");
} finally {
next();
}
});
gulp.task("scss:modules", function () {
return gulp
.src(["src/**/**.scss"])
@ -314,7 +324,10 @@ gulp.task("scss:touch:modules", function() {
return gulp.src("src/**/**.scss").pipe(touch());
});
gulp.task("scss", gulp.series("scss:main", "scss:modules", "scss:concat", "scss:touch:main"));
gulp.task("scss", gulp.series("scss:main",
"scss:modules",
"scss:concat",
"scss:touch:main"));
gulp.task("svg:sprite:icons", function () {
return gulp
@ -419,9 +432,18 @@ gulp.task("clean:dist", function (next) {
});
gulp.task("build:styles", gulp.parallel("scss"));
gulp.task("build:assets", gulp.parallel("polyfills", "templates", "copy:assets"));
gulp.task("watch", gulp.series("dev:dirs", "build:styles", "build:assets", "watch:main"));
gulp.task("build:assets",
gulp.parallel("polyfills",
"templates",
"copy:assets"));
gulp.task("watch",
gulp.series("dev:dirs",
"scss:clean",
"build:styles",
"build:assets",
"watch:main"));
gulp.task("build:copy", function () {
return gulp.src("./resources/public/**/*").pipe(gulp.dest("./target/dist/"));

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 .667h12M12 5.5A1.5 1.5 0 0010.5 4h-5A1.5 1.5 0 004 5.5v1A1.5 1.5 0 005.5 8h5A1.5 1.5 0 0012 6.5v-1zm0 7.333a1.5 1.5 0 00-1.5-1.5h-5a1.5 1.5 0 00-1.5 1.5v1a1.5 1.5 0 001.5 1.5h5a1.5 1.5 0 001.5-1.5v-1z"/>
<path d="M2 15.333h12M12 10.5a1.5 1.5 0 01-1.5 1.5h-5A1.5 1.5 0 014 10.5v-1A1.5 1.5 0 015.5 8h5A1.5 1.5 0 0112 9.5v1zm0-7.333a1.5 1.5 0 01-1.5 1.5h-5a1.5 1.5 0 01-1.5-1.5v-1a1.5 1.5 0 011.5-1.5h5a1.5 1.5 0 011.5 1.5v1z"/>
</svg>

Before

Width:  |  Height:  |  Size: 333 B

After

Width:  |  Height:  |  Size: 339 B

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 15.333h12M12 10.5a1.5 1.5 0 01-1.5 1.5h-5A1.5 1.5 0 014 10.5v-1A1.5 1.5 0 015.5 8h5A1.5 1.5 0 0112 9.5v1zm0-7.333a1.5 1.5 0 01-1.5 1.5h-5a1.5 1.5 0 01-1.5-1.5v-1a1.5 1.5 0 011.5-1.5h5a1.5 1.5 0 011.5 1.5v1z"/>
<path d="M2 .667h12M12 5.5A1.5 1.5 0 0010.5 4h-5A1.5 1.5 0 004 5.5v1A1.5 1.5 0 005.5 8h5A1.5 1.5 0 0012 6.5v-1zm0 7.333a1.5 1.5 0 00-1.5-1.5h-5a1.5 1.5 0 00-1.5 1.5v1a1.5 1.5 0 001.5 1.5h5a1.5 1.5 0 001.5-1.5v-1z"/>
</svg>

Before

Width:  |  Height:  |  Size: 339 B

After

Width:  |  Height:  |  Size: 333 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M15.5 7.617h-14m14 0l-6.008 4.996M15.5 7.617L9.492 2.613"/>
</svg>

After

Width:  |  Height:  |  Size: 186 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M5.8 8a4.7 4.7 0 109.4 0 4.7 4.7 0 00-9.4 0zm0 0H1.5m5.643 1.68h.396m1.184 1.677h.395M7.143 6.321h.396m1.184 1.68h.395m1.185 1.678h.394m1.185 1.678h.396M8.723 4.643h.395m1.185 1.678h.394m1.185 1.68h.396m1.184 1.678h.395m-1.974-5.036h.395m1.184 1.678h.395"/>
</svg>

After

Width:  |  Height:  |  Size: 384 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M6.888 9.656h.391m1.168 1.656h.39M6.888 6.344h.391M8.447 8h.39m1.168 1.656h.39m1.168 1.656h.391M8.447 4.688h.39m1.168 1.656h.39M11.563 8h.391m1.169 1.656h.389m-1.947-4.968h.389m1.169 1.656h.389M1.5 8H5m-.025.18l5.045 5.045a.254.254 0 00.36 0l5.045-5.045a.255.255 0 00.056-.277.255.255 0 00-.056-.083L10.38 2.775a.253.253 0 00-.36 0L4.975 7.82a.253.253 0 000 .36z"/>
</svg>

After

Width:  |  Height:  |  Size: 492 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M7.167 9.667h.393m1.176 1.666h.392m-1.961-5h.393M8.736 8h.392m1.176 1.667h.392m1.176 1.666h.393M8.736 4.667h.392m1.176 1.666h.392M11.872 8h.393m1.176 1.667h.392m-1.96-5h.392m1.176 1.666h.392M1.5 8h5m0-4h8v8h-8V4z"/>
</svg>

After

Width:  |  Height:  |  Size: 342 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M.833 4h10.098c2.34 0 4.236 1.791 4.236 4s-1.896 4-4.236 4H.833"/>
</svg>

After

Width:  |  Height:  |  Size: 193 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M.833 4h14.334v8H.833"/>
</svg>

After

Width:  |  Height:  |  Size: 153 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M7.633 9.627h.374m1.117 1.627h.372M7.633 6.373h.374M9.124 8h.372m1.117 1.627h.372M9.124 4.746h.372m1.117 1.627h.372M12.102 8h.373M1.5 8l5.5.004m7.88-.225l-7.494-4.74a.246.246 0 00-.256-.006.262.262 0 00-.13.227v9.48c0 .094.05.181.13.227.08.046.178.044.256-.006l7.494-4.74A.26.26 0 0015 8a.26.26 0 00-.12-.221z"/>
</svg>

After

Width:  |  Height:  |  Size: 441 B

View file

@ -63,7 +63,7 @@
ptk/WatchEvent
(watch [_ state stream]
(let [stoper-s (rx/filter (ptk/type? ::finalize) stream)
(let [stopper (rx/filter (ptk/type? ::finalize) stream)
profile-id (:profile-id state)]
(->> (rx/merge
@ -92,7 +92,7 @@
(rx/filter #(= id (:id %)))
(rx/map du/set-current-team)))
(rx/take-until stoper-s))))))
(rx/take-until stopper))))))
(defn finalize
[params]

View file

@ -234,7 +234,7 @@
ptk/EffectEvent
(effect [_ _ stream]
(let [session (atom nil)
stoper (rx/filter (ptk/type? ::initialize) stream)
stopper (rx/filter (ptk/type? ::initialize) stream)
buffer (atom #queue [])
profile (->> (rx/from-atom storage {:emit-current-value? true})
(rx/map :profile)
@ -259,7 +259,7 @@
(rx/tap (fn [_]
(l/debug :hint "events chunk persisted" :total (count chunk))))
(rx/map (constantly chunk))))))
(rx/take-until stoper)
(rx/take-until stopper)
(rx/subs! (fn [chunk]
(swap! buffer remove-from-buffer (count chunk)))
(fn [cause]
@ -290,7 +290,7 @@
(swap! buffer append-to-buffer event)))
(rx/switch-map #(rx/timer (inst-ms session-timeout)))
(rx/take-until stoper)
(rx/take-until stopper)
(rx/subs! (fn [_]
(l/debug :hint "session reinitialized")
(reset! session nil))

View file

@ -209,7 +209,7 @@
(rx/filter #(= @resource-id (:resource-id %)))
(rx/share))
stoper
stopper
(rx/filter #(or (= "ended" (:status %))
(= "error" (:status %)))
progress-stream)]
@ -228,12 +228,12 @@
(initialize-export-status exports cmd resource))))
;; We proceed to update the export state with incoming
;; progress updates. We delay the stoper for give some time
;; progress updates. We delay the stopper for give some time
;; to update the status with ended or errored status before
;; close the stream.
(->> progress-stream
(rx/map update-export-status)
(rx/take-until (rx/delay 500 stoper))
(rx/take-until (rx/delay 500 stopper))
(rx/finalize (fn []
(swap! st/ongoing-tasks disj :export))))
@ -246,7 +246,7 @@
(rx/take 1)
(rx/delay default-timeout)
(rx/map #(clear-export-state @resource-id))
(rx/take-until (rx/delay 6000 stoper))))))))
(rx/take-until (rx/delay 6000 stopper))))))))
(defn retry-last-export
[]

View file

@ -61,16 +61,16 @@
ptk/WatchEvent
(watch [_ _ stream]
(rx/merge
(let [stoper (rx/filter (ptk/type? ::hide) stream)]
(let [stopper (rx/filter (ptk/type? ::hide) stream)]
(->> stream
(rx/filter (ptk/type? :app.util.router/navigate))
(rx/map (constantly hide))
(rx/take-until stoper)))
(rx/take-until stopper)))
(when (:timeout data)
(let [stoper (rx/filter (ptk/type? ::show) stream)]
(let [stopper (rx/filter (ptk/type? ::show) stream)]
(->> (rx/of hide)
(rx/delay (:timeout data))
(rx/take-until stoper))))))))
(rx/take-until stopper))))))))
(def hide
(ptk/reify ::hide
@ -80,10 +80,10 @@
ptk/WatchEvent
(watch [_ _ stream]
(let [stoper (rx/filter (ptk/type? ::show) stream)]
(let [stopper (rx/filter (ptk/type? ::show) stream)]
(->> (rx/of #(dissoc % :message))
(rx/delay default-animation-timeout)
(rx/take-until stoper))))))
(rx/take-until stopper))))))
(defn hide-tag
[tag]

View file

@ -51,9 +51,9 @@
(vreset! ws-conn ws)
(let [stoper (rx/merge
(rx/filter (ptk/type? ::finalize) stream)
(rx/filter (ptk/type? ::initialize) stream))]
(let [stopper (rx/merge
(rx/filter (ptk/type? ::finalize) stream)
(rx/filter (ptk/type? ::initialize) stream))]
(->> (rx/merge
(rx/of #(assoc % :ws-conn ws))
@ -64,7 +64,7 @@
(->> (ws/get-rcv-stream ws)
(rx/filter ws/opened-event?)
(rx/map (fn [_] (ptk/data-event ::opened {})))))
(rx/take-until stoper)))))))
(rx/take-until stopper)))))))
;; --- Finalize Websocket

View file

@ -41,7 +41,6 @@
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.collapse :as dwco]
[app.main.data.workspace.drawing :as dwd]
[app.main.data.workspace.drawing.common :as dwdc]
[app.main.data.workspace.edition :as dwe]
[app.main.data.workspace.fix-bool-contents :as fbc]
[app.main.data.workspace.fix-broken-shapes :as fbs]
@ -153,7 +152,7 @@
(watch [_ _ stream]
(let [team-id (:id team)
file-id (:id file)
stoper-s (rx/filter (ptk/type? ::bundle-fetched) stream)]
stopper (rx/filter (ptk/type? ::bundle-fetched) stream)]
(->> (rx/concat
;; Initialize notifications
@ -204,7 +203,7 @@
(rx/of (with-meta (workspace-initialized)
{:file-id file-id})))
(rx/take-until stoper-s))))))
(rx/take-until stopper))))))
(defn- libraries-fetched
[libraries]
@ -1080,7 +1079,7 @@
(let [object (get objects object-id)
parent-id (:parent-id (get objects object-id))
parent (get objects parent-id)]
[(gal/align-to-rect object parent axis)]))
[(gal/align-to-parent object parent axis)]))
(defn align-objects-list
[objects selected axis]
@ -2138,7 +2137,6 @@
(watch [_ _ _]
(if read-only?
(rx/of :interrupt
(dwdc/clear-drawing)
(remove-layout-flag :colorpalette)
(remove-layout-flag :textpalette))
(rx/empty)))))

View file

@ -526,9 +526,9 @@
(ptk/reify ::initialize-colorpicker
ptk/WatchEvent
(watch [_ _ stream]
(let [stoper (rx/merge
(rx/filter (ptk/type? ::finalize-colorpicker) stream)
(rx/filter (ptk/type? ::initialize-colorpicker) stream))]
(let [stopper (rx/merge
(rx/filter (ptk/type? ::finalize-colorpicker) stream)
(rx/filter (ptk/type? ::initialize-colorpicker) stream))]
(->> (rx/merge
(->> stream
@ -537,7 +537,7 @@
(rx/filter (ptk/type? ::update-colorpicker-color) stream)
(rx/filter (ptk/type? ::activate-colorpicker-gradient) stream))
(rx/map (constantly (colorpicker-onchange-runner on-change)))
(rx/take-until stoper))))
(rx/take-until stopper))))
ptk/UpdateEvent
(update [_ state]

View file

@ -34,7 +34,7 @@
(ptk/reify ::initialize-comments
ptk/WatchEvent
(watch [_ _ stream]
(let [stoper (rx/filter #(= ::finalize %) stream)]
(let [stopper (rx/filter #(= ::finalize %) stream)]
(rx/merge
(rx/of (dcm/retrieve-comment-threads file-id))
(->> stream
@ -45,11 +45,11 @@
(rx/filter (fn [[_ space]] (not space)))
(rx/map first)
(rx/map handle-comment-layer-click)
(rx/take-until stoper))
(rx/take-until stopper))
(->> stream
(rx/filter dwco/interrupt?)
(rx/map handle-interrupt)
(rx/take-until stoper)))))))
(rx/take-until stopper)))))))
(defn- handle-interrupt
[]

View file

@ -38,8 +38,7 @@
(watch [_ _ stream]
(rx/merge
(when (= tool :path)
(rx/of (start-drawing :path)
(dwc/hide-toolbar)))
(rx/of (start-drawing :path)))
(when (= tool :curve)
(let [stopper (rx/filter dwc/interrupt? stream)]

View file

@ -78,12 +78,12 @@
(ptk/reify ::handle-drawing
ptk/WatchEvent
(watch [_ state stream]
(let [stoper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> stream
(rx/filter #(= % :interrupt))))
(let [stopper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> stream
(rx/filter #(= % :interrupt))))
layout (get state :workspace-layout)
zoom (dm/get-in state [:workspace-local :zoom] 1)
@ -131,7 +131,7 @@
(rx/filter #(> (gpt/distance % initial) (/ 2 zoom)))
;; Take until before the snap calculation otherwise we could cancel the snap in the worker
;; and its a problem for fast moving drawing
(rx/take-until stoper)
(rx/take-until stopper)
(rx/with-latest-from ms/mouse-position-shift ms/mouse-position-mod)
(rx/switch-map
(fn [[point :as current]]

View file

@ -28,7 +28,7 @@
(def simplify-tolerance 0.3)
(defn stoper-event?
(defn stopper-event?
[{:keys [type] :as event}]
(and (mse/mouse-event? event)
(= type :up)))
@ -104,7 +104,7 @@
(ptk/reify ::handle-drawing
ptk/WatchEvent
(watch [_ _ stream]
(let [stoper (rx/filter stoper-event? stream)
(let [stopper (rx/filter stopper-event? stream)
mouse (rx/sample 10 ms/mouse-position)
shape (cts/setup-shape {:type :path
:initialized? true
@ -115,7 +115,7 @@
(rx/of #(update % :workspace-drawing assoc :object shape))
(->> mouse
(rx/map insert-point)
(rx/take-until stoper))
(rx/take-until stopper))
(rx/of
(setup-frame)
(finish-drawing)

View file

@ -7,8 +7,7 @@
(ns app.main.data.workspace.edition
(:require
[app.common.data.macros :as dm]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.path.common :as dwpc]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
@ -33,25 +32,27 @@
state)))
ptk/WatchEvent
(watch [_ state stream]
(let [objects (wsh/lookup-page-objects state)]
(rx/concat
(if (ctl/grid-layout? objects id)
(rx/of (dwc/hide-toolbar))
(rx/empty))
(->> stream
(rx/filter interrupt?)
(rx/take 1)
(rx/map (constantly clear-edition-mode))))))))
(watch [_ _ stream]
(->> stream
(rx/filter interrupt?)
(rx/take 1)
(rx/map clear-edition-mode)))))
;; If these event change modules review /src/app/main/data/workspace/path/undo.cljs
(def clear-edition-mode
(defn clear-edition-mode
[]
(ptk/reify ::clear-edition-mode
ptk/UpdateEvent
(update [_ state]
(-> state
(update :workspace-local dissoc :edition)
(update :workspace-drawing dissoc :tool :object :lock)
(dissoc :workspace-grid-edition)))
ptk/WatchEvent
(watch [_ state _]
(let [id (get-in state [:workspace-local :edition])]
(-> state
(update :workspace-local dissoc :edition)
(dissoc :workspace-grid-edition)
(assoc-in [:workspace-local :hide-toolbar] false)
(cond-> (some? id) (update-in [:workspace-local :edit-path] dissoc id)))))))
(rx/concat
(when (some? id)
(dwpc/finish-path)))))))

View file

@ -317,10 +317,10 @@
(let [file (wsh/get-file state file-id)
components-v2 (get-in file [:options :components-v2])]
(loop [pages (vals (get file :pages-index))
(loop [containers (ctf/object-containers-seq file)
changes (pcb/empty-changes it)]
(if-let [page (first pages)]
(recur (next pages)
(if-let [container (first containers)]
(recur (next containers)
(pcb/concat-changes
changes
(generate-sync-container it
@ -328,7 +328,7 @@
asset-id
library-id
state
(cfh/make-container page :page)
container
components-v2)))
changes))))
@ -597,9 +597,7 @@
(log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?)
(let [shape-inst (ctn/get-shape container shape-id)
library (dm/get-in libraries [(:component-file shape-inst) :data])
component (or (ctkl/get-component library (:component-id shape-inst))
(and reset?
(ctkl/get-deleted-component library (:component-id shape-inst))))]
component (ctkl/get-component library (:component-id shape-inst) true)]
(if (and (ctk/in-component-copy? shape-inst)
(or (ctf/direct-copy? shape-inst component container nil libraries) reset?)) ; In a normal sync, we don't want to sync remote mains, only direct/near
(let [redirect-shaperef (partial redirect-shaperef container libraries)

View file

@ -38,7 +38,7 @@
(ptk/reify ::initialize
ptk/WatchEvent
(watch [_ state stream]
(let [stoper (rx/filter (ptk/type? ::finalize) stream)
(let [stopper (rx/filter (ptk/type? ::finalize) stream)
profile-id (:profile-id state)
initmsg [{:type :subscribe-file
@ -87,7 +87,7 @@
(rx/pipe (rxs/throttle 100))
(rx/map #(handle-pointer-send file-id (:pt %)))))
(rx/take-until stoper))]
(rx/take-until stopper))]
(rx/concat stream (rx/of (dws/send endmsg)))))))

View file

@ -16,7 +16,6 @@
[app.common.types.shape-tree :as ctst]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.drawing.common :as dwdc]
[app.main.data.workspace.edition :as dwe]
[app.main.data.workspace.path.changes :as changes]
@ -166,16 +165,16 @@
(ptk/reify ::start-path-from-point
ptk/WatchEvent
(watch [_ state stream]
(let [stoper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> stream
(rx/filter helpers/end-path-event?)))
(let [stopper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> stream
(rx/filter helpers/end-path-event?)))
drag-events (->> (streams/position-stream state)
(rx/map #(drag-handler %))
(rx/take-until stoper))]
(rx/take-until stopper))]
(rx/concat
(rx/of (add-node position))
(streams/drag-stream
@ -197,16 +196,16 @@
"should be a pointer"
(gpt/point? down-event))
(let [stoper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> stream
(rx/filter helpers/end-path-event?)))
(let [stopper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> stream
(rx/filter helpers/end-path-event?)))
drag-events (->> (streams/position-stream state)
(rx/map #(drag-handler %))
(rx/take-until stoper))]
(rx/take-until stopper))]
(rx/concat
(rx/of (add-node down-event))
(streams/drag-stream
@ -307,10 +306,8 @@
(ptk/reify ::handle-new-shape
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)
shape (cts/setup-shape {:type :path})]
(let [shape (cts/setup-shape {:type :path})]
(-> state
(assoc-in [:workspace-local :edit-path id :snap-toggled] false)
(update :workspace-drawing assoc :object shape))))
ptk/WatchEvent
@ -357,13 +354,14 @@
(let [id (st/get-path-id state)
content (st/get-path state :content)
old-content (get-in state [:workspace-local :edit-path id :old-content])
mode (get-in state [:workspace-local :edit-path id :edit-mode])]
mode (get-in state [:workspace-local :edit-path id :edit-mode])
empty-content? (empty? content)]
(cond
(not= content old-content) (rx/of (changes/save-path-content)
(start-draw-mode))
(and (not= content old-content) (not empty-content?)) (rx/of (changes/save-path-content))
(= mode :draw) (rx/of :interrupt)
:else (rx/of (common/finish-path)))))))
:else (rx/of
(common/finish-path)
(dwdc/clear-drawing)))))))
(defn change-edit-mode [mode]
(ptk/reify ::change-edit-mode
@ -378,8 +376,7 @@
(let [id (st/get-path-id state)]
(cond
(and id (= :move mode)) (rx/of (common/finish-path))
(and id (= :draw mode)) (rx/of (dwc/hide-toolbar)
(start-draw-mode))
(and id (= :draw mode)) (rx/of (start-draw-mode))
:else (rx/empty))))))
(defn reset-last-handler

View file

@ -15,7 +15,6 @@
[app.common.svg.path.shapes-to-path :as upsp]
[app.common.svg.path.subpath :as ups]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.edition :as dwe]
[app.main.data.workspace.path.changes :as changes]
[app.main.data.workspace.path.drawing :as drawing]
@ -68,7 +67,7 @@
(let [changes (changes/generate-path-changes it objects page-id shape (:content shape) new-content)]
(if (empty? new-content)
(rx/of (dch/commit-changes changes)
dwe/clear-edition-mode)
(dwe/clear-edition-mode))
(rx/of (dch/commit-changes changes)
(selection/update-selection point-change)
(fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers :moving-nodes :moving-handler))))))))))
@ -319,8 +318,7 @@
(= (ptk/type %) ::start-path-edit))))
interrupt (->> stream (rx/filter #(= % :interrupt)) (rx/take 1))]
(rx/concat
(rx/of (dwc/hide-toolbar)
(undo/start-path-undo)
(rx/of (undo/start-path-undo)
(drawing/change-edit-mode mode))
(->> interrupt
(rx/map #(stop-path-edit id))

View file

@ -120,12 +120,12 @@
ptk/WatchEvent
(watch [_ state stream]
(let [zoom (get-in state [:workspace-local :zoom] 1)
stoper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> stream
(rx/filter dwc/interrupt?)))
stopper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> stream
(rx/filter dwc/interrupt?)))
from-p @ms/mouse-position]
(rx/concat
@ -133,7 +133,7 @@
(rx/map #(grc/points->rect [from-p %]))
(rx/filter (partial valid-rect? zoom))
(rx/map update-area-selection)
(rx/take-until stoper))
(rx/take-until stopper))
(rx/of (select-node-area shift?)
(clear-area-selection))))))))

View file

@ -8,7 +8,6 @@
(:require
[app.main.data.shortcuts :as ds]
[app.main.data.workspace :as dw]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.path :as drp]
[app.main.store :as st]
[beicon.v2.core :as rx]
@ -24,16 +23,12 @@
(ptk/reify ::esc-pressed
ptk/WatchEvent
(watch [_ state _]
;; Not interrupt when we're editing a path
;; Not interrupt when we're editing a path
(let [edition-id (or (get-in state [:workspace-drawing :object :id])
(get-in state [:workspace-local :edition]))
content (get-in state [:workspace-drawing :object :content])
path-edit-mode (get-in state [:workspace-local :edit-path edition-id :edit-mode])]
(if-not (= :draw path-edit-mode)
(rx/of :interrupt)
(if (<= (count content) 1)
(rx/of (dwc/show-toolbar))
(rx/empty)))))))
(when-not (= :draw path-edit-mode)
(rx/of :interrupt))))))
(def shortcuts
{:move-nodes {:tooltip "M"

View file

@ -6,13 +6,48 @@
(ns app.main.data.workspace.path.state
(:require
[app.common.data.macros :as dm]
[app.common.files.helpers :as cph]
[app.common.svg.path.shapes-to-path :as upsp]))
(defn path-editing?
"Returns true if we're editing a path or creating a new one."
[{local :workspace-local
drawing :workspace-drawing}]
(let [selected (:selected local)
edition (:edition local)
drawing-obj (:object drawing)
drawing-tool (:tool drawing)
edit-path? (dm/get-in local [:edit-path edition])
shape (or drawing-obj (first selected))
shape-id (:id shape)
single? (= (count selected) 1)
editing? (and (some? shape-id)
(some? edition)
(= shape-id edition))
;; we need to check if we're drawing a new object but we're
;; not using the pencil tool.
draw-path? (and (some? drawing-obj)
(cph/path-shape? drawing-obj)
(not= :curve drawing-tool))]
(or (and ^boolean single?
^boolean editing?
(and (not (cph/text-shape? shape))
(not (cph/frame-shape? shape))))
draw-path?
edit-path?)))
(defn get-path-id
"Retrieves the currently editing path id"
[state]
(or (get-in state [:workspace-local :edition])
(get-in state [:workspace-drawing :object :id])))
(or (dm/get-in state [:workspace-local :edition])
(dm/get-in state [:workspace-drawing :object :id])))
(defn get-path-location
[state & ks]

View file

@ -52,19 +52,19 @@
start (-> @ms/mouse-position to-pixel-snap)
stoper (rx/merge
(->> st/stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> st/stream
(rx/filter finish-edition?)))
stopper (rx/merge
(->> st/stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> st/stream
(rx/filter finish-edition?)))
position-stream
(->> ms/mouse-position
(rx/map to-pixel-snap)
(rx/filter (dragging? start zoom))
(rx/take 1)
(rx/take-until stoper))]
(rx/take-until stopper))]
(rx/merge
(->> position-stream

View file

@ -40,7 +40,7 @@
(rx/of (dch/update-shapes [id] upsp/convert-to-path))
(rx/of (dch/commit-changes changes)
(when (empty? new-content)
dwe/clear-edition-mode))))))))))
(dwe/clear-edition-mode)))))))))))
(defn make-corner
([]

View file

@ -9,7 +9,9 @@
[app.common.data :as d]
[app.common.data.undo-stack :as u]
[app.common.uuid :as uuid]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.path.changes :as changes]
[app.main.data.workspace.path.common :as common]
[app.main.data.workspace.path.state :as st]
[app.main.store :as store]
[beicon.v2.core :as rx]
@ -65,8 +67,14 @@
undo-stack)))))
ptk/WatchEvent
(watch [_ _ _]
(rx/of (changes/save-path-content {:preserve-move-to true})))))
(watch [_ state _]
(let [id (st/get-path-id state)
undo-stack (get-in state [:workspace-local :edit-path id :undo-stack])]
(if (> (:index undo-stack) 0)
(rx/of (changes/save-path-content {:preserve-move-to true}))
(rx/of (changes/save-path-content {:preserve-move-to true})
(common/finish-path)
(dwc/show-toolbar)))))))
(defn redo-path []
(ptk/reify ::redo-path

View file

@ -37,7 +37,7 @@
ptk/WatchEvent
(watch [_ _ stream]
(log/debug :hint "initialize persistence")
(let [stoper (rx/filter (ptk/type? ::initialize-persistence) stream)
(let [stopper (rx/filter (ptk/type? ::initialize-persistence) stream)
commits (l/atom [])
saving? (l/atom false)
@ -53,7 +53,7 @@
on-dirty
(fn []
;; Enable reload stoper
;; Enable reload stopper
(swap! st/ongoing-tasks conj :workspace-change)
(st/emit! (update-persistence-status {:status :pending})))
@ -64,7 +64,7 @@
on-saved
(fn []
;; Disable reload stoper
;; Disable reload stopper
(swap! st/ongoing-tasks disj :workspace-change)
(st/emit! (update-persistence-status {:status :saved}))
(reset! saving? false))]
@ -82,7 +82,7 @@
(assoc :file-id file-id))))
(rx/observe-on :async)
(rx/tap #(swap! commits conj %))
(rx/take-until (rx/delay 100 stoper))
(rx/take-until (rx/delay 100 stopper))
(rx/finalize (fn []
(log/debug :hint "finalize persistence: changes watcher"))))
@ -115,7 +115,7 @@
(rx/tap on-saved)
(rx/ignore)))
(rx/empty))))
(rx/take-until (rx/delay 100 stoper))
(rx/take-until (rx/delay 100 stopper))
(rx/finalize (fn []
(log/debug :hint "finalize persistence: save loop"))))
@ -126,7 +126,7 @@
(rx/filter library-file?)
(rx/filter (complement #(empty? (:changes %))))
(rx/map persist-synchronous-changes)
(rx/take-until (rx/delay 100 stoper))
(rx/take-until (rx/delay 100 stopper))
(rx/finalize (fn []
(log/debug :hint "finalize persistence: synchronous save loop")))))))))

View file

@ -64,12 +64,12 @@
ptk/WatchEvent
(watch [_ state stream]
(let [zoom (dm/get-in state [:workspace-local :zoom] 1)
stoper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> stream
(rx/filter interrupt?)))
stopper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(->> stream
(rx/filter interrupt?)))
init-position @ms/mouse-position
@ -99,7 +99,7 @@
(rx/scan calculate-selrect init-selrect)
(rx/filter #(or (> (dm/get-prop % :width) (/ 10 zoom))
(> (dm/get-prop % :height) (/ 10 zoom))))
(rx/take-until stoper))]
(rx/take-until stopper))]
(rx/concat
(if preserve?
@ -667,9 +667,9 @@
ptk/WatchEvent
(watch [_ _ stream]
(let [stoper (rx/filter (ptk/type? ::memorize-duplicated) stream)]
(let [stopper (rx/filter (ptk/type? ::memorize-duplicated) stream)]
(->> (rx/timer 10000) ;; This time may be adjusted after some user testing.
(rx/take-until stoper)
(rx/take-until stopper)
(rx/map clear-memorize-duplicated))))))
(defn calc-duplicate-delta

View file

@ -228,13 +228,13 @@
:subsections [:text-editor]
:fn #(update-attrs-when-no-readonly {:text-decoration "toggle-line-through"})}
:font-size-inc {:tooltip (ds/meta-shift ds/up-arrow)
:command (ds/c-mod "shift+up")
:font-size-inc {:tooltip (ds/meta-shift ds/right-arrow)
:command (ds/c-mod "shift+right")
:subsections [:text-editor]
:fn #(update-attrs-when-no-readonly {:font-size-inc true})}
:font-size-dec {:tooltip (ds/meta-shift ds/down-arrow)
:command (ds/c-mod "shift+down")
:font-size-dec {:tooltip (ds/meta-shift ds/left-arrow)
:command (ds/c-mod "shift+left")
:subsections [:text-editor]
:fn #(update-attrs-when-no-readonly {:font-size-dec true})}

View file

@ -370,9 +370,9 @@
ptk/WatchEvent
(watch [_ _ stream]
(let [stoper (->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
(let [stopper (->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-up-event?))
group (gsh/shapes->rect shapes)
group-center (grc/rect->center group)
@ -399,7 +399,7 @@
(fn [[pos mod? shift?]]
(let [delta-angle (calculate-angle pos mod? shift?)]
(dwm/set-rotation-modifiers delta-angle shapes group-center))))
(rx/take-until stoper))
(rx/take-until stopper))
(rx/of (dwm/apply-modifiers)
(finish-transform)))))))

View file

@ -196,9 +196,6 @@
(def context-menu
(l/derived :context-menu workspace-local))
(def toolbar-visibility
(l/derived :hide-toolbar workspace-local))
;; page item that it is being edited
(def editing-page-item
(l/derived :page-item workspace-local))

View file

@ -32,7 +32,7 @@
ref (gobj/get props "container")
ids (gobj/get props "ids")
list-class (gobj/get props "list-class")
ids (filter some? ids)
ids (filter some? ids)
on-click
(fn [event]
(let [target (dom/get-target event)
@ -69,7 +69,7 @@
actual-index (d/index-of ids actual-id)
previous-id (if (= 0 actual-index)
(last ids)
(nth ids (- actual-index 1)))]
(get ids (- actual-index 1) (last ids)))]
(dom/focus! (dom/get-element previous-id))))
(when (kbd/down-arrow? event)
@ -78,8 +78,9 @@
actual-index (d/index-of ids actual-id)
next-id (if (= (- len 1) actual-index)
(first ids)
(nth ids (+ 1 actual-index)))]
(dom/focus! (dom/get-element next-id))))
(get ids (+ 1 actual-index) (first ids)))
node-item (dom/get-element next-id)]
(dom/focus! node-item)))
(when (kbd/tab? event)
(on-close))))]
@ -100,5 +101,10 @@
(assert (fn? (gobj/get props "on-close")) "missing `on-close` prop")
(assert (boolean? (gobj/get props "show")) "missing `show` prop")
(when (gobj/get props "show")
(mf/element dropdown-menu' props)))
(let [ids (obj/get props "ids")
ids (d/nilv ids (->> (obj/get props "children")
(keep #(obj/get-in % ["props" "id"]))))]
(when (gobj/get props "show")
(mf/element
dropdown-menu'
(mf/spread-props props {:ids ids})))))

View file

@ -14,6 +14,8 @@
}
.radio-icon {
--radio-icon-border-color: var(--radio-btn-border-color);
@include buttonStyle;
@include flexCenter;
@include focusRadio;
@ -21,6 +23,8 @@
flex-grow: 1;
border-radius: $s-8;
box-sizing: border-box;
border: $br-2 solid var(--radio-icon-border-color);
input {
display: none;
}
@ -37,20 +41,31 @@
stroke: var(--radio-btn-foreground-color-selected);
}
}
}
&.checked {
background-color: var(--radio-btn-background-color-selected);
border-color: var(--radio-btn-border-color-selected);
svg {
stroke: var(--radio-btn-foreground-color-selected);
}
.title-name {
color: var(--radio-btn-foreground-color-selected);
}
.checked {
--radio-icon-border-color: var(--radio-btn-border-color-selected);
background-color: var(--radio-btn-background-color-selected);
svg {
stroke: var(--radio-btn-foreground-color-selected);
}
.title-name {
color: var(--radio-btn-foreground-color-selected);
}
}
&.disabled {
cursor: default;
.disabled {
cursor: default;
background-color: transparent;
border: $s-2 solid transparent;
svg {
stroke: var(--button-foreground-color-disabled);
}
.title-name {
color: var(--button-foreground-color-disabled);
}
&:hover {
background-color: transparent;
border: $s-2 solid transparent;
svg {
@ -59,15 +74,5 @@
.title-name {
color: var(--button-foreground-color-disabled);
}
&:hover {
background-color: transparent;
border: $s-2 solid transparent;
svg {
stroke: var(--button-foreground-color-disabled);
}
.title-name {
color: var(--button-foreground-color-disabled);
}
}
}
}

View file

@ -196,57 +196,69 @@
open-menu? (mf/use-state false)
edit? (mf/use-state false)
state* (mf/use-var (:font-family font))
state* (mf/use-state (:font-family font))
font-family (deref state*)
on-change
(fn [event]
(reset! state* (dom/get-target-val event)))
(mf/use-callback
(fn [event]
(reset! state* (dom/get-target-val event))))
on-save
(fn [_]
(let [font-family font-family]
(when-not (str/blank? font-family)
(st/emit! (df/update-font
{:id font-id
:name font-family})))
(reset! edit? false)))
(mf/use-callback
(mf/deps font-family)
(fn [_]
(when-not (str/blank? font-family)
(st/emit! (df/update-font {:id font-id :name font-family})))
(reset! edit? false)))
on-key-down
(fn [event]
(when (kbd/enter? event)
(on-save event)))
(mf/use-callback
(mf/deps on-save)
(fn [event]
(when (kbd/enter? event)
(on-save event))))
on-cancel
(fn [_]
(reset! edit? false)
(reset! state* (:font-family font)))
(mf/use-callback
(fn [_]
(reset! edit? false)
(reset! state* (:font-family font))))
delete-font-fn
(fn [] (st/emit! (df/delete-font font-id)))
(mf/use-callback
(mf/deps font-id)
(fn []
(st/emit! (df/delete-font font-id))))
delete-variant-fn
(fn [id] (st/emit! (df/delete-font-variant id)))
(mf/use-callback
(fn [id]
(st/emit! (df/delete-font-variant id))))
on-delete
(fn []
(st/emit! (modal/show
{:type :confirm
:title (tr "modals.delete-font.title")
:message (tr "modals.delete-font.message")
:accept-label (tr "labels.delete")
:on-accept (fn [_props] (delete-font-fn))})))
(mf/use-callback
(mf/deps delete-font-fn)
(fn []
(st/emit! (modal/show
{:type :confirm
:title (tr "modals.delete-font.title")
:message (tr "modals.delete-font.message")
:accept-label (tr "labels.delete")
:on-accept (fn [_props] (delete-font-fn))}))))
on-delete-variant
(fn [id]
(st/emit! (modal/show
{:type :confirm
:title (tr "modals.delete-font-variant.title")
:message (tr "modals.delete-font-variant.message")
:accept-label (tr "labels.delete")
:on-accept (fn [_props]
(delete-variant-fn id))})))]
(mf/use-callback
(mf/deps delete-variant-fn)
(fn [id]
(st/emit! (modal/show
{:type :confirm
:title (tr "modals.delete-font-variant.title")
:message (tr "modals.delete-font-variant.message")
:accept-label (tr "labels.delete")
:on-accept (fn [_props]
(delete-variant-fn id))}))))]
[:div {:class (stl/css :font-item :table-row)}
[:div {:class (stl/css :table-field :family)}

View file

@ -95,6 +95,9 @@
;; --- Grid Item Library
(def ^:private menu-icon
(i/icon-xref :menu-refactor (stl/css :menu-icon)))
(mf/defc grid-item-library
{::mf/wrap [mf/memo]}
[{:keys [file] :as props}]
@ -381,7 +384,7 @@
(when (kbd/enter? event)
(dom/stop-propagation event)
(on-menu-click event)))}
i/actions
menu-icon
(when (and selected? file-menu-open?)
[:& file-menu {:files (vals selected-files)
:show? (:menu-open dashboard-local)

View file

@ -220,40 +220,40 @@ $thumbnail-default-height: $s-168; // Default width
span {
color: $db-secondary;
}
}
.project-th-icon {
align-items: center;
display: flex;
margin-right: $s-8;
margin-top: 0;
.project-th-icon {
align-items: center;
display: flex;
margin-right: $s-8;
margin-top: 0;
}
&.menu {
align-items: flex-end;
display: flex;
flex-direction: column;
height: $s-32;
justify-content: center;
margin-right: 0;
margin-top: $s-20;
width: 100%;
.menu {
align-items: flex-end;
display: flex;
flex-direction: column;
height: $s-32;
justify-content: center;
margin-right: 0;
margin-top: $s-20;
width: 100%;
--menu-icon-color: var(--button-tertiary-foreground-color-rest);
> svg {
fill: $df-secondary;
margin-right: 0;
height: $s-16;
width: $s-16;
}
&:hover,
&:focus {
> svg {
fill: $da-tertiary;
}
}
}
&:hover,
&:focus {
--menu-icon-color: var(--button-tertiary-foreground-color-hover);
}
}
.menu-icon {
stroke: var(--menu-icon-color);
fill: none;
margin-right: 0;
height: $s-16;
width: $s-16;
}
.project-th-actions.force-display {
opacity: 1;
}

View file

@ -34,6 +34,9 @@
[potok.v2.core :as ptk]
[rumext.v2 :as mf]))
(def ^:private show-more-icon
(i/icon-xref :arrow-refactor (stl/css :show-more-icon)))
(mf/defc header
{::mf/wrap [mf/memo]}
[]
@ -314,7 +317,7 @@
:aria-label (tr "dashboard.new-file")
:data-test "project-new-file"
:on-key-down handle-create-click}
i/close]
i/add-refactor]
[:button
{:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom)
@ -323,7 +326,7 @@
:aria-label (tr "dashboard.options")
:data-test "project-options"
:on-key-down handle-menu-click}
i/actions]]]]
i/menu-refactor]]]]
[:div {:class (stl/css :grid-container) :ref rowref}
[:& line-grid
@ -343,7 +346,7 @@
(when (kbd/enter? event)
(on-nav)))}
[:div {:class (stl/css :placeholder-label)} (tr "dashboard.show-all-files")]
[:div {:class (stl/css :placeholder-icon)} i/arrow-down]])]))
show-more-icon])]))
(def recent-files-ref

View file

@ -51,31 +51,6 @@
min-height: $s-32;
margin-left: $s-8;
}
.show-more {
align-items: center;
color: $df-secondary;
display: flex;
font-size: $fs-14;
justify-content: space-between;
cursor: pointer;
background-color: transparent;
border: none;
.placeholder-icon {
transform: rotate(-90deg);
margin-left: $s-12;
svg {
height: $s-16;
width: $s-16;
fill: $df-secondary;
}
}
&:hover {
color: $da-tertiary;
svg {
fill: $da-tertiary;
}
}
}
.btn-secondary {
border: none;
@ -137,37 +112,35 @@
opacity: 1;
}
}
}
.show-more {
align-items: center;
color: $df-secondary;
display: flex;
font-size: $fs-14;
justify-content: space-between;
cursor: pointer;
background-color: transparent;
border: none;
position: absolute;
top: $s-8;
right: $s-52;
.placeholder-icon {
transform: rotate(-90deg);
margin-left: $s-8;
svg {
height: $s-16;
width: $s-16;
fill: $df-secondary;
}
}
&:hover {
color: $da-tertiary;
svg {
fill: $da-tertiary;
}
}
.show-more {
display: flex;
align-items: center;
column-gap: $s-12;
color: $df-secondary;
font-size: $fs-14;
justify-content: space-between;
cursor: pointer;
background-color: transparent;
border: none;
position: absolute;
top: $s-8;
right: $s-52;
&:hover {
color: $da-tertiary;
}
}
.show-more-icon {
height: $s-16;
width: $s-16;
fill: none;
stroke: currentColor;
}
.team-hero {
background-color: $db-tertiary;
border-radius: $br-8;

View file

@ -25,6 +25,15 @@
[cuerdas.core :as str]
[rumext.v2 :as mf]))
(def ^:private neutral-icon
(i/icon-xref :msg-neutral-refactor (stl/css :icon)))
(def ^:private error-icon
(i/icon-xref :delete-text-refactor (stl/css :icon)))
(def ^:private close-icon
(i/icon-xref :close-refactor (stl/css :close-icon)))
(mf/defc export-multiple-dialog
[{:keys [exports title cmd no-selection]}]
(let [lstate (mf/deref refs/export)
@ -198,25 +207,34 @@
(mf/defc export-progress-widget
{::mf/wrap [mf/memo]}
[]
(let [state (mf/deref refs/export)
error? (:error state)
healthy? (:healthy? state)
detail-visible? (:detail-visible state)
widget-visible? (:widget-visible state)
progress (:progress state)
exports (:exports state)
total (count exports)
complete? (= progress total)
circ (* 2 Math/PI 12)
pct (- circ (* circ (/ progress total)))
(let [state (mf/deref refs/export)
profile (mf/deref refs/profile)
theme (or (:theme profile) "default")
is-default-theme? (= "default" theme)
error? (:error state)
healthy? (:healthy? state)
detail-visible? (:detail-visible state)
widget-visible? (:widget-visible state)
progress (:progress state)
exports (:exports state)
total (count exports)
complete? (= progress total)
circ (* 2 Math/PI 12)
pct (- circ (* circ (/ progress total)))
pwidth (if error?
280
(/ (* progress 280) total))
color (cond
error? clr/new-danger
healthy? clr/new-primary
healthy? (if is-default-theme?
clr/new-primary
clr/new-primary-light)
(not healthy?) clr/new-warning)
background-clr (if is-default-theme?
clr/background-quaternary
clr/background-quaternary-light)
title (cond
error? (tr "workspace.options.exporting-object-error")
complete? (tr "workspace.options.exporting-complete")
@ -233,57 +251,60 @@
(when widget-visible?
[:div {:class (stl/css :export-progress-widget)
:on-click toggle-detail-visibility}
[:svg {:width "32" :height "32"}
[:circle {:r "12"
:cx "16"
:cy "16"
[:svg {:width "24" :height "24"}
[:circle {:r "10"
:cx "12"
:cy "12"
:fill "transparent"
:stroke clr/gray-40
:stroke background-clr
:stroke-width "4"}]
[:circle {:r "12"
:cx "16"
:cy "16"
[:circle {:r "10"
:cx "12"
:cy "12"
:fill "transparent"
:stroke color
:stroke-width "4"
:stroke-dasharray (dm/str circ " " circ)
:stroke-dashoffset pct
:transform "rotate(-90 16,16)"
:transform "rotate(-90 12,12)"
:style {:transition "stroke-dashoffset 1s ease-in-out"}}]]])
(when detail-visible?
[:div {:class (stl/css :export-progress-modal-overlay)}
[:div {:class (stl/css :export-progress-modal-container)}
[:div {:class (stl/css :export-progress-modal-header)}
[:p {:class (stl/css :export-progress-modal-title)}
[:span {:class (stl/css :title-text)}
title]
(if error?
[:button {:class (stl/css :retry-btn)
:on-click retry-last-export}
(tr "workspace.options.retry")]
[:div {:class (stl/css-case :export-progress-modal true
:has-error error?)}
(if error?
error-icon
neutral-icon)
[:p {:class (stl/css :progress)}
(dm/str progress " / " total)])]
[:p {:class (stl/css :export-progress-title)}
title
(if error?
[:button {:class (stl/css :retry-btn)
:on-click retry-last-export}
(tr "workspace.options.retry")]
[:button {:class (stl/css :modal-close-button)
:on-click toggle-detail-visibility}
i/close-refactor]]
[:p {:class (stl/css :progress)}
(dm/str progress " / " total)])]
[:svg {:class (stl/css :progress-bar)
:height 5
:width 280}
[:g
[:path {:d "M0 0 L280 0"
:stroke clr/black
:stroke-width 30}]
[:path {:d (dm/str "M0 0 L280 0")
:stroke color
:stroke-width 30
:fill "transparent"
:stroke-dasharray 280
:stroke-dashoffset (- 280 pwidth)
:style {:transition "stroke-dashoffset 1s ease-in-out"}}]]]]])]))
[:button {:class (stl/css :progress-close-button)
:on-click toggle-detail-visibility}
close-icon]
(when-not error?
[:svg {:class (stl/css :progress-bar)
:height 4
:width 280}
[:g
[:path {:d "M0 0 L280 0"
:stroke background-clr
:stroke-width 30}]
[:path {:d (dm/str "M0 0 L280 0")
:stroke color
:stroke-width 30
:fill "transparent"
:stroke-dasharray 280
:stroke-dashoffset (- 280 pwidth)
:style {:transition "stroke-dashoffset 1s ease-in-out"}}]]])])]))
(def ^:const options [:all :merge :detach])

View file

@ -6,69 +6,101 @@
@import "refactor/common-refactor.scss";
.export-progress-modal-overlay {
display: flex;
justify-content: center;
position: fixed;
// PROGRESS WIDGET
.export-progress-widget {
@include flexCenter;
width: $s-28;
height: $s-28;
}
// PROGRESS MODAL
.export-progress-modal {
--export-modal-bg-color: var(--alert-background-color-default);
--export-modal-fg-color: var(--alert-text-foreground-color-default);
--export-modal-icon-color: var(--alert-icon-foreground-color-default);
--export-modal-border-color: var(--alert-border-color-default);
position: absolute;
right: $s-16;
top: $s-48;
background-color: var(--modal-background-color);
display: grid;
grid-template-columns: $s-24 1fr $s-24;
grid-template-areas:
"icon text close"
"bar bar bar";
gap: $s-4 $s-8;
padding-block-start: $s-8;
background-color: var(--export-modal-bg-color);
border: $s-1 solid var(--export-modal-border-color);
border-radius: $br-8;
z-index: $z-index-20;
z-index: $z-index-modal;
overflow: hidden;
}
.export-progress-modal-container {
display: flex;
flex-direction: column;
justify-content: space-around;
height: 100%;
width: 100%;
}
.export-progress-modal-header {
display: flex;
align-items: center;
justify-content: stretch;
padding: $s-8;
.has-error {
--export-modal-bg-color: var(--alert-background-color-error);
--export-modal-fg-color: var(--alert-text-foreground-color-error);
--export-modal-icon-color: var(--alert-icon-foreground-color-error);
--export-modal-border-color: var(--alert-border-color-error);
grid-template-areas: "icon text close";
gap: $s-8;
padding-block: $s-8;
}
.export-progress-modal-title {
display: flex;
flex-grow: 1;
padding: 0;
margin: 0;
.icon {
@extend .button-icon;
grid-area: icon;
align-self: center;
margin-inline-start: $s-8;
stroke: var(--export-modal-icon-color);
}
.title-text {
@include flexCenter;
@include bodyLargeTypography;
.export-progress-title {
@include bodyMedTipography;
display: grid;
grid-template-columns: auto 1fr;
gap: $s-8;
grid-area: text;
align-self: center;
padding: 0;
margin: 0;
color: var(--modal-title-foreground-color);
padding-left: $s-4;
color: var(--export-modal-fg-color);
}
.progress {
@include bodyLargeTypography;
@include bodyMedTipography;
padding-left: $s-8;
margin: 0;
align-self: center;
color: var(--modal-text-foreground-color);
}
.retry-btn {
@extend .button-tertiary;
@include buttonStyle;
@include bodyMedTipography;
display: inline;
text-align: left;
color: var(--modal-link-foreground-color);
margin: 0;
padding: 0;
}
.modal-close-button {
@extend .button-tertiary;
svg {
@extend .button-icon-small;
stroke: var(--icon-foreground);
}
.progress-close-button {
@include buttonStyle;
padding: 0;
margin-inline-end: $s-8;
}
.close-icon {
@extend .button-icon;
stroke: var(--export-modal-icon-color);
}
.progress-bar {
margin-top: 0;
grid-area: bar;
}
// EXPORT MODAL
.modal-overlay {
@extend .modal-overlay-base;
&.transparent {

View file

@ -441,6 +441,13 @@
(def ^:icon status-update-refactor (icon-xref :status-update-refactor))
(def ^:icon status-tick-refactor (icon-xref :status-tick-refactor))
(def ^:icon status-wrong-refactor (icon-xref :status-wrong-refactor))
(def ^:icon stroke-arrow-refactor (icon-xref :stroke-arrow-refactor))
(def ^:icon stroke-circle-refactor (icon-xref :stroke-circle-refactor))
(def ^:icon stroke-diamond-refactor (icon-xref :stroke-diamond-refactor))
(def ^:icon stroke-rectangle-refactor (icon-xref :stroke-rectangle-refactor))
(def ^:icon stroke-rounded-refactor (icon-xref :stroke-rounded-refactor))
(def ^:icon stroke-squared-refactor (icon-xref :stroke-squared-refactor))
(def ^:icon stroke-triangle-refactor (icon-xref :stroke-triangle-refactor))
(def ^:icon stroke-size-refactor (icon-xref :stroke-size-refactor))
(def ^:icon svg-refactor (icon-xref :svg-refactor))
(def ^:icon swatches-refactor (icon-xref :swatches-refactor))

View file

@ -29,13 +29,12 @@
:links (:links message)
:content (:content message)}
context-message {:actions (:actions message)
context-message {:type (or (:type message) :info)
:links (:links message)
:content (:content message)}
;; TODO review this options
is-toast-msg (or (= :toast (:notification-type message)) (some? (:timeout message)))
is-inline-msg (or (= :inline (:notification-type message)) (and (some? (:position message)) (= :floating (:position message))))]
is-toast-msg (or (= :toast (:notification-type message)) (some? (:timeout message)))
is-inline-msg (or (= :inline (:notification-type message)) (and (some? (:position message)) (= :floating (:position message))))]
(when message
(cond

View file

@ -56,14 +56,13 @@
[:div {:class (stl/css :context-text)
:dangerouslySetInnerHTML (when is-html #js {:__html content})}
(when-not is-html
content)]
(when (some? links)
[:nav {:class (stl/css :link-nav)}
(for [[index link] (d/enumerate links)]
;; TODO Review this component
[:& lb/link-button {:class (stl/css :link)
:on-click (:callback link)
:value (:label link)
:key (dm/str "link-" index)}])])])
[:*
content
(when (some? links)
(for [[index link] (d/enumerate links)]
;; TODO Review this component
[:& lb/link-button {:class (stl/css :link)
:on-click (:callback link)
:value (:label link)
:key (dm/str "link-" index)}]))])]])

View file

@ -7,16 +7,18 @@
@import "refactor/common-refactor.scss";
.context-notification {
---context-notification-bg-color: var(--alert-background-color-default);
--context-notification-bg-color: var(--alert-background-color-default);
--context-notification-fg-color: var(--alert-text-foreground-color-default);
--context-notification-icon-color: var(--alert-icon-foreground-color-default);
--context-notification-border-color: var(--alert-border-color-default);
box-sizing: border-box;
display: grid;
grid-template-columns: $s-16 auto 1fr;
grid-template-columns: $s-16 1fr;
gap: $s-8;
min-height: $s-32;
height: fit-content;
width: 100%;
padding: $s-8 $s-8 $s-8 $s-16;
padding: $s-8;
border: $s-1 solid var(--context-notification-border-color);
border-radius: $br-8;
background-color: var(--context-notification-bg-color);
@ -63,12 +65,6 @@
stroke: var(--context-notification-icon-color);
}
.link-nav {
align-self: center;
height: $s-24;
margin: 0;
}
.context-text {
@include bodyMedTipography;
align-self: center;
@ -84,6 +80,8 @@
.contain-html .context-text a {
@include bodyMedTipography;
align-self: center;
display: inline;
text-align: left;
height: $s-16;
margin: 0;
color: var(--modal-link-foreground-color);

View file

@ -11,11 +11,8 @@
[app.common.data.macros :as dm]
[app.common.uuid :as uuid]
[app.main.ui.components.link-button :as lb]
[app.main.ui.icons :as i]
[rumext.v2 :as mf]))
(def ^:private neutral-icon
(i/icon-xref :msg-neutral-refactor (stl/css :icon)))
(mf/defc inline-notification
@ -25,18 +22,17 @@
{::mf/props :obj}
[{:keys [content actions links] :as props}]
[:aside {:class (stl/css :inline-notification)}
neutral-icon
[:div {:class (stl/css :inline-text)}
content]
(when (some? links)
[:nav {:class (stl/css :link-nav)}
(for [[index link] (d/enumerate links)]
[:& lb/link-button {:key (dm/str "link-" index)
:class (stl/css :link)
:on-click (:callback link)
:value (:label link)}])])
content
(when (some? links)
[:nav {:class (stl/css :link-nav)}
(for [[index link] (d/enumerate links)]
[:& lb/link-button {:key (dm/str "link-" index)
:class (stl/css :link)
:on-click (:callback link)
:value (:label link)}])])]
[:div {:class (stl/css :actions)}
(for [action actions]

View file

@ -9,7 +9,6 @@
.inline-notification {
--inline-notification-bg-color: var(--alert-background-color-default);
--inline-notification-fg-color: var(--alert-text-foreground-color-default);
--inline-notification-icon-color: var(--alert-icon-foreground-color-default);
--inline-notification-border-color: var(--alert-border-color-default);
@include alertShadow;
position: absolute;
@ -17,12 +16,13 @@
left: 0;
right: 0;
display: grid;
grid-template-columns: $s-16 auto 1fr auto;
gap: $s-8;
grid-template-columns: 1fr auto;
gap: $s-24;
min-height: $s-48;
min-width: $s-640;
max-width: $s-712;
padding: $s-8 $s-8 $s-8 $s-16;
width: fit-content;
max-width: $s-960;
padding: $s-8;
margin-inline: auto;
border: $s-1 solid var(--inline-notification-border-color);
border-radius: $br-8;
@ -31,17 +31,15 @@
color: var(--inline-notification-fg-color);
}
.icon {
@extend .button-icon;
height: 100%;
stroke: var(--inline-notification-icon-color);
}
.inline-text {
@include bodyMedTipography;
align-self: center;
}
.link-nav {
display: inline;
}
.link {
@include bodyMedTipography;
margin: 0;
@ -53,15 +51,16 @@
display: grid;
grid-template-columns: none;
grid-auto-flow: column;
gap: $s-8;
align-self: center;
gap: $s-8;
}
.action-btn {
@extend .button-tertiary;
@extend .button-secondary;
@include uppercaseTitleTipography;
min-height: $s-32;
min-width: $s-32;
width: fit-content;
padding: $s-8 $s-24;
border: $s-1 solid transparent;
}

View file

@ -49,7 +49,6 @@
[{:keys [type content on-close links] :as props}]
[:aside {:class (stl/css-case :toast-notification true
:with-links (some? links)
:warning (= type :warning)
:error (= type :error)
:success (= type :success)
@ -58,15 +57,16 @@
(get-icon-by-type type)
[:div {:class (stl/css :text)}
content]
content
(when (some? links)
[:nav {:class (stl/css :link-nav)}
(for [[index link] (d/enumerate links)]
[:& lb/link-button {:key (dm/str "link-" index)
:class (stl/css :link)
:on-click (:callback link)
:value (:label link)}])])]
(when (some? links)
[:nav {:class (stl/css :link-nav)}
(for [[index link] (d/enumerate links)]
[:& lb/link-button {:key (dm/str "link-" index)
:class (stl/css :link)
:on-click (:callback link)
:value (:label link)}])])
[:button {:class (stl/css :btn-close)
:on-click on-close}

View file

@ -19,9 +19,9 @@
grid-template-columns: $s-16 1fr auto;
gap: $s-8;
min-height: $s-32;
min-width: $s-500;
max-width: calc(10 * $s-100);
padding: $s-8 $s-8 $s-8 $s-16;
min-width: $s-228;
max-width: $s-400;
padding: $s-8;
border: $s-1 solid var(--toast-notification-border-color);
background-color: var(--toast-notification-bg-color);
border-radius: $br-8;
@ -29,10 +29,6 @@
z-index: $z-index-alert;
}
.with-links {
grid-template-columns: $s-16 auto 1fr auto;
}
.warning {
--toast-notification-bg-color: var(--alert-background-color-warning);
--toast-notification-fg-color: var(--alert-text-foreground-color-warning);
@ -69,7 +65,7 @@
}
.link-nav {
height: $s-24;
display: inline;
}
.link {
@ -80,7 +76,7 @@
.icon {
@extend .button-icon;
height: 100%;
align-self: flex-start;
stroke: var(--toast-notification-icon-color);
}
@ -91,9 +87,10 @@
.btn-close {
@include buttonStyle;
@include flexCenter;
height: 100%;
min-width: $s-32;
align-self: flex-start;
width: $s-16;
margin: 0;
padding: 0;
background-color: transparent;
}

View file

@ -20,16 +20,15 @@
display: flex;
justify-content: center;
flex-direction: column;
max-width: $s-368;
max-width: $s-500;
margin-bottom: $s-32;
width: $s-580;
margin: $s-80 auto auto $s-120;
margin: $s-80 auto $s-120 auto;
justify-content: center;
form {
display: flex;
flex-direction: column;
width: $s-500;
.btn-secondary {
width: 100%;

View file

@ -97,7 +97,10 @@
(obj/set! "fill" (str "url(#fill-" index "-" render-id ")")))}
(cond-> browser-props
(obj/merge! browser-props)))
shape (assoc shape :fills (:fills data))]
shape (assoc shape :fills (:fills data))
;; Need to create new render-id per text-block
render-id (dm/str render-id "-" index)]
[:& (mf/provider muc/render-id) {:key index :value render-id}
[:& shape-custom-strokes {:shape shape :position index :render-id render-id}

View file

@ -161,6 +161,8 @@
#(st/emit! dv/zoom-to-fit))]
[:div {:class (stl/css :options-zone)}
[:& export-progress-widget]
(case section
:interactions [:*
(when index
@ -169,8 +171,6 @@
:comments [:& comments-menu]
[:div {:class (stl/css :view-options)}])
[:& export-progress-widget]
[:& zoom-widget
{:zoom zoom
:on-increase handle-increase

View file

@ -18,6 +18,7 @@
[:& title-bar {:collapsable false
:title (tr "workspace.options.component.annotation")
:class (stl/css :title-spacing-annotation)}
[:& copy-button {:data content}]]
[:& copy-button {:data content
:class (stl/css :copy-btn-title)}]]
[:div {:class (stl/css :annotation-content)} content]])

View file

@ -18,3 +18,7 @@
@include bodyMedTipography;
color: var(--entry-foreground-color);
}
.copy-btn-title {
max-width: $s-28;
}

View file

@ -109,7 +109,9 @@
[:span {:class (stl/css :layer-title)} (:name first-shape)]])]
[:div {:class (stl/css :inspect-content)}
[:& tab-container {:on-change-tab handle-change-tab
:selected @section}
:selected @section
:content-class (stl/css :tab-content)
:header-class (stl/css :tab-header)}
[:& tab-element {:id :info :title (tr "inspect.tabs.info")}
[:& attributes {:page-id page-id
:objects objects

View file

@ -96,3 +96,11 @@
flex: 1;
overflow: hidden;
}
.tab-content {
scrollbar-gutter: stable;
}
.tab-header {
margin-right: $s-12;
}

View file

@ -34,6 +34,7 @@
}
}
}
.active-users-opened {
position: absolute;
right: calc(-1 * $s-2);

View file

@ -171,7 +171,7 @@
(mf/use-fn
(fn []
(st/emit! :interrupt
dw/clear-edition-mode)
(dw/clear-edition-mode))
;; Delay so anything that launched :interrupt can finish
(ts/schedule 100 #(st/emit! (dw/select-for-drawing :comments)))))
@ -203,8 +203,9 @@
[:& persistence-state-widget]
[:div {:class (stl/css :separator)}]
[:& export-progress-widget]
[:div {:class (stl/css :separator)}]
[:div {:class (stl/css :zoom-section)}
[:& zoom-widget-workspace
@ -215,8 +216,6 @@
:on-zoom-fit on-zoom-fit
:on-zoom-selected on-zoom-selected}]]
[:& export-progress-widget]
[:div {:class (stl/css :comments-section)}
[:button {:title (tr "workspace.toolbar.comments" (sc/get-tooltip :add-comment))
:aria-label (tr "workspace.toolbar.comments" (sc/get-tooltip :add-comment))

View file

@ -37,6 +37,8 @@
border-radius: $br-8;
.label {
@include bodyMedTipography;
height: 100%;
padding: $s-8 0;
color: var(--button-tertiary-foreground-color-rest);
}
@ -180,14 +182,12 @@
.status-icon {
@include flexCenter;
width: $s-16;
height: $s-16;
width: $s-24;
height: $s-24;
margin: 0;
border-radius: $br-circle;
svg {
@extend .button-icon;
height: $s-12;
width: $s-12;
stroke: var(--status-widget-icon-foreground-color);
}
}

View file

@ -13,7 +13,7 @@
[okulary.core :as l]
[rumext.v2 :as mf]))
(def primary-color "var(--color-accent-tertiary)")
(def accent-color "var(--color-accent-tertiary)")
(def secondary-color "var(--color-accent-quaternary)")
(def black-color "var(--app-black)")
(def white-color "var(--app-white)")

View file

@ -89,8 +89,8 @@
:style {:stroke-width (/ point-radius-stroke-width zoom)
:stroke (cond (or selected? hover?) pc/black-color
preview? pc/secondary-color
:else pc/primary-color)
:fill (cond selected? pc/primary-color
:else pc/accent-color)
:fill (cond selected? pc/accent-color
:else pc/white-color)}}]
[:circle {:cx x
:cy y
@ -150,8 +150,8 @@
:style {:stroke-width (/ handler-stroke-width zoom)
:stroke (cond (or selected? hover?) pc/black-color
:else pc/primary-color)
:fill (cond selected? pc/primary-color
:else pc/accent-color)
:fill (cond selected? pc/accent-color
:else pc/white-color)}}]
[:circle {:cx x
:cy y
@ -288,7 +288,7 @@
[:g.path-editor {:ref editor-ref}
[:path {:d (upf/format-path content)
:style {:fill "none"
:stroke pc/primary-color
:stroke pc/accent-color
:strokeWidth (/ 1 zoom)}}]
(when (and preview (not drag-handler))
[:& path-preview {:command preview

View file

@ -122,8 +122,7 @@
(fn [event]
(dom/stop-propagation event)
(when (kbd/esc? event)
(st/emit! :interrupt)
(st/emit! dw/clear-edition-mode)))
(st/emit! :interrupt (dw/clear-edition-mode))))
on-mount
(fn []

View file

@ -104,7 +104,7 @@
{:on-change-tab on-change-tab
:selected section
:collapsable false
:content-class (stl/css :content-class)
:content-class (stl/css-case :content-class true :inspect (= section :inspect))
:header-class (stl/css :tab-spacing)}
[:& tab-element {:id :design
:title (tr "workspace.options.design")}

View file

@ -34,3 +34,7 @@
gap: $s-8;
padding-top: $s-8;
}
.inspect {
scrollbar-gutter: unset;
}

View file

@ -1279,7 +1279,7 @@
[:button {:on-click open-grid-help
:class (stl/css :help-button)} i/help-refactor]
[:button {:class (stl/css :exit-btn)
:on-click #(st/emit! udw/clear-edition-mode)}
:on-click #(st/emit! (udw/clear-edition-mode))}
(tr "workspace.layout_grid.editor.options.exit")]]
[:div {:class (stl/css :row :first-row)}

View file

@ -123,14 +123,14 @@
stroke-caps-options
[{:value nil :label (tr "workspace.options.stroke-cap.none")}
:separator
{:value :line-arrow :label (tr "workspace.options.stroke-cap.line-arrow-short") :icon :cap-line-arrow}
{:value :triangle-arrow :label (tr "workspace.options.stroke-cap.triangle-arrow-short") :icon :cap-triangle-arrow}
{:value :square-marker :label (tr "workspace.options.stroke-cap.square-marker-short") :icon :cap-square-marker}
{:value :circle-marker :label (tr "workspace.options.stroke-cap.circle-marker-short") :icon :cap-circle-marker}
{:value :diamond-marker :label (tr "workspace.options.stroke-cap.diamond-marker-short") :icon :cap-diamond-marker}
{:value :line-arrow :label (tr "workspace.options.stroke-cap.line-arrow-short") :icon :stroke-arrow-refactor}
{:value :triangle-arrow :label (tr "workspace.options.stroke-cap.triangle-arrow-short") :icon :stroke-triangle-refactor}
{:value :square-marker :label (tr "workspace.options.stroke-cap.square-marker-short") :icon :stroke-rectangle-refactor}
{:value :circle-marker :label (tr "workspace.options.stroke-cap.circle-marker-short") :icon :stroke-circle-refactor}
{:value :diamond-marker :label (tr "workspace.options.stroke-cap.diamond-marker-short") :icon :stroke-diamond-refactor}
:separator
{:value :round :label (tr "workspace.options.stroke-cap.round") :icon :cap-round}
{:value :square :label (tr "workspace.options.stroke-cap.square") :icon :cap-square}]
{:value :round :label (tr "workspace.options.stroke-cap.round") :icon :stroke-rounded-refactor}
{:value :square :label (tr "workspace.options.stroke-cap.square") :icon :stroke-squared-refactor}]
on-cap-switch
(mf/use-callback

View file

@ -7,12 +7,14 @@
(ns app.main.ui.workspace.top-toolbar
(:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
[app.common.geom.point :as gpt]
[app.common.media :as cm]
[app.main.data.events :as ev]
[app.main.data.workspace :as dw]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.media :as dwm]
[app.main.data.workspace.path.state :as pst]
[app.main.data.workspace.shortcuts :as sc]
[app.main.refs :as refs]
[app.main.store :as st]
@ -22,6 +24,7 @@
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.timers :as ts]
[okulary.core :as l]
[rumext.v2 :as mf]))
(mf/defc image-upload
@ -33,7 +36,7 @@
on-click
(mf/use-fn
(fn []
(st/emit! :interrupt dw/clear-edition-mode)
(st/emit! :interrupt (dw/clear-edition-mode))
(dom/click (mf/ref-val ref))))
on-selected
@ -53,7 +56,8 @@
[:button
{:title (tr "workspace.toolbar.image" (sc/get-tooltip :insert-image))
:aria-label (tr "workspace.toolbar.image" (sc/get-tooltip :insert-image))
:on-click on-click}
:on-click on-click
:class (stl/css :main-toolbar-options-button)}
i/img-refactor
[:& file-uploader
{:input-id "image-upload"
@ -62,6 +66,15 @@
:ref ref
:on-selected on-selected}]]]))
(def toolbar-hidden
(l/derived
(fn [state]
(let [visibility (dm/get-in state [:workspace-local :hide-toolbar])
editing? (pst/path-editing? state)
hidden? (if editing? true visibility)]
hidden?))
st/state))
(mf/defc top-toolbar
{::mf/wrap [mf/memo]
::mf/wrap-props false}
@ -72,7 +85,7 @@
read-only? (mf/use-ctx ctx/workspace-read-only?)
rulers? (mf/deref refs/rulers?)
hide-toolbar? (mf/deref refs/toolbar-visibility)
hide-toolbar? (mf/deref toolbar-hidden)
interrupt
(mf/use-fn #(st/emit! :interrupt))
@ -83,8 +96,7 @@
(let [tool (-> (dom/get-current-target event)
(dom/get-data "tool")
(keyword))]
(st/emit! :interrupt
dw/clear-edition-mode)
(st/emit! :interrupt (dw/clear-edition-mode))
;; Delay so anything that launched :interrupt can finish
(ts/schedule 100 #(st/emit! (dw/select-for-drawing tool))))))
@ -114,7 +126,8 @@
[:button
{:title (tr "workspace.toolbar.move" (sc/get-tooltip :move))
:aria-label (tr "workspace.toolbar.move" (sc/get-tooltip :move))
:class (stl/css-case :selected (and (nil? selected-drawtool)
:class (stl/css-case :main-toolbar-options-button true
:selected (and (nil? selected-drawtool)
(not edition)))
:on-click interrupt}
i/move-refactor]]
@ -123,7 +136,7 @@
[:button
{:title (tr "workspace.toolbar.frame" (sc/get-tooltip :draw-frame))
:aria-label (tr "workspace.toolbar.frame" (sc/get-tooltip :draw-frame))
:class (stl/css-case :selected (= selected-drawtool :frame))
:class (stl/css-case :main-toolbar-options-button true :selected (= selected-drawtool :frame))
:on-click select-drawtool
:data-tool "frame"
:data-test "artboard-btn"}
@ -132,7 +145,7 @@
[:button
{:title (tr "workspace.toolbar.rect" (sc/get-tooltip :draw-rect))
:aria-label (tr "workspace.toolbar.rect" (sc/get-tooltip :draw-rect))
:class (stl/css-case :selected (= selected-drawtool :rect))
:class (stl/css-case :main-toolbar-options-button true :selected (= selected-drawtool :rect))
:on-click select-drawtool
:data-tool "rect"
:data-test "rect-btn"}
@ -141,7 +154,7 @@
[:button
{:title (tr "workspace.toolbar.ellipse" (sc/get-tooltip :draw-ellipse))
:aria-label (tr "workspace.toolbar.ellipse" (sc/get-tooltip :draw-ellipse))
:class (stl/css-case :selected (= selected-drawtool :circle))
:class (stl/css-case :main-toolbar-options-button true :selected (= selected-drawtool :circle))
:on-click select-drawtool
:data-tool "circle"
:data-test "ellipse-btn"}
@ -150,7 +163,7 @@
[:button
{:title (tr "workspace.toolbar.text" (sc/get-tooltip :draw-text))
:aria-label (tr "workspace.toolbar.text" (sc/get-tooltip :draw-text))
:class (stl/css-case :selected (= selected-drawtool :text))
:class (stl/css-case :main-toolbar-options-button true :selected (= selected-drawtool :text))
:on-click select-drawtool
:data-tool "text"}
i/text-refactor]]
@ -161,7 +174,7 @@
[:button
{:title (tr "workspace.toolbar.curve" (sc/get-tooltip :draw-curve))
:aria-label (tr "workspace.toolbar.curve" (sc/get-tooltip :draw-curve))
:class (stl/css-case :selected (= selected-drawtool :curve))
:class (stl/css-case :main-toolbar-options-button true :selected (= selected-drawtool :curve))
:on-click select-drawtool
:data-tool "curve"
:data-test "curve-btn"}
@ -170,7 +183,7 @@
[:button
{:title (tr "workspace.toolbar.path" (sc/get-tooltip :draw-path))
:aria-label (tr "workspace.toolbar.path" (sc/get-tooltip :draw-path))
:class (stl/css-case :selected (= selected-drawtool :path))
:class (stl/css-case :main-toolbar-options-button true :selected (= selected-drawtool :path))
:on-click select-drawtool
:data-tool "path"
:data-test "path-btn"}
@ -180,7 +193,7 @@
[:li
[:button
{:title "Debugging tool"
:class (stl/css-case :selected (contains? layout :debug-panel))
:class (stl/css-case :main-toolbar-options-button true :selected (contains? layout :debug-panel))
:on-click toggle-debug-panel}
i/bug-refactor]])]]

View file

@ -48,25 +48,24 @@
transition: opacity 0.3s ease;
li {
position: relative;
}
}
button {
@extend .button-tertiary;
height: $s-36;
width: $s-36;
flex-shrink: 0;
border-radius: $s-8;
border: none;
margin: 0 $s-2;
.main-toolbar-options-button {
@extend .button-tertiary;
height: $s-36;
width: $s-36;
flex-shrink: 0;
border-radius: $s-8;
margin: 0 $s-2;
svg {
@extend .button-icon;
stroke: var(--color-foreground-secondary);
}
svg {
@extend .button-icon;
stroke: var(--color-foreground-secondary);
}
&.selected {
@extend .button-icon-selected;
}
}
&.selected {
@extend .button-icon-selected;
}
}

View file

@ -90,7 +90,7 @@
::dwsp/interrupt)
(when (and (not= edition id) (or text-editing? grid-editing?))
(st/emit! dw/clear-edition-mode))
(st/emit! (dw/clear-edition-mode)))
(when (and (not text-editing?)
(not blocked)

View file

@ -8,6 +8,7 @@
"Drawing components."
(:require
[app.common.math :as mth]
[app.common.types.shape :as cts]
[app.main.ui.shapes.path :refer [path-shape]]
[app.main.ui.workspace.shapes :as shapes]
[app.main.ui.workspace.shapes.path.editor :refer [path-editor]]
@ -19,14 +20,16 @@
(mf/defc draw-area
[{:keys [shape zoom tool] :as props}]
[:g.draw-area
[:g {:style {:pointer-events "none"}}
[:& shapes/shape-wrapper {:shape shape}]]
;; Prevent rendering something that it's not a shape.
(when (cts/shape? shape)
[:g.draw-area
[:g {:style {:pointer-events "none"}}
[:& shapes/shape-wrapper {:shape shape}]]
(case tool
:path [:& path-editor {:shape shape :zoom zoom}]
:curve [:& path-shape {:shape shape :zoom zoom}]
#_:default [:& generic-draw-area {:shape shape :zoom zoom}])])
(case tool
:path [:& path-editor {:shape shape :zoom zoom}]
:curve [:& path-shape {:shape shape :zoom zoom}]
#_:default [:& generic-draw-area {:shape shape :zoom zoom}])]))
(mf/defc generic-draw-area
[{:keys [shape zoom]}]

View file

@ -61,7 +61,7 @@
:on-click #(st/emit! (dwge/locate-board (:id shape)))}
(tr "workspace.layout_grid.editor.top-bar.locate")]
[:button {:class (stl/css :done-btn)
:on-click #(st/emit! dw/clear-edition-mode)}
:on-click #(st/emit! (dw/clear-edition-mode))}
(tr "workspace.layout_grid.editor.top-bar.done")]]])
(mf/defc grid-editor-frame

View file

@ -26,7 +26,7 @@
(def guide-width 1)
(def guide-opacity 0.7)
(def guide-opacity-hover 1)
(def guide-color colors/primary)
(def guide-color colors/new-primary)
(def guide-pill-width 34)
(def guide-pill-height 20)
(def guide-pill-corner-radius 4)

View file

@ -154,7 +154,9 @@
;; These extra operations ensure that we are selecting a frame its initial location is rendered in the ruler
minv (+ minv (mod offset step))
maxv (+ maxv (mod offset step))]
maxv (+ maxv (mod offset step))
rulers-width (* rulers-width zoom-inverse)]
[:g.rulers {:clipPath (str "url(#" clip-id ")")}
[:defs

View file

@ -69,7 +69,7 @@
[:& view-only-actions]
path-edition?
[:div.viewport-actions
[:div {:class (stl/css :viewport-actions)}
[:& path-actions {:shape shape}]]
grid-edition?

View file

@ -149,7 +149,7 @@
ptk/EffectEvent
(effect [_ state stream]
(let [stoper (rx/filter (ptk/type? ::initialize-history) stream)
(let [stopper (rx/filter (ptk/type? ::initialize-history) stream)
history (:history state)
router (:router state)]
(ts/schedule #(on-change router (.getToken ^js history)))
@ -158,5 +158,5 @@
(fn []
(bhistory/disable! history)
(e/unlistenByKey key)))))
(rx/take-until stoper)
(rx/take-until stopper)
(rx/subs! #(on-change router %)))))))