mirror of
https://github.com/penpot/penpot.git
synced 2025-05-25 00:36:11 +02:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
0606ef1c84
29 changed files with 854 additions and 774 deletions
|
@ -1076,14 +1076,13 @@
|
||||||
(->> (cells-seq parent :sort? true)
|
(->> (cells-seq parent :sort? true)
|
||||||
(reduce
|
(reduce
|
||||||
(fn [[parent auto?] cell]
|
(fn [[parent auto?] cell]
|
||||||
|
|
||||||
(let [[cell auto?]
|
(let [[cell auto?]
|
||||||
(cond
|
(cond
|
||||||
(and (empty? (:shapes cell))
|
(and (empty? (:shapes cell))
|
||||||
(= :manual (:position cell))
|
(= :manual (:position cell))
|
||||||
(= (:row-span cell) 1)
|
(= (:row-span cell) 1)
|
||||||
(= (:column-span cell) 1))
|
(= (:column-span cell) 1))
|
||||||
[(assoc cell :position :auto) false]
|
[cell false]
|
||||||
|
|
||||||
(and (or (not= (:row-span cell) 1)
|
(and (or (not= (:row-span cell) 1)
|
||||||
(not= (:column-span cell) 1))
|
(not= (:column-span cell) 1))
|
||||||
|
|
3
frontend/resources/images/icons/exit-refactor.svg
Normal file
3
frontend/resources/images/icons/exit-refactor.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M6 14H3.33333C2.97971 14 2.64057 13.8595 2.39052 13.6095C2.14048 13.3594 2 13.0203 2 12.6667V3.33333C2 2.97971 2.14048 2.64057 2.39052 2.39052C2.64057 2.14048 2.97971 2 3.33333 2H6M10.6667 11.3333L14 8M14 8L10.6667 4.66667M14 8H6"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 361 B |
|
@ -848,6 +848,7 @@
|
||||||
color: var(--title-foreground-color-hover);
|
color: var(--title-foreground-color-hover);
|
||||||
background-color: var(--menu-background-color);
|
background-color: var(--menu-background-color);
|
||||||
border: $s-2 solid var(--panel-border-color);
|
border: $s-2 solid var(--panel-border-color);
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-item-base {
|
.menu-item-base {
|
||||||
|
|
|
@ -155,6 +155,7 @@
|
||||||
--icon-foreground-hover: var(--color-foreground-primary);
|
--icon-foreground-hover: var(--color-foreground-primary);
|
||||||
--icon-foreground-accept: var(--status-color-success-500);
|
--icon-foreground-accept: var(--status-color-success-500);
|
||||||
--icon-foreground-discard: var(--status-color-error-500);
|
--icon-foreground-discard: var(--status-color-error-500);
|
||||||
|
--icon-foreground-active: var(--color-accent-primary);
|
||||||
|
|
||||||
// INPUTS, SELECTS, DROPDOWNS
|
// INPUTS, SELECTS, DROPDOWNS
|
||||||
|
|
||||||
|
@ -201,6 +202,7 @@
|
||||||
|
|
||||||
--menu-background-color: var(--color-background-tertiary);
|
--menu-background-color: var(--color-background-tertiary);
|
||||||
--menu-foreground-color: var(--color-foreground-primary);
|
--menu-foreground-color: var(--color-foreground-primary);
|
||||||
|
--menu-icon-foreground-color: var(--color-foreground-secondary);
|
||||||
--menu-background-color-selected: var(--color-background-tertiary);
|
--menu-background-color-selected: var(--color-background-tertiary);
|
||||||
--menu-background-color-hover: var(--color-background-quaternary);
|
--menu-background-color-hover: var(--color-background-quaternary);
|
||||||
--menu-foreground-color-hover: var(--color-foreground-primary);
|
--menu-foreground-color-hover: var(--color-foreground-primary);
|
||||||
|
@ -358,6 +360,11 @@
|
||||||
--search-bar-background-color: var(--color-background-primary);
|
--search-bar-background-color: var(--color-background-primary);
|
||||||
--search-bar-input-background-color: var(--color-background-tertiary);
|
--search-bar-input-background-color: var(--color-background-tertiary);
|
||||||
--search-bar-input-border-color: var(--color-background-tertiary);
|
--search-bar-input-border-color: var(--color-background-tertiary);
|
||||||
|
--search-bar-input-border-color-focus: var(--color-accent-primary);
|
||||||
|
--search-bar-placeholder-foreground-color: var(--color-foreground-secondary);
|
||||||
|
--search-bar-foreground-color: var(--color-foreground-primary);
|
||||||
|
--search-bar-icon-foreground-color: var(--color-foreground-secondary);
|
||||||
|
--search-bar-icon-foreground-color-hover: var(--color-accent-primary);
|
||||||
|
|
||||||
--pill-background-color: var(--color-background-tertiary);
|
--pill-background-color: var(--color-background-tertiary);
|
||||||
--pill-foreground-color: var(--color-foreground-primary);
|
--pill-foreground-color: var(--color-foreground-primary);
|
||||||
|
@ -369,6 +376,8 @@
|
||||||
--resize-area-background-color: var(--color-background-primary);
|
--resize-area-background-color: var(--color-background-primary);
|
||||||
--resize-area-border-color: var(--color-background-quaternary);
|
--resize-area-border-color: var(--color-background-quaternary);
|
||||||
|
|
||||||
|
--profile-section-background-color: var(--color-background-tertiary);
|
||||||
|
|
||||||
--flow-tag-background-color: var(--color-background-tertiary);
|
--flow-tag-background-color: var(--color-background-tertiary);
|
||||||
--flow-tag-foreground-color: var(--color-foreground-secondary);
|
--flow-tag-foreground-color: var(--color-foreground-secondary);
|
||||||
--flow-tag-background-color-hover: var(--color-background-quaternary);
|
--flow-tag-background-color-hover: var(--color-background-quaternary);
|
||||||
|
@ -393,6 +402,14 @@
|
||||||
// NEW TEAM BUTTON
|
// NEW TEAM BUTTON
|
||||||
// TODO: we should not put these functional tokens here, but rather in the components they belong to
|
// TODO: we should not put these functional tokens here, but rather in the components they belong to
|
||||||
--new-team-button-background-color: var(--color-background-primary);
|
--new-team-button-background-color: var(--color-background-primary);
|
||||||
|
|
||||||
|
//DASHBOARD
|
||||||
|
--sidebar-element-foreground-color: var(--color-foreground-secondary);
|
||||||
|
--sidebar-element-background-color-hover: var(--color-background-secondary);
|
||||||
|
--sidebar-element-foreground-color-hover: var(--color-accent-primary);
|
||||||
|
--sidebar-element-background-color-selected: var(--color-background-quaternary);
|
||||||
|
--sidebar-element-foreground-color-selected: var(--color-accent-primary);
|
||||||
|
--profile-foreground-color: var(--color-foreground-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
(defn notify-start-loading
|
(defn notify-start-loading
|
||||||
[]
|
[]
|
||||||
(st/emit! (msg/show {:content (tr "media.loading")
|
(st/emit! (msg/show {:content (tr "media.loading")
|
||||||
|
:notification-type :toast
|
||||||
:type :info
|
:type :info
|
||||||
:timeout nil})))
|
:timeout nil})))
|
||||||
|
|
||||||
|
|
|
@ -808,7 +808,7 @@
|
||||||
component (ctkl/get-component data component-id)
|
component (ctkl/get-component data component-id)
|
||||||
page-id (:main-instance-page component)
|
page-id (:main-instance-page component)
|
||||||
root-id (:main-instance-id component)]
|
root-id (:main-instance-id component)]
|
||||||
(dwt/request-thumbnail file-id page-id root-id tag)))
|
(dwt/request-thumbnail file-id page-id root-id tag "update-component-thumbnail-sync")))
|
||||||
|
|
||||||
(defn update-component-sync
|
(defn update-component-sync
|
||||||
([shape-id file-id] (update-component-sync shape-id file-id nil))
|
([shape-id file-id] (update-component-sync shape-id file-id nil))
|
||||||
|
|
|
@ -211,6 +211,7 @@
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of (msg/show {:content (tr "media.loading")
|
(rx/of (msg/show {:content (tr "media.loading")
|
||||||
|
:notification-type :toast
|
||||||
:type :info
|
:type :info
|
||||||
:timeout nil
|
:timeout nil
|
||||||
:tag :media-loading}))
|
:tag :media-loading}))
|
||||||
|
@ -440,6 +441,7 @@
|
||||||
|
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of (msg/show {:content (tr "media.loading")
|
(rx/of (msg/show {:content (tr "media.loading")
|
||||||
|
:notification-type :toast
|
||||||
:type :info
|
:type :info
|
||||||
:timeout nil
|
:timeout nil
|
||||||
:tag :media-loading}))
|
:tag :media-loading}))
|
||||||
|
|
|
@ -573,6 +573,7 @@
|
||||||
(> (:row-span cell) 1)
|
(> (:row-span cell) 1)
|
||||||
(> (:column-span cell) 1))
|
(> (:column-span cell) 1))
|
||||||
(-> (d/update-in-when [:layout-grid-cells cell-id] assoc :shapes [] :position :auto)
|
(-> (d/update-in-when [:layout-grid-cells cell-id] assoc :shapes [] :position :auto)
|
||||||
|
(d/update-in-when [:layout-grid-cells cell-id] dissoc :area-name)
|
||||||
(ctl/resize-cell-area (:row cell) (:column cell) (:row cell) (:column cell) 1 1)
|
(ctl/resize-cell-area (:row cell) (:column cell) (:row cell) (:column cell) 1 1)
|
||||||
(ctl/assign-cells objects)))))
|
(ctl/assign-cells objects)))))
|
||||||
shape))
|
shape))
|
||||||
|
@ -585,6 +586,7 @@
|
||||||
(cond-> shape
|
(cond-> shape
|
||||||
(contains? #{:area :auto} (:position cell))
|
(contains? #{:area :auto} (:position cell))
|
||||||
(-> (d/assoc-in-when [:layout-grid-cells cell-id :position] :manual)
|
(-> (d/assoc-in-when [:layout-grid-cells cell-id :position] :manual)
|
||||||
|
(d/update-in-when [:layout-grid-cells cell-id] dissoc :area-name)
|
||||||
(ctl/assign-cells objects)))))
|
(ctl/assign-cells objects)))))
|
||||||
shape))
|
shape))
|
||||||
|
|
||||||
|
|
|
@ -58,15 +58,17 @@
|
||||||
|
|
||||||
(defn request-thumbnail
|
(defn request-thumbnail
|
||||||
"Enqueues a request to generate a thumbnail for the given ids."
|
"Enqueues a request to generate a thumbnail for the given ids."
|
||||||
[file-id page-id shape-id tag]
|
([file-id page-id shape-id tag]
|
||||||
|
(request-thumbnail file-id page-id shape-id tag "unknown"))
|
||||||
|
([file-id page-id shape-id tag requester]
|
||||||
(ptk/reify ::request-thumbnail
|
(ptk/reify ::request-thumbnail
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
(effect [_ _ _]
|
(effect [_ _ _]
|
||||||
(l/dbg :hint "request thumbnail" :file-id file-id :page-id page-id :shape-id shape-id :tag tag)
|
(l/dbg :hint "request thumbnail" :requester requester :file-id file-id :page-id page-id :shape-id shape-id :tag tag)
|
||||||
(q/enqueue-unique
|
(q/enqueue-unique
|
||||||
queue
|
queue
|
||||||
(create-request file-id page-id shape-id tag)
|
(create-request file-id page-id shape-id tag)
|
||||||
(partial find-request file-id page-id shape-id tag)))))
|
(partial find-request file-id page-id shape-id tag))))))
|
||||||
|
|
||||||
;; This function first renders the HTML calling `render/render-frame` that
|
;; This function first renders the HTML calling `render/render-frame` that
|
||||||
;; returns HTML as a string, then we send that data to the iframe rasterizer
|
;; returns HTML as a string, then we send that data to the iframe rasterizer
|
||||||
|
@ -291,6 +293,6 @@
|
||||||
(->> all-changes-s
|
(->> all-changes-s
|
||||||
(rx/buffer-until notifier-s)
|
(rx/buffer-until notifier-s)
|
||||||
(rx/mapcat #(into #{} %))
|
(rx/mapcat #(into #{} %))
|
||||||
(rx/map #(request-thumbnail file-id page-id % "frame"))))
|
(rx/map #(request-thumbnail file-id page-id % "frame" "watch-state-changes"))))
|
||||||
|
|
||||||
(rx/take-until stopper-s))))))
|
(rx/take-until stopper-s))))))
|
||||||
|
|
|
@ -124,6 +124,7 @@
|
||||||
(let [message (tr "errors.paste-data-validation")]
|
(let [message (tr "errors.paste-data-validation")]
|
||||||
(st/async-emit!
|
(st/async-emit!
|
||||||
(msg/show {:content message
|
(msg/show {:content message
|
||||||
|
:notification-type :toast
|
||||||
:type :error
|
:type :error
|
||||||
:timeout 3000})))
|
:timeout 3000})))
|
||||||
|
|
||||||
|
@ -138,6 +139,7 @@
|
||||||
[error]
|
[error]
|
||||||
(ts/schedule
|
(ts/schedule
|
||||||
#(st/emit! (msg/show {:content "Internal Assertion Error"
|
#(st/emit! (msg/show {:content "Internal Assertion Error"
|
||||||
|
:notification-type :toast
|
||||||
:type :error
|
:type :error
|
||||||
:timeout 3000})))
|
:timeout 3000})))
|
||||||
|
|
||||||
|
@ -153,6 +155,7 @@
|
||||||
(ts/schedule
|
(ts/schedule
|
||||||
#(st/emit!
|
#(st/emit!
|
||||||
(msg/show {:content "Something wrong has happened (on worker)."
|
(msg/show {:content "Something wrong has happened (on worker)."
|
||||||
|
:notification-type :toast
|
||||||
:type :error
|
:type :error
|
||||||
:timeout 3000})))
|
:timeout 3000})))
|
||||||
|
|
||||||
|
@ -166,6 +169,7 @@
|
||||||
[_]
|
[_]
|
||||||
(ts/schedule
|
(ts/schedule
|
||||||
#(st/emit! (msg/show {:content "SVG is invalid or malformed"
|
#(st/emit! (msg/show {:content "SVG is invalid or malformed"
|
||||||
|
:notification-type :toast
|
||||||
:type :error
|
:type :error
|
||||||
:timeout 3000}))))
|
:timeout 3000}))))
|
||||||
|
|
||||||
|
@ -174,6 +178,7 @@
|
||||||
[_]
|
[_]
|
||||||
(ts/schedule
|
(ts/schedule
|
||||||
#(st/emit! (msg/show {:content "There was an error with the comment"
|
#(st/emit! (msg/show {:content "There was an error with the comment"
|
||||||
|
:notification-type :toast
|
||||||
:type :error
|
:type :error
|
||||||
:timeout 3000}))))
|
:timeout 3000}))))
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
[app.util.http :as http]
|
[app.util.http :as http]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[clojure.set :as set]
|
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[lambdaisland.uri :as u]
|
[lambdaisland.uri :as u]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
|
@ -273,13 +272,17 @@
|
||||||
|
|
||||||
(defn get-content-fonts
|
(defn get-content-fonts
|
||||||
"Extracts the fonts used by the content of a text shape"
|
"Extracts the fonts used by the content of a text shape"
|
||||||
[{font-id :font-id children :children :as content}]
|
[content]
|
||||||
|
(->> (txt/node-seq content)
|
||||||
|
(filter txt/is-text-node?)
|
||||||
|
(reduce
|
||||||
|
(fn [result {:keys [font-id] :as node}]
|
||||||
(let [current-font
|
(let [current-font
|
||||||
(if (some? font-id)
|
(if (some? font-id)
|
||||||
#{(select-keys content [:font-id :font-variant-id])}
|
(select-keys node [:font-id :font-variant-id])
|
||||||
#{(select-keys txt/default-text-attrs [:font-id :font-variant-id])})
|
(select-keys txt/default-text-attrs [:font-id :font-variant-id]))]
|
||||||
children-font (->> children (mapv get-content-fonts))]
|
(conj result current-font)))
|
||||||
(reduce set/union (conj children-font current-font))))
|
#{})))
|
||||||
|
|
||||||
(defn fetch-font-css
|
(defn fetch-font-css
|
||||||
"Given a font and the variant-id, retrieves the fontface CSS"
|
"Given a font and the variant-id, retrieves the fontface CSS"
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
|
|
||||||
(mf/defc link
|
(mf/defc link
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[{:keys [action klass data-test keyboard-action children]}]
|
[{:keys [action class data-test keyboard-action children]}]
|
||||||
(let [keyboard-action (d/nilv keyboard-action action)]
|
(let [keyboard-action (d/nilv keyboard-action action)]
|
||||||
[:a {:on-click action
|
[:a {:on-click action
|
||||||
:class klass
|
:class class
|
||||||
:on-key-down (fn [event]
|
:on-key-down (fn [event]
|
||||||
(when ^boolean (kbd/enter? event)
|
(when ^boolean (kbd/enter? event)
|
||||||
(keyboard-action event)))
|
(keyboard-action event)))
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
|
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
|
||||||
[app.main.ui.dashboard.project-menu :refer [project-menu]]
|
[app.main.ui.dashboard.project-menu :refer [project-menu]]
|
||||||
[app.main.ui.dashboard.team-form]
|
[app.main.ui.dashboard.team-form]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i :refer [icon-xref]]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.dom.dnd :as dnd]
|
[app.util.dom.dnd :as dnd]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
@ -39,6 +39,33 @@
|
||||||
[potok.v2.core :as ptk]
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(def ^:private clear-search-icon
|
||||||
|
(icon-xref :delete-text-refactor (stl/css :clear-search-icon)))
|
||||||
|
|
||||||
|
(def ^:private search-icon
|
||||||
|
(icon-xref :search-refactor (stl/css :search-icon)))
|
||||||
|
|
||||||
|
(def ^:private tick-icon
|
||||||
|
(icon-xref :tick-refactor (stl/css :tick-icon)))
|
||||||
|
|
||||||
|
(def ^:private logo-icon
|
||||||
|
(icon-xref :logo-refactor (stl/css :logo-icon)))
|
||||||
|
|
||||||
|
(def ^:private add-icon
|
||||||
|
(icon-xref :add-refactor (stl/css :add-icon)))
|
||||||
|
|
||||||
|
(def ^:private arrow-icon
|
||||||
|
(icon-xref :arrow-refactor (stl/css :arrow-icon)))
|
||||||
|
|
||||||
|
(def ^:private menu-icon
|
||||||
|
(icon-xref :menu-refactor (stl/css :menu-icon)))
|
||||||
|
|
||||||
|
(def ^:private pin-icon
|
||||||
|
(icon-xref :pin-refactor (stl/css :pin-icon)))
|
||||||
|
|
||||||
|
(def ^:private exit-icon
|
||||||
|
(icon-xref :exit-refactor (stl/css :exit-icon)))
|
||||||
|
|
||||||
(mf/defc sidebar-project
|
(mf/defc sidebar-project
|
||||||
[{:keys [item selected?] :as props}]
|
[{:keys [item selected?] :as props}]
|
||||||
(let [dstate (mf/deref refs/dashboard-local)
|
(let [dstate (mf/deref refs/dashboard-local)
|
||||||
|
@ -54,13 +81,13 @@
|
||||||
|
|
||||||
local @local*
|
local @local*
|
||||||
on-click
|
on-click
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps item)
|
(mf/deps item)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dd/go-to-files (:id item)))))
|
(st/emit! (dd/go-to-files (:id item)))))
|
||||||
|
|
||||||
on-key-down
|
on-key-down
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps item)
|
(mf/deps item)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
|
@ -74,7 +101,7 @@
|
||||||
(dom/set-attribute! project-title "tabindex" "-1")))))))))
|
(dom/set-attribute! project-title "tabindex" "-1")))))))))
|
||||||
|
|
||||||
on-menu-click
|
on-menu-click
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [position (dom/get-client-position event)]
|
(let [position (dom/get-client-position event)]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
|
@ -83,13 +110,13 @@
|
||||||
:menu-pos position))))
|
:menu-pos position))))
|
||||||
|
|
||||||
on-menu-close
|
on-menu-close
|
||||||
(mf/use-callback #(swap! local* assoc :menu-open false))
|
(mf/use-fn #(swap! local* assoc :menu-open false))
|
||||||
|
|
||||||
on-edit-open
|
on-edit-open
|
||||||
(mf/use-callback #(swap! local* assoc :edition? true))
|
(mf/use-fn #(swap! local* assoc :edition? true))
|
||||||
|
|
||||||
on-edit
|
on-edit
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps item)
|
(mf/deps item)
|
||||||
(fn [name]
|
(fn [name]
|
||||||
(when-not (str/blank? name)
|
(when-not (str/blank? name)
|
||||||
|
@ -98,7 +125,7 @@
|
||||||
(swap! local* assoc :edition? false)))
|
(swap! local* assoc :edition? false)))
|
||||||
|
|
||||||
on-drag-enter
|
on-drag-enter
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps selected-project)
|
(mf/deps selected-project)
|
||||||
(fn [e]
|
(fn [e]
|
||||||
(when (dnd/has-type? e "penpot/files")
|
(when (dnd/has-type? e "penpot/files")
|
||||||
|
@ -108,25 +135,25 @@
|
||||||
(swap! local* assoc :dragging? true))))))
|
(swap! local* assoc :dragging? true))))))
|
||||||
|
|
||||||
on-drag-over
|
on-drag-over
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [e]
|
(fn [e]
|
||||||
(when (dnd/has-type? e "penpot/files")
|
(when (dnd/has-type? e "penpot/files")
|
||||||
(dom/prevent-default e))))
|
(dom/prevent-default e))))
|
||||||
|
|
||||||
on-drag-leave
|
on-drag-leave
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [e]
|
(fn [e]
|
||||||
(when-not (dnd/from-child? e)
|
(when-not (dnd/from-child? e)
|
||||||
(swap! local* assoc :dragging? false))))
|
(swap! local* assoc :dragging? false))))
|
||||||
|
|
||||||
on-drop-success
|
on-drop-success
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps (:id item))
|
(mf/deps (:id item))
|
||||||
#(st/emit! (msg/success (tr "dashboard.success-move-file"))
|
#(st/emit! (msg/success (tr "dashboard.success-move-file"))
|
||||||
(dd/go-to-files (:id item))))
|
(dd/go-to-files (:id item))))
|
||||||
|
|
||||||
on-drop
|
on-drop
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps item selected-files)
|
(mf/deps item selected-files)
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(swap! local* assoc :dragging? false)
|
(swap! local* assoc :dragging? false)
|
||||||
|
@ -139,6 +166,7 @@
|
||||||
[:*
|
[:*
|
||||||
[:li {:tab-index "0"
|
[:li {:tab-index "0"
|
||||||
:class (stl/css-case :project-element true
|
:class (stl/css-case :project-element true
|
||||||
|
:sidebar-nav-item true
|
||||||
:current selected?
|
:current selected?
|
||||||
:dragging (:dragging? local))
|
:dragging (:dragging? local))
|
||||||
:on-click on-click
|
:on-click on-click
|
||||||
|
@ -167,19 +195,19 @@
|
||||||
emit! (mf/use-memo #(f/debounce st/emit! 500))
|
emit! (mf/use-memo #(f/debounce st/emit! 500))
|
||||||
|
|
||||||
on-search-blur
|
on-search-blur
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(reset! focused? false)))
|
(reset! focused? false)))
|
||||||
|
|
||||||
on-search-change
|
on-search-change
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps team-id)
|
(mf/deps team-id)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [value (dom/get-target-val event)]
|
(let [value (dom/get-target-val event)]
|
||||||
(emit! (dd/go-to-search value)))))
|
(emit! (dd/go-to-search value)))))
|
||||||
|
|
||||||
on-clear-click
|
on-clear-click
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps team-id)
|
(mf/deps team-id)
|
||||||
(fn [e]
|
(fn [e]
|
||||||
(let [search-input (dom/get-element "search-input")]
|
(let [search-input (dom/get-element "search-input")]
|
||||||
|
@ -190,7 +218,7 @@
|
||||||
(dom/stop-propagation e))))
|
(dom/stop-propagation e))))
|
||||||
|
|
||||||
on-key-press
|
on-key-press
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [e]
|
(fn [e]
|
||||||
(when (kbd/enter? e)
|
(when (kbd/enter? e)
|
||||||
(ts/schedule-on-idle
|
(ts/schedule-on-idle
|
||||||
|
@ -204,15 +232,14 @@
|
||||||
(dom/stop-propagation e))))
|
(dom/stop-propagation e))))
|
||||||
|
|
||||||
handle-clear-search
|
handle-clear-search
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps on-clear-click)
|
(mf/deps on-clear-click)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
(on-clear-click event))))]
|
(on-clear-click event))))]
|
||||||
|
|
||||||
[:form {:class (stl/css :sidebar-search)}
|
[:form {:class (stl/css :sidebar-search)}
|
||||||
[:input
|
[:input {:class (stl/css :input-text)
|
||||||
{:class (stl/css :input-text)
|
|
||||||
:key "images-search-box"
|
:key "images-search-box"
|
||||||
:id "search-input"
|
:id "search-input"
|
||||||
:type "text"
|
:type "text"
|
||||||
|
@ -227,71 +254,85 @@
|
||||||
:ref #(when % (set! (.-value %) search-term))}]
|
:ref #(when % (set! (.-value %) search-term))}]
|
||||||
|
|
||||||
(if (or @focused? (seq search-term))
|
(if (or @focused? (seq search-term))
|
||||||
[:div
|
[:button {:class (stl/css :search-btn :clear-search-btn)
|
||||||
{:class (stl/css :clear-search)
|
|
||||||
:tab-index "0"
|
:tab-index "0"
|
||||||
:on-click on-clear-click
|
:on-click on-clear-click
|
||||||
:on-key-down handle-clear-search}
|
:on-key-down handle-clear-search}
|
||||||
i/close]
|
clear-search-icon]
|
||||||
|
|
||||||
[:div
|
[:button {:class (stl/css :search-btn)
|
||||||
{:class (stl/css :search)
|
|
||||||
:on-click on-clear-click}
|
:on-click on-clear-click}
|
||||||
i/search])]))
|
search-icon])]))
|
||||||
|
|
||||||
(mf/defc teams-selector-dropdown-items
|
(mf/defc teams-selector-dropdown-items
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[{:keys [team profile teams] :as props}]
|
[{:keys [team profile teams] :as props}]
|
||||||
(let [on-create-clicked
|
(let [on-create-clicked
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
#(st/emit! (modal/show :team-form {})))
|
#(st/emit! (modal/show :team-form {})))
|
||||||
|
|
||||||
team-selected
|
team-selected
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [team-id]
|
(fn [event]
|
||||||
(st/emit! (dd/go-to-projects team-id))))
|
(let [team-id (-> (dom/get-current-target event)
|
||||||
|
(dom/get-data "value"))]
|
||||||
|
(st/emit! (dd/go-to-projects team-id)))))
|
||||||
|
|
||||||
handle-select-default
|
handle-select-default
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps profile team-selected)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
(team-selected (:default-team-id profile) event)))
|
(team-selected (:default-team-id profile) event))))
|
||||||
|
|
||||||
handle-select-team
|
handle-select-team
|
||||||
(fn [id event]
|
(mf/use-fn
|
||||||
|
(mf/deps team-selected)
|
||||||
|
(fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
(team-selected id event)))]
|
(team-selected event))))
|
||||||
|
|
||||||
|
handle-creation-key-down
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps on-create-clicked)
|
||||||
|
(fn [event]
|
||||||
|
(when (kbd/enter? event)
|
||||||
|
(on-create-clicked event))))]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:> dropdown-menu-item* {:on-click (partial team-selected (:default-team-id profile))
|
[:> dropdown-menu-item* {:on-click team-selected
|
||||||
|
:data-value (:default-team-id profile)
|
||||||
:on-key-down handle-select-default
|
:on-key-down handle-select-default
|
||||||
:id "teams-selector-default-team"
|
:id "teams-selector-default-team"
|
||||||
:class (stl/css :team-name)}
|
:class (stl/css :team-dropdown-item)}
|
||||||
[:span {:class (stl/css :team-icon)} i/logo-icon]
|
[:span {:class (stl/css :penpot-icon)} i/logo-icon]
|
||||||
|
|
||||||
[:span {:class (stl/css :team-text)} (tr "dashboard.your-penpot")]
|
[:span {:class (stl/css :team-text)} (tr "dashboard.your-penpot")]
|
||||||
(when (= (:default-team-id profile) (:id team))
|
(when (= (:default-team-id profile) (:id team))
|
||||||
[:span {:class (stl/css :icon)} i/tick])]
|
tick-icon)]
|
||||||
|
|
||||||
(for [team-item (remove :is-default (vals teams))]
|
(for [team-item (remove :is-default (vals teams))]
|
||||||
[:> dropdown-menu-item* {:on-click (partial team-selected (:id team-item))
|
[:> dropdown-menu-item* {:on-click team-selected
|
||||||
:on-key-down (partial handle-select-team (:id team-item))
|
:data-value (:id team-item)
|
||||||
|
:on-key-down handle-select-team
|
||||||
:id (str "teams-selector-" (:id team-item))
|
:id (str "teams-selector-" (:id team-item))
|
||||||
:class (stl/css :team-name)
|
:class (stl/css :team-dropdown-item)
|
||||||
:key (str "teams-selector-" (:id team-item))}
|
:key (str "teams-selector-" (:id team-item))}
|
||||||
[:span {:class (stl/css :team-icon)}
|
|
||||||
[:img {:src (cf/resolve-team-photo-url team-item)
|
[:img {:src (cf/resolve-team-photo-url team-item)
|
||||||
:alt (:name team-item)}]]
|
:class (stl/css :team-picture)
|
||||||
|
:alt (:name team-item)}]
|
||||||
[:span {:class (stl/css :team-text)
|
[:span {:class (stl/css :team-text)
|
||||||
:title (:name team-item)} (:name team-item)]
|
:title (:name team-item)} (:name team-item)]
|
||||||
(when (= (:id team-item) (:id team))
|
(when (= (:id team-item) (:id team))
|
||||||
[:span {:class (stl/css :icon)} i/tick])])
|
tick-icon)])
|
||||||
[:hr {:role "separator"}]
|
|
||||||
|
[:hr {:role "separator"
|
||||||
|
:class (stl/css :team-separator)}]
|
||||||
[:> dropdown-menu-item* {:on-click on-create-clicked
|
[:> dropdown-menu-item* {:on-click on-create-clicked
|
||||||
:on-key-down (fn [event]
|
:on-key-down handle-creation-key-down
|
||||||
(when (kbd/enter? event)
|
|
||||||
(on-create-clicked event)))
|
|
||||||
:id "teams-selector-create-team"
|
:id "teams-selector-create-team"
|
||||||
:class (stl/css :team-name :action)}
|
:class (stl/css :team-dropdown-item :action)}
|
||||||
[:span {:class (stl/css :team-icon :new-team)} i/close]
|
[:span {:class (stl/css :icon-wrapper)} add-icon]
|
||||||
[:span {:class (stl/css :team-text)} (tr "dashboard.create-new-team")]]]))
|
[:span {:class (stl/css :team-text)} (tr "dashboard.create-new-team")]]]))
|
||||||
|
|
||||||
(s/def ::member-id ::us/uuid)
|
(s/def ::member-id ::us/uuid)
|
||||||
|
@ -330,130 +371,200 @@
|
||||||
(rx/throw error)))
|
(rx/throw error)))
|
||||||
|
|
||||||
leave-fn
|
leave-fn
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps on-success on-error)
|
||||||
(fn [member-id]
|
(fn [member-id]
|
||||||
(let [params (cond-> {} (uuid? member-id) (assoc :reassign-to member-id))]
|
(let [params (cond-> {} (uuid? member-id) (assoc :reassign-to member-id))]
|
||||||
(st/emit! (dd/leave-team (with-meta params
|
(st/emit! (dd/leave-team (with-meta params
|
||||||
{:on-success on-success
|
{:on-success on-success
|
||||||
:on-error on-error})))))
|
:on-error on-error}))))))
|
||||||
delete-fn
|
delete-fn
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps team on-success on-error)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dd/delete-team (with-meta team {:on-success on-success
|
(st/emit! (dd/delete-team (with-meta team {:on-success on-success
|
||||||
:on-error on-error}))))
|
:on-error on-error})))))
|
||||||
on-rename-clicked
|
on-rename-clicked
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps team)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (modal/show :team-form {:team team})))
|
(st/emit! (modal/show :team-form {:team team}))))
|
||||||
|
|
||||||
on-leave-clicked
|
on-leave-clicked
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps leave-fn)
|
||||||
#(st/emit! (modal/show
|
#(st/emit! (modal/show
|
||||||
{:type :confirm
|
{:type :confirm
|
||||||
:title (tr "modals.leave-confirm.title")
|
:title (tr "modals.leave-confirm.title")
|
||||||
:message (tr "modals.leave-confirm.message")
|
:message (tr "modals.leave-confirm.message")
|
||||||
:accept-label (tr "modals.leave-confirm.accept")
|
:accept-label (tr "modals.leave-confirm.accept")
|
||||||
:on-accept leave-fn}))
|
:on-accept leave-fn})))
|
||||||
|
|
||||||
on-leave-as-owner-clicked
|
on-leave-as-owner-clicked
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps team profile leave-fn)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dd/fetch-team-members (:id team))
|
(st/emit! (dd/fetch-team-members (:id team))
|
||||||
(modal/show
|
(modal/show
|
||||||
{:type :leave-and-reassign
|
{:type :leave-and-reassign
|
||||||
:profile profile
|
:profile profile
|
||||||
:team team
|
:team team
|
||||||
:accept leave-fn})))
|
:accept leave-fn}))))
|
||||||
|
|
||||||
leave-and-close
|
leave-and-close
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps team delete-fn)
|
||||||
#(st/emit! (modal/show
|
#(st/emit! (modal/show
|
||||||
{:type :confirm
|
{:type :confirm
|
||||||
:title (tr "modals.leave-confirm.title")
|
:title (tr "modals.leave-confirm.title")
|
||||||
:message (tr "modals.leave-and-close-confirm.message" (:name team))
|
:message (tr "modals.leave-and-close-confirm.message" (:name team))
|
||||||
:scd-message (tr "modals.leave-and-close-confirm.hint")
|
:scd-message (tr "modals.leave-and-close-confirm.hint")
|
||||||
:accept-label (tr "modals.leave-confirm.accept")
|
:accept-label (tr "modals.leave-confirm.accept")
|
||||||
:on-accept delete-fn}))
|
:on-accept delete-fn})))
|
||||||
|
|
||||||
on-delete-clicked
|
on-delete-clicked
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps delete-fn)
|
||||||
#(st/emit!
|
#(st/emit!
|
||||||
(modal/show
|
(modal/show
|
||||||
{:type :confirm
|
{:type :confirm
|
||||||
:title (tr "modals.delete-team-confirm.title")
|
:title (tr "modals.delete-team-confirm.title")
|
||||||
:message (tr "modals.delete-team-confirm.message")
|
:message (tr "modals.delete-team-confirm.message")
|
||||||
:accept-label (tr "modals.delete-team-confirm.accept")
|
:accept-label (tr "modals.delete-team-confirm.accept")
|
||||||
:on-accept delete-fn}))]
|
:on-accept delete-fn})))
|
||||||
|
|
||||||
|
handle-members
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps go-members)
|
||||||
|
(fn [event]
|
||||||
|
(when (kbd/enter? event)
|
||||||
|
(go-members))))
|
||||||
|
|
||||||
|
handle-invitations
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps go-invitations)
|
||||||
|
(fn [event]
|
||||||
|
(when (kbd/enter? event)
|
||||||
|
(go-invitations))))
|
||||||
|
|
||||||
|
handle-webhooks
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps go-webhooks)
|
||||||
|
(fn [event]
|
||||||
|
(when (kbd/enter? event)
|
||||||
|
(go-webhooks))))
|
||||||
|
|
||||||
|
handle-settings
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps go-settings)
|
||||||
|
(fn [event]
|
||||||
|
(when (kbd/enter? event)
|
||||||
|
(go-settings))))
|
||||||
|
|
||||||
|
|
||||||
|
handle-rename
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps on-rename-clicked)
|
||||||
|
(fn [event]
|
||||||
|
(when (kbd/enter? event)
|
||||||
|
(on-rename-clicked))))
|
||||||
|
|
||||||
|
|
||||||
|
handle-leave-and-close
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps leave-and-close)
|
||||||
|
(fn [event]
|
||||||
|
(when (kbd/enter? event)
|
||||||
|
(leave-and-close))))
|
||||||
|
|
||||||
|
handle-leave-as-owner-clicked
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps on-leave-as-owner-clicked)
|
||||||
|
(fn [event]
|
||||||
|
(when (kbd/enter? event)
|
||||||
|
(on-leave-as-owner-clicked))))
|
||||||
|
|
||||||
|
|
||||||
|
handle-on-leave-clicked
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps on-leave-clicked)
|
||||||
|
(fn [event]
|
||||||
|
(when (kbd/enter? event)
|
||||||
|
(on-leave-clicked))))
|
||||||
|
|
||||||
|
handle-on-delete-clicked
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps on-delete-clicked)
|
||||||
|
(fn [event]
|
||||||
|
(when (kbd/enter? event)
|
||||||
|
(on-delete-clicked))))]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:> dropdown-menu-item* {:on-click go-members
|
[:> dropdown-menu-item* {:on-click go-members
|
||||||
:on-key-down (fn [event]
|
:on-key-down handle-members
|
||||||
(when (kbd/enter? event)
|
:className (stl/css :team-options-item)
|
||||||
(go-members)))
|
|
||||||
:id "teams-options-members"
|
:id "teams-options-members"
|
||||||
:data-test "team-members"}
|
:data-test "team-members"}
|
||||||
(tr "labels.members")]
|
(tr "labels.members")]
|
||||||
[:> dropdown-menu-item* {:on-click go-invitations
|
[:> dropdown-menu-item* {:on-click go-invitations
|
||||||
:on-key-down (fn [event]
|
:on-key-down handle-invitations
|
||||||
(when (kbd/enter? event)
|
:className (stl/css :team-options-item)
|
||||||
(go-invitations)))
|
|
||||||
:id "teams-options-invitations"
|
:id "teams-options-invitations"
|
||||||
:data-test "team-invitations"}
|
:data-test "team-invitations"}
|
||||||
(tr "labels.invitations")]
|
(tr "labels.invitations")]
|
||||||
|
|
||||||
(when (contains? cf/flags :webhooks)
|
(when (contains? cf/flags :webhooks)
|
||||||
[:> dropdown-menu-item* {:on-click go-webhooks
|
[:> dropdown-menu-item* {:on-click go-webhooks
|
||||||
:on-key-down (fn [event]
|
:on-key-down handle-webhooks
|
||||||
(when (kbd/enter? event)
|
:className (stl/css :team-options-item)
|
||||||
(go-webhooks)))
|
|
||||||
:id "teams-options-webhooks"}
|
:id "teams-options-webhooks"}
|
||||||
(tr "labels.webhooks")])
|
(tr "labels.webhooks")])
|
||||||
|
|
||||||
[:> dropdown-menu-item* {:on-click go-settings
|
[:> dropdown-menu-item* {:on-click go-settings
|
||||||
:on-key-down (fn [event]
|
:on-key-down handle-settings
|
||||||
(when (kbd/enter? event)
|
:className (stl/css :team-options-item)
|
||||||
(go-settings)))
|
|
||||||
:id "teams-options-settings"
|
:id "teams-options-settings"
|
||||||
:data-test "team-settings"}
|
:data-test "team-settings"}
|
||||||
(tr "labels.settings")]
|
(tr "labels.settings")]
|
||||||
|
|
||||||
[:hr]
|
[:hr {:class (stl/css :team-option-separator)}]
|
||||||
(when can-rename?
|
(when can-rename?
|
||||||
[:> dropdown-menu-item* {:on-click on-rename-clicked
|
[:> dropdown-menu-item* {:on-click on-rename-clicked
|
||||||
:on-key-down (fn [event]
|
:on-key-down handle-rename
|
||||||
(when (kbd/enter? event)
|
|
||||||
(on-rename-clicked)))
|
|
||||||
:id "teams-options-rename"
|
:id "teams-options-rename"
|
||||||
|
:className (stl/css :team-options-item)
|
||||||
:data-test "rename-team"}
|
:data-test "rename-team"}
|
||||||
(tr "labels.rename")])
|
(tr "labels.rename")])
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(= (count members) 1)
|
(= (count members) 1)
|
||||||
[:> dropdown-menu-item* {:on-click leave-and-close
|
[:> dropdown-menu-item* {:on-click leave-and-close
|
||||||
:on-key-down (fn [event]
|
:on-key-down handle-leave-and-close
|
||||||
(when (kbd/enter? event)
|
:className (stl/css :team-options-item)
|
||||||
(leave-and-close)))
|
|
||||||
:id "teams-options-leave-team"}
|
:id "teams-options-leave-team"}
|
||||||
(tr "dashboard.leave-team")]
|
(tr "dashboard.leave-team")]
|
||||||
|
|
||||||
|
|
||||||
(get-in team [:permissions :is-owner])
|
(get-in team [:permissions :is-owner])
|
||||||
[:> dropdown-menu-item* {:on-click on-leave-as-owner-clicked
|
[:> dropdown-menu-item* {:on-click on-leave-as-owner-clicked
|
||||||
:on-key-down (fn [event]
|
:on-key-down handle-leave-as-owner-clicked
|
||||||
(when (kbd/enter? event)
|
|
||||||
(on-leave-as-owner-clicked)))
|
|
||||||
:id "teams-options-leave-team"
|
:id "teams-options-leave-team"
|
||||||
|
:className (stl/css :team-options-item)
|
||||||
:data-test "leave-team"}
|
:data-test "leave-team"}
|
||||||
(tr "dashboard.leave-team")]
|
(tr "dashboard.leave-team")]
|
||||||
|
|
||||||
(> (count members) 1)
|
(> (count members) 1)
|
||||||
[:> dropdown-menu-item* {:on-click on-leave-clicked
|
[:> dropdown-menu-item* {:on-click on-leave-clicked
|
||||||
:on-key-down (fn [event]
|
:on-key-down handle-on-leave-clicked
|
||||||
(when (kbd/enter? event)
|
:className (stl/css :team-options-item)
|
||||||
(on-leave-clicked)))
|
|
||||||
:id "teams-options-leave-team"}
|
:id "teams-options-leave-team"}
|
||||||
(tr "dashboard.leave-team")])
|
(tr "dashboard.leave-team")])
|
||||||
|
|
||||||
(when (get-in team [:permissions :is-owner])
|
(when (get-in team [:permissions :is-owner])
|
||||||
[:> dropdown-menu-item* {:on-click on-delete-clicked
|
[:> dropdown-menu-item* {:on-click on-delete-clicked
|
||||||
:on-key-down (fn [event]
|
:on-key-down handle-on-delete-clicked
|
||||||
(when (kbd/enter? event)
|
|
||||||
(on-delete-clicked)))
|
|
||||||
:id "teams-options-delete-team"
|
:id "teams-options-delete-team"
|
||||||
:class (stl/css :warning)
|
:className (stl/css :team-options-item :warning)
|
||||||
:data-test "delete-team"}
|
:data-test "delete-team"}
|
||||||
(tr "dashboard.delete-team")])]))
|
(tr "dashboard.delete-team")])]))
|
||||||
|
|
||||||
|
@ -495,6 +606,10 @@
|
||||||
(when first-element
|
(when first-element
|
||||||
(dom/focus! first-element)))))))
|
(dom/focus! first-element)))))))
|
||||||
|
|
||||||
|
close-team-opts-ddwn
|
||||||
|
(mf/use-fn
|
||||||
|
#(reset! show-team-opts-ddwn? false))
|
||||||
|
|
||||||
handle-show-opts-click
|
handle-show-opts-click
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
|
@ -519,34 +634,32 @@
|
||||||
|
|
||||||
[:div {:class (stl/css :sidebar-team-switch)}
|
[:div {:class (stl/css :sidebar-team-switch)}
|
||||||
[:div {:class (stl/css :switch-content)}
|
[:div {:class (stl/css :switch-content)}
|
||||||
[:button
|
[:button {:class (stl/css :current-team)
|
||||||
{:class (stl/css :current-team)
|
|
||||||
:tab-index "0"
|
|
||||||
:on-click handle-show-team-click
|
:on-click handle-show-team-click
|
||||||
:on-key-down handle-show-team-keydown}
|
:on-key-down handle-show-team-keydown}
|
||||||
|
|
||||||
|
|
||||||
(if (:is-default team)
|
(if (:is-default team)
|
||||||
[:div {:class (stl/css :team-name)}
|
[:div {:class (stl/css :team-name)}
|
||||||
[:span {:class (stl/css :team-icon)} i/logo-icon]
|
[:span {:class (stl/css :penpot-icon)} i/logo-icon]
|
||||||
[:span {:class (stl/css :team-text)} (tr "dashboard.default-team-name")]]
|
[:span {:class (stl/css :team-text)} (tr "dashboard.default-team-name")]]
|
||||||
|
|
||||||
[:div {:class (stl/css :team-name)}
|
[:div {:class (stl/css :team-name)}
|
||||||
[:span {:class (stl/css :team-icon)}
|
|
||||||
[:img {:src (cf/resolve-team-photo-url team)
|
[:img {:src (cf/resolve-team-photo-url team)
|
||||||
:alt (:name team)}]]
|
:class (stl/css :team-picture)
|
||||||
|
:alt (:name team)}]
|
||||||
[:span {:class (stl/css :team-text) :title (:name team)} (:name team)]])
|
[:span {:class (stl/css :team-text) :title (:name team)} (:name team)]])
|
||||||
|
|
||||||
[:span {:class (stl/css :switch-icon)} i/arrow-down]]
|
arrow-icon]
|
||||||
|
|
||||||
(when-not (:is-default team)
|
(when-not (:is-default team)
|
||||||
[:button
|
[:button {:class (stl/css :switch-options)
|
||||||
{:class (stl/css :switch-options)
|
|
||||||
:on-click handle-show-opts-click
|
:on-click handle-show-opts-click
|
||||||
:tab-index "0"
|
:tab-index "0"
|
||||||
:on-key-down handle-show-opts-keydown}
|
:on-key-down handle-show-opts-keydown}
|
||||||
i/actions])]
|
menu-icon])]
|
||||||
|
|
||||||
;; Teams Dropdown
|
;; Teams Dropdown
|
||||||
|
|
||||||
[:& dropdown-menu {:show @show-teams-ddwn?
|
[:& dropdown-menu {:show @show-teams-ddwn?
|
||||||
:on-close handle-close-team
|
:on-close handle-close-team
|
||||||
:ids ids
|
:ids ids
|
||||||
|
@ -557,7 +670,7 @@
|
||||||
:teams teams}]]
|
:teams teams}]]
|
||||||
|
|
||||||
[:& dropdown-menu {:show @show-team-opts-ddwn?
|
[:& dropdown-menu {:show @show-team-opts-ddwn?
|
||||||
:on-close #(reset! show-team-opts-ddwn? false)
|
:on-close close-team-opts-ddwn
|
||||||
:ids options-ids
|
:ids options-ids
|
||||||
:list-class (stl/css :dropdown :options-dropdown)}
|
:list-class (stl/css :dropdown :options-dropdown)}
|
||||||
[:& team-options-dropdown {:team team
|
[:& team-options-dropdown {:team team
|
||||||
|
@ -577,12 +690,12 @@
|
||||||
(= (:id project) default-project-id))
|
(= (:id project) default-project-id))
|
||||||
|
|
||||||
go-projects
|
go-projects
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
#(st/emit! (rt/nav :dashboard-projects {:team-id (:id team)})))
|
#(st/emit! (rt/nav :dashboard-projects {:team-id (:id team)})))
|
||||||
|
|
||||||
go-projects-with-key
|
go-projects-with-key
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
#(st/emit! (rt/nav :dashboard-projects {:team-id (:id team)})
|
#(st/emit! (rt/nav :dashboard-projects {:team-id (:id team)})
|
||||||
(ts/schedule-on-idle
|
(ts/schedule-on-idle
|
||||||
|
@ -594,12 +707,12 @@
|
||||||
(dom/set-attribute! projects-title "tabindex" "-1")))))))
|
(dom/set-attribute! projects-title "tabindex" "-1")))))))
|
||||||
|
|
||||||
go-fonts
|
go-fonts
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
#(st/emit! (rt/nav :dashboard-fonts {:team-id (:id team)})))
|
#(st/emit! (rt/nav :dashboard-fonts {:team-id (:id team)})))
|
||||||
|
|
||||||
go-fonts-with-key
|
go-fonts-with-key
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
#(st/emit! (rt/nav :dashboard-fonts {:team-id (:id team)})
|
#(st/emit! (rt/nav :dashboard-fonts {:team-id (:id team)})
|
||||||
(ts/schedule-on-idle
|
(ts/schedule-on-idle
|
||||||
|
@ -610,7 +723,7 @@
|
||||||
(dom/focus! font-title)
|
(dom/focus! font-title)
|
||||||
(dom/set-attribute! font-title "tabindex" "-1")))))))
|
(dom/set-attribute! font-title "tabindex" "-1")))))))
|
||||||
go-drafts
|
go-drafts
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps team default-project-id)
|
(mf/deps team default-project-id)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (rt/nav :dashboard-files
|
(st/emit! (rt/nav :dashboard-files
|
||||||
|
@ -618,7 +731,7 @@
|
||||||
:project-id default-project-id}))))
|
:project-id default-project-id}))))
|
||||||
|
|
||||||
go-drafts-with-key
|
go-drafts-with-key
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps team default-project-id)
|
(mf/deps team default-project-id)
|
||||||
#(st/emit! (rt/nav :dashboard-files {:team-id (:id team)
|
#(st/emit! (rt/nav :dashboard-files {:team-id (:id team)
|
||||||
:project-id default-project-id})
|
:project-id default-project-id})
|
||||||
|
@ -631,12 +744,12 @@
|
||||||
(dom/set-attribute! drafts-title "tabindex" "-1")))))))
|
(dom/set-attribute! drafts-title "tabindex" "-1")))))))
|
||||||
|
|
||||||
go-libs
|
go-libs
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
#(st/emit! (rt/nav :dashboard-libraries {:team-id (:id team)})))
|
#(st/emit! (rt/nav :dashboard-libraries {:team-id (:id team)})))
|
||||||
|
|
||||||
go-libs-with-key
|
go-libs-with-key
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
#(st/emit! (rt/nav :dashboard-libraries {:team-id (:id team)})
|
#(st/emit! (rt/nav :dashboard-libraries {:team-id (:id team)})
|
||||||
(ts/schedule-on-idle
|
(ts/schedule-on-idle
|
||||||
|
@ -653,45 +766,51 @@
|
||||||
|
|
||||||
[:div {:class (stl/css :sidebar-content)}
|
[:div {:class (stl/css :sidebar-content)}
|
||||||
[:& sidebar-team-switch {:team team :profile profile}]
|
[:& sidebar-team-switch {:team team :profile profile}]
|
||||||
[:hr]
|
|
||||||
[:& sidebar-search {:search-term search-term
|
[:& sidebar-search {:search-term search-term
|
||||||
:team-id (:id team)}]
|
:team-id (:id team)}]
|
||||||
|
|
||||||
[:div {:class (stl/css :sidebar-content-section)}
|
[:div {:class (stl/css :sidebar-content-section)}
|
||||||
[:ul {:class (stl/css :sidebar-nav :no-overflow)}
|
[:ul {:class (stl/css :sidebar-nav)}
|
||||||
[:li
|
[:li {:class (stl/css-case :recent-projects true
|
||||||
{:class (stl/css :recent-projects)
|
:sidebar-nav-item true
|
||||||
:class-name (when projects? (stl/css :current))}
|
:current projects?)}
|
||||||
[:& link {:action go-projects
|
[:& link {:action go-projects
|
||||||
|
:class (stl/css :sidebar-link)
|
||||||
:keyboard-action go-projects-with-key}
|
:keyboard-action go-projects-with-key}
|
||||||
[:span {:class (stl/css :element-title)} (tr "labels.projects")]]]
|
[:span {:class (stl/css :element-title)} (tr "labels.projects")]]]
|
||||||
|
|
||||||
[:li {:class-name (when drafts? (stl/css :current))}
|
[:li {:class (stl/css-case :current drafts?
|
||||||
|
:sidebar-nav-item true)}
|
||||||
[:& link {:action go-drafts
|
[:& link {:action go-drafts
|
||||||
|
:class (stl/css :sidebar-link)
|
||||||
:keyboard-action go-drafts-with-key}
|
:keyboard-action go-drafts-with-key}
|
||||||
[:span {:class (stl/css :element-title)} (tr "labels.drafts")]]]
|
[:span {:class (stl/css :element-title)} (tr "labels.drafts")]]]
|
||||||
|
|
||||||
|
|
||||||
[:li {:class-name (when libs? (stl/css :current))}
|
[:li {:class (stl/css-case :current libs?
|
||||||
|
:sidebar-nav-item true)}
|
||||||
[:& link {:action go-libs
|
[:& link {:action go-libs
|
||||||
|
:class (stl/css :sidebar-link)
|
||||||
:keyboard-action go-libs-with-key}
|
:keyboard-action go-libs-with-key}
|
||||||
[:span {:class (stl/css :element-title)} (tr "labels.shared-libraries")]]]]]
|
[:span {:class (stl/css :element-title)} (tr "labels.shared-libraries")]]]]]
|
||||||
|
|
||||||
[:hr]
|
|
||||||
|
|
||||||
[:div {:class (stl/css :sidebar-content-section)}
|
[:div {:class (stl/css :sidebar-content-section)}
|
||||||
[:ul {:class (stl/css :sidebar-nav :no-overflow)}
|
[:ul {:class (stl/css :sidebar-nav)}
|
||||||
[:li {:class-name (when fonts? (stl/css :current))}
|
[:li {:class (stl/css-case :sidebar-nav-item true
|
||||||
|
:current fonts?)}
|
||||||
[:& link {:action go-fonts
|
[:& link {:action go-fonts
|
||||||
|
:class (stl/css :sidebar-link)
|
||||||
:keyboard-action go-fonts-with-key
|
:keyboard-action go-fonts-with-key
|
||||||
:data-test "fonts"}
|
:data-test "fonts"}
|
||||||
[:span {:class (stl/css :element-title)} (tr "labels.fonts")]]]]]
|
[:span {:class (stl/css :element-title)} (tr "labels.fonts")]]]]]
|
||||||
|
|
||||||
[:hr]
|
|
||||||
[:div {:class (stl/css :sidebar-content-section)
|
[:div {:class (stl/css :sidebar-content-section)
|
||||||
:data-test "pinned-projects"}
|
:data-test "pinned-projects"}
|
||||||
(if (seq pinned-projects)
|
(if (seq pinned-projects)
|
||||||
[:ul {:class (stl/css :sidebar-nav)}
|
[:ul {:class (stl/css :sidebar-nav :pinned-projects)}
|
||||||
(for [item pinned-projects]
|
(for [item pinned-projects]
|
||||||
[:& sidebar-project
|
[:& sidebar-project
|
||||||
{:item item
|
{:item item
|
||||||
|
@ -700,25 +819,26 @@
|
||||||
:team-id (:id team)
|
:team-id (:id team)
|
||||||
:selected? (= (:id item) (:id project))}])]
|
:selected? (= (:id item) (:id project))}])]
|
||||||
[:div {:class (stl/css :sidebar-empty-placeholder)}
|
[:div {:class (stl/css :sidebar-empty-placeholder)}
|
||||||
[:span {:class (stl/css :icon)} i/pin-refactor]
|
pin-icon
|
||||||
[:span {:class (stl/css :text)} (tr "dashboard.no-projects-placeholder")]])]]))
|
[:span {:class (stl/css :empty-text)} (tr "dashboard.no-projects-placeholder")]])]]))
|
||||||
|
|
||||||
(mf/defc profile-section
|
(mf/defc profile-section
|
||||||
[{:keys [profile team] :as props}]
|
[{:keys [profile team] :as props}]
|
||||||
(let [show (mf/use-state false)
|
(let [show* (mf/use-state false)
|
||||||
|
show (deref show*)
|
||||||
photo (cf/resolve-profile-photo-url profile)
|
photo (cf/resolve-profile-photo-url profile)
|
||||||
|
|
||||||
on-click
|
on-click
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [section event]
|
(fn [section event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(reset! show false)
|
(reset! show* false)
|
||||||
(if (keyword? section)
|
(if (keyword? section)
|
||||||
(st/emit! (rt/nav section))
|
(st/emit! (rt/nav section))
|
||||||
(st/emit! section))))
|
(st/emit! section))))
|
||||||
|
|
||||||
show-release-notes
|
show-release-notes
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [version (:main cf/version)]
|
(let [version (:main cf/version)]
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "show-release-notes" :version version}))
|
(st/emit! (ptk/event ::ev/event {::ev/name "show-release-notes" :version version}))
|
||||||
|
@ -730,48 +850,48 @@
|
||||||
show-comments? @show-comments*
|
show-comments? @show-comments*
|
||||||
|
|
||||||
handle-hide-comments
|
handle-hide-comments
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(reset! show-comments* false)))
|
(reset! show-comments* false)))
|
||||||
|
|
||||||
handle-show-comments
|
handle-show-comments
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(reset! show-comments* true)))
|
(reset! show-comments* true)))
|
||||||
|
|
||||||
handle-click
|
handle-click
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(swap! show not)))
|
(swap! show* not)))
|
||||||
|
|
||||||
handle-key-down
|
handle-key-down
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
(reset! show true))))
|
(reset! show* true))))
|
||||||
|
|
||||||
handle-close
|
handle-close
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(reset! show false))
|
(reset! show* false))
|
||||||
|
|
||||||
handle-key-down-profile
|
handle-key-down-profile
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps on-click)
|
(mf/deps on-click)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
(on-click :settings-profile event))))
|
(on-click :settings-profile event))))
|
||||||
|
|
||||||
handle-click-url
|
handle-click-url
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [url (-> (dom/get-current-target event)
|
(let [url (-> (dom/get-current-target event)
|
||||||
(dom/get-data "url"))]
|
(dom/get-data "url"))]
|
||||||
(dom/open-new-window url))))
|
(dom/open-new-window url))))
|
||||||
|
|
||||||
handle-keydown-url
|
handle-keydown-url
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [url (-> (dom/get-current-target event)
|
(let [url (-> (dom/get-current-target event)
|
||||||
(dom/get-data "url"))]
|
(dom/get-data "url"))]
|
||||||
|
@ -779,35 +899,41 @@
|
||||||
(dom/open-new-window url)))))
|
(dom/open-new-window url)))))
|
||||||
|
|
||||||
handle-show-release-notes
|
handle-show-release-notes
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps show-release-notes)
|
(mf/deps show-release-notes)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
(show-release-notes))))
|
(show-release-notes))))
|
||||||
|
|
||||||
handle-feedback-click
|
handle-feedback-click
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps on-click)
|
(mf/deps on-click)
|
||||||
#(on-click :settings-feedback %))
|
#(on-click :settings-feedback %))
|
||||||
|
|
||||||
handle-feedback-keydown
|
handle-feedback-keydown
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps on-click)
|
(mf/deps on-click)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
(on-click :settings-feedback event))))
|
(on-click :settings-feedback event))))
|
||||||
|
|
||||||
handle-logout-click
|
handle-logout-click
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps on-click)
|
(mf/deps on-click)
|
||||||
#(on-click (du/logout) %))
|
#(on-click (du/logout) %))
|
||||||
|
|
||||||
handle-logout-keydown
|
handle-logout-keydown
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps on-click)
|
(mf/deps on-click)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
(on-click (du/logout) event))))]
|
(on-click (du/logout) event))))
|
||||||
|
|
||||||
|
handle-set-profile
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps on-click)
|
||||||
|
(fn [event]
|
||||||
|
(on-click :settings-profile event)))]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
(when (and team profile)
|
(when (and team profile)
|
||||||
|
@ -825,77 +951,89 @@
|
||||||
:on-key-down handle-key-down
|
:on-key-down handle-key-down
|
||||||
:data-test "profile-btn"}
|
:data-test "profile-btn"}
|
||||||
[:img {:src photo
|
[:img {:src photo
|
||||||
|
:class (stl/css :profile-img)
|
||||||
:alt (:fullname profile)}]
|
:alt (:fullname profile)}]
|
||||||
[:span (:fullname profile)]]
|
[:span {:class (stl/css :profile-fullname)} (:fullname profile)]]
|
||||||
|
|
||||||
[:& dropdown-menu {:on-close handle-close :show @show}
|
[:& dropdown-menu {:on-close handle-close :show show :list-class (stl/css :profile-dropdown)}
|
||||||
[:ul {:class (stl/css :dropdown)}
|
[:li {:tab-index (if show "0" "-1")
|
||||||
[:li {:tab-index (if @show "0" "-1")
|
:class (stl/css :profile-dropdown-item)
|
||||||
:on-click (partial on-click :settings-profile)
|
:on-click handle-set-profile
|
||||||
:on-key-down handle-key-down-profile
|
:on-key-down handle-key-down-profile
|
||||||
:data-test "profile-profile-opt"}
|
:data-test "profile-profile-opt"}
|
||||||
[:span {:class (stl/css :text)} (tr "labels.your-account")]]
|
(tr "labels.your-account")]
|
||||||
|
|
||||||
[:li {:class (stl/css :separator)
|
[:li {:class (stl/css :profile-separator)}]
|
||||||
:tab-index (if @show "0" "-1")
|
|
||||||
|
[:li {:class (stl/css :profile-dropdown-item)
|
||||||
|
:tab-index (if show "0" "-1")
|
||||||
:data-url "https://help.penpot.app"
|
:data-url "https://help.penpot.app"
|
||||||
:on-click handle-click-url
|
:on-click handle-click-url
|
||||||
:on-key-down handle-keydown-url
|
:on-key-down handle-keydown-url
|
||||||
:data-test "help-center-profile-opt"}
|
:data-test "help-center-profile-opt"}
|
||||||
[:span {:class (stl/css :text)} (tr "labels.help-center")]]
|
(tr "labels.help-center")]
|
||||||
|
|
||||||
[:li {:tab-index (if @show "0" "-1")
|
[:li {:tab-index (if show "0" "-1")
|
||||||
|
:class (stl/css :profile-dropdown-item)
|
||||||
:data-url "https://community.penpot.app"
|
:data-url "https://community.penpot.app"
|
||||||
:on-click handle-click-url
|
:on-click handle-click-url
|
||||||
:on-key-down handle-keydown-url}
|
:on-key-down handle-keydown-url}
|
||||||
[:span {:class (stl/css :text)} (tr "labels.community")]]
|
(tr "labels.community")]
|
||||||
|
|
||||||
[:li {:tab-index (if @show "0" "-1")
|
[:li {:tab-index (if show "0" "-1")
|
||||||
|
:class (stl/css :profile-dropdown-item)
|
||||||
:data-url "https://www.youtube.com/c/Penpot"
|
:data-url "https://www.youtube.com/c/Penpot"
|
||||||
:on-click handle-click-url
|
:on-click handle-click-url
|
||||||
:on-key-down handle-keydown-url}
|
:on-key-down handle-keydown-url}
|
||||||
[:span {:class (stl/css :text)} (tr "labels.tutorials")]]
|
(tr "labels.tutorials")]
|
||||||
|
|
||||||
[:li {:tab-index (if @show "0" "-1")
|
[:li {:tab-index (if show "0" "-1")
|
||||||
|
:class (stl/css :profile-dropdown-item)
|
||||||
:on-click show-release-notes
|
:on-click show-release-notes
|
||||||
:on-key-down handle-show-release-notes}
|
:on-key-down handle-show-release-notes}
|
||||||
[:span {:class (stl/css :text)} (tr "labels.release-notes")]]
|
(tr "labels.release-notes")]
|
||||||
|
|
||||||
[:li {:class (stl/css :separator)
|
[:li {:class (stl/css :profile-separator)}]
|
||||||
:tab-index (if @show "0" "-1")
|
|
||||||
|
[:li {:class (stl/css :profile-dropdown-item)
|
||||||
|
:tab-index (if show "0" "-1")
|
||||||
:data-url "https://penpot.app/libraries-templates"
|
:data-url "https://penpot.app/libraries-templates"
|
||||||
:on-click handle-click-url
|
:on-click handle-click-url
|
||||||
:on-key-down handle-keydown-url
|
:on-key-down handle-keydown-url
|
||||||
:data-test "libraries-templates-profile-opt"}
|
:data-test "libraries-templates-profile-opt"}
|
||||||
[:span {:class (stl/css :text)} (tr "labels.libraries-and-templates")]]
|
(tr "labels.libraries-and-templates")]
|
||||||
|
|
||||||
[:li {:tab-index (if @show "0" "-1")
|
[:li {:tab-index (if show "0" "-1")
|
||||||
|
:class (stl/css :profile-dropdown-item)
|
||||||
:data-url "https://github.com/penpot/penpot"
|
:data-url "https://github.com/penpot/penpot"
|
||||||
:on-click handle-click-url
|
:on-click handle-click-url
|
||||||
:on-key-down handle-keydown-url}
|
:on-key-down handle-keydown-url}
|
||||||
[:span {:class (stl/css :text)} (tr "labels.github-repo")]]
|
(tr "labels.github-repo")]
|
||||||
|
|
||||||
[:li {:tab-index (if @show "0" "-1")
|
[:li {:tab-index (if show "0" "-1")
|
||||||
|
:class (stl/css :profile-dropdown-item)
|
||||||
:data-url "https://penpot.app/terms"
|
:data-url "https://penpot.app/terms"
|
||||||
:on-click handle-click-url
|
:on-click handle-click-url
|
||||||
:on-key-down handle-keydown-url}
|
:on-key-down handle-keydown-url}
|
||||||
[:span {:class (stl/css :text)} (tr "auth.terms-of-service")]]
|
(tr "auth.terms-of-service")]
|
||||||
|
|
||||||
|
[:li {:class (stl/css :profile-separator)}]
|
||||||
|
|
||||||
(when (contains? cf/flags :user-feedback)
|
(when (contains? cf/flags :user-feedback)
|
||||||
[:li {:class (stl/css :separator)
|
[:li {:class (stl/css :profile-dropdown-item)
|
||||||
:tab-index (if @show "0" "-1")
|
:tab-index (if show "0" "-1")
|
||||||
:on-click handle-feedback-click
|
:on-click handle-feedback-click
|
||||||
:on-key-down handle-feedback-keydown
|
:on-key-down handle-feedback-keydown
|
||||||
:data-test "feedback-profile-opt"}
|
:data-test "feedback-profile-opt"}
|
||||||
[:span {:class (stl/css :text)} (tr "labels.give-feedback")]])
|
(tr "labels.give-feedback")])
|
||||||
|
|
||||||
[:li {:class (stl/css :separator)
|
[:li {:class (stl/css :profile-dropdown-item :item-with-icon)
|
||||||
:tab-index (if @show "0" "-1")
|
:tab-index (if show "0" "-1")
|
||||||
:on-click handle-logout-click
|
:on-click handle-logout-click
|
||||||
:on-key-down handle-logout-keydown
|
:on-key-down handle-logout-keydown
|
||||||
:data-test "logout-profile-opt"}
|
:data-test "logout-profile-opt"}
|
||||||
[:span {:class (stl/css :icon)} i/exit]
|
exit-icon
|
||||||
[:span {:class (stl/css :text)} (tr "labels.logout")]]]]
|
(tr "labels.logout")]]
|
||||||
|
|
||||||
(when (and team profile)
|
(when (and team profile)
|
||||||
[:& comments-icon
|
[:& comments-icon
|
||||||
|
|
|
@ -7,498 +7,375 @@
|
||||||
@use "common/refactor/common-refactor.scss" as *;
|
@use "common/refactor/common-refactor.scss" as *;
|
||||||
@use "common/refactor/common-dashboard";
|
@use "common/refactor/common-dashboard";
|
||||||
|
|
||||||
|
// SIDEBAR COMPONENT
|
||||||
.dashboard-sidebar {
|
.dashboard-sidebar {
|
||||||
grid-row: 1 / span 2;
|
grid-row: 1 / span 2;
|
||||||
grid-column: 1 / span 2;
|
grid-column: 1 / span 2;
|
||||||
|
display: grid;
|
||||||
background-color: var(--panel-background-color);
|
grid-template-rows: 1fr auto;
|
||||||
border-right: $s-1 solid $db-quaternary;
|
height: 100%;
|
||||||
margin: 0 $s-16 0 0;
|
width: 100%;
|
||||||
padding: $s-16 0 0 0;
|
padding: $s-16 0 0 0;
|
||||||
|
margin: 0 $s-16 0 0;
|
||||||
|
border-right: $s-1 solid var(--panel-border-color);
|
||||||
|
background-color: var(--panel-background-color);
|
||||||
z-index: $z-index-1;
|
z-index: $z-index-1;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//SIDEBAR CONTENT COMPONENT
|
||||||
.sidebar-content {
|
.sidebar-content {
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: column;
|
grid-template-rows: auto auto auto auto 1fr;
|
||||||
|
gap: $s-24;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
overflow-y: auto;
|
||||||
hr {
|
|
||||||
border-color: transparent;
|
|
||||||
margin: $s-12 $s-16;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SIDEBAR TEAM SWITCH
|
||||||
.sidebar-team-switch {
|
.sidebar-team-switch {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
|
||||||
margin: $s-4 $s-16;
|
margin: $s-4 $s-16;
|
||||||
|
}
|
||||||
|
|
||||||
.switch-content {
|
.switch-content {
|
||||||
background-color: $db-tertiary;
|
display: grid;
|
||||||
border-radius: $br-8;
|
grid-template-columns: 1fr auto;
|
||||||
|
align-items: center;
|
||||||
height: $s-48;
|
height: $s-48;
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: $s-1 solid $db-tertiary;
|
border-radius: $br-8;
|
||||||
|
border: $s-1 solid var(--menu-background-color);
|
||||||
|
background-color: var(--menu-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-team {
|
||||||
|
@include buttonStyle;
|
||||||
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
svg {
|
gap: $s-8;
|
||||||
fill: #8f9da3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-icon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $df-secondary;
|
|
||||||
width: $s-12;
|
|
||||||
height: $s-12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.current-team {
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-grow: 1;
|
|
||||||
font-size: $fs-14;
|
|
||||||
padding: 0 $s-12;
|
padding: 0 $s-12;
|
||||||
background-color: transparent;
|
}
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-name {
|
.team-name {
|
||||||
flex-grow: 1;
|
display: grid;
|
||||||
display: flex;
|
align-items: center;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
gap: $s-12;
|
||||||
height: $s-40;
|
height: $s-40;
|
||||||
align-items: center;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.team-text {
|
.team-text {
|
||||||
color: $df-primary;
|
@include textEllipsis;
|
||||||
|
@include smallTitleTipography;
|
||||||
width: $s-144;
|
width: $s-144;
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
color: var(--menu-foreground-color-hover);
|
||||||
|
}
|
||||||
.team-icon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-right: $s-12;
|
|
||||||
|
|
||||||
img {
|
|
||||||
border-radius: 50%;
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: $s-24;
|
|
||||||
width: $s-24;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// This icon still use the old svg
|
||||||
|
.penpot-icon {
|
||||||
|
@include flexCenter;
|
||||||
svg {
|
svg {
|
||||||
|
fill: var(--icon-foreground);
|
||||||
width: $s-24;
|
width: $s-24;
|
||||||
height: $s-24;
|
height: $s-24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.switch-options {
|
.team-picture {
|
||||||
|
@include flexCenter;
|
||||||
|
border-radius: 50%;
|
||||||
|
height: $s-24;
|
||||||
|
width: $s-24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow-icon {
|
||||||
|
@extend .button-icon;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
stroke: var(--icon-foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-options {
|
||||||
@include buttonStyle;
|
@include buttonStyle;
|
||||||
@include flexCenter;
|
@include flexCenter;
|
||||||
max-width: $s-24;
|
max-width: $s-24;
|
||||||
min-width: $s-28;
|
min-width: $s-28;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-left: $s-1 solid $db-primary;
|
border-left: $s-1 solid var(--panel-background-color);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
svg {
|
.menu-icon {
|
||||||
fill: $df-secondary;
|
@extend .button-icon;
|
||||||
width: $s-16;
|
stroke: var(--icon-foreground);
|
||||||
height: $s-12;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown {
|
// DROPDOWNS
|
||||||
|
|
||||||
|
.teams-dropdown {
|
||||||
|
@extend .menu-dropdown;
|
||||||
|
left: 0;
|
||||||
|
top: $s-52;
|
||||||
|
height: fit-content;
|
||||||
|
max-height: $s-480;
|
||||||
|
min-width: $s-248;
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-dropdown-item {
|
||||||
|
@extend .menu-item-base;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: $s-24 1fr auto;
|
||||||
|
gap: $s-8;
|
||||||
|
height: $s-40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action {
|
||||||
|
--sidebar-action-icon-color: var(--icon-foreground);
|
||||||
|
--sidebar-icon-backgroun-color: var(--color-background-secondary);
|
||||||
|
&:hover {
|
||||||
|
--sidebar-action-icon-color: var(--color-background-secondary);
|
||||||
|
--sidebar-icon-backgroun-color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-wrapper {
|
||||||
|
@include flexCenter;
|
||||||
|
width: $s-24;
|
||||||
|
height: $s-24;
|
||||||
|
margin-right: $s-12;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--sidebar-icon-backgroun-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-icon {
|
||||||
|
@extend .button-icon;
|
||||||
|
width: $s-24;
|
||||||
|
height: $s-24;
|
||||||
|
stroke: var(--sidebar-action-icon-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-separator {
|
||||||
|
border-top: $s-1 solid var(--dropdown-separator-color);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tick-icon {
|
||||||
|
@extend .button-icon-small;
|
||||||
|
stroke: var(--icon-foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.options-dropdown {
|
||||||
|
@extend .menu-dropdown;
|
||||||
right: $s-2;
|
right: $s-2;
|
||||||
top: $s-52;
|
top: $s-52;
|
||||||
max-height: $s-480;
|
max-height: $s-480;
|
||||||
&:not(.teams-dropdown) {
|
&:not(.teams-dropdown) {
|
||||||
min-width: $s-160;
|
min-width: $s-160;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown {
|
.team-options-item {
|
||||||
@include menuShadow;
|
@extend .menu-item-base;
|
||||||
position: absolute;
|
|
||||||
z-index: $z-index-4;
|
|
||||||
background-color: $db-tertiary;
|
|
||||||
border: $s-1 solid $db-quaternary;
|
|
||||||
border-radius: $br-8;
|
|
||||||
|
|
||||||
.separator {
|
|
||||||
border-color: transparent;
|
|
||||||
margin-top: $s-12;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
border-radius: $br-8;
|
|
||||||
height: $s-40;
|
height: $s-40;
|
||||||
margin: $s-6;
|
}
|
||||||
|
|
||||||
display: flex;
|
.team-option-separator {
|
||||||
align-items: center;
|
height: $s-1;
|
||||||
cursor: pointer;
|
|
||||||
font-size: $fs-14;
|
|
||||||
padding: $s-6 $s-16;
|
|
||||||
|
|
||||||
.warning {
|
|
||||||
color: var(--element-foreground-warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $db-quaternary;
|
|
||||||
}
|
|
||||||
svg {
|
|
||||||
height: $s-12;
|
|
||||||
width: $s-12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
border-color: transparent;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
border-top: $s-1 solid var(--dropdown-separator-color);
|
||||||
|
|
||||||
&.options-dropdown {
|
|
||||||
li {
|
|
||||||
color: $df-primary;
|
|
||||||
&.warning {
|
|
||||||
color: var(--element-foreground-warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.teams-dropdown {
|
|
||||||
background-color: $db-tertiary;
|
|
||||||
border-radius: $br-8;
|
|
||||||
border: $s-1 solid $db-quaternary;
|
|
||||||
min-width: $s-248;
|
|
||||||
|
|
||||||
left: 0;
|
|
||||||
top: $s-52;
|
|
||||||
|
|
||||||
max-height: $s-480;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
li {
|
|
||||||
border-radius: $br-8;
|
|
||||||
height: $s-40;
|
|
||||||
padding: 0 $s-6;
|
|
||||||
margin: $s-6;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $df-secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $db-quaternary;
|
|
||||||
.team-icon {
|
|
||||||
&.new-team {
|
|
||||||
background-color: $da-primary;
|
|
||||||
color: $db-primary;
|
|
||||||
svg {
|
|
||||||
fill: $db-secondary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.team-icon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.team-text {
|
|
||||||
color: $df-primary;
|
|
||||||
width: $s-168;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.action {
|
|
||||||
.team-icon {
|
|
||||||
background-color: #2e3434;
|
|
||||||
background-color: var(--new-team-button-background-color);
|
|
||||||
border-radius: 50%;
|
|
||||||
height: $s-24;
|
|
||||||
margin-right: $s-12;
|
|
||||||
padding: $s-6;
|
|
||||||
width: $s-24;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
height: $s-12;
|
|
||||||
width: $s-12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-empty-placeholder {
|
|
||||||
padding: $s-12;
|
|
||||||
color: $df-secondary;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
padding: 0 $s-12;
|
|
||||||
svg {
|
|
||||||
fill: none;
|
|
||||||
stroke: currentColor;
|
|
||||||
width: $s-12;
|
|
||||||
height: $s-12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.text {
|
|
||||||
font-size: $fs-12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-search {
|
|
||||||
align-items: center;
|
|
||||||
border: $s-1 solid transparent;
|
|
||||||
display: flex;
|
|
||||||
margin: $s-6 $s-16;
|
|
||||||
|
|
||||||
background-color: $db-tertiary;
|
|
||||||
border-radius: $br-8;
|
|
||||||
margin-bottom: $s-32;
|
|
||||||
margin-top: 0;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.input-text {
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
font-size: $fs-14;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: $s-40;
|
|
||||||
|
|
||||||
border-radius: $br-8;
|
|
||||||
color: $df-primary;
|
|
||||||
max-width: 100%;
|
|
||||||
padding: $s-6 $s-12;
|
|
||||||
|
|
||||||
&:focus,
|
|
||||||
&:focus-within {
|
|
||||||
border: $s-1 solid $da-primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
::placeholder {
|
|
||||||
color: $df-secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search,
|
|
||||||
.clear-search {
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
height: $s-24;
|
|
||||||
margin-left: auto;
|
|
||||||
padding: 0 $s-8;
|
|
||||||
width: $s-32;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
top: calc(50% - $s-12);
|
|
||||||
right: $s-2;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $df-secondary;
|
|
||||||
height: $s-16;
|
|
||||||
width: $s-16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.clear-search svg {
|
|
||||||
transform: rotate(45deg);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
fill: $da-primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sections
|
||||||
.sidebar-nav {
|
.sidebar-nav {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow-y: auto;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
overflow: none;
|
||||||
|
}
|
||||||
|
|
||||||
&.no-overflow {
|
.pinned-projects {
|
||||||
overflow: unset;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > li {
|
.sidebar-nav-item {
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
&:hover {
|
||||||
flex-shrink: 0;
|
background-color: var(--sidebar-element-background-color-hover);
|
||||||
|
span {
|
||||||
&.project-element {
|
color: var(--sidebar-element-foreground-color-hover);
|
||||||
padding: $s-8 $s-8 $s-8 $s-24;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
&.current {
|
||||||
|
background-color: var(--sidebar-element-background-color-selected);
|
||||||
|
.element-title {
|
||||||
|
color: var(--sidebar-element-foreground-color-selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.recent-projects svg {
|
||||||
|
stroke: var(--main-icon-foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-link {
|
||||||
|
display: block;
|
||||||
padding: $s-8 $s-8 $s-8 $s-24;
|
padding: $s-8 $s-8 $s-8 $s-24;
|
||||||
font-weight: $fw400;
|
font-weight: $fw400;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
.project-element {
|
||||||
fill: $db-secondary;
|
padding: $s-8 $s-8 $s-8 $s-24;
|
||||||
margin-right: $s-8;
|
}
|
||||||
height: $s-12;
|
|
||||||
width: $s-12;
|
|
||||||
}
|
|
||||||
|
|
||||||
.element-title {
|
.element-title {
|
||||||
color: $df-secondary;
|
@include textEllipsis;
|
||||||
|
color: var(--sidebar-element-foreground-color);
|
||||||
font-size: $fs-14;
|
font-size: $fs-14;
|
||||||
overflow: hidden;
|
}
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.recent-projects {
|
// Pinned projects
|
||||||
svg {
|
|
||||||
fill: $df-primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input.element-title {
|
.sidebar-empty-placeholder {
|
||||||
border: 0;
|
padding: $s-12;
|
||||||
height: $s-32;
|
color: var(--empty-message-foreground-color);
|
||||||
padding: $s-6;
|
display: flex;
|
||||||
margin: 0;
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pin-icon {
|
||||||
|
@extend .button-icon-small;
|
||||||
|
stroke: var(--icon-foreground);
|
||||||
|
margin: 0 $s-12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: $fs-12;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search
|
||||||
|
|
||||||
|
.sidebar-search {
|
||||||
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
align-items: center;
|
||||||
|
border: $s-1 solid transparent;
|
||||||
|
margin: 0 $s-16;
|
||||||
|
border-radius: $br-8;
|
||||||
|
background-color: var(--search-bar-input-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-text {
|
||||||
|
@include smallTitleTipography;
|
||||||
|
height: $s-40;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: $df-primary;
|
padding: $s-6 $s-12;
|
||||||
}
|
|
||||||
|
|
||||||
.close {
|
|
||||||
background-color: $df-primary;
|
|
||||||
cursor: pointer;
|
|
||||||
padding-left: $s-6;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $df-secondary;
|
|
||||||
height: $s-16;
|
|
||||||
transform: rotate(45deg) translateY(7px);
|
|
||||||
width: $s-16;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
border: transparent;
|
||||||
}
|
border-radius: $br-8;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--search-bar-foreground-color);
|
||||||
|
|
||||||
.element-subtitle {
|
&:focus,
|
||||||
color: $df-secondary;
|
&:focus-within,
|
||||||
font-style: italic;
|
&:focus-visible {
|
||||||
}
|
outline: none;
|
||||||
|
border: $s-1 solid var(--search-bar-input-border-color-focus);
|
||||||
&:hover {
|
|
||||||
background-color: $db-secondary;
|
|
||||||
span {
|
|
||||||
color: $da-primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.current {
|
|
||||||
background-color: $db-quaternary;
|
|
||||||
.element-title {
|
|
||||||
color: $da-primary;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
::placeholder {
|
||||||
|
color: var(--search-bar-placeholder-foreground-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-btn {
|
||||||
|
@include buttonStyle;
|
||||||
|
@include flexCenter;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
height: $s-24;
|
||||||
|
width: $s-32;
|
||||||
|
padding: 0 $s-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon,
|
||||||
|
.clear-search-btn {
|
||||||
|
@extend .button-icon;
|
||||||
|
--sidebar-search-foreground-color: var(--search-bar-icon-foreground-color);
|
||||||
|
stroke: var(--sidebar-search-foreground-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear-search-btn:hover {
|
||||||
|
--sidebar-search-foreground-color: var(--search-bar-icon-foreground-color-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Profile
|
||||||
.profile-section {
|
.profile-section {
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
padding: $s-12 $s-16;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: grid;
|
||||||
background-color: $db-tertiary;
|
grid-template-columns: 1fr auto;
|
||||||
border-top: $s-1 solid $db-quaternary;
|
padding: $s-12 $s-16;
|
||||||
|
border-top: $s-1 solid var(--panel-border-color);
|
||||||
.profile {
|
background-color: var(--profile-section-background-color);
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
}
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
span {
|
.profile {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
gap: $s-8;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-fullname {
|
||||||
|
@include smallTitleTipography;
|
||||||
@include text-ellipsis;
|
@include text-ellipsis;
|
||||||
color: $df-primary;
|
align-self: center;
|
||||||
margin: $s-12;
|
|
||||||
font-size: $fs-14;
|
|
||||||
max-width: $s-160;
|
max-width: $s-160;
|
||||||
}
|
color: var(--profile-foreground-color);
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
.profile-img {
|
||||||
border-radius: 50%;
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: $s-40;
|
height: $s-40;
|
||||||
width: $s-40;
|
width: $s-40;
|
||||||
}
|
border-radius: $br-circle;
|
||||||
svg {
|
}
|
||||||
height: $s-12;
|
|
||||||
margin-left: auto;
|
.profile-dropdown {
|
||||||
margin-right: $s-8;
|
@extend .menu-dropdown;
|
||||||
width: $s-12;
|
left: $s-16;
|
||||||
}
|
bottom: $s-72;
|
||||||
}
|
min-width: $s-252;
|
||||||
|
// TODO ADD animation fadeInUp
|
||||||
.dropdown {
|
}
|
||||||
left: $s-16;
|
|
||||||
bottom: $s-44;
|
.profile-dropdown-item {
|
||||||
background-color: var(--profile-drowpdown-background-color);
|
@extend .menu-item-base;
|
||||||
border: $s-1 solid $db-tertiary;
|
@include smallTitleTipography;
|
||||||
border-radius: $br-8;
|
height: $s-40;
|
||||||
min-width: $s-252;
|
padding: $s-8 $s-16;
|
||||||
|
}
|
||||||
@include animation(0, 0.2s, fadeInUp);
|
|
||||||
|
.profile-separator {
|
||||||
li {
|
height: $s-6;
|
||||||
font-size: $fs-14;
|
}
|
||||||
padding: $s-8 $s-16;
|
|
||||||
|
.item-with-icon {
|
||||||
svg {
|
display: grid;
|
||||||
fill: $df-secondary;
|
grid-template-columns: auto 1fr;
|
||||||
margin-right: $s-8;
|
gap: $s-8;
|
||||||
|
}
|
||||||
height: $s-12;
|
|
||||||
width: $s-12;
|
.exit-icon {
|
||||||
}
|
@extend .button-icon;
|
||||||
|
stroke: var(--icon-foreground);
|
||||||
.text {
|
|
||||||
color: $df-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.separator {
|
|
||||||
border-top: $s-1 solid transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,9 @@
|
||||||
|
|
||||||
[:div {:class (stl/css :modal-overlay)}
|
[:div {:class (stl/css :modal-overlay)}
|
||||||
[:div {:class (stl/css :modal-container)}
|
[:div {:class (stl/css :modal-container)}
|
||||||
[:& fm/form {:form form :on-submit on-submit}
|
[:& fm/form {:form form
|
||||||
|
:on-submit on-submit
|
||||||
|
:class (stl/css :team-form)}
|
||||||
|
|
||||||
[:div {:class (stl/css :modal-header)}
|
[:div {:class (stl/css :modal-header)}
|
||||||
(if team
|
(if team
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
margin-bottom: $s-24;
|
margin-bottom: $s-24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.team-form {
|
||||||
|
min-width: $s-400;
|
||||||
|
}
|
||||||
|
|
||||||
.group-name-input {
|
.group-name-input {
|
||||||
@extend .input-element-label;
|
@extend .input-element-label;
|
||||||
label {
|
label {
|
||||||
|
@ -44,7 +48,6 @@
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@include bodySmallTypography;
|
@include bodySmallTypography;
|
||||||
margin-top: $s-8;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,6 +348,7 @@
|
||||||
(def ^:icon easing-ease-in-out-refactor (icon-xref :easing-ease-in-out-refactor))
|
(def ^:icon easing-ease-in-out-refactor (icon-xref :easing-ease-in-out-refactor))
|
||||||
(def ^:icon effects-refactor (icon-xref :effects-refactor))
|
(def ^:icon effects-refactor (icon-xref :effects-refactor))
|
||||||
(def ^:icon elipse-refactor (icon-xref :elipse-refactor))
|
(def ^:icon elipse-refactor (icon-xref :elipse-refactor))
|
||||||
|
(def ^:icon exit-refactor (icon-xref :exit-refactor))
|
||||||
(def ^:icon expand-refactor (icon-xref :expand-refactor))
|
(def ^:icon expand-refactor (icon-xref :expand-refactor))
|
||||||
(def ^:icon feedback-refactor (icon-xref :feedback-refactor))
|
(def ^:icon feedback-refactor (icon-xref :feedback-refactor))
|
||||||
(def ^:icon fill-content-refactor (icon-xref :fill-content-refactor))
|
(def ^:icon fill-content-refactor (icon-xref :fill-content-refactor))
|
||||||
|
@ -394,6 +395,7 @@
|
||||||
(def ^:icon layers-refactor (icon-xref :layers-refactor))
|
(def ^:icon layers-refactor (icon-xref :layers-refactor))
|
||||||
(def ^:icon locate-refactor (icon-xref :locate-refactor))
|
(def ^:icon locate-refactor (icon-xref :locate-refactor))
|
||||||
(def ^:icon lock-refactor (icon-xref :lock-refactor))
|
(def ^:icon lock-refactor (icon-xref :lock-refactor))
|
||||||
|
(def ^:icon logo-refactor (icon-xref :penpot-logo-icon)) ;; This icon will not change
|
||||||
(def ^:icon library-refactor (icon-xref :library-refactor))
|
(def ^:icon library-refactor (icon-xref :library-refactor))
|
||||||
(def ^:icon margin-bottom-refactor (icon-xref :margin-bottom-refactor))
|
(def ^:icon margin-bottom-refactor (icon-xref :margin-bottom-refactor))
|
||||||
(def ^:icon margin-left-refactor (icon-xref :margin-left-refactor))
|
(def ^:icon margin-left-refactor (icon-xref :margin-left-refactor))
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
:links (:links message)
|
:links (:links message)
|
||||||
:content (:content message)}
|
:content (:content message)}
|
||||||
|
|
||||||
|
is-context-msg (and (nil? (:timeout message)) (nil? (:actions message)))
|
||||||
is-toast-msg (or (= :toast (:notification-type message)) (some? (:timeout message)))
|
is-toast-msg (or (= :toast (:notification-type message)) (some? (:timeout message)))
|
||||||
is-inline-msg (or (= :inline (:notification-type message)) (and (some? (:position message)) (= :floating (:position message))))]
|
is-inline-msg (or (= :inline (:notification-type message)) (and (some? (:position message)) (= :floating (:position message))))]
|
||||||
|
|
||||||
|
@ -42,5 +43,7 @@
|
||||||
[:& toast-notification toast-message]
|
[:& toast-notification toast-message]
|
||||||
is-inline-msg
|
is-inline-msg
|
||||||
[:& inline-notification inline-message]
|
[:& inline-notification inline-message]
|
||||||
|
is-context-msg
|
||||||
|
[:& context-notification context-message]
|
||||||
:else
|
:else
|
||||||
[:& context-notification context-message]))))
|
[:& toast-notification toast-message]))))
|
||||||
|
|
|
@ -44,10 +44,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
--bg-color: var(--alert-background-color-info);
|
--toast-notification-bg-color: var(--alert-background-color-info);
|
||||||
--fg-color: var(--alert-text-foreground-color-info);
|
--toast-notification-fg-color: var(--alert-text-foreground-color-info);
|
||||||
--icon-color: var(--alert-icon-foreground-color-info);
|
--toast-notification-icon-color: var(--alert-icon-foreground-color-info);
|
||||||
--border-color: var(--alert-border-color-info);
|
--toast-notification-border-color: var(--alert-border-color-info);
|
||||||
}
|
}
|
||||||
|
|
||||||
.default {
|
.default {
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
(let [valign (:vertical-align node "top")
|
(let [valign (:vertical-align node "top")
|
||||||
base #js {:height (fmt/format-pixels height)
|
base #js {:height (fmt/format-pixels height)
|
||||||
:width (fmt/format-pixels width)
|
:width (fmt/format-pixels width)
|
||||||
:fontFamily "sourcesanspro"
|
|
||||||
:display "flex"
|
:display "flex"
|
||||||
:whiteSpace "break-spaces"}]
|
:whiteSpace "break-spaces"}]
|
||||||
(cond-> base
|
(cond-> base
|
||||||
|
|
|
@ -135,6 +135,7 @@
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(wapi/write-to-clipboard current-link)
|
(wapi/write-to-clipboard current-link)
|
||||||
(st/emit! (msg/show {:type :info
|
(st/emit! (msg/show {:type :info
|
||||||
|
:notification-type :toast
|
||||||
:content (tr "common.share-link.link-copied-success")
|
:content (tr "common.share-link.link-copied-success")
|
||||||
:timeout 1000})))
|
:timeout 1000})))
|
||||||
|
|
||||||
|
|
|
@ -107,9 +107,9 @@
|
||||||
(-> (image-size href)
|
(-> (image-size href)
|
||||||
(p/then
|
(p/then
|
||||||
(fn [{:keys [width height]}]
|
(fn [{:keys [width height]}]
|
||||||
(when (or (not (mth/close? width fixed-width 2))
|
(when (or (not (mth/close? width fixed-width 5))
|
||||||
(not (mth/close? height fixed-height 2)))
|
(not (mth/close? height fixed-height 5)))
|
||||||
(st/emit! (dwt/request-thumbnail file-id page-id frame-id "frame"))))))))
|
(st/emit! (dwt/request-thumbnail file-id page-id frame-id "frame" "check-thumbnail-size"))))))))
|
||||||
|
|
||||||
(defn root-frame-wrapper-factory
|
(defn root-frame-wrapper-factory
|
||||||
[shape-wrapper]
|
[shape-wrapper]
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
(when-not (some? thumbnail-uri)
|
(when-not (some? thumbnail-uri)
|
||||||
(tm/schedule-on-idle
|
(tm/schedule-on-idle
|
||||||
#(st/emit! (dwt/request-thumbnail file-id page-id frame-id "frame"))))
|
#(st/emit! (dwt/request-thumbnail file-id page-id frame-id "frame" "root-frame"))))
|
||||||
#(when-let [task (mf/ref-val task-ref)]
|
#(when-let [task (mf/ref-val task-ref)]
|
||||||
(d/close! task)))
|
(d/close! task)))
|
||||||
|
|
||||||
|
|
|
@ -224,10 +224,10 @@
|
||||||
:on-double-click rename-color-clicked}
|
:on-double-click rename-color-clicked}
|
||||||
|
|
||||||
(if (= (:name color) default-name)
|
(if (= (:name color) default-name)
|
||||||
[:span {:class (stl/css :default-name-only)} default-name]
|
[:span {:class (stl/css :default-name)} default-name]
|
||||||
[:*
|
[:*
|
||||||
[:span {:class (stl/css :name)} (:name color)]
|
(:name color)
|
||||||
[:span {:class (stl/css :default-name)} default-name]])])
|
[:span {:class (stl/css :default-name :default-name-with-color)} default-name]])])
|
||||||
|
|
||||||
(when local?
|
(when local?
|
||||||
[:& cmm/assets-context-menu
|
[:& cmm/assets-context-menu
|
||||||
|
|
|
@ -6,10 +6,15 @@
|
||||||
|
|
||||||
@import "refactor/common-refactor.scss";
|
@import "refactor/common-refactor.scss";
|
||||||
|
|
||||||
|
// TODO: we should be using subgrid in the common "assets component" to avoid
|
||||||
|
// using this SCSS variable here (we cannot use a CSS var in this CSS module because
|
||||||
|
// the elements are not part of the same cascade).
|
||||||
|
$assets-button-width: $s-28;
|
||||||
|
|
||||||
.assets-btn {
|
.assets-btn {
|
||||||
@extend .button-tertiary;
|
@extend .button-tertiary;
|
||||||
height: $s-32;
|
height: $s-32;
|
||||||
width: $s-28;
|
width: $assets-button-width;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: $br-8;
|
border-radius: $br-8;
|
||||||
svg {
|
svg {
|
||||||
|
@ -28,10 +33,12 @@
|
||||||
|
|
||||||
.asset-list-item {
|
.asset-list-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr #{$assets-button-width};
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: $s-32;
|
height: $s-32;
|
||||||
padding: $s-8;
|
padding: $s-8;
|
||||||
|
padding-inline-end: 0;
|
||||||
margin-bottom: $s-4;
|
margin-bottom: $s-4;
|
||||||
border-radius: $br-8;
|
border-radius: $br-8;
|
||||||
background-color: var(--assets-item-background-color);
|
background-color: var(--assets-item-background-color);
|
||||||
|
@ -48,7 +55,6 @@
|
||||||
@include bodySmallTypography;
|
@include bodySmallTypography;
|
||||||
@include removeInputStyle;
|
@include removeInputStyle;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
height: $s-28;
|
|
||||||
max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
|
max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: var(--layer-row-foreground-color);
|
color: var(--layer-row-foreground-color);
|
||||||
|
@ -63,25 +69,23 @@
|
||||||
@include flexCenter;
|
@include flexCenter;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
margin-right: $s-4;
|
margin-inline-end: $s-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name-block {
|
.name-block {
|
||||||
@include bodySmallTypography;
|
@include bodySmallTypography;
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto 1fr;
|
|
||||||
margin: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
.default-name-only,
|
|
||||||
.name {
|
|
||||||
color: var(--assets-item-name-foreground-color);
|
|
||||||
margin-right: $s-6;
|
|
||||||
@include textEllipsis;
|
@include textEllipsis;
|
||||||
}
|
margin: 0;
|
||||||
.default-name {
|
color: var(--assets-item-name-foreground-color);
|
||||||
min-width: 0;
|
}
|
||||||
|
|
||||||
|
.default-name {
|
||||||
|
margin-inline-start: $s-4;
|
||||||
color: var(--assets-item-name-foreground-color-rest);
|
color: var(--assets-item-name-foreground-color-rest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.default-name-with-color {
|
||||||
|
margin-left: $s-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.element-name {
|
.element-name {
|
||||||
|
|
|
@ -380,7 +380,8 @@
|
||||||
{:value "" :label (tr "workspace.options.interaction-none")})]
|
{:value "" :label (tr "workspace.options.interaction-none")})]
|
||||||
destination-options
|
destination-options
|
||||||
(mf/with-memo [frames-opts default-opts]
|
(mf/with-memo [frames-opts default-opts]
|
||||||
(d/concat-vec default-opts frames-opts))
|
(let [sorted-frames-opts (sort-by :label frames-opts)]
|
||||||
|
(d/concat-vec default-opts sorted-frames-opts)))
|
||||||
|
|
||||||
shape-parents-opts (get-shared-frames-options shape-parents)
|
shape-parents-opts (get-shared-frames-options shape-parents)
|
||||||
|
|
||||||
|
|
|
@ -918,8 +918,11 @@
|
||||||
on-gap-change
|
on-gap-change
|
||||||
(fn [multiple? type val]
|
(fn [multiple? type val]
|
||||||
(let [val (mth/finite val 0)]
|
(let [val (mth/finite val 0)]
|
||||||
(if ^boolean multiple?
|
(cond
|
||||||
|
^boolean multiple?
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-gap {:row-gap val :column-gap val}}))
|
(st/emit! (dwsl/update-layout ids {:layout-gap {:row-gap val :column-gap val}}))
|
||||||
|
|
||||||
|
(some? type)
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-gap {type val}})))))
|
(st/emit! (dwsl/update-layout ids {:layout-gap {type val}})))))
|
||||||
|
|
||||||
;; Padding
|
;; Padding
|
||||||
|
@ -941,7 +944,7 @@
|
||||||
(and (= type :simple) (= prop :p2))
|
(and (= type :simple) (= prop :p2))
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-padding {:p2 val :p4 val}}))
|
(st/emit! (dwsl/update-layout ids {:layout-padding {:p2 val :p4 val}}))
|
||||||
|
|
||||||
:else
|
(some? prop)
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-padding {prop val}}))))))
|
(st/emit! (dwsl/update-layout ids {:layout-padding {prop val}}))))))
|
||||||
|
|
||||||
;; Grid-direction
|
;; Grid-direction
|
||||||
|
@ -1126,16 +1129,16 @@
|
||||||
:on-change on-column-justify-change}]
|
:on-change on-column-justify-change}]
|
||||||
[:& justify-grid-row {:is-column false
|
[:& justify-grid-row {:is-column false
|
||||||
:value grid-justify-content-row
|
:value grid-justify-content-row
|
||||||
:on-change on-row-justify-change}]]]
|
:on-change on-row-justify-change}]]
|
||||||
|
|
||||||
[:div {:class (stl/css :row)}
|
[:div {:class (stl/css :row)}
|
||||||
[:& gap-section {:on-change on-gap-change
|
[:& gap-section {:on-change on-gap-change
|
||||||
:value (:layout-gap values)}]]
|
:value (:layout-gap values)}]]
|
||||||
|
|
||||||
[:div {:class (stl/css :row :padding-section)}
|
[:div {:class (stl/css :row :padding-section)}
|
||||||
[:& padding-section {:value (:layout-padding values)
|
[:& padding-section {:value (:layout-padding values)
|
||||||
:type (:layout-padding-type values)
|
:type (:layout-padding-type values)
|
||||||
:on-change-style on-padding-type-change
|
:on-change-style on-padding-type-change
|
||||||
:on-change on-padding-change}]]
|
:on-change on-padding-change}]]]
|
||||||
|
|
||||||
nil))]))
|
nil))]))
|
||||||
|
|
||||||
|
@ -1156,9 +1159,10 @@
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps ids)
|
(mf/deps ids)
|
||||||
(fn [multiple? type val]
|
(fn [multiple? type val]
|
||||||
|
(let [val (mth/finite val 0)]
|
||||||
(if multiple?
|
(if multiple?
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-gap {:row-gap val :column-gap val}}))
|
(st/emit! (dwsl/update-layout ids {:layout-gap {:row-gap val :column-gap val}}))
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-gap {type val}})))))
|
(st/emit! (dwsl/update-layout ids {:layout-gap {type val}}))))))
|
||||||
|
|
||||||
;; Padding
|
;; Padding
|
||||||
on-padding-type-change
|
on-padding-type-change
|
||||||
|
@ -1169,6 +1173,7 @@
|
||||||
|
|
||||||
on-padding-change
|
on-padding-change
|
||||||
(fn [type prop val]
|
(fn [type prop val]
|
||||||
|
(let [val (mth/finite val 0)]
|
||||||
(cond
|
(cond
|
||||||
(and (= type :simple) (= prop :p1))
|
(and (= type :simple) (= prop :p1))
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-padding {:p1 val :p3 val}}))
|
(st/emit! (dwsl/update-layout ids {:layout-padding {:p1 val :p3 val}}))
|
||||||
|
@ -1177,7 +1182,7 @@
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-padding {:p2 val :p4 val}}))
|
(st/emit! (dwsl/update-layout ids {:layout-padding {:p2 val :p4 val}}))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-padding {prop val}}))))
|
(st/emit! (dwsl/update-layout ids {:layout-padding {prop val}})))))
|
||||||
|
|
||||||
;; Align grid
|
;; Align grid
|
||||||
align-items-row (:layout-align-items values)
|
align-items-row (:layout-align-items values)
|
||||||
|
@ -1308,7 +1313,8 @@
|
||||||
:on-change on-row-justify-change}]
|
:on-change on-row-justify-change}]
|
||||||
|
|
||||||
[:button {:on-click handle-locate-grid
|
[:button {:on-click handle-locate-grid
|
||||||
:class (stl/css :locate-button)}
|
:class (stl/css :locate-button)
|
||||||
|
:title (tr "workspace.layout_grid.editor.top-bar.locate.tooltip")}
|
||||||
i/locate-refactor]]
|
i/locate-refactor]]
|
||||||
|
|
||||||
[:div {:class (stl/css :row)}
|
[:div {:class (stl/css :row)}
|
||||||
|
|
|
@ -736,20 +736,23 @@
|
||||||
[track-type value]
|
[track-type value]
|
||||||
(cond
|
(cond
|
||||||
(str/ends-with? value "%")
|
(str/ends-with? value "%")
|
||||||
[:percent value-int]
|
[:percent (d/nilv value-int 50)]
|
||||||
|
|
||||||
(str/ends-with? value "FR")
|
(str/ends-with? value "FR")
|
||||||
[:flex value-int]
|
[:flex (d/nilv value-int 1)]
|
||||||
|
|
||||||
(some? value-int)
|
(some? value-int)
|
||||||
[:fixed value-int]
|
[:fixed (d/nilv value-int 100)]
|
||||||
|
|
||||||
(or (= value "AUTO") (= "" value))
|
:else
|
||||||
[:auto nil])]
|
[:auto nil])
|
||||||
|
|
||||||
|
track-data (when (some? track-type) {:type track-type :value value})]
|
||||||
|
|
||||||
|
(dom/set-value! (mf/ref-val track-input-ref) (format-size track-data))
|
||||||
(if (some? track-type)
|
(if (some? track-type)
|
||||||
(do (st/emit! (dwsl/change-layout-track [(:id shape)] type index {:type track-type :value value}))
|
(do (st/emit! (dwsl/change-layout-track [(:id shape)] type index track-data))
|
||||||
(dom/set-data! target "default-value" (format-size {:type track-type :value value})))
|
(dom/set-data! target "default-value" (format-size track-data)))
|
||||||
(obj/set! target "value" (dom/get-attribute target "data-default-value"))))))
|
(obj/set! target "value" (dom/get-attribute target "data-default-value"))))))
|
||||||
|
|
||||||
handle-keydown-track-input
|
handle-keydown-track-input
|
||||||
|
|
|
@ -3508,6 +3508,9 @@ msgstr "Editing grid"
|
||||||
msgid "workspace.layout_grid.editor.top-bar.locate"
|
msgid "workspace.layout_grid.editor.top-bar.locate"
|
||||||
msgstr "Locate"
|
msgstr "Locate"
|
||||||
|
|
||||||
|
msgid "workspace.layout_grid.editor.top-bar.locate.tooltip"
|
||||||
|
msgstr "Locate grid layout"
|
||||||
|
|
||||||
msgid "workspace.layout_grid.editor.top-bar.done"
|
msgid "workspace.layout_grid.editor.top-bar.done"
|
||||||
msgstr "Done"
|
msgstr "Done"
|
||||||
|
|
||||||
|
|
|
@ -3570,6 +3570,9 @@ msgstr "Editando rejilla"
|
||||||
msgid "workspace.layout_grid.editor.top-bar.locate"
|
msgid "workspace.layout_grid.editor.top-bar.locate"
|
||||||
msgstr "Mostrar"
|
msgstr "Mostrar"
|
||||||
|
|
||||||
|
msgid "workspace.layout_grid.editor.top-bar.locate.tooltip"
|
||||||
|
msgstr "Mostrar grid layout"
|
||||||
|
|
||||||
msgid "workspace.layout_grid.editor.top-bar.done"
|
msgid "workspace.layout_grid.editor.top-bar.done"
|
||||||
msgstr "Hecho"
|
msgstr "Hecho"
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue