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

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

This commit is contained in:
Andrey Antukh 2024-03-04 10:29:11 +01:00
commit 481058b8d4
142 changed files with 1358 additions and 792 deletions

View file

@ -19,8 +19,8 @@
:git/url "https://github.com/funcool/beicon.git"}
funcool/rumext
{:git/tag "v2.11.1"
:git/sha "c9197b0"
{:git/tag "v2.11.3"
:git/sha "b1f6ce4"
:git/url "https://github.com/funcool/rumext.git"}
instaparse/instaparse {:mvn/version "1.4.12"}

Binary file not shown.

After

Width:  |  Height:  |  Size: 985 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

View file

@ -278,7 +278,7 @@
// INPUTS
.input-base {
@include removeInputStyle;
@include bodyMedTipography;
@include bodySmallTypography;
@include textEllipsis;
// @include focusInput;
height: $s-28;
@ -313,7 +313,7 @@
}
.input-element {
@include bodyMedTipography;
@include bodySmallTypography;
@include focusInput;
display: flex;
align-items: center;
@ -383,7 +383,7 @@
}
.input-element-label {
@include bodyMedTipography;
@include bodySmallTypography;
display: flex;
align-items: flex-start;
padding: 0;
@ -488,7 +488,7 @@
display: flex;
align-items: center;
label {
@include bodyMedTipography;
@include bodySmallTypography;
display: flex;
align-items: center;
gap: $s-6;
@ -519,7 +519,7 @@
display: flex;
flex-direction: column;
label {
@include bodyMedTipography;
@include bodySmallTypography;
display: flex;
flex-direction: column;
justify-content: flex-start;
@ -529,7 +529,7 @@
input {
@extend .input-base;
@include bodyMedTipography;
@include bodySmallTypography;
border-radius: $br-8;
height: $s-32;
min-height: $s-32;
@ -606,7 +606,7 @@
}
.modal-hint-base {
@include bodyMedTipography;
@include bodySmallTypography;
color: var(--modal-title-foreground-color);
border-top: $s-1 solid var(--modal-hint-border-color);
border-bottom: $s-1 solid var(--modal-hint-border-color);
@ -666,7 +666,7 @@
}
// UI ELEMENTS
.asset-element {
@include bodyMedTipography;
@include bodySmallTypography;
display: flex;
align-items: center;
height: $s-32;
@ -687,7 +687,7 @@
}
.shortcut-key-base {
@include bodyMedTipography;
@include bodySmallTypography;
@include flexCenter;
height: $s-20;
padding: $s-2 $s-6;
@ -697,7 +697,7 @@
.user-icon {
@include flexCenter;
@include bodyMedTipography;
@include bodySmallTypography;
height: $s-24;
width: $s-24;
border-radius: $br-circle;
@ -709,7 +709,7 @@
}
.mixed-bar {
@include bodyMedTipography;
@include bodySmallTypography;
display: flex;
align-items: center;
flex-grow: 1;
@ -785,7 +785,7 @@
gap: $s-4;
height: $s-32;
:global(.attr-label) {
@include bodyMedTipography;
@include bodySmallTypography;
@include twoLineTextEllipsis;
width: $s-92;
margin: auto 0;
@ -797,12 +797,12 @@
grid-area: content;
display: flex;
color: var(--entry-foreground-color-hover);
@include bodyMedTipography;
@include bodySmallTypography;
}
}
.copy-button-children {
@include bodyMedTipography;
@include bodySmallTypography;
color: var(--color-foreground-primary);
text-align: left;
margin: 0;
@ -816,7 +816,7 @@
}
.comment-bubbles {
@include bodyMedTipography;
@include bodySmallTypography;
@include flexCenter;
height: $s-32;
width: $s-32;
@ -851,7 +851,7 @@
}
.menu-item-base {
@include bodyMedTipography;
@include bodySmallTypography;
display: flex;
align-items: center;
justify-content: space-between;
@ -866,7 +866,7 @@
}
.dropdown-element-base {
@include bodyMedTipography;
@include bodySmallTypography;
display: flex;
align-items: center;
gap: $s-8;
@ -913,7 +913,7 @@
}
.select-wrapper {
@include bodyMedTipography;
@include bodySmallTypography;
position: relative;
display: flex;
align-items: center;

View file

@ -309,6 +309,8 @@
--modal-link-foreground-color: var(--color-accent-primary);
--modal-border-color: var(--color-background-quaternary);
--modal-separator-backogrund-color: var(--color-background-quaternary);
--modal-navigator-foreground-color-rest: var(--color-background-quaternary);
--modal-navigator-foreground-color-active: var(--color-accent-primary);
// ALERTS NOTIFICATION TOAST & STATUS WIDGET
--alert-background-color-success: var(--color-success-background);
@ -372,6 +374,9 @@
--flow-tag-background-color-hover: var(--color-background-quaternary);
--flow-tag-foreground-color-hover: var(--color-accent-primary);
--communication-tag-background-color: var(--color-foreground-primary);
--communication-tag-foreground-color: var(--color-background-tertiary);
// VIEWER
--viewer-background-color: var(--color-background-secondary);
--viewer-paginator-background-color: var(--color-background-tertiary);

View file

@ -63,26 +63,49 @@
line-height: 1.2;
}
@mixin headlineLargeTypography {
font-family: "worksans", sans-serif;
font-size: $fs-18;
line-height: 1.2;
text-transform: uppercase;
font-weight: $fw400;
}
@mixin headlineMediumTypography {
font-family: "worksans", sans-serif;
font-size: $fs-16;
line-height: 1.4;
text-transform: uppercase;
font-weight: normal;
font-weight: $fw400;
}
@mixin headlineSmallTypography {
font-family: "worksans", sans-serif;
font-size: $fs-12;
line-height: 1.2;
text-transform: uppercase;
font-weight: $fw500;
}
@mixin bodyLargeTypography {
font-family: "worksans", sans-serif;
font-size: $fs-16;
line-height: 1.5;
font-weight: normal;
font-weight: $fw400;
}
@mixin bodyMedTipography {
@mixin bodyMediumTypography {
font-family: "worksans", sans-serif;
font-size: $fs-14;
line-height: 1.4;
font-weight: $fw400;
}
@mixin bodySmallTypography {
font-family: "worksans", sans-serif;
font-size: $fs-12;
font-weight: $fw400;
line-height: 1.2;
line-height: 1.4;
}
@mixin codeTypography {
@ -110,7 +133,7 @@
}
@mixin inspectValue {
@include bodyMedTipography;
@include bodySmallTypography;
display: inline-block;
width: fit-content;
padding: 0;

View file

@ -155,6 +155,7 @@ $s-712: #{0.25 * 178}rem;
$s-736: #{0.25 * 184}rem;
$s-744: #{0.25 * 186}rem;
$s-800: #{0.25 * 200}rem;
$s-888: #{0.25 * 222}rem;
$s-908: #{0.25 * 227}rem;
$s-960: #{0.25 * 240}rem;
$s-968: #{0.25 * 242}rem;

View file

@ -12,3 +12,8 @@
body {
color: yellow;
}
.deprecated-icon {
fill: red !important;
stroke: red !important;
}

View file

@ -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))

View file

@ -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

View file

@ -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

View file

@ -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 []))

View file

@ -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

View file

@ -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))))

View file

@ -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)]

View file

@ -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]

View file

@ -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)))))))

View file

@ -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 {} (->>

View file

@ -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))

View file

@ -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]

View file

@ -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;
}
}
}

View file

@ -71,7 +71,7 @@
.color-text {
@include twoLineTextEllipsis;
@include bodyMedTipography;
@include bodySmallTypography;
width: $s-80;
text-align: center;
margin-top: $s-2;

View file

@ -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;

View file

@ -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)]]))

View file

@ -8,7 +8,7 @@
.editable-label-input {
@include textEllipsis;
@include bodyMedTipography;
@include bodySmallTypography;
@include removeInputStyle;
flex-grow: 1;
height: $s-28;

View file

@ -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;

View file

@ -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;

View file

@ -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]])

View file

@ -28,7 +28,7 @@
}
.modal-content {
@include bodyMedTipography;
@include bodySmallTypography;
margin-bottom: $s-24;
}

View file

@ -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"))]

View file

@ -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;

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -53,7 +53,7 @@
flex-direction: column;
border-radius: $s-8;
h3 {
@include bodyMedTipography;
@include bodySmallTypography;
font-size: $fs-24;
width: 100%;
}

View file

@ -31,7 +31,7 @@
}
.modal-content {
@include bodyMedTipography;
@include bodySmallTypography;
margin-bottom: $s-24;
}

View file

@ -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 {

View file

@ -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}]])))

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -45,7 +45,7 @@
}
.release {
@include bodyMedTipography;
@include bodySmallTypography;
position: absolute;
top: calc(-1 * $s-28);
right: 0;

View file

@ -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;
}

View file

@ -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")))

View file

@ -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)}])])

View 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);
}

View 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"]]]]]])))

View 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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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}

View file

@ -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)}]]))

View file

@ -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

View file

@ -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;

View file

@ -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);
}

View file

@ -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)}

View file

@ -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);
}

View file

@ -15,7 +15,7 @@
}
.annotation-content {
@include bodyMedTipography;
@include bodySmallTypography;
color: var(--entry-foreground-color);
}

View file

@ -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)}])]

View file

@ -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;
}

View file

@ -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]

View file

@ -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)

View file

@ -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)

View file

@ -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]

View file

@ -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]

View file

@ -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}]])))

View file

@ -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

View file

@ -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);

View file

@ -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}]])

View file

@ -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)}

View file

@ -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);

View file

@ -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%;

View file

@ -29,7 +29,7 @@
.modal-content {
@include flexColumn;
@include bodyMedTipography;
@include bodySmallTypography;
gap: $s-24;
max-height: $s-400;
width: $s-368;

View file

@ -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);
}

View file

@ -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);

View file

@ -97,6 +97,6 @@
}
.color-palette-empty {
@include bodyMedTipography;
@include bodySmallTypography;
color: var(--palette-text-color);
}

View file

@ -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;

View file

@ -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"

View file

@ -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);

View file

@ -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]])))

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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])]]]))

View file

@ -113,7 +113,7 @@
}
.section-item {
@include bodyMedTipography;
@include bodySmallTypography;
display: flex;
align-items: center;
justify-content: space-between;

View file

@ -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;

View file

@ -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;

View file

@ -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);
}

View file

@ -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);

View file

@ -45,7 +45,7 @@
}
.modal-content {
@include bodyMedTipography;
@include bodySmallTypography;
margin-bottom: $s-24;
}
.input-wrapper {

View file

@ -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?

View file

@ -59,7 +59,7 @@
}
.history-entry-empty-msg {
@include bodyMedTipography;
@include bodySmallTypography;
color: var(--empty-message-foreground-color);
}

View file

@ -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;

View file

@ -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;

View file

@ -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)]

View file

@ -57,7 +57,7 @@
}
}
.label {
@include bodyMedTipography;
@include bodySmallTypography;
flex-grow: 1;
display: flex;
align-items: center;

Some files were not shown because too many files have changed in this diff Show more