mirror of
https://github.com/penpot/penpot.git
synced 2025-05-29 04:46:12 +02:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
481058b8d4
142 changed files with 1358 additions and 792 deletions
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.data.dashboard.shortcuts
|
||||
(:require
|
||||
[app.main.data.dashboard :as dd]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.shortcuts :as ds]
|
||||
[app.main.data.users :as du]
|
||||
[app.main.store :as st]))
|
||||
|
@ -35,7 +36,10 @@
|
|||
:toggle-theme {:tooltip (ds/alt "M")
|
||||
:command (ds/a-mod "m")
|
||||
:subsections [:general-dashboard]
|
||||
:fn #(st/emit! (du/toggle-theme))}})
|
||||
:fn #(st/emit! (with-meta (du/toggle-theme)
|
||||
{::ev/origin "dashboard:shortcuts"}))}})
|
||||
|
||||
|
||||
|
||||
(defn get-tooltip [shortcut]
|
||||
(assert (contains? shortcuts shortcut) (str shortcut))
|
||||
|
|
|
@ -121,26 +121,10 @@
|
|||
(derive :app.main.data.workspace/set-workspace-layout ::generic-action)
|
||||
(derive :app.main.data.workspace/toggle-layout-flag ::generic-action)
|
||||
|
||||
(defmulti process-event ptk/type)
|
||||
(defmethod process-event :default [_] nil)
|
||||
(defprotocol Event
|
||||
(-data [_] "Get event data"))
|
||||
|
||||
(defmethod process-event ::event
|
||||
[event]
|
||||
(let [data (deref event)
|
||||
origin (::origin data)]
|
||||
(when (::name data)
|
||||
(d/without-nils
|
||||
{:type (::type data "action")
|
||||
:name (::name data)
|
||||
:context (::context data)
|
||||
:props (-> data
|
||||
(dissoc ::name)
|
||||
(dissoc ::type)
|
||||
(dissoc ::origin)
|
||||
(dissoc ::context)
|
||||
(cond-> origin (assoc :origin origin)))}))))
|
||||
|
||||
(defn- normalize-props
|
||||
(defn- simplify-props
|
||||
"Removes complex data types from props."
|
||||
[data]
|
||||
(into {}
|
||||
|
@ -156,24 +140,65 @@
|
|||
:else kv))))
|
||||
data))
|
||||
|
||||
(defmethod process-event ::generic-action
|
||||
|
||||
(defmulti process-event-by-type ptk/type)
|
||||
|
||||
(defn- process-event-by-proto
|
||||
[event]
|
||||
(let [data (d/deep-merge (-data event) (meta event))
|
||||
type (ptk/type event)
|
||||
ev-name (name type)
|
||||
context (-> (::context data)
|
||||
(assoc :event-origin (::origin data))
|
||||
(assoc :event-namespace (namespace type))
|
||||
(assoc :event-symbol ev-name)
|
||||
(d/without-nils))
|
||||
props (-> data d/without-qualified simplify-props)]
|
||||
|
||||
{:type (::type data "action")
|
||||
:name (::name data ev-name)
|
||||
:context context
|
||||
:props props}))
|
||||
|
||||
(defn- process-event
|
||||
[event]
|
||||
(if (satisfies? Event event)
|
||||
(process-event-by-proto event)
|
||||
(process-event-by-type event)))
|
||||
|
||||
(defmethod process-event-by-type :default [_] nil)
|
||||
|
||||
(defmethod process-event-by-type ::event
|
||||
[event]
|
||||
(let [data (deref event)
|
||||
context (-> (::context data)
|
||||
(assoc :event-origin (::origin data))
|
||||
(d/without-nils))
|
||||
props (-> data d/without-qualified simplify-props)]
|
||||
|
||||
{:type (::type data "action")
|
||||
:name (::name data "unnamed")
|
||||
:context context
|
||||
:props props}))
|
||||
|
||||
(defmethod process-event-by-type ::generic-action
|
||||
[event]
|
||||
(let [type (ptk/type event)
|
||||
mdata (meta event)
|
||||
data (if (satisfies? IDeref event)
|
||||
(deref event)
|
||||
{})]
|
||||
{})
|
||||
data (d/deep-merge data (meta event))]
|
||||
|
||||
{:type "action"
|
||||
:name (or (::name mdata) (name type))
|
||||
:props (-> (merge data (::props mdata))
|
||||
(normalize-props))
|
||||
:name (or (::name data) (name type))
|
||||
:props (-> (d/without-qualified data)
|
||||
(simplify-props))
|
||||
:context (d/without-nils
|
||||
{:event-origin (::origin mdata)
|
||||
{:event-origin (::origin data)
|
||||
:event-namespace (namespace type)
|
||||
:event-symbol (name type)})}))
|
||||
|
||||
(defmethod process-event :app.util.router/navigated
|
||||
(defmethod process-event-by-type :app.util.router/navigated
|
||||
[event]
|
||||
(let [match (deref event)
|
||||
route (get-in match [:data :name])
|
||||
|
@ -183,9 +208,9 @@
|
|||
:project-id (get-in match [:path-params :project-id])}]
|
||||
{:name "navigate"
|
||||
:type "action"
|
||||
:props (normalize-props props)}))
|
||||
:props (simplify-props props)}))
|
||||
|
||||
(defmethod process-event :app.main.data.users/logged-in
|
||||
(defmethod process-event-by-type :app.main.data.users/logged-in
|
||||
[event]
|
||||
(let [data (deref event)
|
||||
mdata (meta data)
|
||||
|
@ -196,10 +221,11 @@
|
|||
:is-muted (:is-muted data)
|
||||
:default-team-id (str (:default-team-id data))
|
||||
:default-project-id (str (:default-project-id data))}]
|
||||
|
||||
{:name "signin"
|
||||
:type "identify"
|
||||
:profile-id (:id data)
|
||||
:props (normalize-props props)}))
|
||||
:props (simplify-props props)}))
|
||||
|
||||
;; --- MAIN LOOP
|
||||
|
||||
|
|
|
@ -53,7 +53,9 @@
|
|||
|
||||
(defn set-current-team!
|
||||
[team-id]
|
||||
(swap! storage assoc ::current-team-id team-id))
|
||||
(if (nil? team-id)
|
||||
(swap! storage dissoc ::current-team-id)
|
||||
(swap! storage assoc ::current-team-id team-id)))
|
||||
|
||||
;; --- EVENT: fetch-teams
|
||||
|
||||
|
@ -132,7 +134,7 @@
|
|||
(swap! storage assoc :profile profile)
|
||||
(i18n/set-locale! (:lang profile))
|
||||
(when (not= previous-email email)
|
||||
(swap! storage dissoc ::current-team-id)))))))
|
||||
(set-current-team! nil)))))))
|
||||
|
||||
(defn fetch-profile
|
||||
[]
|
||||
|
@ -295,6 +297,19 @@
|
|||
|
||||
;; --- Update Profile
|
||||
|
||||
(defn persist-profile
|
||||
[& {:as opts}]
|
||||
(ptk/reify ::persist-profile
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [on-success (:on-success opts identity)
|
||||
on-error (:on-error opts rx/throw)
|
||||
profile (:profile state)]
|
||||
|
||||
(->> (rp/cmd! :update-profile (dissoc profile :props))
|
||||
(rx/tap on-success)
|
||||
(rx/catch on-error))))))
|
||||
|
||||
(defn update-profile
|
||||
[data]
|
||||
(dm/assert!
|
||||
|
@ -303,21 +318,19 @@
|
|||
|
||||
(ptk/reify ::update-profile
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ stream]
|
||||
(let [mdata (meta data)
|
||||
on-success (:on-success mdata identity)
|
||||
on-error (:on-error mdata rx/throw)]
|
||||
(->> (rp/cmd! :update-profile (dissoc data :props))
|
||||
(rx/mapcat
|
||||
(fn [_]
|
||||
(rx/merge
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::profile-fetched))
|
||||
(rx/take 1)
|
||||
(rx/tap on-success)
|
||||
(rx/ignore))
|
||||
(rx/of (profile-fetched data)))))
|
||||
(rx/catch on-error))))))
|
||||
(watch [_ state _]
|
||||
(let [data (dissoc data :props)
|
||||
profile (:profile state)
|
||||
profile' (d/deep-merge profile data)]
|
||||
|
||||
(rx/concat
|
||||
(rx/of #(assoc % :profile profile'))
|
||||
|
||||
(when (not= (:theme profile) (:theme profile'))
|
||||
(rx/of (ptk/data-event ::ev/event
|
||||
{::ev/name "activate-theme"
|
||||
::ev/origin "settings"
|
||||
:theme (:theme profile')}))))))))
|
||||
|
||||
;; --- Toggle Theme
|
||||
|
||||
|
@ -327,18 +340,19 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:profile :theme]
|
||||
(fn [theme]
|
||||
(cond
|
||||
(= theme "default")
|
||||
(fn [current]
|
||||
(if (= current "default")
|
||||
"light"
|
||||
|
||||
:else
|
||||
"default"))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(rx/of (update-profile (:profile state))))))
|
||||
|
||||
(watch [it state _]
|
||||
(let [profile (get state :profile)
|
||||
origin (::ev/origin (meta it))]
|
||||
(rx/of (ptk/data-event ::ev/event {:theme (:theme profile)
|
||||
::ev/name "activate-theme"
|
||||
::ev/origin origin})
|
||||
(persist-profile))))))
|
||||
|
||||
;; --- Request Email Change
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.main.data.comments :as dcm]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.fonts :as df]
|
||||
[app.main.features :as features]
|
||||
[app.main.repo :as rp]
|
||||
|
@ -546,6 +547,11 @@
|
|||
(defn go-to-section
|
||||
[section]
|
||||
(ptk/reify ::go-to-section
|
||||
ev/Event
|
||||
(-data [_]
|
||||
{::ev/origin "viewer"
|
||||
:section (name section)})
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state :viewer-overlays []))
|
||||
|
|
|
@ -2210,14 +2210,12 @@
|
|||
(ptk/reify ::update-component-annotation
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
|
||||
(let [data (get state :workspace-data)
|
||||
|
||||
update-fn
|
||||
(fn [component]
|
||||
;; NOTE: we need to ensure the component exists,
|
||||
;; because there are small possibilities of race
|
||||
;; conditions with component deletion.
|
||||
;; NOTE: we need to ensure the component exists,
|
||||
;; because there are small possibilities of race
|
||||
;; conditions with component deletion.
|
||||
(when component
|
||||
(if (nil? annotation)
|
||||
(dissoc component :annotation)
|
||||
|
@ -2227,14 +2225,17 @@
|
|||
(pcb/with-library-data data)
|
||||
(pcb/update-component id update-fn))]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
(rx/concat
|
||||
(rx/of (dch/commit-changes changes))
|
||||
(when (nil? annotation)
|
||||
(rx/of (ptk/data-event ::ev/event {::ev/name "delete-component-annotation"}))))))))
|
||||
|
||||
(defn set-annotations-expanded
|
||||
[expanded?]
|
||||
[expanded]
|
||||
(ptk/reify ::set-annotations-expanded
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-annotations :expanded?] expanded?))))
|
||||
(assoc-in state [:workspace-annotations :expanded] expanded))))
|
||||
|
||||
(defn set-annotations-id-for-create
|
||||
[id]
|
||||
|
@ -2243,8 +2244,13 @@
|
|||
(update [_ state]
|
||||
(if id
|
||||
(-> (assoc-in state [:workspace-annotations :id-for-create] id)
|
||||
(assoc-in [:workspace-annotations :expanded?] true))
|
||||
(d/dissoc-in state [:workspace-annotations :id-for-create])))))
|
||||
(assoc-in [:workspace-annotations :expanded] true))
|
||||
(d/dissoc-in state [:workspace-annotations :id-for-create])))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(when (some? id)
|
||||
(rx/of (ptk/data-event ::ev/event {::ev/name "create-component-annotation"}))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Preview blend modes
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"Workspace layout management events and helpers."
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.events :as ev]
|
||||
[app.util.storage :refer [storage]]
|
||||
[clojure.set :as set]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -114,8 +115,16 @@
|
|||
|
||||
(defn set-options-mode
|
||||
[mode]
|
||||
(dm/assert! (contains? valid-options-mode mode))
|
||||
(dm/assert!
|
||||
"expected valid options mode"
|
||||
(contains? valid-options-mode mode))
|
||||
|
||||
(ptk/reify ::set-options-mode
|
||||
ev/Event
|
||||
(-data [_]
|
||||
{::ev/origin "workspace:sidebar"
|
||||
:mode (name mode)})
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-global :options-mode] mode))))
|
||||
|
|
|
@ -953,6 +953,10 @@
|
|||
(dm/assert! (uuid? id-new-component))
|
||||
(dm/assert! (uuid? file-id))
|
||||
(ptk/reify ::component-multi-swap
|
||||
ev/Event
|
||||
(-data [_]
|
||||
{::ev/name "component-swap"})
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [undo-id (js/Symbol)]
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.colors :as cl]
|
||||
[app.main.data.workspace.grid-layout.editor :as dwge]
|
||||
|
@ -123,7 +124,10 @@
|
|||
|
||||
(defn create-layout-from-id
|
||||
[id type from-frame?]
|
||||
(assert (uuid? id) (str id))
|
||||
(dm/assert!
|
||||
"expected uuid for `id`"
|
||||
(uuid? id))
|
||||
|
||||
(ptk/reify ::create-layout-from-id
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
|
@ -192,7 +196,7 @@
|
|||
|
||||
(defn remove-layout
|
||||
[ids]
|
||||
(ptk/reify ::remove-layout
|
||||
(ptk/reify ::remove-shape-layout
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [undo-id (js/Symbol)]
|
||||
|
@ -204,7 +208,11 @@
|
|||
|
||||
(defn create-layout
|
||||
[type]
|
||||
(ptk/reify ::create-layout
|
||||
(ptk/reify ::create-shape-layout
|
||||
ev/Event
|
||||
(-data [_]
|
||||
{:layout (name type)})
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
|
@ -224,19 +232,21 @@
|
|||
|
||||
(defn toggle-layout
|
||||
[type]
|
||||
(ptk/reify ::toggle-layout-flex
|
||||
(ptk/reify ::toggle-shape-layout
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(watch [it state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (wsh/lookup-selected state)
|
||||
selected-shapes (map (d/getf objects) selected)
|
||||
single? (= (count selected-shapes) 1)
|
||||
has-layout? (and single? (ctl/any-layout? objects (:id (first selected-shapes))))]
|
||||
has-layout? (and single?
|
||||
(ctl/any-layout? objects (:id (first selected-shapes))))]
|
||||
|
||||
(when (not= 0 (count selected))
|
||||
(if has-layout?
|
||||
(rx/of (remove-layout selected))
|
||||
(rx/of (create-layout type))))))))
|
||||
(let [event (if has-layout?
|
||||
(remove-layout selected)
|
||||
(create-layout type))]
|
||||
(rx/of (with-meta event (meta it)))))))))
|
||||
|
||||
(defn update-layout
|
||||
[ids changes]
|
||||
|
|
|
@ -436,9 +436,11 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
pages (-> state :workspace-data :pages-index vals)]
|
||||
pages (-> state :workspace-data :pages-index vals)
|
||||
undo-id (js/Symbol)]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (dwu/start-undo-transaction undo-id))
|
||||
;; First: clear the `:use-for-thumbnail` flag from all not
|
||||
;; selected frames.
|
||||
(rx/from
|
||||
|
@ -456,4 +458,5 @@
|
|||
(dch/update-shapes frame-ids #(dissoc % :use-for-thumbnail) {:page-id page-id})))))
|
||||
|
||||
;; And finally: toggle the flag value on all the selected shapes
|
||||
(rx/of (dch/update-shapes selected #(update % :use-for-thumbnail not))))))))
|
||||
(rx/of (dch/update-shapes selected #(update % :use-for-thumbnail not))
|
||||
(dwu/commit-undo-transaction undo-id)))))))
|
||||
|
|
|
@ -222,13 +222,16 @@
|
|||
:toggle-layout-flex {:tooltip (ds/shift "A")
|
||||
:command "shift+a"
|
||||
:subsections [:modify-layers]
|
||||
:fn #(emit-when-no-readonly (dwsl/toggle-layout :flex))}
|
||||
:fn #(emit-when-no-readonly
|
||||
(with-meta (dwsl/toggle-layout :flex)
|
||||
{::ev/origin "workspace:shortcuts"}))}
|
||||
|
||||
:toggle-layout-grid {:tooltip (ds/meta-shift "A")
|
||||
:command (ds/c-mod "shift+a")
|
||||
:subsections [:modify-layers]
|
||||
:fn #(emit-when-no-readonly (dwsl/toggle-layout :grid))}
|
||||
|
||||
:fn #(emit-when-no-readonly
|
||||
(with-meta (dwsl/toggle-layout :grid)
|
||||
{::ev/origin "workspace:shortcuts"}))}
|
||||
;; TOOLS
|
||||
|
||||
:draw-frame {:tooltip "B"
|
||||
|
@ -292,10 +295,10 @@
|
|||
:subsections [:tools]
|
||||
:fn #(emit-when-no-readonly (dw/toggle-proportion-lock))}
|
||||
|
||||
:toggle-scale-text {:tooltip "K"
|
||||
:command "k"
|
||||
:subsections [:tools]
|
||||
:fn #(emit-when-no-readonly (toggle-layout-flag :scale-text))}
|
||||
:scale {:tooltip "K"
|
||||
:command "k"
|
||||
:subsections [:tools]
|
||||
:fn #(emit-when-no-readonly (toggle-layout-flag :scale-text))}
|
||||
|
||||
:open-color-picker {:tooltip "I"
|
||||
:command "i"
|
||||
|
@ -549,12 +552,12 @@
|
|||
:command (ds/c-mod "alt+enter")
|
||||
:fn #(emit-when-no-readonly (dp/open-preview-selected))}
|
||||
|
||||
|
||||
;; THEME
|
||||
:toggle-theme {:tooltip (ds/alt "M")
|
||||
:command (ds/a-mod "m")
|
||||
:subsections [:basics]
|
||||
:fn #(st/emit! (du/toggle-theme))}})
|
||||
:fn #(st/emit! (with-meta (du/toggle-theme)
|
||||
{::ev/origin "workspace:shortcut"}))}})
|
||||
|
||||
(def opacity-shortcuts
|
||||
(into {} (->>
|
||||
|
|
|
@ -539,6 +539,7 @@
|
|||
(every? (partial ctl/grid-layout-immediate-child? objects))))
|
||||
workspace-page-objects =))
|
||||
|
||||
;; FIXME: move to viewer.inspect.code
|
||||
(defn get-flex-child-viewer
|
||||
[ids page-id]
|
||||
(l/derived
|
||||
|
@ -550,7 +551,7 @@
|
|||
ids)))
|
||||
st/state =))
|
||||
|
||||
|
||||
;; FIXME: move to viewer.inspect.code
|
||||
(defn get-viewer-objects
|
||||
([]
|
||||
(let [route (deref route)
|
||||
|
@ -574,9 +575,6 @@
|
|||
[id]
|
||||
(l/derived #(get % id) workspace-grid-edition))
|
||||
|
||||
(def workspace-annotations
|
||||
(l/derived #(get % :workspace-annotations {}) st/state))
|
||||
|
||||
(def current-file-id
|
||||
(l/derived :current-file-id st/state))
|
||||
|
||||
|
|
|
@ -100,26 +100,27 @@
|
|||
:initial initial)
|
||||
|
||||
on-error
|
||||
(fn [cause]
|
||||
(cond
|
||||
(and (= :restriction (:type cause))
|
||||
(= :profile-blocked (:code cause)))
|
||||
(reset! error (tr "errors.profile-blocked"))
|
||||
(fn [err]
|
||||
(let [cause (ex-data err)]
|
||||
(cond
|
||||
(and (= :restriction (:type cause))
|
||||
(= :profile-blocked (:code cause)))
|
||||
(reset! error (tr "errors.profile-blocked"))
|
||||
|
||||
(and (= :restriction (:type cause))
|
||||
(= :admin-only-profile (:code cause)))
|
||||
(reset! error (tr "errors.profile-blocked"))
|
||||
(and (= :restriction (:type cause))
|
||||
(= :admin-only-profile (:code cause)))
|
||||
(reset! error (tr "errors.profile-blocked"))
|
||||
|
||||
(and (= :validation (:type cause))
|
||||
(= :wrong-credentials (:code cause)))
|
||||
(reset! error (tr "errors.wrong-credentials"))
|
||||
(and (= :validation (:type cause))
|
||||
(= :wrong-credentials (:code cause)))
|
||||
(reset! error (tr "errors.wrong-credentials"))
|
||||
|
||||
(and (= :validation (:type cause))
|
||||
(= :account-without-password (:code cause)))
|
||||
(reset! error (tr "errors.wrong-credentials"))
|
||||
(and (= :validation (:type cause))
|
||||
(= :account-without-password (:code cause)))
|
||||
(reset! error (tr "errors.wrong-credentials"))
|
||||
|
||||
:else
|
||||
(reset! error (tr "errors.generic"))))
|
||||
:else
|
||||
(reset! error (tr "errors.generic")))))
|
||||
|
||||
on-success-default
|
||||
(fn [data]
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
}
|
||||
|
||||
.section-title {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
height: $s-32;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -55,7 +55,7 @@
|
|||
|
||||
// Comment-thread
|
||||
.comment {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-12;
|
||||
|
@ -98,7 +98,7 @@
|
|||
}
|
||||
|
||||
.content {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--color-foreground-primary);
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@
|
|||
.comment-container {
|
||||
position: relative;
|
||||
.comment {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
.author {
|
||||
display: flex;
|
||||
gap: $s-8;
|
||||
|
@ -195,7 +195,7 @@
|
|||
.content {
|
||||
position: relative;
|
||||
.text {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
|
||||
.color-text {
|
||||
@include twoLineTextEllipsis;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
width: $s-80;
|
||||
text-align: center;
|
||||
margin-top: $s-2;
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
.context-menu-item {
|
||||
display: flex;
|
||||
.context-menu-action {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
|
|
@ -8,32 +8,40 @@
|
|||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.events :as-alias ev]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.timers :as timers]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.timers :as tm]
|
||||
[app.util.webapi :as wapi]
|
||||
[beicon.v2.core :as rx]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc copy-button [{:keys [data on-copied children class]}]
|
||||
(let [just-copied (mf/use-state false)]
|
||||
(mf/use-effect
|
||||
(mf/deps @just-copied)
|
||||
(fn []
|
||||
(when @just-copied
|
||||
(when (fn? on-copied)
|
||||
(on-copied))
|
||||
(let [sub (timers/schedule 1000 #(reset! just-copied false))]
|
||||
;; On unmount we dispose the timer
|
||||
#(rx/-dispose sub)))))
|
||||
[:button {:class (dm/str class " " (stl/css-case :copy-button (not (some? children))
|
||||
:copy-wrapper (some? children)))
|
||||
:on-click #(when-not @just-copied
|
||||
(reset! just-copied true)
|
||||
(wapi/write-to-clipboard (if (fn? data) (data) data)))}
|
||||
(mf/defc copy-button
|
||||
{::mf/props :obj}
|
||||
[{:keys [data on-copied children class]}]
|
||||
(let [active* (mf/use-state false)
|
||||
active? (deref active*)
|
||||
|
||||
(when children
|
||||
children)
|
||||
class (dm/str class " "
|
||||
(stl/css-case
|
||||
:copy-button (not (some? children))
|
||||
:copy-wrapper (some? children)))
|
||||
|
||||
on-click
|
||||
(mf/use-fn
|
||||
(mf/deps data)
|
||||
(fn [event]
|
||||
(when-not (dom/get-boolean-data event "active")
|
||||
(reset! active* true)
|
||||
(tm/schedule 1000 #(reset! active* false))
|
||||
(when (fn? on-copied) (on-copied event))
|
||||
(wapi/write-to-clipboard
|
||||
(if (fn? data) (data) data)))))]
|
||||
|
||||
[:button {:class class
|
||||
:data-active (dm/str active?)
|
||||
:on-click on-click}
|
||||
children
|
||||
[:span {:class (stl/css :icon-btn)}
|
||||
(if @just-copied
|
||||
(if active?
|
||||
i/tick-refactor
|
||||
i/clipboard-refactor)]]))
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
.editable-label-input {
|
||||
@include textEllipsis;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include removeInputStyle;
|
||||
flex-grow: 1;
|
||||
height: $s-28;
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
.input-with-label {
|
||||
@include flexColumn;
|
||||
gap: $s-8;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
height: 100%;
|
||||
|
@ -143,7 +143,7 @@
|
|||
}
|
||||
|
||||
.hint {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--modal-text-foreground-color);
|
||||
width: 99%;
|
||||
}
|
||||
|
@ -151,7 +151,7 @@
|
|||
.checkbox {
|
||||
@extend .input-checkbox;
|
||||
.checkbox-label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row-reverse;
|
||||
|
@ -186,7 +186,7 @@
|
|||
background-color: var(--input-background-color);
|
||||
.main-content {
|
||||
@include flexColumn;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
flex-grow: 1;
|
||||
|
@ -231,7 +231,7 @@
|
|||
|
||||
select {
|
||||
@extend .menu-dropdown;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -247,7 +247,7 @@
|
|||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
option {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--title-foreground-color-hover);
|
||||
background-color: var(--menu-background-color);
|
||||
appearance: none;
|
||||
|
@ -276,7 +276,7 @@
|
|||
overflow-y: hidden;
|
||||
.inside-input {
|
||||
@include removeInputStyle;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
width: 100%;
|
||||
max-width: calc(100% - $s-1);
|
||||
|
@ -315,7 +315,7 @@
|
|||
border: $s-1 solid var(--pill-background-color);
|
||||
box-sizing: border-box;
|
||||
.text {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
padding-right: $s-8;
|
||||
color: var(--pill-foreground-color);
|
||||
}
|
||||
|
@ -352,7 +352,7 @@
|
|||
}
|
||||
|
||||
.radio-label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include flexRow;
|
||||
align-items: flex-start;
|
||||
gap: $s-8;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
--icon-color: var(--icon-foreground);
|
||||
--text-color: var(--menu-foreground-color);
|
||||
@extend .new-scrollbar;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
|
|
|
@ -15,9 +15,13 @@
|
|||
(i/icon-xref :arrow-refactor (stl/css :chevron-icon)))
|
||||
|
||||
(mf/defc title-bar
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [collapsable collapsed on-collapsed title children on-btn-click btn-children class all-clickable add-icon-gap origin]}]
|
||||
(let [klass (dm/str (stl/css-case :title-bar true :all-clickable all-clickable) " " class)]
|
||||
{::mf/props :obj}
|
||||
[{:keys [class collapsable collapsed title children
|
||||
btn-children all-clickable add-icon-gap
|
||||
on-collapsed on-btn-click]}]
|
||||
(let [klass (stl/css-case :title-bar true
|
||||
:all-clickable all-clickable)
|
||||
klass (dm/str klass " " class)]
|
||||
[:div {:class klass}
|
||||
(if ^boolean collapsable
|
||||
[:div {:class (stl/css :title-wrapper)}
|
||||
|
@ -35,13 +39,20 @@
|
|||
:collapsed collapsed)
|
||||
:on-click on-collapsed}
|
||||
chevron-icon]
|
||||
[:div {:class (stl/css :title)} title]])]
|
||||
[:div {:class (stl/css-case :title-only true
|
||||
:title-only-icon-gap add-icon-gap
|
||||
:title-only (not= :inspect origin)
|
||||
:inspect-title (= :inspect origin))} title])
|
||||
[:div {:class (stl/css :title)}
|
||||
title]])]
|
||||
[:div {:class (stl/css-case
|
||||
:title-only true
|
||||
:title-only-icon-gap add-icon-gap)}
|
||||
title])
|
||||
children
|
||||
(when (some? on-btn-click)
|
||||
[:button {:class (stl/css :title-button)
|
||||
:on-click on-btn-click}
|
||||
btn-children])]))
|
||||
|
||||
(mf/defc inspect-title-bar
|
||||
{::mf/props :obj}
|
||||
[{:keys [class title]}]
|
||||
[:div {:class (dm/str (stl/css :title-bar) " " class)}
|
||||
[:div {:class (stl/css :title-only :inspect-title)} title]])
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
}
|
||||
|
||||
.modal-content {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin-bottom: $s-24;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,9 +58,16 @@
|
|||
(let [fonts* (mf/use-state {})
|
||||
fonts (deref fonts*)
|
||||
input-ref (mf/use-ref)
|
||||
|
||||
uploading (mf/use-state #{})
|
||||
|
||||
bad-font-family-tmp?
|
||||
(mf/use-fn
|
||||
(fn [font]
|
||||
(and (contains? font :font-family-tmp)
|
||||
(str/blank? (:font-family-tmp font)))))
|
||||
|
||||
disable-upload-all? (some bad-font-family-tmp? (vals fonts))
|
||||
|
||||
handle-click
|
||||
(mf/use-fn #(dom/click (mf/ref-val input-ref)))
|
||||
|
||||
|
@ -95,7 +102,13 @@
|
|||
on-blur-name
|
||||
(fn [id event]
|
||||
(let [name (dom/get-target-val event)]
|
||||
(swap! fonts* df/rename-and-regroup id name installed-fonts)))
|
||||
(when-not (str/blank? name)
|
||||
(swap! fonts* df/rename-and-regroup id name installed-fonts))))
|
||||
|
||||
on-change-name
|
||||
(fn [id event]
|
||||
(let [name (dom/get-target-val event)]
|
||||
(swap! fonts* update-in [id] #(assoc % :font-family-tmp name))))
|
||||
|
||||
on-delete
|
||||
(mf/use-fn
|
||||
|
@ -145,9 +158,11 @@
|
|||
[:div {:class (stl/css :font-item :table-row)}
|
||||
[:span (tr "dashboard.fonts.fonts-added" (i18n/c (count (vals fonts))))]
|
||||
[:div {:class (stl/css :table-field :options)}
|
||||
[:button {:class (stl/css :btn-primary)
|
||||
[:button {:class (stl/css-case :btn-primary true
|
||||
:disabled disable-upload-all?)
|
||||
:on-click handle-upload-all
|
||||
:data-test "upload-all"}
|
||||
:data-test "upload-all"
|
||||
:disabled disable-upload-all?}
|
||||
[:span (tr "dashboard.fonts.upload-all")]]
|
||||
[:button {:class (stl/css :btn-secondary)
|
||||
:on-click handle-dismiss-all
|
||||
|
@ -155,12 +170,15 @@
|
|||
[:span (tr "dashboard.fonts.dismiss-all")]]]])
|
||||
|
||||
(for [item (sort-by :font-family (vals fonts))]
|
||||
(let [uploading? (contains? @uploading (:id item))]
|
||||
(let [uploading? (contains? @uploading (:id item))
|
||||
disable-upload? (or uploading?
|
||||
(bad-font-family-tmp? item))]
|
||||
[:div {:class (stl/css :font-item :table-row)
|
||||
:key (:id item)}
|
||||
[:div {:class (stl/css :table-field :family)}
|
||||
[:input {:type "text"
|
||||
:on-blur #(on-blur-name (:id item) %)
|
||||
:on-change #(on-change-name (:id item) %)
|
||||
:default-value (:font-family item)}]]
|
||||
[:div {:class (stl/css :table-field :variants)}
|
||||
[:span {:class (stl/css :label)}
|
||||
|
@ -177,8 +195,8 @@
|
|||
[:button {:on-click #(on-upload item)
|
||||
:class (stl/css-case :btn-primary true
|
||||
:upload-button true
|
||||
:disabled uploading?)
|
||||
:disabled uploading?}
|
||||
:disabled disable-upload?)
|
||||
:disabled disable-upload?}
|
||||
(if uploading?
|
||||
(tr "labels.uploading")
|
||||
(tr "labels.upload"))]
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
}
|
||||
|
||||
.modal-content {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: $s-16;
|
||||
|
@ -52,7 +52,7 @@
|
|||
.modal-scd-msg,
|
||||
.modal-subtitle,
|
||||
.modal-msg {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--modal-text-foreground-color);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@
|
|||
flex-grow: 1;
|
||||
}
|
||||
.file-name-label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-12;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
[app.util.timers :as ts]
|
||||
[beicon.v2.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[goog.functions :as f]
|
||||
[potok.v2.core :as ptk]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -91,8 +92,9 @@
|
|||
(mf/use-callback
|
||||
(mf/deps item)
|
||||
(fn [name]
|
||||
(st/emit! (-> (dd/rename-project (assoc item :name name))
|
||||
(with-meta {::ev/origin "dashboard:sidebar"})))
|
||||
(when-not (str/blank? name)
|
||||
(st/emit! (-> (dd/rename-project (assoc item :name name))
|
||||
(with-meta {::ev/origin "dashboard:sidebar"}))))
|
||||
(swap! local* assoc :edition? false)))
|
||||
|
||||
on-drag-enter
|
||||
|
|
|
@ -131,8 +131,10 @@
|
|||
.dropdown {
|
||||
right: $s-2;
|
||||
top: $s-52;
|
||||
min-width: $s-160;
|
||||
max-height: $s-480;
|
||||
&:not(.teams-dropdown) {
|
||||
min-width: $s-160;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -612,7 +612,7 @@
|
|||
}
|
||||
}
|
||||
.message {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--alert-foreground-color-error);
|
||||
}
|
||||
}
|
||||
|
@ -636,7 +636,7 @@
|
|||
}
|
||||
}
|
||||
.message {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--alert-foreground-color-warning);
|
||||
}
|
||||
}
|
||||
|
@ -694,7 +694,7 @@
|
|||
.modal-content {
|
||||
@include flexColumn;
|
||||
gap: $s-24;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin-bottom: $s-24;
|
||||
}
|
||||
|
||||
|
@ -703,7 +703,7 @@
|
|||
}
|
||||
|
||||
.select-title {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
@extend .input-element-label;
|
||||
label {
|
||||
@include flexColumn;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
border: none;
|
||||
|
@ -43,7 +43,7 @@
|
|||
height: 100%;
|
||||
|
||||
input {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin-top: $s-8;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
flex-direction: column;
|
||||
border-radius: $s-8;
|
||||
h3 {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
font-size: $fs-24;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
}
|
||||
|
||||
.modal-content {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin-bottom: $s-24;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
}
|
||||
|
||||
.export-progress-title {
|
||||
@include bodyMedTipography;
|
||||
@include bodyMediumTypography;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: $s-8;
|
||||
|
@ -67,7 +67,7 @@
|
|||
}
|
||||
|
||||
.progress {
|
||||
@include bodyMedTipography;
|
||||
@include bodyMediumTypography;
|
||||
padding-left: $s-8;
|
||||
margin: 0;
|
||||
align-self: center;
|
||||
|
@ -76,7 +76,7 @@
|
|||
|
||||
.retry-btn {
|
||||
@include buttonStyle;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: inline;
|
||||
text-align: left;
|
||||
color: var(--modal-link-foreground-color);
|
||||
|
@ -128,10 +128,10 @@
|
|||
|
||||
.modal-content,
|
||||
.no-selection {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin-bottom: $s-24;
|
||||
.modal-hint {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--modal-text-foreground-color);
|
||||
}
|
||||
.modal-link {
|
||||
|
|
|
@ -10,10 +10,18 @@
|
|||
[cuerdas.core :as str]
|
||||
[rumext.v2]))
|
||||
|
||||
(def exceptions #{:penpot-logo-icon})
|
||||
|
||||
(defmacro icon-xref
|
||||
[id & [class]]
|
||||
(let [href (str "#icon-" (name id))
|
||||
class (or class (str "icon-" (name id)))]
|
||||
class (or class (str "icon-" (name id)))
|
||||
|
||||
;; FIXME: Debug tool. Remove when we remove the old icons
|
||||
class (cond-> class
|
||||
(and (not (str/ends-with? (name id) "-refactor"))
|
||||
(not (contains? exceptions id)))
|
||||
(str " deprecated-icon"))]
|
||||
`(rumext.v2/html
|
||||
[:svg {:width 500 :height 500 :class ~class}
|
||||
[:use {:href ~href}]])))
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
}
|
||||
|
||||
.context-text {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
align-self: center;
|
||||
color: var(--context-notification-fg-color);
|
||||
margin: auto 0;
|
||||
|
@ -78,7 +78,7 @@
|
|||
|
||||
.link,
|
||||
.contain-html .context-text a {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
align-self: center;
|
||||
display: inline;
|
||||
text-align: left;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
}
|
||||
|
||||
.inline-text {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
|||
}
|
||||
|
||||
.link {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
color: var(--modal-link-foreground-color);
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
}
|
||||
|
||||
.link {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--modal-link-foreground-color);
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@
|
|||
}
|
||||
|
||||
.text {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
}
|
||||
|
||||
.release {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
position: absolute;
|
||||
top: calc(-1 * $s-28);
|
||||
right: 0;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
|
||||
.paginator {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
position: absolute;
|
||||
top: $s-40;
|
||||
right: $s-100;
|
||||
|
@ -140,7 +140,7 @@
|
|||
@extend .input-element-label;
|
||||
label {
|
||||
@include flexColumn;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
border: none;
|
||||
|
@ -148,7 +148,7 @@
|
|||
height: 100%;
|
||||
|
||||
input {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin-top: $s-8;
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +185,7 @@
|
|||
}
|
||||
|
||||
.modal-hint {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--modal-text-foreground-color);
|
||||
text-align: right;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
[app.main.ui.releases.v1-7]
|
||||
[app.main.ui.releases.v1-8]
|
||||
[app.main.ui.releases.v1-9]
|
||||
[app.main.ui.releases.v2-0]
|
||||
[app.util.object :as obj]
|
||||
[app.util.timers :as tm]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -90,4 +91,4 @@
|
|||
|
||||
(defmethod rc/render-release-notes "0.0"
|
||||
[params]
|
||||
(rc/render-release-notes (assoc params :version "1.19")))
|
||||
(rc/render-release-notes (assoc params :version "2.0")))
|
||||
|
|
|
@ -5,15 +5,16 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.releases.common
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defmulti render-release-notes :version)
|
||||
|
||||
(mf/defc navigation-bullets
|
||||
[{:keys [slide navigate total]}]
|
||||
[:ul.step-dots
|
||||
[:ul {:class (stl/css :step-dots)}
|
||||
(for [i (range total)]
|
||||
[:li {:class (dom/classnames :current (= slide i))
|
||||
[:li {:class (stl/css-case :dot true
|
||||
:current (= slide i))
|
||||
:on-click #(navigate i)}])])
|
||||
|
|
32
frontend/src/app/main/ui/releases/common.scss
Normal file
32
frontend/src/app/main/ui/releases/common.scss
Normal file
|
@ -0,0 +1,32 @@
|
|||
// 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) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.step-dots {
|
||||
display: grid;
|
||||
grid-template-columns: none;
|
||||
grid-auto-flow: column;
|
||||
gap: $s-8;
|
||||
height: fit-content;
|
||||
width: fit-content;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
align-self: center;
|
||||
justify-self: flex-start;
|
||||
}
|
||||
|
||||
.dot {
|
||||
height: $s-12;
|
||||
width: $s-12;
|
||||
border-radius: $br-circle;
|
||||
background-color: var(--modal-navigator-foreground-color-rest);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.current {
|
||||
background-color: var(--modal-navigator-foreground-color-active);
|
||||
}
|
166
frontend/src/app/main/ui/releases/v2_0.cljs
Normal file
166
frontend/src/app/main/ui/releases/v2_0.cljs
Normal file
|
@ -0,0 +1,166 @@
|
|||
;; 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) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.releases.v2-0
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.releases.common :as c]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
;; TODO: Review all copies and alt text
|
||||
(defmethod c/render-release-notes "2.0"
|
||||
[{:keys [slide klass next finish navigate version]}]
|
||||
(mf/html
|
||||
(case slide
|
||||
:start
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
;; TODO: Review alt
|
||||
[:img {:src "images/features/2.0-intro-image.png"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Community code contributions"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"What's new?"]
|
||||
|
||||
[:div {:class (stl/css :verstion-tag)}
|
||||
(dm/str "Version " version)]]
|
||||
|
||||
[:div {:class (stl/css :features-block)}
|
||||
[:div {:class (stl/css :feature)}
|
||||
[:h2 {:class (stl/css :feature-title)}
|
||||
"CSS Grid Layout"]
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Crea una estructura flexible para componer
|
||||
los elementos de tu diseño y obten el código html/css."]]
|
||||
|
||||
[:div {:class (stl/css :feature)}
|
||||
[:h2 {:class (stl/css :feature-title)}
|
||||
"New Components"]
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Ahora tus main components estarán en un espacio
|
||||
físico, para que los puedas ver y gestionar fácilmente."]]
|
||||
|
||||
[:div {:class (stl/css :feature)}
|
||||
[:h2 {:class (stl/css :feature-title)}
|
||||
"New User Interface"]
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Hemos hecho Penpot aún más bonito, y además
|
||||
ahora puedes elegir entre tema oscuro y claro."]]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
[:button {:class (stl/css :next-btn)
|
||||
:on-click next} "Continue"]]]]]]
|
||||
|
||||
0
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
;; TODO: Review alt
|
||||
[:img {:src "images/features/2.0-css-grid.gif"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Community code contributions"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"css grid layout"]]
|
||||
[:div {:class (stl/css :feature)}
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"¿Querías más flexibilidad para componer tus diseños?
|
||||
Selecciona GridLayout para crear una estructura con los
|
||||
márgenes y espacios que necesites. Los elementos de tu diseño
|
||||
se adaptarán como un guante. Además tendrás en el momento el
|
||||
código html y css con estándares web."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Elige entre FlexLayout o GridLayout en tu panel lateral derecho."]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 3}]
|
||||
|
||||
[:button {:on-click next
|
||||
:class (stl/css :next-btn)} "Continue"]]]]]]
|
||||
|
||||
1
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
[:img {:src "images/features/2.0-components.gif"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Community code contributions"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"New components"]]
|
||||
[:div {:class (stl/css :feature)}
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Os hemos escuchado y ahora los main components están
|
||||
disponibles en el archivo para gestionarlos más cómodamente."]
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"No te preocupes por tus archivos con main componentes v1,
|
||||
al abrirlos con la nueva versión los encontrarás agrupados
|
||||
en una página nueva, sanos y salvos."]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 3}]
|
||||
|
||||
[:button {:on-click next
|
||||
:class (stl/css :next-btn)} "Continue"]]]]]]
|
||||
|
||||
2
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
[:img {:src "images/features/2.0-new-ui.gif"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Community code contributions"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"REDISEÑO Y MEJORAS DE RENDIMIENTO"]]
|
||||
|
||||
[:div {:class (stl/css :feature)}
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Le hemos dado una vuelta al interface y añadido
|
||||
pequeñas mejoras de usabilidad.
|
||||
Además, ahora puedes elegir entre tema oscuro y tema claro,
|
||||
dignos de Dark Vader y Luke Skywalker."]
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Aunque siempre estamos puliendo el rendimiento
|
||||
y la estabilidad, en esta versión hemos
|
||||
conseguido grandes mejoras en ese sentido."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Que lo disfrutes!"]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 3}]
|
||||
|
||||
[:button {:on-click finish
|
||||
:class (stl/css :next-btn)} "Let's go"]]]]]])))
|
||||
|
90
frontend/src/app/main/ui/releases/v2_0.scss
Normal file
90
frontend/src/app/main/ui/releases/v2_0.scss
Normal file
|
@ -0,0 +1,90 @@
|
|||
// 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) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.modal-overlay {
|
||||
@extend .modal-overlay-base;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
display: grid;
|
||||
grid-template-columns: $s-324 1fr;
|
||||
height: $s-500;
|
||||
width: $s-888;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--modal-background-color);
|
||||
border: $s-2 solid var(--modal-border-color);
|
||||
}
|
||||
|
||||
.start-image {
|
||||
width: $s-324;
|
||||
border-radius: $br-8 0 0 $br-8;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
padding: $s-40;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr $s-32;
|
||||
gap: $s-24;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: grid;
|
||||
gap: $s-8;
|
||||
}
|
||||
|
||||
.verstion-tag {
|
||||
@include flexCenter;
|
||||
@include headlineSmallTypography;
|
||||
height: $s-32;
|
||||
width: $s-96;
|
||||
background-color: var(--communication-tag-background-color);
|
||||
color: var(--communication-tag-foreground-color);
|
||||
border-radius: $br-8;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
@include headlineLargeTypography;
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
.features-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-16;
|
||||
width: $s-440;
|
||||
}
|
||||
|
||||
.feature {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-8;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
@include bodyLargeTypography;
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
.feature-content {
|
||||
@include bodyMediumTypography;
|
||||
margin: 0;
|
||||
color: var(--modal-text-foreground-color);
|
||||
}
|
||||
|
||||
.navigation {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-areas: "bullets button";
|
||||
}
|
||||
|
||||
.next-btn {
|
||||
@extend .button-primary;
|
||||
width: $s-100;
|
||||
justify-self: flex-end;
|
||||
grid-area: button;
|
||||
}
|
|
@ -191,7 +191,7 @@
|
|||
.modal-content {
|
||||
@include flexColumn;
|
||||
gap: $s-24;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin-bottom: $s-24;
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@
|
|||
}
|
||||
|
||||
.select-title {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,7 @@
|
|||
|
||||
.token-value {
|
||||
@include textEllipsis;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
.modal-content {
|
||||
@include flexColumn;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
gap: $s-24;
|
||||
margin-bottom: $s-24;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@
|
|||
}
|
||||
|
||||
.select-title {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
.modal-content {
|
||||
@include flexColumn;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
gap: $s-24;
|
||||
margin-bottom: $s-24;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@
|
|||
}
|
||||
|
||||
.select-title {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,15 +24,12 @@
|
|||
(s/def ::options-form
|
||||
(s/keys :opt-un [::lang ::theme]))
|
||||
|
||||
(defn- on-success
|
||||
[_]
|
||||
(st/emit! (msg/success (tr "notifications.profile-saved"))))
|
||||
|
||||
(defn- on-submit
|
||||
[form _event]
|
||||
(let [data (:clean-data @form)
|
||||
mdata {:on-success (partial on-success form)}]
|
||||
(st/emit! (du/update-profile (with-meta data mdata)))))
|
||||
(let [data (:clean-data @form)]
|
||||
(st/emit! (du/update-profile data)
|
||||
(du/persist-profile)
|
||||
(msg/success (tr "notifications.profile-saved")))))
|
||||
|
||||
(mf/defc options-form
|
||||
{::mf/wrap-props false}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
(defn- on-error
|
||||
[form error]
|
||||
(case (:code error)
|
||||
(case (:code (ex-data error))
|
||||
:old-password-not-match
|
||||
(swap! form assoc-in [:errors :password-old]
|
||||
{:message (tr "errors.wrong-old-password")})
|
||||
|
@ -103,7 +103,7 @@
|
|||
:label (t locale "labels.confirm-password")}]]
|
||||
|
||||
[:> fm/submit-button*
|
||||
{:label (t locale "dashboard.update-settings")
|
||||
{:label (t locale "dashboard.password-change")
|
||||
:data-test "submit-password"
|
||||
:class (stl/css :update-btn)}]]))
|
||||
|
||||
|
|
|
@ -27,15 +27,12 @@
|
|||
(s/def ::profile-form
|
||||
(s/keys :req-un [::fullname ::email]))
|
||||
|
||||
(defn- on-success
|
||||
[_]
|
||||
(st/emit! (msg/success (tr "notifications.profile-saved"))))
|
||||
|
||||
(defn- on-submit
|
||||
[form _event]
|
||||
(let [data (:clean-data @form)
|
||||
mdata {:on-success (partial on-success form)}]
|
||||
(st/emit! (du/update-profile (with-meta data mdata)))))
|
||||
(let [data (:clean-data @form)]
|
||||
(st/emit! (du/update-profile data)
|
||||
(du/persist-profile)
|
||||
(msg/success (tr "notifications.profile-saved")))))
|
||||
|
||||
;; --- Profile Form
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
}
|
||||
|
||||
.empty-state {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--empty-message-foreground-color);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
|
@ -134,7 +134,7 @@
|
|||
|
||||
.counter {
|
||||
@include flexCenter;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
border-radius: $br-8;
|
||||
width: $s-64;
|
||||
height: $s-32;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
// COMMENT DROPDOWN ON HEADER
|
||||
.view-options {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
@ -29,7 +29,7 @@
|
|||
}
|
||||
|
||||
.dropdown-title {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
flex-grow: 1;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
|
|
|
@ -269,7 +269,8 @@
|
|||
(mf/deps permissions)
|
||||
(fn []
|
||||
(if (:is-logged permissions)
|
||||
(st/emit! dv/close-thumbnails-panel (dv/go-to-section :inspect))
|
||||
(st/emit! dv/close-thumbnails-panel
|
||||
(dv/go-to-section :inspect))
|
||||
(open-login-dialog))))
|
||||
|
||||
navigate
|
||||
|
@ -279,11 +280,11 @@
|
|||
(let [section (-> (dom/get-current-target event)
|
||||
(dom/get-data "value")
|
||||
(keyword))]
|
||||
|
||||
(if (or (= section :interactions) (:is-logged permissions))
|
||||
(st/emit! (dv/go-to-section section))
|
||||
(open-login-dialog)))))]
|
||||
|
||||
|
||||
[:header {:class (stl/css-case :viewer-header true
|
||||
:fullscreen (mf/deref fullscreen-ref))}
|
||||
[:div {:class (stl/css :nav-zone)}
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
}
|
||||
|
||||
.breadcrumb {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include flexRow;
|
||||
color: var(--title-foreground-color);
|
||||
cursor: pointer;
|
||||
|
@ -114,7 +114,7 @@
|
|||
}
|
||||
|
||||
.current-frame {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include flexRow;
|
||||
flex-grow: 1;
|
||||
color: var(--title-foreground-color-hover);
|
||||
|
@ -198,7 +198,7 @@
|
|||
|
||||
.go-log-btn {
|
||||
@extend .button-tertiary;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
height: $s-32;
|
||||
padding: 0 $s-8;
|
||||
border-radius: $br-8;
|
||||
|
@ -213,7 +213,7 @@
|
|||
min-width: $s-64;
|
||||
border-radius: $br-8;
|
||||
.label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--button-tertiary-foreground-color-rest);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
}
|
||||
|
||||
.annotation-content {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--entry-foreground-color);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.components.title-bar :refer [inspect-title-bar]]
|
||||
[app.util.code-gen.style-css :as css]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -22,10 +22,9 @@
|
|||
(let [shapes (->> shapes (filter has-blur?))]
|
||||
(when (seq shapes)
|
||||
[:div {:class (stl/css :attributes-block)}
|
||||
[:& title-bar {:collapsable false
|
||||
:title (tr "inspect.attributes.blur")
|
||||
:origin :inspect
|
||||
:class (stl/css :title-spacing-blur)}
|
||||
[:& inspect-title-bar
|
||||
{:title (tr "inspect.attributes.blur")
|
||||
:class (stl/css :title-spacing-blur)}
|
||||
(when (= (count shapes) 1)
|
||||
[:& copy-button {:data (css/get-css-property objects (first shapes) :filter)
|
||||
:class (stl/css :copy-btn-title)}])]
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.color-name-wrapper {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include flexColumn;
|
||||
padding: $s-8 $s-4 $s-8 $s-8;
|
||||
height: $s-32;
|
||||
|
@ -89,21 +89,21 @@
|
|||
max-width: $s-124;
|
||||
}
|
||||
.color-name-library {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
text-align: left;
|
||||
height: $s-16;
|
||||
color: var(--menu-foreground-color-rest);
|
||||
}
|
||||
.color-value-wrapper {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
height: $s-16;
|
||||
color: var(--menu-foreground-color);
|
||||
}
|
||||
}
|
||||
|
||||
.opacity-info {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--menu-foreground-color);
|
||||
padding: $s-8 0;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
(ns app.main.ui.viewer.inspect.attributes.fill
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.components.title-bar :refer [inspect-title-bar]]
|
||||
[app.main.ui.viewer.inspect.attributes.common :refer [color-row]]
|
||||
[app.util.code-gen.style-css :as css]
|
||||
[app.util.i18n :refer [tr]]
|
||||
|
@ -53,10 +53,9 @@
|
|||
(let [shapes (filter has-fill? shapes)]
|
||||
(when (seq shapes)
|
||||
[:div {:class (stl/css :attributes-block)}
|
||||
[:& title-bar {:collapsable false
|
||||
:origin :inspect
|
||||
:title (tr "inspect.attributes.fill")
|
||||
:class (stl/css :title-spacing-fill)}]
|
||||
[:& inspect-title-bar
|
||||
{:title (tr "inspect.attributes.fill")
|
||||
:class (stl/css :title-spacing-fill)}]
|
||||
|
||||
[:div {:class (stl/css :attributes-content)}
|
||||
(for [shape shapes]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.components.title-bar :refer [inspect-title-bar]]
|
||||
[app.main.ui.viewer.inspect.attributes.common :as cmm]
|
||||
[app.util.code-gen.style-css :as css]
|
||||
[app.util.i18n :refer [tr]]
|
||||
|
@ -36,10 +36,9 @@
|
|||
(mf/defc geometry-panel
|
||||
[{:keys [objects shapes]}]
|
||||
[:div {:class (stl/css :attributes-block)}
|
||||
[:& title-bar {:collapsable false
|
||||
:title (tr "inspect.attributes.size")
|
||||
:origin :inspect
|
||||
:class (stl/css :title-spacing-geometry)}
|
||||
[:& inspect-title-bar
|
||||
{:title (tr "inspect.attributes.size")
|
||||
:class (stl/css :title-spacing-geometry)}
|
||||
|
||||
(when (= (count shapes) 1)
|
||||
[:& copy-button {:data (css/get-shape-properties-css objects (first shapes) properties)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.components.title-bar :refer [inspect-title-bar]]
|
||||
[app.main.ui.viewer.inspect.attributes.common :as cmm]
|
||||
[app.util.code-gen.style-css :as css]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -52,10 +52,9 @@
|
|||
|
||||
(when (seq shapes)
|
||||
[:div {:class (stl/css :attributes-block)}
|
||||
[:& title-bar {:collapsable false
|
||||
:origin :inspect
|
||||
:title "Layout"
|
||||
:class (stl/css :title-spacing-layout)}
|
||||
[:& inspect-title-bar
|
||||
{:title "Layout"
|
||||
:class (stl/css :title-spacing-layout)}
|
||||
|
||||
(when (= (count shapes) 1)
|
||||
[:& copy-button {:data (css/get-shape-properties-css objects (first shapes) properties)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.components.title-bar :refer [inspect-title-bar]]
|
||||
[app.main.ui.viewer.inspect.attributes.common :refer [color-row]]
|
||||
[app.util.code-gen.style-css :as css]
|
||||
[app.util.i18n :refer [tr]]
|
||||
|
@ -53,10 +53,9 @@
|
|||
|
||||
(when (and (seq shapes) (> (count shapes) 0))
|
||||
[:div {:class (stl/css :attributes-block)}
|
||||
[:& title-bar {:collapsable false
|
||||
:origin :inspect
|
||||
:title (tr "inspect.attributes.shadow")
|
||||
:class (stl/css :title-spacing-shadow)}]
|
||||
[:& inspect-title-bar
|
||||
{:title (tr "inspect.attributes.shadow")
|
||||
:class (stl/css :title-spacing-shadow)}]
|
||||
|
||||
[:div {:class (stl/css :attributes-content)}
|
||||
(for [shape shapes]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.components.title-bar :refer [inspect-title-bar]]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.viewer.inspect.attributes.common :refer [color-row]]
|
||||
[app.util.code-gen.style-css-formats :as cssf]
|
||||
|
@ -61,10 +61,9 @@
|
|||
(let [shapes (->> shapes (filter has-stroke?))]
|
||||
(when (seq shapes)
|
||||
[:div {:class (stl/css :attributes-block)}
|
||||
[:& title-bar {:collapsable false
|
||||
:origin :inspect
|
||||
:title (tr "inspect.attributes.stroke")
|
||||
:class (stl/css :title-spacing-stroke)}]
|
||||
[:& inspect-title-bar
|
||||
{:title (tr "inspect.attributes.stroke")
|
||||
:class (stl/css :title-spacing-stroke)}]
|
||||
|
||||
[:div {:class (stl/css :attributes-content)}
|
||||
(for [shape shapes]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.components.title-bar :refer [inspect-title-bar]]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -53,8 +53,7 @@
|
|||
(let [shape (first shapes)]
|
||||
(when (seq (:svg-attrs shape))
|
||||
[:div {:class (stl/css :attributes-block)}
|
||||
[:& title-bar {:collapsable false
|
||||
:origin :inspect
|
||||
:title (tr "workspace.sidebar.options.svg-attrs.title")
|
||||
:class (stl/css :title-spacing-svg)}]
|
||||
[:& inspect-title-bar
|
||||
{:title (tr "workspace.sidebar.options.svg-attrs.title")
|
||||
:class (stl/css :title-spacing-svg)}]
|
||||
[:& svg-block {:shape shape}]])))
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.components.title-bar :refer [inspect-title-bar]]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.viewer.inspect.attributes.common :refer [color-row]]
|
||||
[app.util.i18n :refer [tr]]
|
||||
|
@ -190,10 +190,9 @@
|
|||
[{:keys [shapes]}]
|
||||
(when-let [shapes (seq (filter has-text? shapes))]
|
||||
[:div {:class (stl/css :attributes-block)}
|
||||
[:& title-bar {:collapsable false
|
||||
:origin :inspect
|
||||
:title (tr "inspect.attributes.typography")
|
||||
:class (stl/css :title-spacing-text)}]
|
||||
[:& inspect-title-bar
|
||||
{:title (tr "inspect.attributes.typography")
|
||||
:class (stl/css :title-spacing-text)}]
|
||||
|
||||
(for [shape shapes]
|
||||
[:& text-block {:shape shape
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
border: $s-1 solid var(--menu-border-color-disabled);
|
||||
margin-top: $s-4;
|
||||
.content {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
width: 100%;
|
||||
padding: $s-4 0;
|
||||
color: var(--color-foreground-secondary);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
[app.main.ui.components.code-block :refer [code-block]]
|
||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.hooks.resize :refer [use-resize-hook]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.shapes.text.fontfaces :refer [shapes->fonts]]
|
||||
|
@ -50,30 +49,16 @@
|
|||
</body>
|
||||
</html>")
|
||||
|
||||
(defn get-flex-elements [page-id shapes from]
|
||||
(let [ids (mapv :id shapes)
|
||||
ids (hooks/use-equal-memo ids)
|
||||
|
||||
get-layout-children-refs
|
||||
(mf/use-memo
|
||||
(mf/deps ids page-id from)
|
||||
#(if (= from :workspace)
|
||||
(refs/workspace-get-flex-child ids)
|
||||
(refs/get-flex-child-viewer ids page-id)))]
|
||||
|
||||
(mf/deref get-layout-children-refs)))
|
||||
|
||||
(defn get-objects [from]
|
||||
(defn- use-objects [from]
|
||||
(let [page-objects-ref
|
||||
(mf/use-memo
|
||||
(mf/deps from)
|
||||
(fn []
|
||||
(if (= from :workspace)
|
||||
refs/workspace-page-objects
|
||||
(refs/get-viewer-objects))))]
|
||||
(mf/with-memo [from]
|
||||
(if (= from :workspace)
|
||||
;; FIXME: fix naming consistency issues
|
||||
refs/workspace-page-objects
|
||||
(refs/get-viewer-objects)))]
|
||||
(mf/deref page-objects-ref)))
|
||||
|
||||
(defn shapes->images
|
||||
(defn- shapes->images
|
||||
[shapes]
|
||||
(->> shapes
|
||||
(keep
|
||||
|
@ -81,7 +66,7 @@
|
|||
(when-let [data (or (:metadata shape) (:fill-image shape) (-> shape :fills first :fill-image))]
|
||||
[(:id shape) (cfg/resolve-file-media data)])))))
|
||||
|
||||
(defn replace-map
|
||||
(defn- replace-map
|
||||
[value map]
|
||||
(reduce
|
||||
(fn [value [old new]]
|
||||
|
@ -104,35 +89,39 @@
|
|||
fontfaces-css* (mf/use-state nil)
|
||||
images-data* (mf/use-state nil)
|
||||
|
||||
collapsed* (mf/use-state #{})
|
||||
collapsed-css? (contains? @collapsed* :css)
|
||||
style-type (deref style-type*)
|
||||
markup-type (deref markup-type*)
|
||||
fontfaces-css (deref fontfaces-css*)
|
||||
images-data (deref images-data*)
|
||||
|
||||
collapsed* (mf/use-state #{})
|
||||
collapsed-css? (contains? @collapsed* :css)
|
||||
collapsed-markup? (contains? @collapsed* :markup)
|
||||
|
||||
style-type (deref style-type*)
|
||||
markup-type (deref markup-type*)
|
||||
fontfaces-css (deref fontfaces-css*)
|
||||
images-data (deref images-data*)
|
||||
objects (use-objects from)
|
||||
|
||||
shapes (->> shapes
|
||||
(map #(gsh/translate-to-frame % frame)))
|
||||
shapes
|
||||
(mf/with-memo [shapes frame]
|
||||
(mapv #(gsh/translate-to-frame % frame) shapes))
|
||||
|
||||
objects (get-objects from)
|
||||
all-children
|
||||
(mf/use-memo
|
||||
(mf/deps shapes objects)
|
||||
(fn []
|
||||
(->> shapes
|
||||
(map :id)
|
||||
(cfh/selected-with-children objects)
|
||||
(ctst/sort-z-index objects)
|
||||
(map (d/getf objects)))))
|
||||
|
||||
all-children (->> shapes
|
||||
(map :id)
|
||||
(cfh/selected-with-children objects)
|
||||
(ctst/sort-z-index objects)
|
||||
(map (d/getf objects)))
|
||||
fonts
|
||||
(mf/with-memo [all-children]
|
||||
(shapes->fonts all-children))
|
||||
|
||||
images-urls
|
||||
(mf/with-memo [all-children]
|
||||
(shapes->images all-children))
|
||||
|
||||
shapes (hooks/use-equal-memo shapes)
|
||||
all-children (hooks/use-equal-memo all-children)
|
||||
|
||||
fonts (-> (shapes->fonts all-children)
|
||||
(hooks/use-equal-memo))
|
||||
|
||||
images-urls (-> (shapes->images all-children)
|
||||
(hooks/use-equal-memo))
|
||||
style-code
|
||||
(mf/use-memo
|
||||
(mf/deps fontfaces-css style-type all-children cg/generate-style-code)
|
||||
|
@ -150,20 +139,28 @@
|
|||
(cb/format-code markup-type))))
|
||||
|
||||
on-markup-copied
|
||||
(mf/use-callback
|
||||
(mf/deps markup-type)
|
||||
(mf/use-fn
|
||||
(mf/deps markup-type from)
|
||||
(fn []
|
||||
(st/emit! (ptk/event ::ev/event
|
||||
{::ev/name "copy-inspect-code"
|
||||
:type markup-type}))))
|
||||
(let [origin (if (= :workspace from)
|
||||
"workspace"
|
||||
"viewer")]
|
||||
(st/emit! (ptk/event ::ev/event
|
||||
{::ev/name "copy-inspect-code"
|
||||
::ev/origin origin
|
||||
:type markup-type})))))
|
||||
|
||||
on-style-copied
|
||||
(mf/use-callback
|
||||
(mf/deps style-type)
|
||||
(mf/use-fn
|
||||
(mf/deps style-type from)
|
||||
(fn []
|
||||
(st/emit! (ptk/event ::ev/event
|
||||
{::ev/name "copy-inspect-style"
|
||||
:type style-type}))))
|
||||
(let [origin (if (= :workspace from)
|
||||
"workspace"
|
||||
"viewer")]
|
||||
(st/emit! (ptk/event ::ev/event
|
||||
{::ev/name "copy-inspect-style"
|
||||
::ev/origin origin
|
||||
:type style-type})))))
|
||||
|
||||
{on-markup-pointer-down :on-pointer-down
|
||||
on-markup-lost-pointer-capture :on-lost-pointer-capture
|
||||
|
@ -178,40 +175,50 @@
|
|||
(use-resize-hook :code 400 100 800 :y false :bottom)
|
||||
|
||||
;; set-style
|
||||
;; (mf/use-callback
|
||||
;; (mf/use-fn
|
||||
;; (fn [value]
|
||||
;; (reset! style-type* value)))
|
||||
|
||||
set-markup
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps markup-type*)
|
||||
(fn [value]
|
||||
(reset! markup-type* value)))
|
||||
|
||||
handle-copy-all-code
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps style-code markup-code images-data)
|
||||
(fn []
|
||||
(wapi/write-to-clipboard (gen-all-code style-code markup-code images-data))))
|
||||
|
||||
;;handle-open-review
|
||||
;;(mf/use-callback
|
||||
;;(mf/use-fn
|
||||
;; (fn []
|
||||
;; (st/emit! (dp/open-preview-selected))))
|
||||
|
||||
handle-collapse
|
||||
(mf/use-callback
|
||||
(fn [e]
|
||||
(let [panel-type (keyword (dom/get-data (dom/get-current-target e) "type"))]
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(let [panel-type (-> (dom/get-current-target event)
|
||||
(dom/get-data "type")
|
||||
(keyword))]
|
||||
(swap! collapsed*
|
||||
(fn [collapsed]
|
||||
(if (contains? collapsed panel-type)
|
||||
(disj collapsed panel-type)
|
||||
(conj collapsed panel-type)))))))]
|
||||
(conj collapsed panel-type)))))))
|
||||
copy-css-fn
|
||||
(mf/use-fn
|
||||
(mf/deps style-code images-data)
|
||||
#(replace-map style-code images-data))
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps fonts)
|
||||
#(->> (rx/from fonts)
|
||||
copy-html-fn
|
||||
(mf/use-fn
|
||||
(mf/deps markup-code images-data)
|
||||
#(replace-map markup-code images-data))]
|
||||
|
||||
(mf/with-effect [fonts]
|
||||
(->> (rx/from fonts)
|
||||
(rx/merge-map fonts/fetch-font-css)
|
||||
(rx/reduce conj [])
|
||||
(rx/subs!
|
||||
|
@ -219,9 +226,8 @@
|
|||
(let [css (str/join "\n" result)]
|
||||
(reset! fontfaces-css* css))))))
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps images-urls)
|
||||
#(->> (rx/from images-urls)
|
||||
(mf/with-effect [images-urls]
|
||||
(->> (rx/from images-urls)
|
||||
(rx/merge-map
|
||||
(fn [[_ uri]]
|
||||
(->> (http/fetch-data-uri uri true)
|
||||
|
@ -254,24 +260,24 @@
|
|||
|
||||
[:div {:class (stl/css :code-lang-option)}
|
||||
"CSS"]
|
||||
;; We will have a select when we have more than one option
|
||||
;; [:& select {:default-value style-type
|
||||
;; :class (stl/css :code-lang-select)
|
||||
;; :on-change set-style
|
||||
;; :options [{:label "CSS" :value "css"}]}]
|
||||
;; We will have a select when we have more than one option
|
||||
;; [:& select {:default-value style-type
|
||||
;; :class (stl/css :code-lang-select)
|
||||
;; :on-change set-style
|
||||
;; :options [{:label "CSS" :value "css"}]}]
|
||||
|
||||
[:div {:class (stl/css :action-btns)}
|
||||
[:button {:class (stl/css :expand-button)
|
||||
:on-click on-expand}
|
||||
i/code-refactor]
|
||||
|
||||
[:& copy-button {:data #(replace-map style-code images-data)
|
||||
[:& copy-button {:data copy-css-fn
|
||||
:class (stl/css :css-copy-btn)
|
||||
:on-copied on-style-copied}]]]
|
||||
|
||||
(when-not collapsed-css?
|
||||
[:div {:class (stl/css :code-row-display)
|
||||
:style #js {"--code-height" (str (or style-size 400) "px")}}
|
||||
:style {:--code-height (dm/str (or style-size 400) "px")}}
|
||||
[:& code-block {:type style-type
|
||||
:code style-code}]])
|
||||
|
||||
|
@ -306,13 +312,13 @@
|
|||
:on-click on-expand}
|
||||
i/code-refactor]
|
||||
|
||||
[:& copy-button {:data #(replace-map markup-code images-data)
|
||||
[:& copy-button {:data copy-html-fn
|
||||
:class (stl/css :html-copy-btn)
|
||||
:on-copied on-markup-copied}]]]
|
||||
|
||||
(when-not collapsed-markup?
|
||||
[:div {:class (stl/css :code-row-display)
|
||||
:style #js {"--code-height" (str (or markup-size 400) "px")}}
|
||||
:style {:--code-height (dm/str (or markup-size 400) "px")}}
|
||||
[:& code-block {:type markup-type
|
||||
:code markup-code}]])
|
||||
|
||||
|
|
|
@ -40,16 +40,16 @@
|
|||
|
||||
(mf/defc right-sidebar
|
||||
[{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
|
||||
:or {from :inspect}}]
|
||||
(let [section (mf/use-state :info #_:code)
|
||||
objects (or objects (:objects page))
|
||||
shapes (or shapes
|
||||
(resolve-shapes objects selected))
|
||||
first-shape (first shapes)
|
||||
page-id (or page-id (:id page))
|
||||
file-id (or file-id (:id file))
|
||||
:or {from :viewer}}]
|
||||
(let [section (mf/use-state :info #_:code)
|
||||
objects (or objects (:objects page))
|
||||
shapes (or shapes
|
||||
(resolve-shapes objects selected))
|
||||
first-shape (first shapes)
|
||||
page-id (or page-id (:id page))
|
||||
file-id (or file-id (:id file))
|
||||
|
||||
libraries (get-libraries from)
|
||||
libraries (get-libraries from)
|
||||
|
||||
file (mf/deref refs/viewer-file)
|
||||
components-v2 (dm/get-in file [:data :options :components-v2])
|
||||
|
@ -83,7 +83,7 @@
|
|||
(handle-change-tab :info))))
|
||||
|
||||
[:aside {:class (stl/css-case :settings-bar-right true
|
||||
:viewer-code (= from :inspect))}
|
||||
:viewer-code (= from :viewer))}
|
||||
(if (seq shapes)
|
||||
[:div {:class (stl/css :tool-windows)}
|
||||
[:div {:class (stl/css :shape-row)}
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
}
|
||||
|
||||
.layer-title {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include text-ellipsis;
|
||||
height: $s-32;
|
||||
padding: $s-8 0;
|
||||
|
@ -79,7 +79,7 @@
|
|||
}
|
||||
|
||||
.placeholder-label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
text-align: center;
|
||||
width: $s-200;
|
||||
color: var(--empty-message-foreground-color);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
@use "common/refactor/common-refactor.scss" as *;
|
||||
|
||||
.view-options {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
@ -19,7 +19,7 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
.dropdown-title {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
flex-grow: 1;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
|
@ -35,10 +35,13 @@
|
|||
top: calc($s-2 + $s-48);
|
||||
width: $s-272;
|
||||
padding: $s-6;
|
||||
max-height: calc(100vh - 3 * ($s-2 + $s-48));
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.dropdown-element {
|
||||
@extend .dropdown-element-base;
|
||||
min-height: $s-32;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: 100%;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
.modal-content {
|
||||
@include flexColumn;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
gap: $s-24;
|
||||
max-height: $s-400;
|
||||
width: $s-368;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
}
|
||||
|
||||
.modal-content {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include flexColumn;
|
||||
gap: $s-24;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@
|
|||
}
|
||||
|
||||
.description {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--modal-text-foreground-color);
|
||||
margin-bottom: $s-24;
|
||||
}
|
||||
|
@ -181,7 +181,7 @@
|
|||
}
|
||||
.count-pages,
|
||||
.current-tag {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--input-foreground-color);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
}
|
||||
|
||||
.counter {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--viewer-thumbnails-control-foreground-color);
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@
|
|||
}
|
||||
|
||||
.thumbnail-info {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
text-align: center;
|
||||
color: var(--viewer-thumbnails-control-foreground-color);
|
||||
|
|
|
@ -97,6 +97,6 @@
|
|||
}
|
||||
|
||||
.color-palette-empty {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--palette-text-color);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
.option-wrapper {
|
||||
width: 100%;
|
||||
.library-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--context-menu-foreground-color);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr $s-24;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.config :as cfg]
|
||||
[app.main.data.events :as-alias ev]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
|
@ -32,6 +33,7 @@
|
|||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[potok.v2.core :as ptk]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
;; --- Refs
|
||||
|
@ -103,11 +105,16 @@
|
|||
(mf/use-fn
|
||||
(mf/deps current-color)
|
||||
(fn []
|
||||
(let [keep-aspect-ratio? (-> current-color :image :keep-aspect-ratio not)]
|
||||
(st/emit! (dc/update-colorpicker-color
|
||||
{:image (-> (:image current-color)
|
||||
(assoc :keep-aspect-ratio keep-aspect-ratio?))}
|
||||
true)))))
|
||||
(let [keep-aspect-ratio? (-> current-color :image :keep-aspect-ratio not)
|
||||
image (-> (:image current-color)
|
||||
(assoc :keep-aspect-ratio keep-aspect-ratio?))]
|
||||
|
||||
|
||||
(st/emit!
|
||||
(dc/update-colorpicker-color {:image image} true)
|
||||
(ptk/data-event ::ev/event {::ev/name "toggle-image-aspect-ratio"
|
||||
::ev/origin "workspace:colorpicker"
|
||||
:checked keep-aspect-ratio?})))))
|
||||
|
||||
on-change-tab
|
||||
(mf/use-fn
|
||||
|
@ -279,7 +286,8 @@
|
|||
[:label {:for "keep-aspect-ratio"
|
||||
:class (stl/css-case :global/checked keep-aspect-ratio?)}
|
||||
[:span {:class (stl/css-case :global/checked keep-aspect-ratio?)}
|
||||
(when keep-aspect-ratio? i/status-tick-refactor)]
|
||||
(when keep-aspect-ratio?
|
||||
i/status-tick-refactor)]
|
||||
(tr "media.keep-aspect-ratio")
|
||||
[:input {:type "checkbox"
|
||||
:id "keep-aspect-ratio"
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
}
|
||||
}
|
||||
.label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
}
|
||||
&:hover {
|
||||
.icon svg {
|
||||
|
@ -164,7 +164,7 @@
|
|||
}
|
||||
|
||||
.placeholder-label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
text-align: center;
|
||||
width: $s-184;
|
||||
color: var(--empty-message-foreground-color);
|
||||
|
|
|
@ -48,9 +48,11 @@
|
|||
(dom/stop-propagation event))
|
||||
|
||||
(mf/defc menu-entry
|
||||
[{:keys [title shortcut on-click on-pointer-enter on-pointer-leave on-unmount children selected? icon disabled] :as props}]
|
||||
{::mf/props :obj}
|
||||
[{:keys [title shortcut on-click on-pointer-enter on-pointer-leave
|
||||
on-unmount children selected? icon disabled value]}]
|
||||
(let [submenu-ref (mf/use-ref nil)
|
||||
hovering? (mf/use-ref false)
|
||||
hovering? (mf/use-ref false)
|
||||
on-pointer-enter
|
||||
(mf/use-callback
|
||||
(fn []
|
||||
|
@ -86,6 +88,7 @@
|
|||
(if icon
|
||||
[:li {:class (stl/css :icon-menu-item)
|
||||
:disabled disabled
|
||||
:data-value value
|
||||
:ref set-dom-node
|
||||
:on-click on-click
|
||||
:on-pointer-enter on-pointer-enter
|
||||
|
@ -100,6 +103,7 @@
|
|||
[:li {:class (stl/css :context-menu-item)
|
||||
:disabled disabled
|
||||
:ref set-dom-node
|
||||
:data-value value
|
||||
:on-click on-click
|
||||
:on-pointer-enter on-pointer-enter
|
||||
:on-pointer-leave on-pointer-leave}
|
||||
|
@ -383,39 +387,56 @@
|
|||
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.flow-start")
|
||||
:on-click do-add-flow}])))))
|
||||
(mf/defc context-menu-flex
|
||||
|
||||
(mf/defc context-menu-layout
|
||||
{::mf/props :obj}
|
||||
[{:keys [shapes]}]
|
||||
(let [single? (= (count shapes) 1)
|
||||
has-frame? (->> shapes (d/seek cfh/frame-shape?))
|
||||
is-flex-container? (and single? has-frame? (= :flex (:layout (first shapes))))
|
||||
ids (->> shapes (map :id))
|
||||
(let [single? (= (count shapes) 1)
|
||||
|
||||
add-layout
|
||||
(fn [type]
|
||||
(if (and single? has-frame?)
|
||||
(st/emit! (dwsl/create-layout-from-id (first ids) type true))
|
||||
(st/emit! (dwsl/create-layout-from-selection type))))
|
||||
has-flex?
|
||||
(and single? (every? ctl/flex-layout? shapes))
|
||||
|
||||
remove-flex
|
||||
(fn []
|
||||
(st/emit! (dwsl/remove-layout ids)))]
|
||||
has-grid?
|
||||
(and single? (every? ctl/grid-layout? shapes))
|
||||
|
||||
[:*
|
||||
(when (not is-flex-container?)
|
||||
[:div
|
||||
[:& menu-separator]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.add-flex")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-flex)
|
||||
:on-click #(add-layout :flex)}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.add-grid")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-grid)
|
||||
:on-click #(add-layout :grid)}]])
|
||||
(when is-flex-container?
|
||||
[:div
|
||||
[:& menu-separator]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.remove-flex")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-flex)
|
||||
:on-click remove-flex}]])]))
|
||||
on-add-layout
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(let [type (-> (dom/get-current-target event)
|
||||
(dom/get-data "value")
|
||||
(keyword))]
|
||||
(st/emit! (with-meta (dwsl/create-layout type)
|
||||
{::ev/origin "workspace:context-menu"})))))
|
||||
|
||||
on-remove-layout
|
||||
(mf/use-fn
|
||||
(mf/deps shapes)
|
||||
(fn [_event]
|
||||
(let [ids (map :id shapes)]
|
||||
(st/emit! (dwsl/remove-layout ids)))))]
|
||||
|
||||
(if (or ^boolean has-flex?
|
||||
^boolean has-grid?)
|
||||
[:div
|
||||
[:& menu-separator]
|
||||
(if has-flex?
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.remove-flex")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-flex)
|
||||
:on-click on-remove-layout}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.remove-grid")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-grid)
|
||||
:on-click on-remove-layout}])]
|
||||
|
||||
[:div
|
||||
[:& menu-separator]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.add-flex")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-flex)
|
||||
:value "flex"
|
||||
:on-click on-add-layout}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.add-grid")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-grid)
|
||||
:value "grid"
|
||||
:on-click on-add-layout}]])))
|
||||
|
||||
(mf/defc context-menu-component
|
||||
[{:keys [shapes]}]
|
||||
|
@ -476,7 +497,7 @@
|
|||
[:> context-menu-path props]
|
||||
[:> context-menu-layer-options props]
|
||||
[:> context-menu-prototype props]
|
||||
[:> context-menu-flex props]
|
||||
[:> context-menu-layout props]
|
||||
[:> context-menu-component props]
|
||||
[:> context-menu-delete props]])))
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
cursor: pointer;
|
||||
|
||||
.title {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--menu-foreground-color);
|
||||
}
|
||||
.shortcut {
|
||||
|
@ -45,7 +45,7 @@
|
|||
gap: $s-2;
|
||||
color: var(--menu-shortcut-foreground-color);
|
||||
.shortcut-key {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include flexCenter;
|
||||
height: $s-20;
|
||||
padding: $s-2 $s-6;
|
||||
|
|
|
@ -184,7 +184,7 @@
|
|||
(tr "workspace.header.menu.disable-scale-content")
|
||||
(tr "workspace.header.menu.enable-scale-content"))]
|
||||
[:span {:class (stl/css :shortcut)}
|
||||
(for [sc (scd/split-sc (sc/get-tooltip :toggle-scale-text))]
|
||||
(for [sc (scd/split-sc (sc/get-tooltip :scale))]
|
||||
[:span {:class (stl/css :shortcut-key) :key sc} sc])]]
|
||||
|
||||
[:> dropdown-menu-item* {:on-click toggle-flag
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
width: $s-48;
|
||||
border-radius: $br-8;
|
||||
.label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
height: 100%;
|
||||
padding: $s-8 0;
|
||||
color: var(--button-tertiary-foreground-color-rest);
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
[app.main.ui.workspace.sidebar.sitemap :refer [sitemap]]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[app.util.object :as obj]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
;; --- Left Sidebar (Component)
|
||||
|
@ -157,10 +156,9 @@
|
|||
(set-size (if (> size 276) 276 768))))
|
||||
|
||||
props
|
||||
(-> props
|
||||
(obj/clone)
|
||||
(obj/set! "on-change-section" handle-change-section)
|
||||
(obj/set! "on-expand" handle-expand))]
|
||||
(mf/spread props
|
||||
:on-change-section handle-change-section
|
||||
:on-expand handle-expand)]
|
||||
|
||||
[:& (mf/provider muc/sidebar) {:value :right}
|
||||
[:aside {:class (stl/css-case :right-settings-bar true
|
||||
|
@ -186,7 +184,7 @@
|
|||
[:& comments-sidebar]
|
||||
|
||||
(true? is-history?)
|
||||
[:& history-toolbox]
|
||||
[:> history-toolbox {}]
|
||||
|
||||
:else
|
||||
[:> options-toolbox props])]]]))
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
}
|
||||
|
||||
.section-item {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
border: $s-1 solid var(--input-border-color-focus);
|
||||
input.element-name {
|
||||
@include textEllipsis;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include removeInputStyle;
|
||||
flex-grow: 1;
|
||||
height: $s-28;
|
||||
|
@ -67,7 +67,7 @@
|
|||
}
|
||||
|
||||
.name-block {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
margin: 0;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
cursor: pointer;
|
||||
|
||||
.cell-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
display: none;
|
||||
position: absolute;
|
||||
|
@ -44,7 +44,7 @@
|
|||
color: var(--assets-item-name-foreground-color);
|
||||
input {
|
||||
@include textEllipsis;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include removeInputStyle;
|
||||
height: auto;
|
||||
padding: 0;
|
||||
|
@ -132,13 +132,13 @@
|
|||
}
|
||||
|
||||
.item-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
order: 2;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
input {
|
||||
@include textEllipsis;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include removeInputStyle;
|
||||
height: $s-32;
|
||||
padding: $s-4;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
}
|
||||
|
||||
.file-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
@ -71,6 +71,6 @@
|
|||
}
|
||||
|
||||
.no-found-text {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--not-found-foreground-color);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
height: 10vh;
|
||||
}
|
||||
.cell-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
display: none;
|
||||
position: absolute;
|
||||
|
@ -110,7 +110,7 @@
|
|||
}
|
||||
|
||||
.item-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
padding-left: $s-8;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
}
|
||||
|
||||
.modal-content {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin-bottom: $s-24;
|
||||
}
|
||||
.input-wrapper {
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [t] :as i18n]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
|
@ -283,8 +285,18 @@
|
|||
nil)]))
|
||||
|
||||
(mf/defc history-entry [{:keys [locale entry idx-entry disabled? current?]}]
|
||||
{::mf/props :obj}
|
||||
(let [hover? (mf/use-state false)
|
||||
show-detail? (mf/use-state false)]
|
||||
show-detail? (mf/use-state false)
|
||||
toggle-show-detail
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(let [has-entry? (-> (dom/get-current-target event)
|
||||
(dom/get-data "has-entry")
|
||||
(parse-boolean))]
|
||||
(dom/stop-propagation event)
|
||||
(when has-entry?
|
||||
(swap! show-detail? not)))))]
|
||||
[:div {:class (stl/css-case :history-entry true
|
||||
:disabled disabled?
|
||||
:current current?
|
||||
|
@ -301,8 +313,8 @@
|
|||
(when (:detail entry)
|
||||
[:div {:class (stl/css-case :history-entry-summary-button true
|
||||
:button-opened @show-detail?)
|
||||
:on-click #(when (:detail entry)
|
||||
(swap! show-detail? not))}
|
||||
:on-click toggle-show-detail
|
||||
:data-has-entry (dm/str (not (nil? (:detail entry))))}
|
||||
i/arrow-refactor])]
|
||||
|
||||
(when @show-detail?
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
}
|
||||
|
||||
.history-entry-empty-msg {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--empty-message-foreground-color);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
.element-name {
|
||||
@include textEllipsis;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
flex-grow: 1;
|
||||
color: var(--context-hover-color, var(--layer-row-foreground-color));
|
||||
&.selected {
|
||||
|
@ -27,7 +27,7 @@
|
|||
}
|
||||
.element-name-input {
|
||||
@include textEllipsis;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include removeInputStyle;
|
||||
flex-grow: 1;
|
||||
height: $s-28;
|
||||
|
|
|
@ -108,7 +108,7 @@
|
|||
}
|
||||
|
||||
.focus-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
@ -124,7 +124,7 @@
|
|||
|
||||
.focus-mode-tag {
|
||||
@include flexCenter;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
height: $s-20;
|
||||
padding: $s-4 $s-6;
|
||||
border: $s-1 solid var(--tag-background-color);
|
||||
|
@ -160,7 +160,7 @@
|
|||
|
||||
.layer-filter-name {
|
||||
@include flexCenter;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--pill-foreground-color);
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@
|
|||
left: $s-20;
|
||||
width: $s-192;
|
||||
.filter-menu-item {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
[app.main.ui.workspace.sidebar.options.shapes.svg-raw :as svg-raw]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.text :as text]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.object :as obj]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
;; --- Options
|
||||
|
@ -75,7 +74,8 @@
|
|||
|
||||
|
||||
(mf/defc options-content
|
||||
{::mf/wrap [mf/memo]}
|
||||
{::mf/memo true
|
||||
::mf/props :obj}
|
||||
[{:keys [selected section shapes shapes-with-children page-id file-id on-change-section on-expand]}]
|
||||
(let [drawing (mf/deref refs/workspace-drawing)
|
||||
objects (mf/deref refs/workspace-page-objects)
|
||||
|
@ -104,7 +104,9 @@
|
|||
{:on-change-tab on-change-tab
|
||||
:selected section
|
||||
:collapsable false
|
||||
:content-class (stl/css-case :content-class true :inspect (= section :inspect))
|
||||
: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")}
|
||||
|
@ -172,14 +174,10 @@
|
|||
;; need on multiple selection in majority of cases
|
||||
|
||||
(mf/defc options-toolbox
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
[props]
|
||||
(let [section (obj/get props "section")
|
||||
selected (obj/get props "selected")
|
||||
on-change-section (obj/get props "on-change-section")
|
||||
on-expand (obj/get props "on-expand")
|
||||
page-id (mf/use-ctx ctx/current-page-id)
|
||||
{::mf/memo true
|
||||
::mf/props :obj}
|
||||
[{:keys [section selected on-change-section on-expand]}]
|
||||
(let [page-id (mf/use-ctx ctx/current-page-id)
|
||||
file-id (mf/use-ctx ctx/current-file-id)
|
||||
shapes (mf/deref refs/selected-objects)
|
||||
shapes-with-children (mf/deref refs/selected-shapes-with-children)]
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
}
|
||||
}
|
||||
.label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.ui.workspace.sidebar.options.menus.component
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.types.component :as ctk]
|
||||
|
@ -31,152 +32,199 @@
|
|||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.timers :as tm]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def ref:annotations-state
|
||||
(l/derived :workspace-annotations st/state))
|
||||
|
||||
(mf/defc component-annotation
|
||||
[{:keys [id shape component] :as props}]
|
||||
(let [main-instance? (:main-instance shape)
|
||||
component-id (:component-id shape)
|
||||
annotation (:annotation component)
|
||||
editing? (mf/use-state false)
|
||||
invalid-text? (mf/use-state (or (nil? annotation) (str/blank? annotation)))
|
||||
size (mf/use-state (count annotation))
|
||||
textarea-ref (mf/use-ref)
|
||||
{::mf/props :obj}
|
||||
[{:keys [id shape component]}]
|
||||
(let [main-instance? (:main-instance shape)
|
||||
component-id (:component-id shape)
|
||||
annotation (:annotation component)
|
||||
shape-id (:id shape)
|
||||
|
||||
;; hack to create an autogrowing textarea
|
||||
;; based on https://css-tricks.com/the-cleanest-trick-for-autogrowing-textareas/
|
||||
autogrow #(let [textarea (mf/ref-val textarea-ref)
|
||||
text (when textarea (.-value textarea))]
|
||||
(reset! invalid-text? (str/blank? text))
|
||||
(when textarea
|
||||
(reset! size (count text))
|
||||
(aset (.-dataset (.-parentNode textarea)) "replicatedValue" text)))
|
||||
initialize #(let [textarea (mf/ref-val textarea-ref)]
|
||||
(when textarea
|
||||
(aset textarea "value" annotation)
|
||||
(autogrow)))
|
||||
editing* (mf/use-state false)
|
||||
editing? (deref editing*)
|
||||
|
||||
discard (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [textarea (mf/ref-val textarea-ref)]
|
||||
(aset textarea "value" annotation)
|
||||
(reset! editing? false)
|
||||
(st/emit! (dw/set-annotations-id-for-create nil))
|
||||
(autogrow)))
|
||||
save (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [textarea (mf/ref-val textarea-ref)
|
||||
text (.-value textarea)]
|
||||
(when-not (str/blank? text)
|
||||
(reset! editing? false)
|
||||
(st/emit!
|
||||
(dw/set-annotations-id-for-create nil)
|
||||
(dw/update-component-annotation component-id text)))))
|
||||
workspace-annotations (mf/deref refs/workspace-annotations)
|
||||
annotations-expanded? (:expanded? workspace-annotations)
|
||||
creating? (= id (:id-for-create workspace-annotations))
|
||||
invalid-text* (mf/use-state #(str/blank? annotation))
|
||||
invalid-text? (deref invalid-text*)
|
||||
|
||||
expand #(when-not (or @editing? creating?)
|
||||
(st/emit! (dw/set-annotations-expanded %)))
|
||||
edit (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when main-instance?
|
||||
(let [textarea (mf/ref-val textarea-ref)]
|
||||
(reset! editing? true)
|
||||
(dom/focus! textarea))))
|
||||
on-delete-annotation
|
||||
(mf/use-callback
|
||||
(mf/deps (:id shape))
|
||||
size* (mf/use-state #(count annotation))
|
||||
size (deref size*)
|
||||
|
||||
textarea-ref (mf/use-ref)
|
||||
|
||||
state (mf/deref ref:annotations-state)
|
||||
expanded? (:expanded state)
|
||||
create-id (:id-for-create state)
|
||||
creating? (= id create-id)
|
||||
|
||||
;; hack to create an autogrowing textarea based on
|
||||
;; https://css-tricks.com/the-cleanest-trick-for-autogrowing-textareas/
|
||||
adjust-textarea-size
|
||||
(mf/use-fn
|
||||
#(when-let [textarea (mf/ref-val textarea-ref)]
|
||||
(let [text (dom/get-value textarea)]
|
||||
(reset! invalid-text* (str/blank? text))
|
||||
(reset! size* (count text))
|
||||
(let [^js parent (.-parentNode textarea)
|
||||
^js dataset (.-dataset parent)]
|
||||
(set! (.-replicatedValue dataset) text)))))
|
||||
|
||||
on-toggle-expand
|
||||
(mf/use-fn
|
||||
(mf/deps expanded? editing? creating?)
|
||||
(fn [_]
|
||||
(st/emit! (dw/set-annotations-expanded (not expanded?)))))
|
||||
|
||||
on-discard
|
||||
(mf/use-fn
|
||||
(mf/deps adjust-textarea-size creating?)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:title (tr "modals.delete-component-annotation.title")
|
||||
:message (tr "modals.delete-component-annotation.message")
|
||||
:accept-label (tr "ds.confirm-ok")
|
||||
:on-accept (fn []
|
||||
(st/emit!
|
||||
(dw/set-annotations-id-for-create nil)
|
||||
(dw/update-component-annotation component-id nil)))}))))]
|
||||
(when-let [textarea (mf/ref-val textarea-ref)]
|
||||
(dom/set-value! textarea annotation)
|
||||
(reset! editing* false)
|
||||
(when creating?
|
||||
(st/emit! (dw/set-annotations-id-for-create nil)))
|
||||
(adjust-textarea-size))))
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps (:id shape))
|
||||
(fn []
|
||||
(initialize)
|
||||
(when (and (not creating?) (:id-for-create workspace-annotations)) ;; cleanup set-annotations-id-for-create if we aren't on the marked component
|
||||
(st/emit! (dw/set-annotations-id-for-create nil)))
|
||||
(fn [] (st/emit! (dw/set-annotations-id-for-create nil))))) ;; cleanup set-annotationsid-for-create on unload
|
||||
on-edit
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when ^boolean main-instance?
|
||||
(when-let [textarea (mf/ref-val textarea-ref)]
|
||||
(reset! editing* true)
|
||||
(dom/focus! textarea)))))
|
||||
|
||||
on-save
|
||||
(mf/use-fn
|
||||
(mf/deps creating?)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when-let [textarea (mf/ref-val textarea-ref)]
|
||||
(let [text (dom/get-value textarea)]
|
||||
(when-not (str/blank? text)
|
||||
(reset! editing* false)
|
||||
(when ^boolean creating?
|
||||
(st/emit! (dw/set-annotations-id-for-create nil)))
|
||||
(dw/update-component-annotation component-id text))))))
|
||||
|
||||
on-delete-annotation
|
||||
(mf/use-fn
|
||||
(mf/deps shape-id component-id creating?)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [on-accept (fn []
|
||||
(st/emit!
|
||||
;; (ptk/data-event {::ev/name "delete-component-annotation"})
|
||||
(when creating?
|
||||
(dw/set-annotations-id-for-create nil))
|
||||
(dw/update-component-annotation component-id nil)))]
|
||||
(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:title (tr "modals.delete-component-annotation.title")
|
||||
:message (tr "modals.delete-component-annotation.message")
|
||||
:accept-label (tr "ds.confirm-ok")
|
||||
:on-accept on-accept})))))]
|
||||
|
||||
(mf/with-effect [shape-id state create-id creating?]
|
||||
(when-let [textarea (mf/ref-val textarea-ref)]
|
||||
(dom/set-value! textarea annotation)
|
||||
(adjust-textarea-size))
|
||||
|
||||
;; cleanup set-annotations-id-for-create if we aren't on the marked component
|
||||
(when (and (not creating?) (some? create-id))
|
||||
(st/emit! (dw/set-annotations-id-for-create nil)))
|
||||
|
||||
;; cleanup set-annotationsid-for-create on unload
|
||||
(fn []
|
||||
(when creating?
|
||||
(st/emit! (dw/set-annotations-id-for-create nil)))))
|
||||
|
||||
(when (or creating? annotation)
|
||||
[:div {:class (stl/css-case :component-annotation true
|
||||
:editing @editing?
|
||||
:creating creating?)}
|
||||
[:div {:class (stl/css-case :annotation-title true
|
||||
:expandeable (not (or @editing? creating?))
|
||||
:expanded annotations-expanded?)
|
||||
:on-click #(expand (not annotations-expanded?))}
|
||||
[:div {:class (stl/css-case
|
||||
:component-annotation true
|
||||
:editing editing?
|
||||
:creating creating?)}
|
||||
[:div {:class (stl/css-case
|
||||
:annotation-title true
|
||||
:expandeable (not (or editing? creating?))
|
||||
:expanded expanded?)
|
||||
:on-click on-toggle-expand}
|
||||
|
||||
(if (or @editing? creating?)
|
||||
(if (or editing? creating?)
|
||||
[:span {:class (stl/css :annotation-text)}
|
||||
(if @editing?
|
||||
(if editing?
|
||||
(tr "workspace.options.component.edit-annotation")
|
||||
(tr "workspace.options.component.create-annotation"))]
|
||||
|
||||
[:*
|
||||
[:span {:class (stl/css-case :icon-arrow true
|
||||
:expanded annotations-expanded?)}
|
||||
[:span {:class (stl/css-case
|
||||
:icon-arrow true
|
||||
:expanded expanded?)}
|
||||
i/arrow-refactor]
|
||||
[:span {:class (stl/css :annotation-text)}
|
||||
(tr "workspace.options.component.annotation")]])
|
||||
|
||||
[:div {:class (stl/css :icons-wrapper)}
|
||||
(when (and main-instance? annotations-expanded?)
|
||||
(if (or @editing? creating?)
|
||||
(when (and ^boolean main-instance?
|
||||
^boolean expanded?)
|
||||
(if (or ^boolean editing?
|
||||
^boolean creating?)
|
||||
[:*
|
||||
[:div {:title (if creating? (tr "labels.create") (tr "labels.save"))
|
||||
:on-click save
|
||||
:class (stl/css-case :icon true
|
||||
:icon-tick true
|
||||
:hidden @invalid-text?)}
|
||||
[:div {:title (if ^boolean creating?
|
||||
(tr "labels.create")
|
||||
(tr "labels.save"))
|
||||
:on-click on-save
|
||||
:class (stl/css-case
|
||||
:icon true
|
||||
:icon-tick true
|
||||
:hidden invalid-text?)}
|
||||
i/tick-refactor]
|
||||
[:div {:class (stl/css :icon :icon-cross)
|
||||
:title (tr "labels.discard")
|
||||
:on-click discard}
|
||||
:on-click on-discard}
|
||||
i/close-refactor]]
|
||||
|
||||
[:*
|
||||
[:div {:class (stl/css :icon :icon-edit)
|
||||
:title (tr "labels.edit")
|
||||
:on-click edit}
|
||||
:on-click on-edit}
|
||||
i/curve-refactor]
|
||||
[:div {:class (stl/css :icon :icon-trash)
|
||||
:title (tr "labels.delete")
|
||||
:on-click on-delete-annotation}
|
||||
i/delete-refactor]]))]]
|
||||
|
||||
[:div {:class (stl/css-case :hidden (not annotations-expanded?))}
|
||||
[:div {:class (stl/css-case :hidden (not expanded?))}
|
||||
[:div {:class (stl/css :grow-wrap)}
|
||||
[:div {:class (stl/css :texarea-copy)}]
|
||||
[:textarea
|
||||
{:ref textarea-ref
|
||||
:id "annotation-textarea"
|
||||
:data-debug annotation
|
||||
:auto-focus (or @editing? creating?)
|
||||
:auto-focus (or editing? creating?)
|
||||
:maxLength 300
|
||||
:on-input autogrow
|
||||
:on-input adjust-textarea-size
|
||||
:default-value annotation
|
||||
:read-only (not (or creating? @editing?))}]]
|
||||
(when (or @editing? creating?)
|
||||
[:div {:class (stl/css :counter)} (str @size "/300")])]])))
|
||||
:read-only (not (or creating? editing?))}]]
|
||||
(when (or editing? creating?)
|
||||
[:div {:class (stl/css :counter)} (str size "/300")])]])))
|
||||
|
||||
(mf/defc component-swap-item
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [item loop shapes file-id root-shape container component-id is-search listing-thumbs] :as props}]
|
||||
(let [on-select-component
|
||||
{::mf/props :obj}
|
||||
[{:keys [item loop shapes file-id root-shape container component-id is-search listing-thumbs]}]
|
||||
(let [on-select
|
||||
(mf/use-fn
|
||||
(mf/deps shapes file-id item)
|
||||
#(when-not loop
|
||||
(st/emit! (dwl/component-multi-swap shapes file-id (:id item)))))
|
||||
|
||||
item-ref (mf/use-ref)
|
||||
visible? (h/use-visible item-ref :once? true)]
|
||||
[:div {:ref item-ref
|
||||
|
@ -186,7 +234,7 @@
|
|||
:selected (= (:id item) component-id)
|
||||
:disabled loop)
|
||||
:key (str "swap-item-" (:id item))
|
||||
:on-click on-select-component}
|
||||
:on-click on-select}
|
||||
(when visible?
|
||||
[:& cmm/component-item-thumbnail {:file-id (:file-id item)
|
||||
:root-shape root-shape
|
||||
|
@ -197,12 +245,13 @@
|
|||
(if is-search (:full-name item) (:name item))]]))
|
||||
|
||||
(mf/defc component-group-item
|
||||
[{:keys [item on-enter-group] :as props}]
|
||||
{::mf/props :obj}
|
||||
[{:keys [item on-enter-group]}]
|
||||
(let [group-name (:name item)
|
||||
path (cfh/butlast-path-with-dots group-name)
|
||||
on-group-click #(on-enter-group group-name)]
|
||||
[:div {:class (stl/css :component-group)
|
||||
:key (uuid/next) :on-click on-group-click
|
||||
:on-click on-group-click
|
||||
:title group-name}
|
||||
|
||||
[:div {:class (stl/css :path-wrapper)}
|
||||
|
@ -215,43 +264,75 @@
|
|||
[:span {:class (stl/css :arrow-icon)}
|
||||
i/arrow-refactor]]))
|
||||
|
||||
(def ^:private ref:swap-libraries
|
||||
(letfn [(get-libraries [state]
|
||||
(let [file (:workspace-file state)
|
||||
data (:workspace-data state)
|
||||
libs (:workspace-libraries state)]
|
||||
(assoc libs (:id file)
|
||||
(assoc file :data data))))]
|
||||
(l/derived get-libraries st/state)))
|
||||
|
||||
|
||||
(defn- find-common-path
|
||||
([components]
|
||||
(let [paths (map (comp cfh/last-path :path) components)]
|
||||
(find-common-path paths [] 0)))
|
||||
([paths path n]
|
||||
(let [current (nth (first paths) n nil)]
|
||||
(if (or (nil? current)
|
||||
(not (every? #(= current (nth % n nil)) paths)))
|
||||
path
|
||||
(find-common-path paths (conj path current) (inc n))))))
|
||||
|
||||
(defn- same-component-file?
|
||||
[shape-a shape-b]
|
||||
(= (:component-file shape-a)
|
||||
(:component-file shape-b)))
|
||||
|
||||
(defn- same-component?
|
||||
[shape-a shape-b]
|
||||
(= (:component-id shape-a)
|
||||
(:component-id shape-b)))
|
||||
|
||||
;; Get the ids of the components and its root-shapes that are parents of the current shape, to avoid loops
|
||||
(defn get-parent-component-ids
|
||||
[objects shape ids]
|
||||
(let [shape-id (:id shape)]
|
||||
(if (uuid/zero? shape-id)
|
||||
ids
|
||||
(let [ids (if (ctk/instance-head? shape)
|
||||
(conj ids shape-id (:component-id shape))
|
||||
ids)]
|
||||
(get-parent-component-ids objects (get objects (:parent-id shape)) ids)))))
|
||||
|
||||
(mf/defc component-swap
|
||||
[{:keys [shapes] :as props}]
|
||||
{::mf/props :obj}
|
||||
[{:keys [shapes]}]
|
||||
(let [single? (= 1 (count shapes))
|
||||
shape (first shapes)
|
||||
current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
workspace-file (mf/deref refs/workspace-file)
|
||||
workspace-data (mf/deref refs/workspace-data)
|
||||
workspace-libraries (mf/deref refs/workspace-libraries)
|
||||
libraries (mf/deref ref:swap-libraries)
|
||||
objects (mf/deref refs/workspace-page-objects)
|
||||
libraries (assoc workspace-libraries current-file-id (assoc workspace-file :data workspace-data))
|
||||
single-comp (ctf/get-component libraries (:component-file shape) (:component-id shape))
|
||||
every-same-file? (every? #(= (:component-file shape) (:component-file %)) shapes)
|
||||
current-comp-id (when (every? #(= (:component-id shape) (:component-id %)) shapes)
|
||||
(:component-id shape))
|
||||
|
||||
^boolean
|
||||
every-same-file? (every? (partial same-component-file? shape) shapes)
|
||||
|
||||
component-id (if (every? (partial same-component? shape) shapes)
|
||||
(:component-id shape)
|
||||
nil)
|
||||
|
||||
file-id (if every-same-file?
|
||||
(:component-file shape)
|
||||
current-file-id)
|
||||
|
||||
orig-components (map #(ctf/get-component libraries (:component-file %) (:component-id %)) shapes)
|
||||
|
||||
paths (->> orig-components
|
||||
(map :path)
|
||||
(map cfh/split-path))
|
||||
|
||||
find-common-path (fn common-path [path n]
|
||||
(let [current (nth (first paths) n nil)]
|
||||
(if (or (nil? current)
|
||||
(not (every? #(= current (nth % n nil)) paths)))
|
||||
path
|
||||
(common-path (conj path current) (inc n)))))
|
||||
components (map #(ctf/get-component libraries (:component-file %) (:component-id %)) shapes)
|
||||
|
||||
path (if single?
|
||||
(:path single-comp)
|
||||
(:path (first components))
|
||||
(cfh/join-path (if (not every-same-file?)
|
||||
""
|
||||
(find-common-path [] 0))))
|
||||
(find-common-path components))))
|
||||
|
||||
filters* (mf/use-state
|
||||
{:term ""
|
||||
|
@ -263,13 +344,14 @@
|
|||
|
||||
is-search? (not (str/blank? (:term filters)))
|
||||
|
||||
current-library-id (if (contains? libraries (:file-id filters))
|
||||
(:file-id filters)
|
||||
current-file-id)
|
||||
|
||||
current-library-id (if (contains? libraries (:file-id filters))
|
||||
(:file-id filters)
|
||||
current-file-id)
|
||||
|
||||
current-library-name (if (= current-library-id current-file-id)
|
||||
(str/upper (tr "workspace.assets.local-library"))
|
||||
(get-in libraries [current-library-id :name]))
|
||||
(dm/get-in libraries [current-library-id :name]))
|
||||
|
||||
components (->> (get-in libraries [current-library-id :data :components])
|
||||
vals
|
||||
|
@ -292,7 +374,7 @@
|
|||
|
||||
groups (when-not is-search?
|
||||
(->> (sort (sequence xform components))
|
||||
(map #(assoc {} :name %))))
|
||||
(map (fn [name] {:name name}))))
|
||||
|
||||
components (if is-search?
|
||||
(filter #(str/includes? (str/lower (:full-name %)) (str/lower (:term filters))) components)
|
||||
|
@ -303,22 +385,16 @@
|
|||
(->> (concat groups components)
|
||||
(sort-by :name)))
|
||||
|
||||
;; Get the ids of the components and its root-shapes that are parents of the current shape, to avoid loops
|
||||
get-comps-ids (fn get-comps-ids [shape ids]
|
||||
(if (uuid/zero? (:id shape))
|
||||
ids
|
||||
(let [ids (if (ctk/instance-head? shape)
|
||||
(conj ids (:id shape) (:component-id shape))
|
||||
ids)]
|
||||
(get-comps-ids (get objects (:parent-id shape)) ids))))
|
||||
parent-components (mf/with-memo [shapes objects]
|
||||
(into #{}
|
||||
(comp
|
||||
(map :parent-id)
|
||||
(map (d/getf objects))
|
||||
(mapcat #(get-parent-component-ids objects % [])))
|
||||
shapes))
|
||||
|
||||
parent-components (->> shapes
|
||||
(map :parent-id)
|
||||
(map #(get objects %))
|
||||
(mapcat #(get-comps-ids % []))
|
||||
set)
|
||||
|
||||
libraries-options (map (fn [library] {:value (:id library) :label (:name library)}) (vals libraries))
|
||||
libraries-options (map (fn [library] {:value (:id library) :label (:name library)})
|
||||
(vals libraries))
|
||||
|
||||
on-library-change
|
||||
(mf/use-fn
|
||||
|
@ -409,27 +485,29 @@
|
|||
:component-list (not (:listing-thumbs? filters)))}
|
||||
(for [item items]
|
||||
(if (:id item)
|
||||
(let [data (get-in libraries [current-library-id :data])
|
||||
(let [data (dm/get-in libraries [current-library-id :data])
|
||||
container (ctf/get-component-page data item)
|
||||
root-shape (ctf/get-component-root data item)
|
||||
loop? (or (contains? parent-components (:main-instance-id item))
|
||||
(contains? parent-components (:id item)))]
|
||||
[:& component-swap-item {:key (:id item)
|
||||
[:& component-swap-item {:key (dm/str (:id item))
|
||||
:item item
|
||||
:loop loop?
|
||||
:shapes shapes
|
||||
:file-id current-library-id
|
||||
:root-shape root-shape
|
||||
:container container
|
||||
:component-id current-comp-id
|
||||
:component-id component-id
|
||||
:is-search is-search?
|
||||
:listing-thumbs (:listing-thumbs? filters)}])
|
||||
|
||||
[:& component-group-item {:item item
|
||||
:key (:id item)
|
||||
:key (:name item)
|
||||
:on-enter-group on-enter-group}]))]]]]))
|
||||
|
||||
(mf/defc component-ctx-menu
|
||||
[{:keys [menu-entries on-close show main-instance] :as props}]
|
||||
{::mf/props :obj}
|
||||
[{:keys [menu-entries on-close show main-instance]}]
|
||||
(let [do-action
|
||||
(fn [action event]
|
||||
(dom/stop-propagation event)
|
||||
|
@ -438,15 +516,16 @@
|
|||
[:& dropdown {:show show :on-close on-close}
|
||||
[:ul {:class (stl/css-case :custom-select-dropdown true
|
||||
:not-main (not main-instance))}
|
||||
(for [entry menu-entries :when (not (nil? entry))]
|
||||
[:li {:key (uuid/next)
|
||||
:class (stl/css :dropdown-element)
|
||||
:on-click (partial do-action (:action entry))}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr (:msg entry))]])]]))
|
||||
(for [{:keys [msg] :as entry} menu-entries]
|
||||
(when (some? msg)
|
||||
[:li {:key msg
|
||||
:class (stl/css :dropdown-element)
|
||||
:on-click (partial do-action (:action entry))}
|
||||
[:span {:class (stl/css :dropdown-label)} (tr msg)]]))]]))
|
||||
|
||||
(mf/defc component-menu
|
||||
[{:keys [shapes swap-opened?] :as props}]
|
||||
{::mf/props :obj}
|
||||
[{:keys [shapes swap-opened?]}]
|
||||
(let [current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
workspace-data (deref refs/workspace-data)
|
||||
|
@ -467,7 +546,11 @@
|
|||
shape (first shapes)
|
||||
id (:id shape)
|
||||
shape-name (:name shape)
|
||||
component (ctf/resolve-component shape {:id current-file-id :data workspace-data} workspace-libraries {:include-deleted? true})
|
||||
component (ctf/resolve-component shape
|
||||
{:id current-file-id
|
||||
:data workspace-data}
|
||||
workspace-libraries
|
||||
{:include-deleted? true})
|
||||
main-instance? (if components-v2 (ctk/main-instance? shape) true)
|
||||
|
||||
toggle-content
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
}
|
||||
|
||||
.component-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
direction: rtl;
|
||||
text-align: left;
|
||||
|
@ -104,7 +104,7 @@
|
|||
}
|
||||
|
||||
.component-parent-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
direction: rtl;
|
||||
text-align: left;
|
||||
|
@ -143,7 +143,7 @@
|
|||
}
|
||||
|
||||
.copy-text {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -244,7 +244,7 @@
|
|||
}
|
||||
|
||||
.path-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
direction: rtl;
|
||||
height: $s-32;
|
||||
|
@ -252,7 +252,7 @@
|
|||
}
|
||||
|
||||
.path-name-last {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
height: $s-32;
|
||||
padding: $s-8 0 $s-8 $s-2;
|
||||
|
@ -260,7 +260,7 @@
|
|||
}
|
||||
|
||||
.component-list-empty {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin: 0 $s-4 0 $s-8;
|
||||
color: $df-secondary;
|
||||
}
|
||||
|
@ -346,7 +346,7 @@
|
|||
object-fit: contain;
|
||||
}
|
||||
.component-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
display: none;
|
||||
position: absolute;
|
||||
|
@ -431,7 +431,7 @@
|
|||
}
|
||||
|
||||
.library-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
color: var(--title-foreground-color);
|
||||
padding: $s-8 0 $s-8 $s-2;
|
||||
|
@ -452,7 +452,7 @@
|
|||
}
|
||||
|
||||
.component-group {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr $s-12;
|
||||
height: $s-32;
|
||||
|
@ -495,7 +495,7 @@
|
|||
// Component annotation
|
||||
|
||||
.component-annotation {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
color: var(--entry-foreground-color);
|
||||
border-radius: $br-8;
|
||||
|
||||
|
@ -613,7 +613,7 @@
|
|||
}
|
||||
|
||||
.counter {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
text-align: right;
|
||||
color: var(--entry-foreground-color);
|
||||
margin: 0 $s-8 $s-8 0;
|
||||
|
|
|
@ -134,7 +134,7 @@
|
|||
}
|
||||
|
||||
label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-2;
|
||||
|
|
|
@ -55,12 +55,12 @@
|
|||
}
|
||||
|
||||
.after {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
margin-top: $s-1;
|
||||
}
|
||||
|
||||
.interactions-help {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
text-align: center;
|
||||
color: var(--title-foreground-color);
|
||||
}
|
||||
|
@ -120,7 +120,7 @@
|
|||
}
|
||||
.interaction-name {
|
||||
@include twoLineTextEllipsis;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
padding-left: $s-4;
|
||||
width: $s-92;
|
||||
margin: auto 0;
|
||||
|
@ -287,7 +287,7 @@
|
|||
}
|
||||
|
||||
.flow-name-wrapper {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include focusInput;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -324,7 +324,7 @@
|
|||
}
|
||||
|
||||
.flow-input-wrapper {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-28;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.common.math :as mth]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.config :as cf]
|
||||
[app.main.data.events :as-alias ev]
|
||||
[app.main.data.workspace :as udw]
|
||||
[app.main.data.workspace.grid-layout.editor :as dwge]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
|
@ -855,7 +856,9 @@
|
|||
(let [type (-> (dom/get-current-target event)
|
||||
(dom/get-data "type")
|
||||
(keyword))]
|
||||
(st/emit! (dwsl/create-layout type))
|
||||
(st/emit! (with-meta (dwsl/create-layout type)
|
||||
{::ev/origin "workspace:sidebar"}))
|
||||
|
||||
(reset! open* true))))
|
||||
|
||||
on-remove-layout
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
}
|
||||
|
||||
.select-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
|
||||
.attr-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include twoLineTextEllipsis;
|
||||
width: $s-88;
|
||||
margin: auto $s-4;
|
||||
|
@ -60,7 +60,7 @@
|
|||
}
|
||||
|
||||
.attr-title {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
font-size: $fs-10;
|
||||
text-transform: uppercase;
|
||||
margin-inline-start: $s-4;
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
}
|
||||
|
||||
.multiple-text {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
flex-grow: 1;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
|
||||
.typography-name,
|
||||
.typography-font {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -90,7 +90,7 @@
|
|||
}
|
||||
|
||||
.font-name-wrapper {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
|
@ -169,7 +169,7 @@
|
|||
color: var(--assets-item-name-foreground-color-hover);
|
||||
}
|
||||
.typography-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -178,7 +178,7 @@
|
|||
color: var(--assets-item-name-foreground-color-hover);
|
||||
}
|
||||
.typography-font {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
margin-left: $s-6;
|
||||
display: flex;
|
||||
|
@ -207,14 +207,14 @@
|
|||
--calcualted-width: calc(var(--width) - $s-48);
|
||||
padding-left: $s-2;
|
||||
.info-label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
width: calc(var(--calcualted-width) / 2);
|
||||
padding-top: $s-8;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
}
|
||||
.info-content {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
padding-top: $s-8;
|
||||
width: calc(var(--calcualted-width) / 2);
|
||||
|
@ -254,7 +254,7 @@
|
|||
position: relative;
|
||||
}
|
||||
.font-option {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@extend .asset-element;
|
||||
padding: $s-8 0 $s-8 $s-8;
|
||||
cursor: pointer;
|
||||
|
@ -277,7 +277,7 @@
|
|||
gap: $s-4;
|
||||
.font-size-options {
|
||||
@extend .asset-element;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
flex-grow: 1;
|
||||
width: $s-60;
|
||||
margin: 0;
|
||||
|
@ -331,7 +331,7 @@
|
|||
|
||||
.font-size-select {
|
||||
@include removeInputStyle;
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
height: $s-32;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
@ -410,7 +410,7 @@
|
|||
}
|
||||
|
||||
.label {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
}
|
||||
}
|
||||
.color-name {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
@include textEllipsis;
|
||||
padding-inline: $s-6;
|
||||
border-radius: $br-8;
|
||||
|
@ -86,7 +86,7 @@
|
|||
stroke: var(--detach-icon-foreground-color);
|
||||
}
|
||||
.color-input-wrapper {
|
||||
@include bodyMedTipography;
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-28;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue