mirror of
https://github.com/penpot/penpot.git
synced 2025-06-20 22:57:01 +02:00
✨ Add new palette UI
This commit is contained in:
parent
56bee7dd7c
commit
fe8f13ed57
114 changed files with 6754 additions and 3172 deletions
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.ui
|
||||
(:require
|
||||
[app.config :as cf]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.auth :refer [auth]]
|
||||
|
@ -37,8 +38,10 @@
|
|||
(mf/defc main-page
|
||||
{::mf/wrap [#(mf/catch % {:fallback on-main-error})]}
|
||||
[{:keys [route profile]}]
|
||||
(let [{:keys [data params]} route]
|
||||
(let [{:keys [data params]} route
|
||||
new-css-system (features/use-feature :new-css-system)]
|
||||
[:& (mf/provider ctx/current-route) {:value route}
|
||||
[:& (mf/provider ctx/new-css-system) {:value new-css-system}
|
||||
(case (:name data)
|
||||
(:auth-login
|
||||
:auth-register
|
||||
|
@ -131,7 +134,7 @@
|
|||
:page-id page-id
|
||||
:layout-name layout
|
||||
:key file-id}])
|
||||
nil)]))
|
||||
nil)]]))
|
||||
|
||||
(mf/defc app
|
||||
[]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"components_color_bullet_new_button-primary_pDkQg","button-secondary":"components_color_bullet_new_button-secondary_y3A8V","button-icon":"components_color_bullet_new_button-icon_uAC1e","button-icon-small":"components_color_bullet_new_button-icon-small_rz5pc","color-bullet":"components_color_bullet_new_color-bullet_b1w8U","mini":"components_color_bullet_new_mini_B261Z","is-not-library-color":"components_color_bullet_new_is-not-library-color_PSveA","color-bullet-wrapper":"components_color_bullet_new_color-bullet-wrapper_clt4r","is-gradient":"components_color_bullet_new_is-gradient_6RdV2","is-transparent":"components_color_bullet_new_is-transparent_g0iwn","color-text":"components_color_bullet_new_color-text_HM6mp","small-text":"components_color_bullet_new_small-text_Y4OeK","no-text":"components_color_bullet_new_no-text_pbTQf"}
|
||||
{"button-primary":"components_color_bullet_new_button-primary_pDkQg","button-secondary":"components_color_bullet_new_button-secondary_y3A8V","button-tertiary":"components_color_bullet_new_button-tertiary_zPQ8t","button-tag":"components_color_bullet_new_button-tag_2Ur4i","button-icon":"components_color_bullet_new_button-icon_uAC1e","button-icon-small":"components_color_bullet_new_button-icon-small_rz5pc","asset-element":"components_color_bullet_new_asset-element_s3Yqx","color-bullet":"components_color_bullet_new_color-bullet_b1w8U","mini":"components_color_bullet_new_mini_B261Z","is-not-library-color":"components_color_bullet_new_is-not-library-color_PSveA","color-bullet-wrapper":"components_color_bullet_new_color-bullet-wrapper_clt4r","is-gradient":"components_color_bullet_new_is-gradient_6RdV2","is-transparent":"components_color_bullet_new_is-transparent_g0iwn","color-text":"components_color_bullet_new_color-text_HM6mp","small-text":"components_color_bullet_new_small-text_Y4OeK","no-text":"components_color_bullet_new_no-text_pbTQf"}
|
|
@ -10,12 +10,15 @@
|
|||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: var(--bullet-size);
|
||||
height: var(--bullet-size);
|
||||
width: var(--bullet-size, $s-24);
|
||||
height: var(--bullet-size, $s-24);
|
||||
margin-top: $s-4;
|
||||
border: $s-2 solid var(--color-bullet-border-color);
|
||||
border-radius: $br-circle;
|
||||
&.mini {
|
||||
width: var(--bullet-size, $s-16);
|
||||
height: var(--bullet-size, $s-16);
|
||||
margin-top: 0;
|
||||
border: 1px solid var(--color-bullet-border-color);
|
||||
}
|
||||
|
||||
|
|
|
@ -258,6 +258,7 @@
|
|||
:key id
|
||||
:class (if (and new-css-system workspace?)
|
||||
(dom/classnames (css :is-selected) (and selected (= option-name selected))
|
||||
(css :selected) (and selected (= data-test selected))
|
||||
(css :context-menu-item) true)
|
||||
(dom/classnames :is-selected (and selected (= option-name selected))))
|
||||
:key-index (dm/str "context-item-" index)
|
||||
|
@ -274,7 +275,11 @@
|
|||
:data-test data-test}
|
||||
(if (and in-dashboard? (= option-name "Default"))
|
||||
(tr "dashboard.default-team-name")
|
||||
option-name)]
|
||||
option-name)
|
||||
|
||||
(when (and new-css-system selected (= data-test selected))
|
||||
[:span {:class (dom/classnames (css :selected-icon) true)}
|
||||
i/tick-refactor])]
|
||||
[:a {:class (if (and new-css-system workspace?)
|
||||
(dom/classnames (css :context-menu-action) true
|
||||
(css :submenu) true)
|
||||
|
@ -289,7 +294,6 @@
|
|||
i/arrow-refactor
|
||||
i/arrow-slide)]])]))))])])])))
|
||||
|
||||
|
||||
(mf/defc context-menu-a11y
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"components_context_menu_a11y_button-primary_FTrG6","button-secondary":"components_context_menu_a11y_button-secondary_tIeiM","button-icon":"components_context_menu_a11y_button-icon_eOLGl","button-icon-small":"components_context_menu_a11y_button-icon-small_bQvvB","context-menu":"components_context_menu_a11y_context-menu_bS2vM","context-menu-items":"components_context_menu_a11y_context-menu-items_lQC7H","context-menu-item":"components_context_menu_a11y_context-menu-item_E2GpJ","context-menu-action":"components_context_menu_a11y_context-menu-action_E53yg","submenu-back":"components_context_menu_a11y_submenu-back_AboXg","submenu-icon-back":"components_context_menu_a11y_submenu-icon-back_gy-B6","submenu":"components_context_menu_a11y_submenu_MuyM8","submenu-icon":"components_context_menu_a11y_submenu-icon_tWTVU","is-open":"components_context_menu_a11y_is-open_FbqIp","fixed":"components_context_menu_a11y_fixed_iJxPr","separator":"components_context_menu_a11y_separator_DrZoB","min-width":"components_context_menu_a11y_min-width_w-ron","is-selected":"components_context_menu_a11y_is-selected_UPMXx","is-selectable":"components_context_menu_a11y_is-selectable_n7sdb"}
|
||||
{"button-primary":"components_context_menu_a11y_button-primary_FTrG6","button-secondary":"components_context_menu_a11y_button-secondary_tIeiM","button-tertiary":"components_context_menu_a11y_button-tertiary_0A2mW","button-tag":"components_context_menu_a11y_button-tag_iLpM-","context-menu":"components_context_menu_a11y_context-menu_bS2vM","context-menu-items":"components_context_menu_a11y_context-menu-items_lQC7H","context-menu-item":"components_context_menu_a11y_context-menu-item_E2GpJ","selected":"components_context_menu_a11y_selected_on-en","selected-icon":"components_context_menu_a11y_selected-icon_H2S7W","button-icon":"components_context_menu_a11y_button-icon_eOLGl","button-icon-small":"components_context_menu_a11y_button-icon-small_bQvvB","context-menu-action":"components_context_menu_a11y_context-menu-action_E53yg","submenu-back":"components_context_menu_a11y_submenu-back_AboXg","submenu-icon-back":"components_context_menu_a11y_submenu-icon-back_gy-B6","submenu":"components_context_menu_a11y_submenu_MuyM8","submenu-icon":"components_context_menu_a11y_submenu-icon_tWTVU","asset-element":"components_context_menu_a11y_asset-element_r3q1-","is-open":"components_context_menu_a11y_is-open_FbqIp","fixed":"components_context_menu_a11y_fixed_iJxPr","separator":"components_context_menu_a11y_separator_DrZoB","min-width":"components_context_menu_a11y_min-width_w-ron","is-selected":"components_context_menu_a11y_is-selected_UPMXx","is-selectable":"components_context_menu_a11y_is-selectable_n7sdb"}
|
|
@ -109,6 +109,21 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
.context-menu-action {
|
||||
justify-content: space-between;
|
||||
color: var(--menu-foreground-color-focus);
|
||||
}
|
||||
.selected-icon {
|
||||
@extend .button-tag;
|
||||
border-radius: $br-8;
|
||||
height: 100%;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--menu-foreground-color-focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.is-selected .context-menu-action {
|
||||
padding-left: $s-28;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
(ns app.main.ui.components.editable-label
|
||||
(:require
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.keyboard :as kbd]
|
||||
|
@ -18,6 +19,7 @@
|
|||
tooltip (get props :tooltip)
|
||||
input (mf/use-ref nil)
|
||||
state (mf/use-state (:editing false))
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
is-editing (:editing @state)
|
||||
start-editing (fn []
|
||||
(swap! state assoc :editing true)
|
||||
|
@ -52,7 +54,11 @@
|
|||
:default-value value
|
||||
:on-key-up on-key-up
|
||||
:on-blur cancel-editing}]
|
||||
[:span.editable-label-close {:on-click cancel-editing} i/close]]
|
||||
|
||||
[:span.editable-label-close {:on-click cancel-editing}
|
||||
(if new-css-system
|
||||
i/delete-text-refactor
|
||||
i/close)]]
|
||||
[:span.editable-label {:class class-name
|
||||
:title tooltip
|
||||
:on-double-click on-dbl-click} display-value])))
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"components_editable_label_button-primary_fp-ma","button-secondary":"components_editable_label_button-secondary_QPaT-","button-tertiary":"components_editable_label_button-tertiary_wOORv","button-tag":"components_editable_label_button-tag_pwEqY","button-icon":"components_editable_label_button-icon_acX7H","button-icon-small":"components_editable_label_button-icon-small_tSz5O","asset-element":"components_editable_label_asset-element_Bs5bh","editable-label-input":"components_editable_label_editable-label-input_q2Puk"}
|
21
frontend/src/app/main/ui/components/editable_label.scss
Normal file
21
frontend/src/app/main/ui/components/editable_label.scss
Normal file
|
@ -0,0 +1,21 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.editable-label-input {
|
||||
@include textEllipsis;
|
||||
@include titleTipography;
|
||||
@include removeInputStyle;
|
||||
flex-grow: 1;
|
||||
height: $s-28;
|
||||
max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
|
||||
margin: 0;
|
||||
padding-left: $s-6;
|
||||
border-radius: $br-8;
|
||||
border: $s-1 solid var(--input-border-color-focus);
|
||||
color: var(--layer-row-foreground-color);
|
||||
}
|
|
@ -35,6 +35,7 @@
|
|||
default-val (obj/get props "default")
|
||||
nillable (obj/get props "nillable")
|
||||
select-on-focus? (obj/get props "data-select-on-focus" true)
|
||||
class (obj/get props "klass")
|
||||
|
||||
;; We need a ref pointing to the input dom element, but the user
|
||||
;; of this component may provide one (that is forwarded here).
|
||||
|
@ -218,7 +219,7 @@
|
|||
|
||||
props (-> props
|
||||
(obj/without ["value" "onChange" "nillable" "onFocus"])
|
||||
(obj/set! "className" "input-text")
|
||||
(obj/set! "className" (or class "input-text"))
|
||||
(obj/set! "type" "text")
|
||||
(obj/set! "ref" ref)
|
||||
(obj/set! "defaultValue" (fmt/format-number value))
|
||||
|
|
78
frontend/src/app/main/ui/components/radio_buttons.cljs
Normal file
78
frontend/src/app/main/ui/components/radio_buttons.cljs
Normal file
|
@ -0,0 +1,78 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.radio-buttons
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.math :as math]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def ctx-radio-button (mf/create-context nil))
|
||||
|
||||
(mf/defc radio-button
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [ctx (mf/use-ctx ctx-radio-button)
|
||||
icon (unchecked-get props "icon")
|
||||
id (unchecked-get props "id")
|
||||
on-change (:on-change ctx)
|
||||
selected (:selected ctx)
|
||||
value (unchecked-get props "value")
|
||||
checked? (= selected value)
|
||||
name (:name ctx)]
|
||||
[:label {:for id
|
||||
:class (dom/classnames (css :radio-icon) true
|
||||
(css :checked) checked?)}
|
||||
icon
|
||||
[:input {:id id
|
||||
:on-change on-change
|
||||
:type "radio"
|
||||
:name name
|
||||
:value value
|
||||
:checked checked?}]]))
|
||||
|
||||
(mf/defc nilable-option
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [ctx (mf/use-ctx ctx-radio-button)
|
||||
icon (unchecked-get props "icon")
|
||||
id (unchecked-get props "id")
|
||||
on-change (:on-change ctx)
|
||||
selected (:selected ctx)
|
||||
value (unchecked-get props "value")
|
||||
checked? (= selected value)
|
||||
name (:name ctx)]
|
||||
[:label {:for id
|
||||
:class (dom/classnames (css :radio-icon) true
|
||||
(css :checked) checked?)}
|
||||
icon
|
||||
[:input {:id id
|
||||
:on-change on-change
|
||||
:type "checkbox"
|
||||
:name name
|
||||
:value value
|
||||
:checked checked?}]]))
|
||||
|
||||
(mf/defc radio-buttons
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [children (unchecked-get props "children")
|
||||
on-change (unchecked-get props "on-change")
|
||||
selected (unchecked-get props "selected")
|
||||
name (unchecked-get props "name")
|
||||
calculate-width (fmt/format-pixels (+ (math/pow 2 (count children)) (* 28 (count children))))
|
||||
handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps on-change)
|
||||
(fn [event]
|
||||
(let [value (dom/get-target-val event)]
|
||||
(on-change value event))))]
|
||||
[:& (mf/provider ctx-radio-button) {:value {:selected selected :on-change handle-change :name name}}
|
||||
[:div {:class (css :radio-btn-wrapper)
|
||||
:style {:width calculate-width}}
|
||||
children]]))
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"components_radio_buttons_button-primary_-XZNO","button-secondary":"components_radio_buttons_button-secondary_yj3Oe","button-tertiary":"components_radio_buttons_button-tertiary_s2RvI","radio-icon":"components_radio_buttons_radio-icon_1OnG1","button-tag":"components_radio_buttons_button-tag_4VTp-","button-icon":"components_radio_buttons_button-icon_jP0XC","button-icon-small":"components_radio_buttons_button-icon-small_3AO-R","asset-element":"components_radio_buttons_asset-element_l2wMX","radio-btn-wrapper":"components_radio_buttons_radio-btn-wrapper_mH6QX","checked":"components_radio_buttons_checked_sjVzy"}
|
42
frontend/src/app/main/ui/components/radio_buttons.scss
Normal file
42
frontend/src/app/main/ui/components/radio_buttons.scss
Normal file
|
@ -0,0 +1,42 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.radio-btn-wrapper {
|
||||
@include flexCenter;
|
||||
border-radius: $br-8;
|
||||
height: $s-32;
|
||||
background-color: var(--radio-btns-background-color);
|
||||
}
|
||||
.radio-icon {
|
||||
@extend .button-tertiary;
|
||||
height: $s-28;
|
||||
width: 100%;
|
||||
border-radius: $s-6;
|
||||
border: solid $s-2 transparent;
|
||||
box-sizing: content-box;
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
stroke: var(--radio-btn-foreground-color);
|
||||
}
|
||||
&:hover {
|
||||
border: solid $s-2 var(--radio-btns-background-color);
|
||||
}
|
||||
&.checked {
|
||||
background-color: var(--radio-btn-background-color-selected);
|
||||
border: $s-2 solid var(--radio-btn-border-color-selected);
|
||||
svg {
|
||||
stroke: var(--radio-btn-foreground-color-selected);
|
||||
}
|
||||
&:hover {
|
||||
border: $s-2 solid var(--radio-btn-border-color-selected);
|
||||
}
|
||||
}
|
||||
}
|
60
frontend/src/app/main/ui/components/search_bar.cljs
Normal file
60
frontend/src/app/main/ui/components/search_bar.cljs
Normal file
|
@ -0,0 +1,60 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.search-bar
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.keyboard :as kbd]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc search-bar
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [children (unchecked-get props "children")
|
||||
on-change (unchecked-get props "on-change")
|
||||
value (unchecked-get props "value")
|
||||
on-clear (unchecked-get props "clear-action")
|
||||
placeholder (unchecked-get props "placeholder")
|
||||
icon (unchecked-get props "icon")
|
||||
|
||||
handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps on-change)
|
||||
(fn [event]
|
||||
(let [value (dom/get-target-val event)]
|
||||
(on-change value event))))
|
||||
|
||||
handle-clear
|
||||
(mf/use-fn
|
||||
(mf/deps on-clear on-change)
|
||||
(fn [event]
|
||||
(if on-clear
|
||||
(on-clear event)
|
||||
(on-change "" event))))
|
||||
|
||||
handle-key-down
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(let [enter? (kbd/enter? event)
|
||||
esc? (kbd/esc? event)
|
||||
node (dom/event->target event)]
|
||||
(when ^boolean enter? (dom/blur! node))
|
||||
(when ^boolean esc? (dom/blur! node)))))]
|
||||
[:span {:class (dom/classnames (css :search-box) true
|
||||
(css :has-children) (some? children))}
|
||||
children
|
||||
[:div {:class (dom/classnames (css :search-input-wrapper) true)}
|
||||
icon
|
||||
[:input {:on-change handle-change
|
||||
:value value
|
||||
:placeholder placeholder
|
||||
:on-key-down handle-key-down}]
|
||||
(when (not= "" value)
|
||||
[:button {:class (dom/classnames (css :clear) true)
|
||||
:on-click handle-clear}
|
||||
i/delete-text-refactor])]]))
|
1
frontend/src/app/main/ui/components/search_bar.css.json
Normal file
1
frontend/src/app/main/ui/components/search_bar.css.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"button-primary":"components_search_bar_button-primary_-9D1J","button-secondary":"components_search_bar_button-secondary_GbDgI","button-tertiary":"components_search_bar_button-tertiary_VTCfX","button-tag":"components_search_bar_button-tag_dKink","search-box":"components_search_bar_search-box_AFEzz","search-input-wrapper":"components_search_bar_search-input-wrapper_Djsml","clear":"components_search_bar_clear_B6lfz","button-icon":"components_search_bar_button-icon_CdwNa","button-icon-small":"components_search_bar_button-icon-small_gSOsT","asset-element":"components_search_bar_asset-element_rH-5k","has-children":"components_search_bar_has-children_u-VSq"}
|
66
frontend/src/app/main/ui/components/search_bar.scss
Normal file
66
frontend/src/app/main/ui/components/search_bar.scss
Normal file
|
@ -0,0 +1,66 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
gap: $s-2;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--search-bar-background-color);
|
||||
|
||||
.search-input-wrapper {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
border: $s-1 solid var(--search-bar-input-border-color);
|
||||
border-radius: $br-8;
|
||||
background-color: var(--search-bar-input-background-color);
|
||||
input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0 $s-8 0 $s-4;
|
||||
border: 0;
|
||||
background-color: var(--input-background-color);
|
||||
font-size: $fs-12;
|
||||
color: var(--input-foreground-color);
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
border: $s-1 solid var(--input-background-color-hover);
|
||||
background-color: var(--input-background-color-hover);
|
||||
input {
|
||||
background-color: var(--input-background-color-hover);
|
||||
}
|
||||
}
|
||||
&:focus-within {
|
||||
background-color: var(--input-background-color-active);
|
||||
color: var(--input-foreground-color-active);
|
||||
border: $s-1 solid var(--input-border-color-focus);
|
||||
input {
|
||||
background-color: var(--input-background-color-active);
|
||||
}
|
||||
}
|
||||
|
||||
.clear {
|
||||
@extend .button-tag;
|
||||
border-radius: $br-8;
|
||||
height: 100%;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.has-children .search-input-wrapper {
|
||||
border-radius: $br-2 $br-8 $br-8 $br-2;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
|
@ -5,11 +5,13 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.select
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -22,7 +24,8 @@
|
|||
|
||||
(mf/defc select
|
||||
[{:keys [default-value options class is-open? on-change on-pointer-enter-option on-pointer-leave-option]}]
|
||||
(let [label-index (mf/with-memo [options]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
label-index (mf/with-memo [options]
|
||||
(into {} (map as-key-value) options))
|
||||
|
||||
state* (mf/use-state
|
||||
|
@ -73,22 +76,46 @@
|
|||
|
||||
(mf/with-effect [default-value]
|
||||
(swap! state* assoc :current-value default-value))
|
||||
(if new-css-system
|
||||
[:div {:on-click open-dropdown :class (dom/classnames (css class) true
|
||||
(css :custom-select) true)}
|
||||
[:span {:class (css :current-label)} current-label]
|
||||
[:span {:class (css :dropdown-button)} i/arrow-refactor]
|
||||
[:& dropdown {:show is-open? :on-close close-dropdown}
|
||||
[:ul {:class (css :custom-select-dropdown)}
|
||||
(for [[index item] (d/enumerate options)]
|
||||
(if (= :separator item)
|
||||
[:hr {:key (dm/str current-id "-" index)}]
|
||||
(let [[value label] (as-key-value item)]
|
||||
[:li
|
||||
{:key (dm/str current-id "-" index)
|
||||
:class (dom/classnames
|
||||
(css :checked-element) true
|
||||
(css :is-selected) (= value current-value))
|
||||
:data-value (pr-str value)
|
||||
:on-pointer-enter highlight-item
|
||||
:on-pointer-leave unhighlight-item
|
||||
:on-click select-item}
|
||||
[:span {:class (css :label)} label]
|
||||
[:span {:class (css :check-icon)} i/tick-refactor]])))]]]
|
||||
|
||||
|
||||
|
||||
[:div.custom-select {:on-click open-dropdown :class class}
|
||||
[:span current-label]
|
||||
[:span.dropdown-button i/arrow-down]
|
||||
[:& dropdown {:show is-open? :on-close close-dropdown}
|
||||
[:ul.custom-select-dropdown
|
||||
(for [[index item] (d/enumerate options)]
|
||||
(if (= :separator item)
|
||||
[:hr {:key (dm/str current-id "-" index)}]
|
||||
(let [[value label] (as-key-value item)]
|
||||
[:li.checked-element
|
||||
{:key (dm/str current-id "-" index)
|
||||
:class (when (= value current-value) "is-selected")
|
||||
:data-value (pr-str value)
|
||||
:on-pointer-enter highlight-item
|
||||
:on-pointer-leave unhighlight-item
|
||||
:on-click select-item}
|
||||
[:span.check-icon i/tick]
|
||||
[:span label]])))]]]))
|
||||
[:div.custom-select {:on-click open-dropdown :class class}
|
||||
[:span current-label]
|
||||
[:span.dropdown-button i/arrow-down]
|
||||
[:& dropdown {:show is-open? :on-close close-dropdown}
|
||||
[:ul.custom-select-dropdown
|
||||
(for [[index item] (d/enumerate options)]
|
||||
(if (= :separator item)
|
||||
[:hr {:key (dm/str current-id "-" index)}]
|
||||
(let [[value label] (as-key-value item)]
|
||||
[:li.checked-element
|
||||
{:key (dm/str current-id "-" index)
|
||||
:class (when (= value current-value) "is-selected")
|
||||
:data-value (pr-str value)
|
||||
:on-pointer-enter highlight-item
|
||||
:on-pointer-leave unhighlight-item
|
||||
:on-click select-item}
|
||||
[:span.check-icon i/tick]
|
||||
[:span label]])))]]])))
|
||||
|
|
1
frontend/src/app/main/ui/components/select.css.json
Normal file
1
frontend/src/app/main/ui/components/select.css.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"button-primary":"components_select_button-primary_peYzv","button-secondary":"components_select_button-secondary_Kse6w","button-tertiary":"components_select_button-tertiary_srwoV","button-tag":"components_select_button-tag_AJXtX","button-icon":"components_select_button-icon_86LWm","custom-select":"components_select_custom-select_OM8-6","dropdown-button":"components_select_dropdown-button_IcpuR","button-icon-small":"components_select_button-icon-small_H0Bue","checked-element":"components_select_checked-element_c5-i4","check-icon":"components_select_check-icon_9x082","asset-element":"components_select_asset-element_5vxj7","current-label":"components_select_current-label_CUaQs","custom-select-dropdown":"components_select_custom-select-dropdown_2yZj9","label":"components_select_label_kTY8t","is-selected":"components_select_is-selected_nTUGr"}
|
84
frontend/src/app/main/ui/components/select.scss
Normal file
84
frontend/src/app/main/ui/components/select.scss
Normal file
|
@ -0,0 +1,84 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.custom-select {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: $s-8;
|
||||
border-radius: $br-8;
|
||||
cursor: pointer;
|
||||
.current-label {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.dropdown-button {
|
||||
@include flexCenter;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
.custom-select-dropdown {
|
||||
position: absolute;
|
||||
top: $s-32;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding: $s-2;
|
||||
margin: 0;
|
||||
margin-top: $s-4;
|
||||
border-radius: $br-8;
|
||||
z-index: $z-index-10;
|
||||
overflow-y: auto;
|
||||
background-color: var(--menu-background-color);
|
||||
box-shadow: 0px 0px $s-12 0px var(--menu-shadow-color);
|
||||
}
|
||||
.checked-element {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
padding: $s-8;
|
||||
border-radius: $br-6;
|
||||
color: var(--menu-foreground-color);
|
||||
.label {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
@include flexCenter;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
.check-icon svg {
|
||||
stroke: var(--menu-foreground-color);
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
color: var(--menu-foreground-color-hover);
|
||||
.check-icon svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.dropdown-button {
|
||||
color: var(--menu-foreground-color-hover);
|
||||
svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,10 +35,10 @@
|
|||
on-change (unchecked-get props "on-change-tab")
|
||||
collapsable? (unchecked-get props "collapsable?")
|
||||
handle-collapse (unchecked-get props "handle-collapse")
|
||||
klass (unchecked-get props "klass")
|
||||
|
||||
state (mf/use-state #(or selected (-> children first .-props .-id)))
|
||||
selected (or selected @state)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
select-fn
|
||||
(mf/use-fn
|
||||
|
@ -48,42 +48,26 @@
|
|||
(reset! state id)
|
||||
(when (fn? on-change) (on-change id)))))]
|
||||
|
||||
[:div {:class (if new-css-system
|
||||
(dom/classnames (css :tab-container) true)
|
||||
(dom/classnames :tab-container true))}
|
||||
[:div {:class (if new-css-system
|
||||
(dom/classnames (css :tab-container-tabs) true)
|
||||
(dom/classnames :tab-container-tabs true))}
|
||||
(when (and new-css-system collapsable?)
|
||||
[:div {:class (dom/classnames (css :tab-container) true)}
|
||||
[:div {:class (dom/classnames (css :tab-container-tabs) true
|
||||
klass true)}
|
||||
(when collapsable?
|
||||
[:button
|
||||
{:on-click handle-collapse
|
||||
:class (dom/classnames (css :collapse-sidebar) true)
|
||||
:aria-label (tr "workspace.sidebar.collapse")}
|
||||
i/arrow-refactor])
|
||||
(if new-css-system
|
||||
[:div {:class (dom/classnames (css :tab-container-tab-wrapper) new-css-system)}
|
||||
(for [tab children]
|
||||
(let [props (.-props tab)
|
||||
id (.-id props)
|
||||
title (.-title props)]
|
||||
[:div
|
||||
{:key (str/concat "tab-" (d/name id))
|
||||
:data-id (pr-str id)
|
||||
:on-click select-fn
|
||||
:class (dom/classnames (css :tab-container-tab-title) true
|
||||
(css :current) (= selected id))}
|
||||
title]))]
|
||||
(for [tab children]
|
||||
(let [props (.-props tab)
|
||||
id (.-id props)
|
||||
title (.-title props)]
|
||||
[:div.tab-container-tab-title
|
||||
{:key (str/concat "tab-" (d/name id))
|
||||
:data-id (pr-str id)
|
||||
:on-click select-fn
|
||||
:class (when (= selected id) "current")}
|
||||
title])))]
|
||||
[:div {:class (if new-css-system
|
||||
(dom/classnames (css :tab-container-content) true)
|
||||
(dom/classnames :tab-container-content true))}
|
||||
[:div {:class (dom/classnames (css :tab-container-tab-wrapper) true)}
|
||||
(for [tab children]
|
||||
(let [props (.-props tab)
|
||||
id (.-id props)
|
||||
title (.-title props)]
|
||||
[:div
|
||||
{:key (str/concat "tab-" (d/name id))
|
||||
:data-id (pr-str id)
|
||||
:on-click select-fn
|
||||
:class (dom/classnames (css :tab-container-tab-title) true
|
||||
(css :current) (= selected id))}
|
||||
title]))]]
|
||||
[:div {:class (dom/classnames (css :tab-container-content) true)}
|
||||
(d/seek #(= selected (-> % .-props .-id)) children)]]))
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"components_tab_container_button-primary_ibiAz","button-secondary":"components_tab_container_button-secondary_wZR80","button-icon":"components_tab_container_button-icon_2NhVr","button-icon-small":"components_tab_container_button-icon-small_yU7na","tab-container":"components_tab_container_tab-container_P6HRr","tab-container-content":"components_tab_container_tab-container-content_yfM9F","tab-element":"components_tab_container_tab-element_gBIwV","tab-container-tabs":"components_tab_container_tab-container-tabs_6gXOY","tab-container-tab-wrapper":"components_tab_container_tab-container-tab-wrapper_-ngrN","tab-container-tab-title":"components_tab_container_tab-container-tab-title_IN1Dx","current":"components_tab_container_current_jrovp","collapse-sidebar":"components_tab_container_collapse-sidebar_e5hFv","collapsed":"components_tab_container_collapsed_lfkjK"}
|
||||
{"button-primary":"components_tab_container_button-primary_ibiAz","button-secondary":"components_tab_container_button-secondary_wZR80","button-tertiary":"components_tab_container_button-tertiary_JHJAx","button-tag":"components_tab_container_button-tag_NnL8y","button-icon":"components_tab_container_button-icon_2NhVr","button-icon-small":"components_tab_container_button-icon-small_yU7na","asset-element":"components_tab_container_asset-element_1-YWa","tab-container":"components_tab_container_tab-container_P6HRr","tab-container-content":"components_tab_container_tab-container-content_yfM9F","tab-element":"components_tab_container_tab-element_gBIwV","tab-container-tabs":"components_tab_container_tab-container-tabs_6gXOY","tab-container-tab-wrapper":"components_tab_container_tab-container-tab-wrapper_-ngrN","tab-container-tab-title":"components_tab_container_tab-container-tab-title_IN1Dx","current":"components_tab_container_current_jrovp","collapse-sidebar":"components_tab_container_collapse-sidebar_e5hFv","collapsed":"components_tab_container_collapsed_lfkjK"}
|
|
@ -26,8 +26,7 @@
|
|||
flex-direction: row;
|
||||
gap: $s-2;
|
||||
height: $s-32;
|
||||
margin: $s-4 $s-4 0 $s-4;
|
||||
padding: $s-2 $s-2 $s-2 0;
|
||||
padding: $s-2 $s-2 $s-2 $s-2;
|
||||
border-radius: $br-8;
|
||||
background: var(--color-background-secondary);
|
||||
cursor: pointer;
|
||||
|
@ -43,10 +42,12 @@
|
|||
@include tabTitleTipography;
|
||||
height: $s-28;
|
||||
width: 100%;
|
||||
padding: 0 $s-8;
|
||||
margin: 0;
|
||||
border-radius: $br-5;
|
||||
background-color: transparent;
|
||||
color: var(--tab-foreground-color);
|
||||
white-space: nowrap;
|
||||
|
||||
&.current,
|
||||
&.current:hover {
|
||||
|
@ -63,12 +64,13 @@
|
|||
@include buttonStyle;
|
||||
height: 100%;
|
||||
width: $s-24;
|
||||
padding: 0;
|
||||
min-width: $s-24;
|
||||
padding: 0 $s-6 0 0;
|
||||
border-radius: $br-5;
|
||||
svg {
|
||||
@include flexCenter;
|
||||
height: 12px;
|
||||
width: 16px;
|
||||
height: $s-16;
|
||||
width: $s-16;
|
||||
stroke: var(--icon-foreground);
|
||||
transform: rotate(180deg);
|
||||
fill: none;
|
||||
|
@ -83,6 +85,7 @@
|
|||
&.collapsed {
|
||||
svg {
|
||||
transform: rotate(0deg);
|
||||
padding: 0 0 0 $s-6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
42
frontend/src/app/main/ui/components/title_bar.cljs
Normal file
42
frontend/src/app/main/ui/components/title_bar.cljs
Normal file
|
@ -0,0 +1,42 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.title-bar
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc title-bar
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [collapsable? (unchecked-get props "collapsable?")
|
||||
collapsed? (unchecked-get props "collapsed?")
|
||||
on-collapsed (unchecked-get props "on-collapsed")
|
||||
title (unchecked-get props "title")
|
||||
children (unchecked-get props "children")
|
||||
on-btn-click (unchecked-get props "on-btn-click")
|
||||
btn-children (unchecked-get props "btn-children")
|
||||
klass (unchecked-get props "klass")]
|
||||
|
||||
[:div {:class (dom/classnames (css :title-bar) true
|
||||
klass true)}
|
||||
(if collapsable?
|
||||
[:button {:class (dom/classnames (css :toggle-btn) true)
|
||||
:on-click on-collapsed}
|
||||
[:span {:class (dom/classnames (css :collased-icon) true
|
||||
(css :rotated) collapsed?)}
|
||||
i/arrow-refactor]
|
||||
[:div {:class (dom/classnames (css :title) true)}
|
||||
title]]
|
||||
[:div {:class (dom/classnames (css :title-only) true)}
|
||||
title])
|
||||
children
|
||||
(when (some? on-btn-click)
|
||||
[:button {:class (dom/classnames (css :title-button) true)
|
||||
:on-click on-btn-click}
|
||||
btn-children])]))
|
1
frontend/src/app/main/ui/components/title_bar.css.json
Normal file
1
frontend/src/app/main/ui/components/title_bar.css.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"button-primary":"components_title_bar_button-primary_svLtU","button-secondary":"components_title_bar_button-secondary_JA5NP","button-tertiary":"components_title_bar_button-tertiary_yqQfO","title-bar":"components_title_bar_title-bar_oUkS0","title-button":"components_title_bar_title-button_xTE-7","button-tag":"components_title_bar_button-tag_o9yFT","button-icon":"components_title_bar_button-icon_ROHrz","button-icon-small":"components_title_bar_button-icon-small_WibJp","toggle-btn":"components_title_bar_toggle-btn_9ekUv","collased-icon":"components_title_bar_collased-icon_SJ1ls","asset-element":"components_title_bar_asset-element_64u6f","title":"components_title_bar_title_qPuju","title-only":"components_title_bar_title-only_aSsdC","rotated":"components_title_bar_rotated_9z7Rn"}
|
78
frontend/src/app/main/ui/components/title_bar.scss
Normal file
78
frontend/src/app/main/ui/components/title_bar.scss
Normal file
|
@ -0,0 +1,78 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.title-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
min-height: $s-32;
|
||||
background-color: var(--title-background-color);
|
||||
.title,
|
||||
.title-only {
|
||||
@include tabTitleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
min-height: $s-32;
|
||||
margin-right: $s-8;
|
||||
color: var(--title-foreground-color);
|
||||
}
|
||||
.title-only {
|
||||
margin-left: $s-8;
|
||||
}
|
||||
|
||||
.toggle-btn {
|
||||
@include buttonStyle;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
gap: $s-4;
|
||||
padding: 0;
|
||||
color: var(--title-foreground-color);
|
||||
stroke: var(--title-foreground-color);
|
||||
.collased-icon {
|
||||
@include flexCenter;
|
||||
height: $s-24;
|
||||
width: $s-24;
|
||||
border-radius: $br-8;
|
||||
padding: 0 $s-4 0 $s-8;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
&.rotated svg {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
color: var(--title-foreground-color-hover);
|
||||
stroke: var(--title-foreground-color-hover);
|
||||
.title {
|
||||
color: var(--title-foreground-color-hover);
|
||||
stroke: var(--title-foreground-color-hover);
|
||||
}
|
||||
.collased-icon svg {
|
||||
stroke: var(--title-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title-button {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: calc($s-24 + $s-4);
|
||||
padding: 0;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,9 +10,23 @@
|
|||
[app.main.data.users :as du]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
|
||||
[app.main.ui.components.search-bar :refer [search-bar]]
|
||||
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc component-wrapper
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [children (unchecked-get props "children")
|
||||
title (unchecked-get props "title")]
|
||||
[:div {:class (dom/classnames (css :component) true)}
|
||||
[:h4 {:class (dom/classnames (css :component-name) true)} title]
|
||||
children]))
|
||||
|
||||
(mf/defc components-preview
|
||||
{::mf/wrap-props false}
|
||||
[]
|
||||
|
@ -24,7 +38,6 @@
|
|||
(let [theme (dom/event->value event)
|
||||
data (assoc initial :theme theme)]
|
||||
(st/emit! (du/update-profile data))))
|
||||
|
||||
colors [:bg-primary
|
||||
:bg-secondary
|
||||
:bg-tertiary
|
||||
|
@ -34,10 +47,37 @@
|
|||
:acc
|
||||
:acc-muted
|
||||
:acc-secondary
|
||||
:acc-tertiary]]
|
||||
:acc-tertiary]
|
||||
|
||||
;; COMPONENTS FNs
|
||||
state* (mf/use-state {:collapsed? true
|
||||
:tab-selected :first
|
||||
:input-value ""
|
||||
:radio-selected "first"})
|
||||
state (deref state*)
|
||||
|
||||
collapsed? (:collapsed? state)
|
||||
toggle-collapsed
|
||||
(mf/use-fn #(swap! state* update :collapsed? not))
|
||||
|
||||
tab-selected (:tab-selected state)
|
||||
set-tab (mf/use-fn #(swap! state* assoc :tab-selected %))
|
||||
|
||||
input-value (:input-value state)
|
||||
radio-selected (:radio-selected state)
|
||||
|
||||
set-radio-selected (mf/use-fn #(swap! state* assoc :radio-selected %))
|
||||
|
||||
update-search
|
||||
(mf/use-fn
|
||||
(fn [value _event]
|
||||
(swap! state* assoc :input-value value)))
|
||||
|
||||
|
||||
on-btn-click (mf/use-fn #(prn "eyy"))]
|
||||
|
||||
[:section.debug-components-preview
|
||||
[:div {:class (css :themes-row)}
|
||||
[:div {:class (dom/classnames (css :themes-row) true)}
|
||||
[:h2 "Themes"]
|
||||
[:select {:label "Select theme color"
|
||||
:name :theme
|
||||
|
@ -46,12 +86,135 @@
|
|||
:on-change on-change}
|
||||
[:option {:label "Penpot Dark (default)" :value "default"}]
|
||||
[:option {:label "Penpot Light" :value "light"}]]
|
||||
[:div {:class (css :wrapper)}
|
||||
[:div {:class (dom/classnames (css :wrapper) true)}
|
||||
(let [css (styles)]
|
||||
(for [color colors]
|
||||
[:div {:class (dom/classnames (get css color) true
|
||||
[:div {:key color
|
||||
:class (dom/classnames (get css color) true
|
||||
(get css :rect) true)}
|
||||
(d/name color)]))]]
|
||||
[:div {:class (css :components-row)}
|
||||
[:h2 {:class (css :title)} "Components"]
|
||||
[:div {:class (css :component-wrapper)}]]]))
|
||||
[:div {:class (dom/classnames (css :components-row) true)}
|
||||
[:h2 {:class (dom/classnames (css :title) true)} "Components"]
|
||||
[:div {:class (dom/classnames (css :components-wrapper) true)}
|
||||
[:div {:class (dom/classnames (css :component-group) true)}
|
||||
[:h3 "Titles"]
|
||||
[:& component-wrapper
|
||||
{:title "Title"}
|
||||
[:& title-bar {:collapsable? false
|
||||
:title "Title"}]]
|
||||
[:& component-wrapper
|
||||
{:title "Title and action button"}
|
||||
[:& title-bar {:collapsable? false
|
||||
:title "Title"
|
||||
:on-btn-click on-btn-click
|
||||
:btn-children i/add-refactor}]]
|
||||
[:& component-wrapper
|
||||
{:title "Collapsed title and action button"}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? collapsed?
|
||||
:on-collapsed toggle-collapsed
|
||||
:title "Title"
|
||||
:on-btn-click on-btn-click
|
||||
:btn-children i/add-refactor}]]
|
||||
[:& component-wrapper
|
||||
{:title "Collapsed title and children"}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? collapsed?
|
||||
:on-collapsed toggle-collapsed
|
||||
:title "Title"}
|
||||
[:& tab-container {:on-change-tab set-tab
|
||||
:selected tab-selected}
|
||||
[:& tab-element {:id :first
|
||||
:title "A tab"}]
|
||||
[:& tab-element {:id :second
|
||||
:title "B tab"}]]]]]
|
||||
|
||||
[:div {:class (dom/classnames (css :component-group) true)}
|
||||
[:h3 "Tabs component"]
|
||||
[:& component-wrapper
|
||||
{:title "2 tab component"}
|
||||
[:& tab-container {:on-change-tab set-tab
|
||||
:selected tab-selected}
|
||||
[:& tab-element {:id :first :title "First tab"}
|
||||
[:div "This is first tab content"]]
|
||||
|
||||
[:& tab-element {:id :second :title "Second tab"}
|
||||
[:div "This is second tab content"]]]]
|
||||
[:& component-wrapper
|
||||
{:title "3 tab component"}
|
||||
[:& tab-container {:on-change-tab set-tab
|
||||
:selected tab-selected}
|
||||
[:& tab-element {:id :first :title "First tab"}
|
||||
[:div "This is first tab content"]]
|
||||
|
||||
[:& tab-element {:id :second
|
||||
:title "Second tab"}
|
||||
[:div "This is second tab content"]]
|
||||
[:& tab-element {:id :third
|
||||
:title "Third tab"}
|
||||
[:div "This is third tab content"]]]]]
|
||||
|
||||
[:div {:class (dom/classnames (css :component-group) true)}
|
||||
[:h3 "Search bar"]
|
||||
[:& component-wrapper
|
||||
{:title "Search bar only"}
|
||||
[:& search-bar {:on-change update-search
|
||||
:value input-value
|
||||
:placeholder "Test value"}]]
|
||||
[:& component-wrapper
|
||||
{:title "Search and button"}
|
||||
[:& search-bar {:on-change update-search
|
||||
:value input-value
|
||||
:placeholder "Test value"}
|
||||
[:button {:class (dom/classnames (css :test-button) true)
|
||||
:on-click on-btn-click}
|
||||
"X"]]]]
|
||||
|
||||
[:div {:class (dom/classnames (css :component-group) true)}
|
||||
[:h3 "Radio buttons"]
|
||||
[:& component-wrapper
|
||||
{:title "Two radio buttons (toggle)"}
|
||||
[:& radio-buttons {:selected radio-selected
|
||||
:on-change set-radio-selected
|
||||
:name "listing-style"}
|
||||
[:& radio-button {:icon (mf/html i/view-as-list-refactor)
|
||||
:value "first"
|
||||
:id :list}]
|
||||
[:& radio-button {:icon (mf/html i/flex-grid-refactor)
|
||||
:value "second"
|
||||
:id :grid}]]]
|
||||
[:& component-wrapper
|
||||
{:title "Three radio buttons"}
|
||||
[:& radio-buttons {:selected radio-selected
|
||||
:on-change set-radio-selected
|
||||
:name "listing-style"}
|
||||
[:& radio-button {:icon (mf/html i/view-as-list-refactor)
|
||||
:value "first"
|
||||
:id :first}]
|
||||
[:& radio-button {:icon (mf/html i/flex-grid-refactor)
|
||||
:value "second"
|
||||
:id :second}]
|
||||
|
||||
[:& radio-button {:icon (mf/html i/add-refactor)
|
||||
:value "third"
|
||||
:id :third}]]]
|
||||
|
||||
[:& component-wrapper
|
||||
{:title "Four radio buttons"}
|
||||
[:& radio-buttons {:selected radio-selected
|
||||
:on-change set-radio-selected
|
||||
:name "listing-style"}
|
||||
[:& radio-button {:icon (mf/html i/view-as-list-refactor)
|
||||
:value "first"
|
||||
:id :first}]
|
||||
[:& radio-button {:icon (mf/html i/flex-grid-refactor)
|
||||
:value "second"
|
||||
:id :second}]
|
||||
|
||||
[:& radio-button {:icon (mf/html i/add-refactor)
|
||||
:value "third"
|
||||
:id :third}]
|
||||
|
||||
[:& radio-button {:icon (mf/html i/board-refactor)
|
||||
:value "forth"
|
||||
:id :forth}]]]]]]]))
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"debug_components_preview_button-primary_Q2m40","button-secondary":"debug_components_preview_button-secondary_yPp3n","button-icon":"debug_components_preview_button-icon_J36A6","button-icon-small":"debug_components_preview_button-icon-small_Pf3jb","themes-row":"debug_components_preview_themes-row_wEU8d","wrapper":"debug_components_preview_wrapper_535-4","rect":"debug_components_preview_rect_jomnq","bg-primary":"debug_components_preview_bg-primary_Rt4oW","bg-secondary":"debug_components_preview_bg-secondary_rcmll","bg-tertiary":"debug_components_preview_bg-tertiary_7rITE","bg-cuaternary":"debug_components_preview_bg-cuaternary_UEBPN","fg-primary":"debug_components_preview_fg-primary_naliT","fg-secondary":"debug_components_preview_fg-secondary_zT9IX","acc":"debug_components_preview_acc_h3Bia","acc-muted":"debug_components_preview_acc-muted_uingh","acc-secondary":"debug_components_preview_acc-secondary_oHH6y","acc-tertiary":"debug_components_preview_acc-tertiary_SwBjy","components-row":"debug_components_preview_components-row_N3f-J","title":"debug_components_preview_title_TVtzz","component-wrapper":"debug_components_preview_component-wrapper_yC9G1"}
|
||||
{"button-primary":"debug_components_preview_button-primary_Q2m40","button-secondary":"debug_components_preview_button-secondary_yPp3n","button-tertiary":"debug_components_preview_button-tertiary_FIKgJ","button-tag":"debug_components_preview_button-tag_NNepE","button-icon":"debug_components_preview_button-icon_J36A6","button-icon-small":"debug_components_preview_button-icon-small_Pf3jb","asset-element":"debug_components_preview_asset-element_LhcNS","themes-row":"debug_components_preview_themes-row_wEU8d","wrapper":"debug_components_preview_wrapper_535-4","rect":"debug_components_preview_rect_jomnq","bg-primary":"debug_components_preview_bg-primary_Rt4oW","bg-secondary":"debug_components_preview_bg-secondary_rcmll","bg-tertiary":"debug_components_preview_bg-tertiary_7rITE","bg-cuaternary":"debug_components_preview_bg-cuaternary_UEBPN","fg-primary":"debug_components_preview_fg-primary_naliT","fg-secondary":"debug_components_preview_fg-secondary_zT9IX","acc":"debug_components_preview_acc_h3Bia","acc-muted":"debug_components_preview_acc-muted_uingh","acc-secondary":"debug_components_preview_acc-secondary_oHH6y","acc-tertiary":"debug_components_preview_acc-tertiary_SwBjy","components-row":"debug_components_preview_components-row_N3f-J","title":"debug_components_preview_title_TVtzz","components-wrapper":"debug_components_preview_components-wrapper_A8IgV","component-group":"debug_components_preview_component-group_dI55k","component":"debug_components_preview_component_xBMSU","component-name":"debug_components_preview_component-name_3ZJMW"}
|
|
@ -79,7 +79,33 @@
|
|||
.title {
|
||||
padding: $s-20;
|
||||
}
|
||||
.component-wrapper {
|
||||
.components-wrapper {
|
||||
padding: $s-20;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.component-group {
|
||||
@include flexCenter;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
// width: $s-256;
|
||||
border-radius: $s-8;
|
||||
h3 {
|
||||
@include titleTipography;
|
||||
font-size: $fs-25;
|
||||
width: 100%;
|
||||
}
|
||||
.component {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-8;
|
||||
width: $s-240;
|
||||
max-height: $s-80;
|
||||
margin-bottom: $s-16;
|
||||
.component-name {
|
||||
@include tabTitleTipography;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -297,6 +297,7 @@
|
|||
(def distribute-vertical-sapcing-refactor (icon-xref :distribute-vertical-spacing-refactor))
|
||||
(def delete-refactor (icon-xref :delete-refactor))
|
||||
(def delete-text-refactor (icon-xref :delete-text-refactor))
|
||||
(def detach-refactor (icon-xref :detach-refactor))
|
||||
(def document-refactor (icon-xref :document-refactor))
|
||||
(def drop-refactor (icon-xref :drop-refactor))
|
||||
(def effects-refactor (icon-xref :effects-refactor))
|
||||
|
@ -365,9 +366,23 @@
|
|||
(def text-align-right-refactor (icon-xref :text-align-right-refactor))
|
||||
(def text-auto-height-refactor (icon-xref :text-auto-height-refactor))
|
||||
(def text-auto-width-refactor (icon-xref :text-auto-width-refactor))
|
||||
|
||||
(def text-fixed-refactor (icon-xref :textfixed--refactor))
|
||||
(def text-justify-refactor (icon-xref :text-justify-refactor))
|
||||
(def text-letterspacing-refactor (icon-xref :text-letterspacing-refactor))
|
||||
(def text-lineheight-refactor (icon-xref :text-lineheight-refactor))
|
||||
(def text-lowercase-refactor (icon-xref :text-lowercase-refactor))
|
||||
(def text-LTR-refactor (icon-xref :text-LTR-refactor))
|
||||
(def text-middle-refactor (icon-xref :text-middle-refactor))
|
||||
(def text-mixed-refactor (icon-xref :text-mixed-refactor))
|
||||
(def text-palette-refactor (icon-xref :text-palette-refactor))
|
||||
(def text-paragraph-refactor (icon-xref :text-paragraph-refactor))
|
||||
(def text-refactor (icon-xref :text-refactor))
|
||||
(def text-palette-refactor (icon-xref :text-palette-refactor))
|
||||
(def text-RTL-refactor (icon-xref :text-RTL-refactor))
|
||||
(def text-stroked-refactor (icon-xref :text-stroked-refactor))
|
||||
(def text-top-refactor (icon-xref :text-top-refactor))
|
||||
(def text-underlined-refactor (icon-xref :text-underlined-refactor))
|
||||
(def text-uppercase-refactor (icon-xref :text-uppercase-refactor))
|
||||
(def tick-refactor (icon-xref :tick-refactor))
|
||||
(def unlock-refactor (icon-xref :unlock-refactor))
|
||||
(def vertical-align-items-center-refactor (icon-xref :vertical-align-items-center-refactor))
|
||||
|
@ -375,6 +390,7 @@
|
|||
(def vertical-align-items-start-refactor (icon-xref :vertical-align-items-start-refactor))
|
||||
(def view-as-icons-refactor (icon-xref :view-as-icons-refactor))
|
||||
(def wrap-refactor (icon-xref :wrap-refactor))
|
||||
(def view-as-list-refactor (icon-xref :view-as-list-refactor))
|
||||
(def loader-pencil
|
||||
(mf/html
|
||||
[:svg
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
(events/listen js/document EventType.KEYDOWN handle-keydown)
|
||||
|
||||
;; Changing to js/document breaks the color picker
|
||||
(events/listen (dom/get-root) EventType.POINTERDOWN handle-click-outside)
|
||||
(events/listen (dom/get-root) EventType.POINTERDOWN handle-click-outside)
|
||||
|
||||
(events/listen js/document EventType.CONTEXTMENU handle-click-outside)]]
|
||||
#(doseq [key keys]
|
||||
|
|
|
@ -169,7 +169,7 @@
|
|||
file-ready? (mf/deref file-ready*)
|
||||
|
||||
components-v2? (features/use-feature :components-v2)
|
||||
new-css? (features/use-feature :new-css-system)
|
||||
new-css-system (features/use-feature :new-css-system)
|
||||
|
||||
background-color (:background-color wglobal)]
|
||||
|
||||
|
@ -192,9 +192,9 @@
|
|||
[:& (mf/provider ctx/current-team-id) {:value team-id}
|
||||
[:& (mf/provider ctx/current-page-id) {:value page-id}
|
||||
[:& (mf/provider ctx/components-v2) {:value components-v2?}
|
||||
[:& (mf/provider ctx/new-css-system) {:value new-css?}
|
||||
[:& (mf/provider ctx/new-css-system) {:value new-css-system}
|
||||
[:& (mf/provider ctx/workspace-read-only?) {:value read-only?}
|
||||
[:section#workspace {:class (when new-css? (css :workspace))
|
||||
[:section#workspace {:class (when new-css-system (css :workspace))
|
||||
:style {:background-color background-color
|
||||
:touch-action "none"}}
|
||||
(when (not (:hide-ui layout))
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"ui_workspace_button-primary_FZJ-T","button-secondary":"ui_workspace_button-secondary_oDzCJ","button-icon":"ui_workspace_button-icon_L5y8h","button-icon-small":"ui_workspace_button-icon-small_Ppp3W","workspace":"ui_workspace_workspace_xutJr"}
|
||||
{"button-primary":"ui_workspace_button-primary_FZJ-T","button-secondary":"ui_workspace_button-secondary_oDzCJ","button-tertiary":"ui_workspace_button-tertiary_LVpr3","button-tag":"ui_workspace_button-tag_cU1Th","button-icon":"ui_workspace_button-icon_L5y8h","button-icon-small":"ui_workspace_button-icon-small_Ppp3W","asset-element":"ui_workspace_asset-element_LTbhl","workspace":"ui_workspace_workspace_xutJr"}
|
|
@ -1 +1 @@
|
|||
{"button-primary":"workspace_color_palette_button-primary_0d2e2","button-secondary":"workspace_color_palette_button-secondary_C8qJL","button-icon":"workspace_color_palette_button-icon_-tBR6","color-palette":"workspace_color_palette_color-palette_hfJPA","left-arrow":"workspace_color_palette_left-arrow_PK7sj","right-arrow":"workspace_color_palette_right-arrow_swpS9","button-icon-small":"workspace_color_palette_button-icon-small_RrGTg","disabled":"workspace_color_palette_disabled_bz-he","color-palette-content":"workspace_color_palette_color-palette-content_okg18","color-palette-inside":"workspace_color_palette_color-palette-inside_dCIeR","color-cell":"workspace_color_palette_color-cell_ITDgl","is-not-library-color":"workspace_color_palette_is-not-library-color_EqCM6","no-text":"workspace_color_palette_no-text_QMPK0"}
|
||||
{"button-primary":"workspace_color_palette_button-primary_0d2e2","button-secondary":"workspace_color_palette_button-secondary_C8qJL","button-tertiary":"workspace_color_palette_button-tertiary_X6-9C","button-tag":"workspace_color_palette_button-tag_GtZK2","button-icon":"workspace_color_palette_button-icon_-tBR6","color-palette":"workspace_color_palette_color-palette_hfJPA","left-arrow":"workspace_color_palette_left-arrow_PK7sj","right-arrow":"workspace_color_palette_right-arrow_swpS9","button-icon-small":"workspace_color_palette_button-icon-small_RrGTg","asset-element":"workspace_color_palette_asset-element_3Q2Mp","disabled":"workspace_color_palette_disabled_bz-he","color-palette-content":"workspace_color_palette_color-palette-content_okg18","color-palette-inside":"workspace_color_palette_color-palette-inside_dCIeR","color-cell":"workspace_color_palette_color-cell_ITDgl","is-not-library-color":"workspace_color_palette_is-not-library-color_EqCM6","no-text":"workspace_color_palette_no-text_QMPK0"}
|
|
@ -1 +1 @@
|
|||
{"button-primary":"workspace_color_palette_ctx_menu_button-primary_2ka4z","button-secondary":"workspace_color_palette_ctx_menu_button-secondary_jfajf","button-icon":"workspace_color_palette_ctx_menu_button-icon_cCaY2","button-icon-small":"workspace_color_palette_ctx_menu_button-icon-small_-knT4","palette-menu":"workspace_color_palette_ctx_menu_palette-menu_Vrjfy","palette-library":"workspace_color_palette_ctx_menu_palette-library_0LFV5","selected":"workspace_color_palette_ctx_menu_selected_lfchf","icon-wrapper":"workspace_color_palette_ctx_menu_icon-wrapper_v8-ys","recent-colors":"workspace_color_palette_ctx_menu_recent-colors_Q4fss","file-library":"workspace_color_palette_ctx_menu_file-library_8qsbr","option-wrapper":"workspace_color_palette_ctx_menu_option-wrapper_st9Cq","library-name":"workspace_color_palette_ctx_menu_library-name_BL8b8","color-sample":"workspace_color_palette_ctx_menu_color-sample_jQUGL"}
|
||||
{"button-primary":"workspace_color_palette_ctx_menu_button-primary_2ka4z","button-secondary":"workspace_color_palette_ctx_menu_button-secondary_jfajf","button-tertiary":"workspace_color_palette_ctx_menu_button-tertiary_NLctS","button-tag":"workspace_color_palette_ctx_menu_button-tag_GN3ad","button-icon":"workspace_color_palette_ctx_menu_button-icon_cCaY2","button-icon-small":"workspace_color_palette_ctx_menu_button-icon-small_-knT4","palette-menu":"workspace_color_palette_ctx_menu_palette-menu_Vrjfy","palette-library":"workspace_color_palette_ctx_menu_palette-library_0LFV5","selected":"workspace_color_palette_ctx_menu_selected_lfchf","icon-wrapper":"workspace_color_palette_ctx_menu_icon-wrapper_v8-ys","recent-colors":"workspace_color_palette_ctx_menu_recent-colors_Q4fss","file-library":"workspace_color_palette_ctx_menu_file-library_8qsbr","asset-element":"workspace_color_palette_ctx_menu_asset-element_pV16m","option-wrapper":"workspace_color_palette_ctx_menu_option-wrapper_st9Cq","library-name":"workspace_color_palette_ctx_menu_library-name_BL8b8","color-sample":"workspace_color_palette_ctx_menu_color-sample_jQUGL"}
|
|
@ -1 +1 @@
|
|||
{"button-primary":"workspace_context_menu_button-primary_d6q-P","button-secondary":"workspace_context_menu_button-secondary_bIdqe","button-icon":"workspace_context_menu_button-icon_tXvxe","button-icon-small":"workspace_context_menu_button-icon-small_c0rVU","workspace-context-menu":"workspace_context_menu_workspace-context-menu_2NyvR","icon-menu-item":"workspace_context_menu_icon-menu-item_P3-bA","shape-icon":"workspace_context_menu_shape-icon_xx1Ll","workspace-context-submenu":"workspace_context_menu_workspace-context-submenu_BUNLt","selected-icon":"workspace_context_menu_selected-icon_pZqBp","context-menu-item":"workspace_context_menu_context-menu-item_Tx-Ty","submenu-icon":"workspace_context_menu_submenu-icon_JwYm8","separator":"workspace_context_menu_separator_E9-aR","title":"workspace_context_menu_title_P8iFL","shortcut":"workspace_context_menu_shortcut_rypUe","shortcut-key":"workspace_context_menu_shortcut-key_3rF3t","icon-wrapper":"workspace_context_menu_icon-wrapper_n7VO2"}
|
||||
{"button-primary":"workspace_context_menu_button-primary_d6q-P","button-secondary":"workspace_context_menu_button-secondary_bIdqe","button-tertiary":"workspace_context_menu_button-tertiary_vGSns","button-tag":"workspace_context_menu_button-tag_rOUbd","button-icon":"workspace_context_menu_button-icon_tXvxe","button-icon-small":"workspace_context_menu_button-icon-small_c0rVU","workspace-context-menu":"workspace_context_menu_workspace-context-menu_2NyvR","icon-menu-item":"workspace_context_menu_icon-menu-item_P3-bA","shape-icon":"workspace_context_menu_shape-icon_xx1Ll","workspace-context-submenu":"workspace_context_menu_workspace-context-submenu_BUNLt","selected-icon":"workspace_context_menu_selected-icon_pZqBp","context-menu-item":"workspace_context_menu_context-menu-item_Tx-Ty","submenu-icon":"workspace_context_menu_submenu-icon_JwYm8","asset-element":"workspace_context_menu_asset-element_jkrbj","separator":"workspace_context_menu_separator_E9-aR","title":"workspace_context_menu_title_P8iFL","shortcut":"workspace_context_menu_shortcut_rypUe","shortcut-key":"workspace_context_menu_shortcut-key_3rF3t","icon-wrapper":"workspace_context_menu_icon-wrapper_n7VO2"}
|
|
@ -66,10 +66,10 @@
|
|||
(let [selected-drawtool (mf/deref refs/selected-drawing-tool)
|
||||
edition (mf/deref refs/selected-edition)
|
||||
|
||||
new-css? (mf/use-ctx ctx/new-css-system)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
|
||||
show-palette-btn? (and (not ^boolean read-only?) (not ^boolean new-css?))
|
||||
show-palette-btn? (and (not ^boolean read-only?) (not ^boolean new-css-system))
|
||||
|
||||
|
||||
interrupt
|
||||
|
|
|
@ -5,14 +5,20 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.libraries
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.search-bar :refer [search-bar]]
|
||||
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
|
@ -56,6 +62,39 @@
|
|||
(conj (tr "workspace.libraries.typography" typography-count))))
|
||||
"\u00A0"))
|
||||
|
||||
(mf/defc describe-library-blocks
|
||||
[{:keys [components-count graphics-count colors-count typography-count] :as props}]
|
||||
|
||||
(let [last-one (cond
|
||||
(> colors-count 0) :color
|
||||
(> graphics-count 0) :graphics
|
||||
(> components-count 0) :components)]
|
||||
[:*
|
||||
(when (pos? components-count)
|
||||
[:*
|
||||
[:span {:class (css :element-count)}
|
||||
(tr "workspace.libraries.components" components-count)]
|
||||
(when (not= last-one :components)
|
||||
[:span " · "])])
|
||||
|
||||
(when (pos? graphics-count)
|
||||
[:*
|
||||
[:span {:class (css :element-count)}
|
||||
(tr "workspace.libraries.graphics" graphics-count)]
|
||||
(when (not= last-one :graphics)
|
||||
[:span " · "])])
|
||||
|
||||
(when (pos? colors-count)
|
||||
[:*
|
||||
[:span {:class (css :element-count)}
|
||||
(tr "workspace.libraries.colors" colors-count)]
|
||||
(when (not= last-one :colors)
|
||||
[:span " · "])])
|
||||
|
||||
(when (pos? typography-count)
|
||||
[:span {:class (css :element-count)}
|
||||
(tr "workspace.libraries.typography" typography-count)])]))
|
||||
|
||||
(defn- describe-linked-library
|
||||
[library]
|
||||
(let [components-count (count (or (ctkl/components-seq (:data library)) []))
|
||||
|
@ -75,16 +114,16 @@
|
|||
(mf/defc libraries-tab
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file-id shared? linked-libraries shared-libraries]}]
|
||||
(let [search-term* (mf/use-state "")
|
||||
search-term (deref search-term*)
|
||||
|
||||
library-ref (mf/with-memo [file-id]
|
||||
(create-file-library-ref file-id))
|
||||
library (deref library-ref)
|
||||
colors (:colors library)
|
||||
components (:components library)
|
||||
media (:media library)
|
||||
typographies (:typographies library)
|
||||
(let [search-term* (mf/use-state "")
|
||||
search-term (deref search-term*)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
library-ref (mf/with-memo [file-id]
|
||||
(create-file-library-ref file-id))
|
||||
library (deref library-ref)
|
||||
colors (:colors library)
|
||||
components (:components library)
|
||||
media (:media library)
|
||||
typographies (:typographies library)
|
||||
|
||||
shared-libraries
|
||||
(mf/with-memo [shared-libraries linked-libraries file-id search-term]
|
||||
|
@ -101,9 +140,12 @@
|
|||
|
||||
change-search-term
|
||||
(mf/use-fn
|
||||
(mf/deps new-css-system)
|
||||
(fn [event]
|
||||
(let [value (-> (dom/get-target event)
|
||||
(dom/get-value))]
|
||||
(let [value (if new-css-system
|
||||
event
|
||||
(-> (dom/get-target event)
|
||||
(dom/get-value)))]
|
||||
(reset! search-term* value))))
|
||||
|
||||
clear-search-term
|
||||
|
@ -111,20 +153,28 @@
|
|||
|
||||
link-library
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(mf/deps file-id new-css-system)
|
||||
(fn [event]
|
||||
(let [library-id (some-> (dom/get-target event)
|
||||
(dom/get-data "library-id")
|
||||
(parse-uuid))]
|
||||
(let [library-id (if new-css-system
|
||||
(some-> (dom/get-current-target event)
|
||||
(dom/get-data "library-id")
|
||||
(parse-uuid))
|
||||
(some-> (dom/get-target event)
|
||||
(dom/get-data "library-id")
|
||||
(parse-uuid)))]
|
||||
(st/emit! (dwl/link-file-to-library file-id library-id)))))
|
||||
|
||||
unlink-library
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn [event]
|
||||
(let [library-id (some-> (dom/get-target event)
|
||||
(dom/get-data "library-id")
|
||||
(parse-uuid))]
|
||||
(let [library-id (if new-css-system
|
||||
(some-> (dom/get-current-target event)
|
||||
(dom/get-data "library-id")
|
||||
(parse-uuid))
|
||||
(some-> (dom/get-target event)
|
||||
(dom/get-data "library-id")
|
||||
(parse-uuid)))]
|
||||
(st/emit! (dwl/unlink-file-from-library file-id library-id)
|
||||
(dwl/sync-file file-id library-id)))))
|
||||
|
||||
|
@ -140,7 +190,10 @@
|
|||
publish
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
#(st/emit! (dwl/set-file-shared file-id true)))
|
||||
(fn [event]
|
||||
(let [input-node (dom/event->target event)]
|
||||
(st/emit! (dwl/set-file-shared file-id true))
|
||||
(dom/blur! input-node))))
|
||||
|
||||
unpublish
|
||||
(mf/use-fn
|
||||
|
@ -165,122 +218,230 @@
|
|||
(when ^boolean esc?
|
||||
(dom/blur! input-node)))))]
|
||||
|
||||
[:*
|
||||
[:div.section
|
||||
[:div.section-title (tr "workspace.libraries.in-this-file")]
|
||||
[:div.section-list
|
||||
(if new-css-system
|
||||
[:*
|
||||
[:div {:class (css :section)}
|
||||
[:& title-bar {:collapsable? false
|
||||
:title (tr "workspace.libraries.in-this-file")
|
||||
:klass :title-spacing-lib}]
|
||||
[:div {:class (css :section-list)}
|
||||
|
||||
[:div.section-list-item
|
||||
[:div
|
||||
[:div.item-name (tr "workspace.libraries.file-library")]
|
||||
[:div.item-contents (describe-library
|
||||
(count components)
|
||||
(count media)
|
||||
(count colors)
|
||||
(count typographies))]]
|
||||
[:div
|
||||
(if ^boolean shared?
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "common.unpublish")
|
||||
:on-click unpublish}]
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "common.publish")
|
||||
:on-click publish}])]]
|
||||
[:div {:class (css :section-list-item)}
|
||||
[:div
|
||||
[:div {:class (css :item-name)} (tr "workspace.libraries.file-library")]
|
||||
[:div {:class (css :item-contents)}
|
||||
[:& describe-library-blocks {:components-count (count components)
|
||||
:graphics-count (count media)
|
||||
:colors-count (count colors)
|
||||
:typography-count (count typographies)}]]]
|
||||
[:div
|
||||
(if ^boolean shared?
|
||||
[:input {:class (css :item-unpublish)
|
||||
:type "button"
|
||||
:value (tr "common.unpublish")
|
||||
:on-click unpublish}]
|
||||
[:input {:class (css :item-publish)
|
||||
:type "button"
|
||||
:value (tr "common.publish")
|
||||
:on-click publish}])]]
|
||||
|
||||
(for [{:keys [id name] :as library} linked-libraries]
|
||||
[:div.section-list-item {:key (dm/str id)}
|
||||
[:div.item-name name]
|
||||
[:div.item-contents (describe-linked-library library)]
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "labels.remove")
|
||||
:data-library-id (dm/str id)
|
||||
:on-click unlink-library}]])]]
|
||||
(for [{:keys [id name] :as library} linked-libraries]
|
||||
[:div {:class (css :section-list-item)
|
||||
:key (dm/str id)}
|
||||
[:div
|
||||
[:div {:class (css :item-name)} name]
|
||||
[:div {:class (css :item-contents)}
|
||||
(let [components-count (count (or (ctkl/components-seq (:data library)) []))
|
||||
graphics-count (count (dm/get-in library [:data :media] []))
|
||||
colors-count (count (dm/get-in library [:data :colors] []))
|
||||
typography-count (count (dm/get-in library [:data :typographies] []))]
|
||||
[:& describe-library-blocks {:components-count components-count
|
||||
:graphics-count graphics-count
|
||||
:colors-count colors-count
|
||||
:typography-count typography-count}])]]
|
||||
|
||||
[:div.section
|
||||
[:div.section-title (tr "workspace.libraries.shared-libraries")]
|
||||
[:div.libraries-search
|
||||
[:input.search-input
|
||||
{:placeholder (tr "workspace.libraries.search-shared-libraries")
|
||||
:type "text"
|
||||
:value search-term
|
||||
:on-change change-search-term
|
||||
:on-key-down handle-key-down}]
|
||||
(if (str/empty? search-term)
|
||||
[:div.search-icon
|
||||
i/search]
|
||||
[:div.search-icon.search-close
|
||||
{:on-click clear-search-term}
|
||||
i/close])]
|
||||
[:button {:class (css :item-button)
|
||||
:type "button"
|
||||
:data-library-id (dm/str id)
|
||||
:on-click unlink-library}
|
||||
i/delete-refactor]])]]
|
||||
|
||||
(if (seq shared-libraries)
|
||||
[:div {:class (css :section)}
|
||||
[:& title-bar {:collapsable? false
|
||||
:title (tr "workspace.libraries.shared-libraries")
|
||||
:klass :title-spacing-lib}]
|
||||
[:div {:class (css :libraries-search)}
|
||||
[:& search-bar {:on-change change-search-term
|
||||
:value search-term
|
||||
:placeholder (tr "workspace.libraries.search-shared-libraries")
|
||||
:icon (mf/html [:span {:class (css :search-icon)} i/search-refactor])}]]
|
||||
|
||||
(if (seq shared-libraries)
|
||||
[:div {:class (css :section-list)}
|
||||
(for [{:keys [id name] :as library} shared-libraries]
|
||||
[:div {:class (css :section-list-item)
|
||||
:key (dm/str id)}
|
||||
[:div
|
||||
[:div {:class (css :item-name)} name]
|
||||
[:div {:class (css :item-contents)}
|
||||
(let [components-count (dm/get-in library [:library-summary :components :count] 0)
|
||||
graphics-count (dm/get-in library [:library-summary :media :count] 0)
|
||||
colors-count (dm/get-in library [:library-summary :colors :count] 0)
|
||||
typography-count (dm/get-in library [:library-summary :typographies :count] 0)]
|
||||
[:& describe-library-blocks {:components-count components-count
|
||||
:graphics-count graphics-count
|
||||
:colors-count colors-count
|
||||
:typography-count typography-count}])]]
|
||||
[:button {:class (css :item-button)
|
||||
:data-library-id (dm/str id)
|
||||
:on-click link-library}
|
||||
i/add-refactor]])]
|
||||
|
||||
[:div {:class (css :section-list-empty)}
|
||||
(if (nil? shared-libraries)
|
||||
i/loader-pencil
|
||||
(if (str/empty? search-term)
|
||||
(tr "workspace.libraries.no-shared-libraries-available")
|
||||
(tr "workspace.libraries.no-matches-for" search-term)))])]]
|
||||
|
||||
[:*
|
||||
[:div.section
|
||||
[:div.section-title (tr "workspace.libraries.in-this-file")]
|
||||
[:div.section-list
|
||||
(for [{:keys [id name] :as library} shared-libraries]
|
||||
|
||||
[:div.section-list-item
|
||||
[:div
|
||||
[:div.item-name (tr "workspace.libraries.file-library")]
|
||||
[:div.item-contents (describe-library
|
||||
(count components)
|
||||
(count media)
|
||||
(count colors)
|
||||
(count typographies))]]
|
||||
[:div
|
||||
(if ^boolean shared?
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "common.unpublish")
|
||||
:on-click unpublish}]
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "common.publish")
|
||||
:on-click publish}])]]
|
||||
|
||||
(for [{:keys [id name] :as library} linked-libraries]
|
||||
[:div.section-list-item {:key (dm/str id)}
|
||||
[:div.item-name name]
|
||||
[:div.item-contents (describe-external-library library)]
|
||||
[:div.item-contents (describe-linked-library library)]
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "workspace.libraries.add")
|
||||
:value (tr "labels.remove")
|
||||
:data-library-id (dm/str id)
|
||||
:on-click link-library}]])]
|
||||
:on-click unlink-library}]])]]
|
||||
|
||||
[:div.section-list-empty
|
||||
(if (nil? shared-libraries)
|
||||
i/loader-pencil
|
||||
[:* i/library
|
||||
(if (str/empty? search-term)
|
||||
(tr "workspace.libraries.no-shared-libraries-available")
|
||||
(tr "workspace.libraries.no-matches-for" search-term))])])]]))
|
||||
[:div.section
|
||||
[:div.section-title (tr "workspace.libraries.shared-libraries")]
|
||||
[:div.libraries-search
|
||||
[:input.search-input
|
||||
{:placeholder (tr "workspace.libraries.search-shared-libraries")
|
||||
:type "text"
|
||||
:value search-term
|
||||
:on-change change-search-term
|
||||
:on-key-down handle-key-down}]
|
||||
(if (str/empty? search-term)
|
||||
[:div.search-icon
|
||||
i/search]
|
||||
[:div.search-icon.search-close
|
||||
{:on-click clear-search-term}
|
||||
i/close])]
|
||||
|
||||
(if (seq shared-libraries)
|
||||
[:div.section-list
|
||||
(for [{:keys [id name] :as library} shared-libraries]
|
||||
[:div.section-list-item {:key (dm/str id)}
|
||||
[:div.item-name name]
|
||||
[:div.item-contents (describe-external-library library)]
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "workspace.libraries.add")
|
||||
:data-library-id (dm/str id)
|
||||
:on-click link-library}]])]
|
||||
|
||||
[:div.section-list-empty
|
||||
(if (nil? shared-libraries)
|
||||
i/loader-pencil
|
||||
[:* i/library
|
||||
(if (str/empty? search-term)
|
||||
(tr "workspace.libraries.no-shared-libraries-available")
|
||||
(tr "workspace.libraries.no-matches-for" search-term))])])]])))
|
||||
|
||||
(mf/defc updates-tab
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file-id file-data libraries]}]
|
||||
(let [libraries (mf/with-memo [file-data libraries]
|
||||
(filter #(seq (dwl/assets-need-sync % file-data))
|
||||
(vals libraries)))
|
||||
(let [libraries (mf/with-memo [file-data libraries]
|
||||
(filter #(seq (dwl/assets-need-sync % file-data)) (vals libraries)))
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
update (mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn [event]
|
||||
(let [library-id (some-> (dom/get-target event)
|
||||
(dom/get-data "library-id")
|
||||
(parse-uuid))]
|
||||
(st/emit! (dwl/sync-file file-id library-id)))))]
|
||||
[:div.section
|
||||
(if (empty? libraries)
|
||||
[:div.section-list-empty
|
||||
i/library
|
||||
(tr "workspace.libraries.no-libraries-need-sync")]
|
||||
[:*
|
||||
[:div.section-title (tr "workspace.libraries.library")]
|
||||
[:div.section-list
|
||||
(for [{:keys [id name] :as library} libraries]
|
||||
[:div.section-list-item {:key (dm/str id)}
|
||||
[:div.item-name name]
|
||||
[:div.item-contents (describe-external-library library)]
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "workspace.libraries.update")
|
||||
:data-library-id (dm/str id)
|
||||
:on-click update}]])]])]))
|
||||
update (mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn [event]
|
||||
(let [library-id (some-> (dom/get-target event)
|
||||
(dom/get-data "library-id")
|
||||
(parse-uuid))]
|
||||
(st/emit! (dwl/sync-file file-id library-id)))))]
|
||||
(if new-css-system
|
||||
[:div {:class (css :section)}
|
||||
(if (empty? libraries)
|
||||
[:div {:class (css :section-list-empty)}
|
||||
(tr "workspace.libraries.no-libraries-need-sync")]
|
||||
[:*
|
||||
[:div {:class (css :section-title)} (tr "workspace.libraries.library")]
|
||||
|
||||
[:div {:class (css :section-list)}
|
||||
(for [{:keys [id name] :as library} libraries]
|
||||
[:div {:class (css :section-list-item)
|
||||
:key (dm/str id)}
|
||||
[:div
|
||||
[:div {:class (css :item-name)} name]
|
||||
[:div {:class (css :item-contents)} (describe-external-library library)]]
|
||||
[:input {:class (css :item-update)
|
||||
:type "button"
|
||||
:value (tr "workspace.libraries.update")
|
||||
:data-library-id (dm/str id)
|
||||
:on-click update}]])]])]
|
||||
|
||||
[:div.section
|
||||
(if (empty? libraries)
|
||||
[:div.section-list-empty
|
||||
i/library
|
||||
(tr "workspace.libraries.no-libraries-need-sync")]
|
||||
[:*
|
||||
[:div.section-title (tr "workspace.libraries.library")]
|
||||
|
||||
[:div.section-list
|
||||
(for [{:keys [id name] :as library} libraries]
|
||||
[:div.section-list-item {:key (dm/str id)}
|
||||
[:div.item-name name]
|
||||
[:div.item-contents (describe-external-library library)]
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "workspace.libraries.update")
|
||||
:data-library-id (dm/str id)
|
||||
:on-click update}]])]])])))
|
||||
|
||||
(mf/defc libraries-dialog
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :libraries-dialog}
|
||||
[]
|
||||
(let [project (mf/deref refs/workspace-project)
|
||||
file-data (mf/deref refs/workspace-data)
|
||||
file (mf/deref ref:workspace-file)
|
||||
(let [new-css-system (features/use-feature :new-css-system)
|
||||
project (mf/deref refs/workspace-project)
|
||||
file-data (mf/deref refs/workspace-data)
|
||||
file (mf/deref ref:workspace-file)
|
||||
|
||||
team-id (:team-id project)
|
||||
file-id (:id file)
|
||||
shared? (:is-shared file)
|
||||
team-id (:team-id project)
|
||||
file-id (:id file)
|
||||
shared? (:is-shared file)
|
||||
|
||||
selected-tab* (mf/use-state :libraries)
|
||||
selected-tab (deref selected-tab*)
|
||||
selected-tab* (mf/use-state :libraries)
|
||||
selected-tab (deref selected-tab*)
|
||||
|
||||
libraries (mf/deref refs/workspace-libraries)
|
||||
libraries (mf/with-memo [libraries]
|
||||
(d/removem (fn [[_ val]] (:is-indirect val)) libraries))
|
||||
libraries (mf/deref refs/workspace-libraries)
|
||||
libraries (mf/with-memo [libraries]
|
||||
(d/removem (fn [[_ val]] (:is-indirect val)) libraries))
|
||||
|
||||
;; NOTE: we really don't need react on shared files
|
||||
shared-libraries
|
||||
|
@ -292,35 +453,61 @@
|
|||
select-updates-tab
|
||||
(mf/use-fn #(reset! selected-tab* :updates))
|
||||
|
||||
on-tab-change
|
||||
(mf/use-fn #(reset! selected-tab* %))
|
||||
|
||||
close-dialog
|
||||
(mf/use-fn #(modal/hide!))]
|
||||
(mf/use-fn (fn [_] (modal/hide!)
|
||||
(modal/disallow-click-outside!)))]
|
||||
|
||||
(mf/with-effect [team-id]
|
||||
(when team-id
|
||||
(st/emit! (dwl/fetch-shared-files {:team-id team-id}))))
|
||||
[:& (mf/provider ctx/new-css-system) {:value new-css-system}
|
||||
(if new-css-system
|
||||
[:div {:class (css :modal-overlay)}
|
||||
[:div {:class (css :modal-dialog)}
|
||||
[:div {:class (css :modal-content)}
|
||||
[:div {:class (css :libraries-header)}
|
||||
|
||||
[:div.modal-overlay
|
||||
[:div.modal.libraries-dialog
|
||||
[:a.close {:on-click close-dialog} i/close]
|
||||
[:div.modal-content
|
||||
[:div.libraries-header
|
||||
[:div.header-item
|
||||
{:class (dom/classnames :active (= selected-tab :libraries))
|
||||
:on-click select-libraries-tab}
|
||||
(tr "workspace.libraries.libraries")]
|
||||
[:div.header-item
|
||||
{:class (dom/classnames :active (= selected-tab :updates))
|
||||
:on-click select-updates-tab}
|
||||
(tr "workspace.libraries.updates")]]
|
||||
[:div.libraries-content
|
||||
(case selected-tab
|
||||
:libraries
|
||||
[:& libraries-tab {:file-id file-id
|
||||
:shared? shared?
|
||||
:linked-libraries libraries
|
||||
:shared-libraries shared-libraries}]
|
||||
:updates
|
||||
[:& updates-tab {:file-id file-id
|
||||
:file-data file-data
|
||||
:libraries libraries}])]]]]))
|
||||
[:& tab-container
|
||||
{:on-change-tab on-tab-change
|
||||
:selected selected-tab
|
||||
:collapsable? false}
|
||||
[:& tab-element {:id :libraries :title (tr "workspace.libraries.libraries")}
|
||||
[:div {:class (dom/classnames (css :libraries-content) true)}
|
||||
[:& libraries-tab {:file-id file-id
|
||||
:shared? shared?
|
||||
:linked-libraries libraries
|
||||
:shared-libraries shared-libraries}]]]
|
||||
[:& tab-element {:id :updates :title (tr "workspace.libraries.updates")}
|
||||
[:div {:class (dom/classnames (css :updates-content) true)}
|
||||
[:& updates-tab {:file-id file-id
|
||||
:file-data file-data
|
||||
:libraries libraries}]]]]]]]]
|
||||
|
||||
[:div.modal-overlay
|
||||
[:div.modal.libraries-dialog
|
||||
[:a.close {:on-click close-dialog} i/close]
|
||||
[:div.modal-content
|
||||
[:div.libraries-header
|
||||
[:div.header-item
|
||||
{:class (dom/classnames :active (= selected-tab :libraries))
|
||||
:on-click select-libraries-tab}
|
||||
(tr "workspace.libraries.libraries")]
|
||||
[:div.header-item
|
||||
{:class (dom/classnames :active (= selected-tab :updates))
|
||||
:on-click select-updates-tab}
|
||||
(tr "workspace.libraries.updates")]]
|
||||
[:div.libraries-content
|
||||
(case selected-tab
|
||||
:libraries
|
||||
[:& libraries-tab {:file-id file-id
|
||||
:shared? shared?
|
||||
:linked-libraries libraries
|
||||
:shared-libraries shared-libraries}]
|
||||
:updates
|
||||
[:& updates-tab {:file-id file-id
|
||||
:file-data file-data
|
||||
:libraries libraries}])]]]])]))
|
||||
|
||||
|
|
1
frontend/src/app/main/ui/workspace/libraries.css.json
Normal file
1
frontend/src/app/main/ui/workspace/libraries.css.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"button-primary":"workspace_libraries_button-primary_Hsioh","modal-overlay":"workspace_libraries_modal-overlay_qC-df","modal-dialog":"workspace_libraries_modal-dialog_Kj293","modal-content":"workspace_libraries_modal-content_4EVEQ","libraries-content":"workspace_libraries_libraries-content_ycQdm","section":"workspace_libraries_section_SUsgi","section-list":"workspace_libraries_section-list_lGSrM","section-list-item":"workspace_libraries_section-list-item_hwASN","item-publish":"workspace_libraries_item-publish_ZMopF","item-unpublish":"workspace_libraries_item-unpublish_1seca","item-update":"workspace_libraries_item-update_GklIE","updates-content":"workspace_libraries_updates-content_lqMoE","button-secondary":"workspace_libraries_button-secondary_l5M0x","button-tertiary":"workspace_libraries_button-tertiary_C54rH","item-button":"workspace_libraries_item-button_dKUeX","close":"workspace_libraries_close_bED7B","button-tag":"workspace_libraries_button-tag_wAh-s","button-icon":"workspace_libraries_button-icon_kxS7q","item-button-icon":"workspace_libraries_item-button-icon_CeJWg","button-icon-small":"workspace_libraries_button-icon-small_Q9eo3","section-list-empty":"workspace_libraries_section-list-empty_mOKkJ","libraries-search":"workspace_libraries_libraries-search_JS70w","search-icon":"workspace_libraries_search-icon_y7N9S","asset-element":"workspace_libraries_asset-element_-FuJl","libraries-header":"workspace_libraries_libraries-header_-W6bJ","item-name":"workspace_libraries_item-name_Zjbsw","item-contents":"workspace_libraries_item-contents_EPTF6","section-title":"workspace_libraries_section-title_7rsm7","element-count":"workspace_libraries_element-count_07SV2"}
|
139
frontend/src/app/main/ui/workspace/libraries.scss
Normal file
139
frontend/src/app/main/ui/workspace/libraries.scss
Normal file
|
@ -0,0 +1,139 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
.modal-overlay {
|
||||
@include flexCenter;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: $z-index-modal;
|
||||
background-color: var(--overlay-color);
|
||||
pointer-events: none; // This is to allow outside click that closes modal.
|
||||
.modal-dialog {
|
||||
height: $s-400;
|
||||
max-height: 100%;
|
||||
width: $s-664;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--modal-background-color);
|
||||
pointer-events: all;
|
||||
.close {
|
||||
@extend .button-tertiary;
|
||||
width: $s-32;
|
||||
height: $s-32;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
.modal-content {
|
||||
.libraries-header {
|
||||
padding: $s-12;
|
||||
}
|
||||
|
||||
.libraries-content,
|
||||
.updates-content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: $s-24;
|
||||
padding-top: $s-16;
|
||||
height: 100%;
|
||||
|
||||
.section {
|
||||
height: 100%;
|
||||
:global(.title-spacing-lib) {
|
||||
margin: 0 0 $s-8 calc(-1 * $s-8);
|
||||
}
|
||||
.section-list {
|
||||
height: 100%;
|
||||
max-height: 250px;
|
||||
overflow: auto;
|
||||
.section-list-item {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
margin-bottom: $s-12;
|
||||
|
||||
.item-name {
|
||||
@include titleTipography;
|
||||
color: var(--library-name-foreground-color);
|
||||
}
|
||||
.item-contents {
|
||||
@include titleTipography;
|
||||
color: var(--library-content-foreground-color);
|
||||
}
|
||||
|
||||
.item-publish,
|
||||
.item-unpublish,
|
||||
.item-update {
|
||||
@extend .button-primary;
|
||||
@include tabTitleTipography;
|
||||
height: $s-32;
|
||||
min-width: $s-92;
|
||||
padding: $s-8 $s-12;
|
||||
border-radius: $br-8;
|
||||
}
|
||||
.item-unpublish {
|
||||
@extend .button-secondary;
|
||||
}
|
||||
.item-button {
|
||||
@extend .button-tertiary;
|
||||
width: $s-32;
|
||||
height: $s-32;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
.item-button-icon {
|
||||
width: $s-28;
|
||||
height: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@include titleTipography;
|
||||
margin-bottom: $s-12;
|
||||
}
|
||||
.libraries-search {
|
||||
margin-bottom: $s-12;
|
||||
.search-icon {
|
||||
@include flexCenter;
|
||||
padding: 0 0 0 $s-8;
|
||||
width: $s-20;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
}
|
||||
}
|
||||
}
|
||||
.section-list-empty {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
width: $s-16;
|
||||
height: $s-16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.updates-content {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.element-count {
|
||||
white-space: nowrap;
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"button-primary":"workspace_palette_button-primary_zEUyD","palettes":"workspace_palette_palettes_JHGUw","palette-actions":"workspace_palette_palette-actions_2GwR6","palette-btn-list":"workspace_palette_palette-btn-list_x7gPS","palette-item":"workspace_palette_palette-item_50uj6","palette-btn":"workspace_palette_palette-btn_kP66y","button-secondary":"workspace_palette_button-secondary_ksr24","button-icon":"workspace_palette_button-icon_pmEDv","button-icon-small":"workspace_palette_button-icon-small_vbLDq","wide":"workspace_palette_wide_3G4e1","mid-palette":"workspace_palette_mid-palette_rGR5I","small-palette":"workspace_palette_small-palette_18Otk","resize-area":"workspace_palette_resize-area_0LwVu","selected":"workspace_palette_selected_Z6BFo","palette":"workspace_palette_palette_eqp3q","handler":"workspace_palette_handler_4JV0J","handler-btn":"workspace_palette_handler-btn_7lnlF","hidden-bts":"workspace_palette_hidden-bts_mhbc0"}
|
||||
{"button-primary":"workspace_palette_button-primary_zEUyD","button-secondary":"workspace_palette_button-secondary_ksr24","button-tertiary":"workspace_palette_button-tertiary_91YQK","palettes":"workspace_palette_palettes_JHGUw","palette-actions":"workspace_palette_palette-actions_2GwR6","palette-btn-list":"workspace_palette_palette-btn-list_x7gPS","palette-item":"workspace_palette_palette-item_50uj6","palette-btn":"workspace_palette_palette-btn_kP66y","button-tag":"workspace_palette_button-tag_S9v-Z","button-icon":"workspace_palette_button-icon_pmEDv","button-icon-small":"workspace_palette_button-icon-small_vbLDq","asset-element":"workspace_palette_asset-element_4bXi3","wide":"workspace_palette_wide_3G4e1","mid-palette":"workspace_palette_mid-palette_rGR5I","small-palette":"workspace_palette_small-palette_18Otk","resize-area":"workspace_palette_resize-area_0LwVu","selected":"workspace_palette_selected_Z6BFo","palette":"workspace_palette_palette_eqp3q","handler":"workspace_palette_handler_4JV0J","handler-btn":"workspace_palette_handler-btn_7lnlF","hidden-bts":"workspace_palette_hidden-bts_mhbc0"}
|
|
@ -57,7 +57,7 @@
|
|||
opacity: $op-10;
|
||||
transition: opacity 1s ease;
|
||||
.palette-btn {
|
||||
@extend .button-primary;
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-32;
|
||||
border-radius: $br-8;
|
||||
|
@ -82,7 +82,7 @@
|
|||
}
|
||||
}
|
||||
.palette-actions {
|
||||
@extend .button-primary;
|
||||
@extend .button-tertiary;
|
||||
grid-area: actions;
|
||||
height: calc(var(--height) - $s-16);
|
||||
width: $s-32;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[app.main.ui.components.tabs-container :refer [tabs-container tabs-element]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks.resize :refer [use-resize-hook]]
|
||||
[app.main.ui.icons :as i]
|
||||
|
@ -40,7 +41,7 @@
|
|||
(contains? layout :assets) :assets)
|
||||
shortcuts? (contains? layout :shortcuts)
|
||||
show-debug? (contains? layout :debug-panel)
|
||||
new-css? (mf/use-ctx ctx/new-css-system)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
{:keys [on-pointer-down on-lost-pointer-capture on-pointer-move parent-ref size]}
|
||||
(use-resize-hook :left-sidebar 255 255 500 :x false :left)
|
||||
|
@ -49,12 +50,14 @@
|
|||
(mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
|
||||
|
||||
on-tab-change
|
||||
(mf/use-fn #(st/emit! (dw/go-to-layout %)))
|
||||
]
|
||||
(mf/use-fn #(st/emit! (dw/go-to-layout %)))]
|
||||
|
||||
[:aside {:ref parent-ref
|
||||
:class (if ^boolean new-css?
|
||||
(dom/classnames (css :left-settings-bar) true)
|
||||
:class (if ^boolean new-css-system
|
||||
(dom/classnames (css :left-settings-bar) true
|
||||
:two-row (<= size 300)
|
||||
:three-row (and (> size 300) (<= size 400))
|
||||
:four-row (> size 400))
|
||||
(dom/classnames :settings-bar true
|
||||
:settings-bar-left true
|
||||
:two-row (<= size 300)
|
||||
|
@ -65,10 +68,10 @@
|
|||
[:div {:on-pointer-down on-pointer-down
|
||||
:on-lost-pointer-capture on-lost-pointer-capture
|
||||
:on-pointer-move on-pointer-move
|
||||
:class (if ^boolean new-css?
|
||||
:class (if ^boolean new-css-system
|
||||
(dom/classnames (css :resize-area) true)
|
||||
(dom/classnames :resize-area true))}]
|
||||
[:div {:class (if ^boolean new-css?
|
||||
[:div {:class (if ^boolean new-css-system
|
||||
(dom/classnames (css :settings-bar-inside) true)
|
||||
(dom/classnames :settings-bar-inside true))}
|
||||
(cond
|
||||
|
@ -79,22 +82,23 @@
|
|||
[:& debug-panel]
|
||||
|
||||
:else
|
||||
(if ^boolean new-css?
|
||||
[:& tab-container
|
||||
{:on-change-tab on-tab-change
|
||||
:selected section
|
||||
:shortcuts? shortcuts?
|
||||
:collapsable? true
|
||||
:handle-collapse handle-collapse}
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :tabs-wrapper) true)}
|
||||
[:& tab-container
|
||||
{:on-change-tab on-tab-change
|
||||
:selected section
|
||||
:shortcuts? shortcuts?
|
||||
:collapsable? true
|
||||
:handle-collapse handle-collapse
|
||||
:klass :tab-spacing}
|
||||
[:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")}
|
||||
[:div {:class (dom/classnames (css :layers-tab) true)}
|
||||
[:& sitemap {:layout layout}]
|
||||
[:& layers-toolbox {:size-parent size}]]]
|
||||
|
||||
[:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")}
|
||||
[:div {:class (dom/classnames (css :layers-tab) true)}
|
||||
[:& sitemap {:layout layout}]
|
||||
[:& layers-toolbox {:size-parent size}]]]
|
||||
|
||||
(when-not ^boolean mode-inspect?
|
||||
[:& tab-element {:id :assets :title (tr "workspace.toolbar.assets")}
|
||||
[:& assets-toolbox]])]
|
||||
(when-not ^boolean mode-inspect?
|
||||
[:& tab-element {:id :assets :title (tr "workspace.toolbar.assets")}
|
||||
[:& assets-toolbox]])]]
|
||||
|
||||
[:*
|
||||
[:button.collapse-sidebar
|
||||
|
@ -102,20 +106,20 @@
|
|||
:aria-label (tr "workspace.sidebar.collapse")}
|
||||
i/arrow-slide]
|
||||
|
||||
[:& tab-container
|
||||
[:& tabs-container
|
||||
{:on-change-tab on-tab-change
|
||||
:selected section
|
||||
:shortcuts? shortcuts?
|
||||
:collapsable? true
|
||||
:handle-collapse handle-collapse}
|
||||
|
||||
[:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")}
|
||||
[:& tabs-element {:id :layers :title (tr "workspace.sidebar.layers")}
|
||||
[:div {:class (dom/classnames :layers-tab true)}
|
||||
[:& sitemap {:layout layout}]
|
||||
[:& layers-toolbox {:size-parent size}]]]
|
||||
|
||||
(when-not ^boolean mode-inspect?
|
||||
[:& tab-element {:id :assets :title (tr "workspace.toolbar.assets")}
|
||||
[:& tabs-element {:id :assets :title (tr "workspace.toolbar.assets")}
|
||||
[:& assets-toolbox]])]]))]]))
|
||||
|
||||
;; --- Right Sidebar (Component)
|
||||
|
@ -150,4 +154,3 @@
|
|||
|
||||
:else
|
||||
[:> options-toolbox props])]]))
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"workspace_sidebar_button-primary_K7xW6","button-secondary":"workspace_sidebar_button-secondary_e2eQE","button-icon":"workspace_sidebar_button-icon_OXdmL","button-icon-small":"workspace_sidebar_button-icon-small_EYb9x","left-settings-bar":"workspace_sidebar_left-settings-bar_7co5t","resize-area":"workspace_sidebar_resize-area_ny1v0","settings-bar-inside":"workspace_sidebar_settings-bar-inside_YnFv8","layers-tab":"workspace_sidebar_layers-tab_soxRL"}
|
||||
{"button-primary":"workspace_sidebar_button-primary_K7xW6","button-secondary":"workspace_sidebar_button-secondary_e2eQE","button-tertiary":"workspace_sidebar_button-tertiary_QKqHT","button-tag":"workspace_sidebar_button-tag_Xc0Sm","button-icon":"workspace_sidebar_button-icon_OXdmL","button-icon-small":"workspace_sidebar_button-icon-small_EYb9x","asset-element":"workspace_sidebar_asset-element_vzrfV","left-settings-bar":"workspace_sidebar_left-settings-bar_7co5t","resize-area":"workspace_sidebar_resize-area_ny1v0","settings-bar-inside":"workspace_sidebar_settings-bar-inside_YnFv8","tabs-wrapper":"workspace_sidebar_tabs-wrapper_YDo4o","layers-tab":"workspace_sidebar_layers-tab_soxRL"}
|
|
@ -33,12 +33,17 @@ $width-settings-bar-max: 500px;
|
|||
grid-template-columns: 100%;
|
||||
grid-template-rows: 100%;
|
||||
height: calc(100% - 2px);
|
||||
.layers-tab {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
grid-template-columns: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
.tabs-wrapper {
|
||||
.layers-tab {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
grid-template-columns: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
:global(.tab-spacing) {
|
||||
margin: $s-4 $s-4 0 $s-4;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1 @@
|
|||
{"button-primary":"sidebar_assets_button-primary_a9p4J","button-secondary":"sidebar_assets_button-secondary_hbgBA","assets-bar":"sidebar_assets_assets-bar_gzAPj","libraries-button":"sidebar_assets_libraries-button_cKUY7","button-tertiary":"sidebar_assets_button-tertiary_KoPen","button-tag":"sidebar_assets_button-tag_yzpPm","button-icon":"sidebar_assets_button-icon_M5Yy6","libraries-icon":"sidebar_assets_libraries-icon_ikusB","button-icon-small":"sidebar_assets_button-icon-small_xZWe1","asset-element":"sidebar_assets_asset-element_xHJzG","section-button":"sidebar_assets_section-button_RSjn8","sections-container":"sidebar_assets_sections-container_r2YTM","section-item":"sidebar_assets_section-item_u6EYM","section-btn":"sidebar_assets_section-btn_s4h2P","libraries-wrapper":"sidebar_assets_libraries-wrapper_agaHg","assets-header":"sidebar_assets_assets-header_aFHCj"}
|
119
frontend/src/app/main/ui/workspace/sidebar/assets.scss
Normal file
119
frontend/src/app/main/ui/workspace/sidebar/assets.scss
Normal file
|
@ -0,0 +1,119 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.assets-bar {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.libraries-button {
|
||||
@include tabTitleTipography;
|
||||
@extend .button-secondary;
|
||||
gap: $s-2;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
border-radius: $s-8;
|
||||
margin-bottom: $s-4;
|
||||
.libraries-icon {
|
||||
@include flexCenter;
|
||||
width: $s-24;
|
||||
height: 100%;
|
||||
svg {
|
||||
@include flexCenter;
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--button-secondary-background-color-hover);
|
||||
color: var(--button-secondary-foreground-color-hover);
|
||||
border: $s-1 solid var(--button-secondary-border-color-hover);
|
||||
svg {
|
||||
stroke: var(--button-secondary-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
&:focus {
|
||||
background-color: var(--button-secondary-background-color-focus);
|
||||
color: var(--button-secondary-foreground-color-focus);
|
||||
border: $s-1 solid var(--button-secondary-border-color-focus);
|
||||
svg {
|
||||
stroke: var(--button-secondary-foreground-color-focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
.section-button {
|
||||
@include flexCenter;
|
||||
@include buttonStyle;
|
||||
height: $s-32;
|
||||
width: $s-32;
|
||||
margin: 0;
|
||||
border: 1px solid var(--color-background-tertiary);
|
||||
border-radius: $br-8 $br-2 $br-2 $br-8;
|
||||
background-color: var(--color-background-tertiary);
|
||||
svg {
|
||||
height: $s-16;
|
||||
width: $s-16;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
&:focus {
|
||||
border: 1px solid var(--input-border-color-focus);
|
||||
outline: 0;
|
||||
background-color: var(--input-background-color-active);
|
||||
color: var(--input-foreground-color-active);
|
||||
svg {
|
||||
background-color: var(--input-background-color-active);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
border: 1px solid var(--input-background-color-hover);
|
||||
background-color: var(--input-background-color-hover);
|
||||
svg {
|
||||
background-color: var(--input-background-color-hover);
|
||||
stroke: var(--button-foreground-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.sections-container {
|
||||
position: absolute;
|
||||
top: $s-84;
|
||||
left: $s-12;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
width: $s-192;
|
||||
padding: $s-4;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--menu-background-color);
|
||||
z-index: $z-index-4;
|
||||
box-shadow: 0px 0px 10px 0px var(--menu-shadow-color);
|
||||
.section-item {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: $s-6;
|
||||
border-radius: $br-8;
|
||||
.section-btn {
|
||||
@include buttonStyle;
|
||||
}
|
||||
}
|
||||
}
|
||||
.libraries-wrapper {
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100% - $s-72);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scrollbar-gutter: stable;
|
||||
overflow-y: overlay;
|
||||
}
|
||||
.assets-header {
|
||||
padding: $s-8 $s-12 $s-4 $s-12;
|
||||
}
|
||||
}
|
621
frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs
Normal file
621
frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs
Normal file
|
@ -0,0 +1,621 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.assets.colors
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.color-bullet :as bc]
|
||||
[app.main.ui.components.color-bullet-new :as cb]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||
[app.main.ui.workspace.sidebar.assets.groups :as grp]
|
||||
[app.util.color :as uc]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.keyboard :as kbd]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[potok.core :as ptk]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc color-item
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [color local? file-id selected multi-colors? multi-assets?
|
||||
on-asset-click on-assets-delete on-clear-selection on-group
|
||||
selected-full selected-paths move-color]}]
|
||||
|
||||
(let [color (mf/with-memo [color file-id]
|
||||
(cond-> color
|
||||
(:value color) (assoc :color (:value color) :opacity 1)
|
||||
(:value color) (dissoc :value)
|
||||
true (assoc :file-id file-id)))
|
||||
|
||||
|
||||
color-id (:id color)
|
||||
|
||||
item-ref (mf/use-ref)
|
||||
dragging* (mf/use-state false)
|
||||
dragging? (deref dragging*)
|
||||
|
||||
rename? (= (:color-for-rename @refs/workspace-local) color-id)
|
||||
input-ref (mf/use-ref)
|
||||
|
||||
editing* (mf/use-state rename?)
|
||||
editing? (deref editing*)
|
||||
|
||||
menu-state (mf/use-state cmm/initial-context-menu-state)
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
default-name (cond
|
||||
(:gradient color) (uc/gradient-type->string (dm/get-in color [:gradient :type]))
|
||||
(:color color) (:color color)
|
||||
:else (:value color))
|
||||
|
||||
apply-color
|
||||
(mf/use-fn
|
||||
(mf/deps color)
|
||||
(fn [event]
|
||||
(st/emit! (dc/apply-color-from-palette (merge uc/empty-color color) (kbd/alt? event)))))
|
||||
|
||||
rename-color
|
||||
(mf/use-fn
|
||||
(mf/deps file-id color-id)
|
||||
(fn [name]
|
||||
(st/emit! (dwl/rename-color file-id color-id name))))
|
||||
|
||||
edit-color
|
||||
(mf/use-fn
|
||||
(mf/deps color file-id)
|
||||
(fn [attrs]
|
||||
(let [name (cph/merge-path-item (:path color) (:name color))
|
||||
color (-> attrs
|
||||
(assoc :id (:id color))
|
||||
(assoc :file-id file-id)
|
||||
(assoc :name name))]
|
||||
(st/emit! (dwl/update-color color file-id)))))
|
||||
|
||||
delete-color
|
||||
(mf/use-fn
|
||||
(mf/deps multi-colors? multi-assets? file-id color-id)
|
||||
(fn []
|
||||
(if (or multi-colors? multi-assets?)
|
||||
(on-assets-delete)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id)
|
||||
(dwl/delete-color color)
|
||||
(dwl/sync-file file-id file-id :colors color-id)
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
rename-color-clicked
|
||||
(mf/use-fn
|
||||
(mf/deps read-only? local?)
|
||||
(fn [event]
|
||||
(when (and local? (not read-only?))
|
||||
(dom/prevent-default event)
|
||||
(reset! editing* true))))
|
||||
|
||||
input-blur
|
||||
(mf/use-fn
|
||||
(mf/deps rename-color)
|
||||
(fn [event]
|
||||
(let [target (dom/event->target event)
|
||||
name (dom/get-value target)]
|
||||
(rename-color name)
|
||||
(st/emit! dwl/clear-color-for-rename)
|
||||
(reset! editing* false))))
|
||||
|
||||
input-key-down
|
||||
(mf/use-fn
|
||||
(mf/deps input-blur)
|
||||
(fn [event]
|
||||
(when (kbd/esc? event)
|
||||
(st/emit! dwl/clear-color-for-rename)
|
||||
(reset! editing* false))
|
||||
(when (kbd/enter? event)
|
||||
(input-blur event))))
|
||||
|
||||
edit-color-clicked
|
||||
(mf/use-fn
|
||||
(mf/deps edit-color color)
|
||||
(fn [event]
|
||||
(modal/show! :colorpicker
|
||||
{:x (.-clientX ^js event)
|
||||
:y (.-clientY ^js event)
|
||||
:on-accept edit-color
|
||||
:data color
|
||||
:position :right})))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps color-id selected on-clear-selection read-only?)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(let [pos (dom/get-client-position event)]
|
||||
(when (and local? (not read-only?))
|
||||
(when-not (contains? selected color-id)
|
||||
(on-clear-selection))
|
||||
(swap! menu-state cmm/open-context-menu pos)))))
|
||||
|
||||
on-close-menu
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(swap! menu-state cmm/close-context-menu)))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps color dragging* selected selected-full selected-paths move-color)
|
||||
(fn [event]
|
||||
(cmm/on-drop-asset event color dragging* selected selected-full
|
||||
selected-paths move-color)))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-fn
|
||||
(mf/deps color dragging* selected selected-paths)
|
||||
(fn [event]
|
||||
(cmm/on-drag-enter-asset event color dragging* selected selected-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-fn
|
||||
(mf/deps dragging*)
|
||||
(fn [event]
|
||||
(cmm/on-drag-leave-asset event dragging*)))
|
||||
|
||||
on-color-drag-start
|
||||
(mf/use-fn
|
||||
(mf/deps color file-id selected item-ref read-only?)
|
||||
(fn [event]
|
||||
(if read-only?
|
||||
(dom/prevent-default event)
|
||||
(cmm/on-asset-drag-start event file-id color selected item-ref :colors identity))))
|
||||
|
||||
on-click
|
||||
(mf/use-fn
|
||||
(mf/deps color-id apply-color on-asset-click)
|
||||
(partial on-asset-click color-id apply-color))]
|
||||
|
||||
(mf/with-effect [editing?]
|
||||
(when editing?
|
||||
(let [input (mf/ref-val input-ref)]
|
||||
(dom/select-text! input)
|
||||
nil)))
|
||||
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :asset-list-item) true
|
||||
(css :selected) (contains? selected (:id color))
|
||||
(css :editing) editing?)
|
||||
:style #js {"--bullet-size" "16px"}
|
||||
:on-context-menu on-context-menu
|
||||
:on-click (when-not editing? on-click)
|
||||
:ref item-ref
|
||||
:draggable (and (not read-only?) (not editing?))
|
||||
:on-drag-start on-color-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
[:div {:class (dom/classnames (css :bullet-block) true)}
|
||||
[:& cb/color-bullet {:color color
|
||||
:mini? true}]]
|
||||
|
||||
(if ^boolean editing?
|
||||
[:input
|
||||
{:type "text"
|
||||
:class (dom/classnames (css :element-name) true)
|
||||
:ref input-ref
|
||||
:on-blur input-blur
|
||||
:on-key-down input-key-down
|
||||
:auto-focus true
|
||||
:default-value (cph/merge-path-item (:path color) (:name color))}]
|
||||
|
||||
[:div {:title (:name color)
|
||||
:class (dom/classnames (css :name-block) true)
|
||||
:on-double-click rename-color-clicked}
|
||||
|
||||
(if (= (:name color) default-name)
|
||||
[:span {:class (dom/classnames (css :default-name-only) true)} default-name]
|
||||
[:*
|
||||
[:span {:class (dom/classnames (css :name) true)} (:name color)]
|
||||
[:span {:class (dom/classnames (css :default-name) true)} default-name]])])
|
||||
|
||||
(when local?
|
||||
[:& cmm/assets-context-menu
|
||||
{:on-close on-close-menu
|
||||
:state @menu-state
|
||||
:options [(when-not (or multi-colors? multi-assets?)
|
||||
{:option-name (tr "workspace.assets.rename")
|
||||
:id "assets-rename-color"
|
||||
:option-handler rename-color-clicked})
|
||||
(when-not (or multi-colors? multi-assets?)
|
||||
{:option-name (tr "workspace.assets.edit")
|
||||
:id "assets-edit-color"
|
||||
:option-handler edit-color-clicked})
|
||||
|
||||
{:option-name (tr "workspace.assets.delete")
|
||||
:id "assets-delete-color"
|
||||
:option-handler delete-color}
|
||||
(when-not multi-assets?
|
||||
{:option-name (tr "workspace.assets.group")
|
||||
:id "assets-group-color"
|
||||
:option-handler (on-group (:id color))})]}])
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div {:class (dom/classnames (css :dragging) true)}])]
|
||||
|
||||
[:div.asset-list-item
|
||||
{:class-name (dom/classnames
|
||||
:selected (contains? selected (:id color)))
|
||||
:on-context-menu on-context-menu
|
||||
:on-click (when-not editing? on-click)
|
||||
:ref item-ref
|
||||
:draggable (and (not read-only?) (not editing?))
|
||||
:on-drag-start on-color-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
[:& bc/color-bullet {:color color}]
|
||||
|
||||
(if ^boolean editing?
|
||||
[:input.element-name
|
||||
{:type "text"
|
||||
:ref input-ref
|
||||
:on-blur input-blur
|
||||
:on-key-down input-key-down
|
||||
:auto-focus true
|
||||
:default-value (cph/merge-path-item (:path color) (:name color))}]
|
||||
|
||||
[:div.name-block {:title (:name color)
|
||||
:on-double-click rename-color-clicked}
|
||||
(:name color)
|
||||
(when-not (= (:name color) default-name)
|
||||
[:span default-name])])
|
||||
|
||||
(when local?
|
||||
[:& cmm/assets-context-menu
|
||||
{:on-close on-close-menu
|
||||
:state @menu-state
|
||||
:options [(when-not (or multi-colors? multi-assets?)
|
||||
[(tr "workspace.assets.rename") rename-color-clicked])
|
||||
(when-not (or multi-colors? multi-assets?)
|
||||
[(tr "workspace.assets.edit") edit-color-clicked])
|
||||
[(tr "workspace.assets.delete") delete-color]
|
||||
(when-not multi-assets?
|
||||
[(tr "workspace.assets.group") (on-group (:id color))])]}])
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div.dragging])])))
|
||||
|
||||
(mf/defc colors-group
|
||||
[{:keys [file-id prefix groups open-groups local? selected
|
||||
multi-colors? multi-assets? on-asset-click on-assets-delete
|
||||
on-clear-selection on-group on-rename-group on-ungroup colors
|
||||
selected-full]}]
|
||||
(let [group-open? (get open-groups prefix true)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
dragging* (mf/use-state false)
|
||||
dragging? (deref dragging*)
|
||||
|
||||
selected-paths (mf/with-memo [selected-full]
|
||||
(into #{}
|
||||
(comp (map :path) (d/nilv ""))
|
||||
selected-full))
|
||||
|
||||
move-color
|
||||
(mf/use-fn (mf/deps file-id) (partial dwl/rename-color file-id))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* prefix selected-paths)
|
||||
(fn [event]
|
||||
(cmm/on-drag-enter-asset-group event dragging* prefix selected-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-fn
|
||||
(mf/deps dragging*)
|
||||
(fn [event]
|
||||
(cmm/on-drag-leave-asset event dragging*)))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* prefix selected-paths selected-full move-color)
|
||||
(fn [event]
|
||||
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full move-color)))]
|
||||
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :colors-group) true)
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
[:& grp/asset-group-title {:file-id file-id
|
||||
:section :colors
|
||||
:path prefix
|
||||
:group-open? group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup}]
|
||||
(when group-open?
|
||||
[:*
|
||||
(let [colors (get groups "" [])]
|
||||
[:div {:class (dom/classnames (css :asset-list) true)
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div {:class (dom/classnames (css :grid-placeholder) true)}
|
||||
"\u00A0"])
|
||||
|
||||
(when (and (empty? colors)
|
||||
(some? groups))
|
||||
[:div {:class (dom/classnames (css :drop-space) true)}])
|
||||
|
||||
(for [color colors]
|
||||
[:& color-item {:key (dm/str (:id color))
|
||||
:color color
|
||||
:file-id file-id
|
||||
:local? local?
|
||||
:selected selected
|
||||
:multi-colors? multi-colors?
|
||||
:multi-assets? multi-assets?
|
||||
:on-asset-click on-asset-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection
|
||||
:on-group on-group
|
||||
:colors colors
|
||||
:selected-full selected-full
|
||||
:selected-paths selected-paths
|
||||
:move-color move-color}])])
|
||||
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& colors-group {:file-id file-id
|
||||
:prefix (cph/merge-path-item prefix path-item)
|
||||
:key (dm/str "group-" path-item)
|
||||
:groups content
|
||||
:open-groups open-groups
|
||||
:local? local?
|
||||
:selected selected
|
||||
:multi-colors? multi-colors?
|
||||
:multi-assets? multi-assets?
|
||||
:on-asset-click on-asset-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection
|
||||
:on-group on-group
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:colors colors
|
||||
:selected-full selected-full}]))])]
|
||||
|
||||
|
||||
[:div {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
[:& grp/asset-group-title {:file-id file-id
|
||||
:section :colors
|
||||
:path prefix
|
||||
:group-open? group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup}]
|
||||
(when group-open?
|
||||
[:*
|
||||
(let [colors (get groups "" [])]
|
||||
[:div.asset-list {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div.grid-placeholder "\u00A0"])
|
||||
|
||||
(when (and (empty? colors)
|
||||
(some? groups))
|
||||
[:div.drop-space])
|
||||
|
||||
(for [color colors]
|
||||
[:& color-item {:key (dm/str (:id color))
|
||||
:color color
|
||||
:file-id file-id
|
||||
:local? local?
|
||||
:selected selected
|
||||
:multi-colors? multi-colors?
|
||||
:multi-assets? multi-assets?
|
||||
:on-asset-click on-asset-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection
|
||||
:on-group on-group
|
||||
:colors colors
|
||||
:selected-full selected-full
|
||||
:selected-paths selected-paths
|
||||
:move-color move-color}])])
|
||||
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& colors-group {:file-id file-id
|
||||
:prefix (cph/merge-path-item prefix path-item)
|
||||
:key (dm/str "group-" path-item)
|
||||
:groups content
|
||||
:open-groups open-groups
|
||||
:local? local?
|
||||
:selected selected
|
||||
:multi-colors? multi-colors?
|
||||
:multi-assets? multi-assets?
|
||||
:on-asset-click on-asset-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection
|
||||
:on-group on-group
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:colors colors
|
||||
:selected-full selected-full}]))])])))
|
||||
|
||||
(mf/defc colors-section
|
||||
[{:keys [file-id local? colors open? open-status-ref selected reverse-sort?
|
||||
on-asset-click on-assets-delete on-clear-selection] :as props}]
|
||||
|
||||
(let [selected (:colors selected)
|
||||
selected-full (mf/with-memo [selected colors]
|
||||
(into #{} (filter #(contains? selected (:id %))) colors))
|
||||
|
||||
open-groups-ref (mf/with-memo [open-status-ref]
|
||||
(-> (l/in [:groups :colors])
|
||||
(l/derived open-status-ref)))
|
||||
open-groups (mf/deref open-groups-ref)
|
||||
|
||||
multi-colors? (> (count selected) 1)
|
||||
multi-assets? (or (seq (:components selected))
|
||||
(seq (:graphics selected))
|
||||
(seq (:typographies selected)))
|
||||
|
||||
groups (mf/with-memo [colors reverse-sort?]
|
||||
(grp/group-assets colors reverse-sort?))
|
||||
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
add-color
|
||||
(mf/use-fn
|
||||
(fn [value _]
|
||||
(st/emit! (dwl/add-color value))))
|
||||
|
||||
add-color-clicked
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn [event]
|
||||
(st/emit! (dw/set-assets-section-open file-id :colors true)
|
||||
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
||||
:asset-type "color"}))
|
||||
(modal/show! :colorpicker
|
||||
{:x (.-clientX event)
|
||||
:y (.-clientY event)
|
||||
:on-accept add-color
|
||||
:data {:color "#406280"
|
||||
:opacity 1}
|
||||
:position :right})))
|
||||
|
||||
create-group
|
||||
(mf/use-fn
|
||||
(mf/deps colors selected on-clear-selection file-id)
|
||||
(fn [color-id]
|
||||
(fn [group-name]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> colors
|
||||
(filter #(if multi-colors?
|
||||
(contains? selected (:id %))
|
||||
(= color-id (:id %))))
|
||||
(map #(dwl/update-color
|
||||
(assoc % :name
|
||||
(cmm/add-group % group-name))
|
||||
file-id))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
rename-group
|
||||
(mf/use-fn
|
||||
(mf/deps colors)
|
||||
(fn [path last-path]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> colors
|
||||
(filter #(str/starts-with? (:path %) path))
|
||||
(map #(dwl/update-color
|
||||
(assoc % :name
|
||||
(cmm/rename-group % path last-path))
|
||||
file-id))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
on-group
|
||||
(mf/use-fn
|
||||
(mf/deps colors selected)
|
||||
(fn [color-id]
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(modal/show! :name-group-dialog {:accept (create-group color-id)}))))
|
||||
|
||||
on-rename-group
|
||||
(mf/use-fn
|
||||
(mf/deps colors)
|
||||
(fn [event path last-path]
|
||||
(dom/stop-propagation event)
|
||||
(modal/show! :name-group-dialog {:path path
|
||||
:last-path last-path
|
||||
:accept rename-group})))
|
||||
on-ungroup
|
||||
(mf/use-fn
|
||||
(mf/deps colors)
|
||||
(fn [path]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(apply st/emit!
|
||||
(->> colors
|
||||
(filter #(str/starts-with? (:path %) path))
|
||||
(map #(dwl/update-color
|
||||
(assoc % :name
|
||||
(cmm/ungroup % path))
|
||||
file-id))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
on-asset-click
|
||||
(mf/use-fn (mf/deps groups on-asset-click) (partial on-asset-click groups))]
|
||||
|
||||
|
||||
[:& cmm/asset-section {:file-id file-id
|
||||
:title (tr "workspace.assets.colors")
|
||||
:section :colors
|
||||
:assets-count (count colors)
|
||||
:open? open?}
|
||||
(if ^boolean new-css-system
|
||||
(when local?
|
||||
[:& cmm/asset-section-block {:role :title-button}
|
||||
(when-not read-only?
|
||||
[:button {:class (dom/classnames (css :assets-btn) true)
|
||||
:on-click add-color-clicked}
|
||||
i/add-refactor])])
|
||||
|
||||
(when local?
|
||||
[:& cmm/asset-section-block {:role :title-button}
|
||||
(when-not read-only?
|
||||
[:div.assets-button {:on-click add-color-clicked}
|
||||
i/plus])]))
|
||||
|
||||
|
||||
[:& cmm/asset-section-block {:role :content}
|
||||
[:& colors-group {:file-id file-id
|
||||
:prefix ""
|
||||
:groups groups
|
||||
:open-groups open-groups
|
||||
:local? local?
|
||||
:selected selected
|
||||
:multi-colors? multi-colors?
|
||||
:multi-assets? multi-assets?
|
||||
:on-asset-click on-asset-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection
|
||||
:on-group on-group
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:colors colors
|
||||
:selected-full selected-full}]]]))
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"assets_colors_button-primary_6ZMmx","button-secondary":"assets_colors_button-secondary_dNSLH","button-tertiary":"assets_colors_button-tertiary_h20-o","assets-btn":"assets_colors_assets-btn_t8DHG","button-tag":"assets_colors_button-tag_ux-NH","button-icon":"assets_colors_button-icon_f-EVH","button-icon-small":"assets_colors_button-icon-small_zq8dv","asset-element":"assets_colors_asset-element_XSxD1","colors-group":"assets_colors_colors-group_fUsuo","asset-list":"assets_colors_asset-list_wMm1l","asset-list-item":"assets_colors_asset-list-item_ZFtXC","bullet-block":"assets_colors_bullet-block_ZRR2Y","name-block":"assets_colors_name-block_Zvmy3","default-name-only":"assets_colors_default-name-only_JFCGo","name":"assets_colors_name_AjZzr","default-name":"assets_colors_default-name_8gEAb","element-name":"assets_colors_element-name_ADGM8","selected":"assets_colors_selected_ElMu0","editing":"assets_colors_editing_FWnHU","grid-placeholder":"assets_colors_grid-placeholder_7wTFd","drop-space":"assets_colors_drop-space_lbzeC","dragging":"assets_colors_dragging_EmBOk"}
|
102
frontend/src/app/main/ui/workspace/sidebar/assets/colors.scss
Normal file
102
frontend/src/app/main/ui/workspace/sidebar/assets/colors.scss
Normal file
|
@ -0,0 +1,102 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.assets-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: calc($s-24 + $s-4);
|
||||
padding: 0;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
|
||||
.colors-group {
|
||||
margin-top: $s-4;
|
||||
.asset-list {
|
||||
padding: 0 0 0 $s-12;
|
||||
.asset-list-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
padding: $s-8 $s-12 $s-8 $s-8;
|
||||
margin-bottom: $s-4;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--assets-item-background-color);
|
||||
cursor: pointer;
|
||||
.bullet-block {
|
||||
@include flexCenter;
|
||||
height: 100%;
|
||||
width: $s-32;
|
||||
}
|
||||
.name-block {
|
||||
@include titleTipography;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
.default-name-only,
|
||||
.name {
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
margin-right: $s-6;
|
||||
@include textEllipsis;
|
||||
}
|
||||
.default-name {
|
||||
min-width: 0;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
}
|
||||
}
|
||||
.element-name {
|
||||
@include textEllipsis;
|
||||
color: var(--color-foreground-primary);
|
||||
}
|
||||
&.selected {
|
||||
border: $s-1 solid var(--assets-item-border-color);
|
||||
}
|
||||
|
||||
&.editing {
|
||||
border: $s-1 solid var(--input-border-color-focus);
|
||||
input.element-name {
|
||||
@include textEllipsis;
|
||||
@include titleTipography;
|
||||
@include removeInputStyle;
|
||||
flex-grow: 1;
|
||||
height: $s-28;
|
||||
max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
|
||||
margin: 0;
|
||||
color: var(--layer-row-foreground-color);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--assets-item-background-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.grid-placeholder {
|
||||
height: $s-2;
|
||||
margin-bottom: $s-2;
|
||||
background-color: var(--color-accent-primary);
|
||||
}
|
||||
.drop-space {
|
||||
height: $s-12;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--assets-item-background-color);
|
||||
}
|
||||
.dragging {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: $s-8;
|
||||
background-color: var(--assets-item-background-color-drag);
|
||||
border: $s-2 solid var(--assets-item-border-color-drag);
|
||||
}
|
||||
}
|
257
frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
Normal file
257
frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
Normal file
|
@ -0,0 +1,257 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.assets.common
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||
[app.main.ui.components.context-menu-a11y :refer [context-menu-a11y]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.dom.dnd :as dnd]
|
||||
[app.util.strings :refer [matches-search]]
|
||||
[app.util.timers :as ts]
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def assets-filters (mf/create-context nil))
|
||||
(def assets-toggle-ordering (mf/create-context nil))
|
||||
(def assets-toggle-list-style (mf/create-context nil))
|
||||
|
||||
(defn apply-filters
|
||||
[coll {:keys [ordering term] :as filters}]
|
||||
(let [reverse? (= :desc ordering)
|
||||
comp-fn (if ^boolean reverse? > <)]
|
||||
(->> coll
|
||||
(filter (fn [item]
|
||||
(or (matches-search (:name item "!$!") term)
|
||||
(matches-search (:value item "!$!") term))))
|
||||
; Sort by folder order, but
|
||||
; putting all "root" items
|
||||
; always first, independently
|
||||
; of sort order.
|
||||
(sort-by #(str/lower (cph/merge-path-item (if (empty? (:path %))
|
||||
(if reverse? "z" "a")
|
||||
(:path %))
|
||||
(:name %)))
|
||||
comp-fn))))
|
||||
|
||||
(defn add-group
|
||||
[asset group-name]
|
||||
(-> (:path asset)
|
||||
(cph/merge-path-item group-name)
|
||||
(cph/merge-path-item (:name asset))))
|
||||
|
||||
(defn rename-group
|
||||
[asset path last-path]
|
||||
(-> (:path asset)
|
||||
(str/slice 0 (count path))
|
||||
(cph/split-path)
|
||||
butlast
|
||||
(vec)
|
||||
(conj last-path)
|
||||
(cph/join-path)
|
||||
(str (str/slice (:path asset) (count path)))
|
||||
(cph/merge-path-item (:name asset))))
|
||||
|
||||
(defn ungroup
|
||||
[asset path]
|
||||
(-> (:path asset)
|
||||
(str/slice 0 (count path))
|
||||
(cph/split-path)
|
||||
butlast
|
||||
(cph/join-path)
|
||||
(str (str/slice (:path asset) (count path)))
|
||||
(cph/merge-path-item (:name asset))))
|
||||
|
||||
(s/def ::asset-name ::us/not-empty-string)
|
||||
(s/def ::name-group-form
|
||||
(s/keys :req-un [::asset-name]))
|
||||
|
||||
(def initial-context-menu-state
|
||||
{:open? false :top nil :left nil})
|
||||
|
||||
(defn open-context-menu
|
||||
[state pos]
|
||||
(let [top (:y pos)
|
||||
left (+ (:x pos) 10)]
|
||||
(assoc state
|
||||
:open? true
|
||||
:top top
|
||||
:left left)))
|
||||
|
||||
(defn close-context-menu
|
||||
[state]
|
||||
(assoc state :open? false))
|
||||
|
||||
(mf/defc assets-context-menu
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [options state on-close]}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
|
||||
(if new-css-system
|
||||
[:& context-menu-a11y
|
||||
{:show (:open? state)
|
||||
:fixed? (or (not= (:top state) 0) (not= (:left state) 0))
|
||||
:on-close on-close
|
||||
:top (:top state)
|
||||
:left (:left state)
|
||||
:options options
|
||||
:workspace? true}]
|
||||
|
||||
[:& context-menu
|
||||
{:selectable false
|
||||
:show (:open? state)
|
||||
:on-close on-close
|
||||
:top (:top state)
|
||||
:left (:left state)
|
||||
:options options}])))
|
||||
|
||||
(mf/defc section-icon
|
||||
[{:keys [section] :as props}]
|
||||
(case section
|
||||
:colors i/drop-refactor
|
||||
:components i/component-refactor
|
||||
:typographies i/text-palette-refactor
|
||||
i/add-refactor))
|
||||
|
||||
(mf/defc asset-section
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [children file-id title section assets-count open?]}]
|
||||
(let [children (->> (if (array? children) children [children])
|
||||
(filter some?))
|
||||
get-role #(.. % -props -role)
|
||||
title-buttons (filter #(= (get-role %) :title-button) children)
|
||||
content (filter #(= (get-role %) :content) children)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)]
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :asset-section) true)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed #(st/emit! (dw/set-assets-section-open file-id section (not open?)))
|
||||
:klass :title-spacing
|
||||
:title (mf/html [:span {:class (dom/classnames (css :title-name) true)}
|
||||
[:span {:class (dom/classnames (css :section-icon) true)}
|
||||
[:& section-icon {:section section}]]
|
||||
[:span {:class (dom/classnames (css :section-name) true)}
|
||||
title]
|
||||
|
||||
[:span {:class (dom/classnames (css :num-assets) true)}
|
||||
assets-count]])}
|
||||
title-buttons]
|
||||
(when ^boolean open?
|
||||
content)]
|
||||
[:div.asset-section
|
||||
[:div.asset-title {:class (when (not ^boolean open?) "closed")}
|
||||
[:span {:on-click #(st/emit! (dw/set-assets-section-open file-id section (not open?)))}
|
||||
i/arrow-slide title]
|
||||
[:span.num-assets (dm/str "\u00A0(") assets-count ")"] ;; Unicode 00A0 is non-breaking space
|
||||
title-buttons]
|
||||
(when ^boolean open?
|
||||
content)])))
|
||||
|
||||
(mf/defc asset-section-block
|
||||
[{:keys [children]}]
|
||||
[:* children])
|
||||
|
||||
(defn create-assets-group
|
||||
[rename components-to-group group-name]
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(apply st/emit!
|
||||
(->> components-to-group
|
||||
(map #(rename
|
||||
(:id %)
|
||||
(add-group % group-name)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id))))
|
||||
|
||||
(defn on-drop-asset
|
||||
[event asset dragging* selected selected-full selected-paths rename]
|
||||
(let [create-typed-assets-group (partial create-assets-group rename)]
|
||||
(when (not (dnd/from-child? event))
|
||||
(reset! dragging* false)
|
||||
(when
|
||||
(and (not (contains? selected (:id asset)))
|
||||
(every? #(= % (:path asset)) selected-paths))
|
||||
(let [components-to-group (conj selected-full asset)
|
||||
create-typed-assets-group (partial create-typed-assets-group components-to-group)]
|
||||
(modal/show! :name-group-dialog {:accept create-typed-assets-group}))))))
|
||||
|
||||
(defn on-drag-enter-asset
|
||||
[event asset dragging* selected selected-paths]
|
||||
(when (and
|
||||
(not (dnd/from-child? event))
|
||||
(every? #(= % (:path asset)) selected-paths)
|
||||
(not (contains? selected (:id asset))))
|
||||
(reset! dragging* true)))
|
||||
|
||||
(defn on-drag-leave-asset
|
||||
[event dragging*]
|
||||
(when (not (dnd/from-child? event))
|
||||
(reset! dragging* false)))
|
||||
|
||||
(defn create-counter-element
|
||||
[asset-count]
|
||||
(let [counter-el (dom/create-element "div")]
|
||||
(dom/set-property! counter-el "class" "drag-counter")
|
||||
(dom/set-text! counter-el (str asset-count))
|
||||
counter-el))
|
||||
|
||||
(defn set-drag-image
|
||||
[event item-ref num-selected]
|
||||
(let [offset (dom/get-offset-position (.-nativeEvent event))
|
||||
item-el (mf/ref-val item-ref)
|
||||
counter-el (create-counter-element num-selected)]
|
||||
|
||||
;; set-drag-image requires that the element is rendered and
|
||||
;; visible to the user at the moment of creating the ghost
|
||||
;; image (to make a snapshot), but you may remove it right
|
||||
;; afterwards, in the next render cycle.
|
||||
(dom/append-child! item-el counter-el)
|
||||
(dnd/set-drag-image! event item-el (:x offset) (:y offset))
|
||||
(ts/raf #(.removeChild ^js item-el counter-el))))
|
||||
|
||||
(defn on-asset-drag-start
|
||||
[event file-id asset selected item-ref asset-type on-drag-start]
|
||||
(let [id-asset (:id asset)
|
||||
num-selected (if (contains? selected id-asset)
|
||||
(count selected)
|
||||
1)]
|
||||
(when (not (contains? selected id-asset))
|
||||
(st/emit! (dw/unselect-all-assets file-id)
|
||||
(dw/toggle-selected-assets file-id id-asset asset-type)))
|
||||
(on-drag-start asset event)
|
||||
(when (> num-selected 1)
|
||||
(set-drag-image event item-ref num-selected))))
|
||||
|
||||
(defn on-drag-enter-asset-group
|
||||
[event dragging* prefix selected-paths]
|
||||
(dom/stop-propagation event)
|
||||
(when (and (not (dnd/from-child? event))
|
||||
(not (every? #(= % prefix) selected-paths)))
|
||||
(reset! dragging* true)))
|
||||
|
||||
(defn on-drop-asset-group
|
||||
[event dragging* prefix selected-paths selected-full rename]
|
||||
(dom/stop-propagation event)
|
||||
(when (not (dnd/from-child? event))
|
||||
(reset! dragging* false)
|
||||
(when (not (every? #(= % prefix) selected-paths))
|
||||
(doseq [target-asset selected-full]
|
||||
(st/emit!
|
||||
(rename
|
||||
(:id target-asset)
|
||||
(cph/merge-path-item prefix (:name target-asset))))))))
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"assets_common_button-primary_-eBqD","button-secondary":"assets_common_button-secondary_qo2kg","button-tertiary":"assets_common_button-tertiary_ApdBb","button-tag":"assets_common_button-tag_MHJlj","button-icon":"assets_common_button-icon_0R1zt","button-icon-small":"assets_common_button-icon-small_5kQfO","asset-element":"assets_common_asset-element_frsFR","asset-section":"assets_common_asset-section_uKhc8","title-name":"assets_common_title-name_ZOz9E","section-icon":"assets_common_section-icon_Kitcf","section-name":"assets_common_section-name_RVo-u","num-assets":"assets_common_num-assets_Dguaz"}
|
|
@ -0,0 +1,40 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.asset-section {
|
||||
.title-name {
|
||||
@include tabTitleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
.section-icon {
|
||||
@include flexCenter;
|
||||
padding-right: $s-8;
|
||||
svg {
|
||||
@include flexCenter;
|
||||
height: $s-16;
|
||||
width: $s-16;
|
||||
color: transparent;
|
||||
fill: none;
|
||||
}
|
||||
}
|
||||
.section-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.num-assets {
|
||||
@include flexCenter;
|
||||
height: 100%;
|
||||
padding-left: $s-8;
|
||||
}
|
||||
}
|
||||
}
|
||||
:global(.title-spacing) {
|
||||
margin-bottom: $s-4;
|
||||
}
|
|
@ -0,0 +1,662 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.assets.components
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.media :as cm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.media :as dwm]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.render :refer [component-svg]]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.editable-label :refer [editable-label]]
|
||||
[app.main.ui.components.file-uploader :refer [file-uploader]]
|
||||
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||
[app.main.ui.workspace.sidebar.assets.groups :as grp]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.dom.dnd :as dnd]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[potok.core :as ptk]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- get-component-root-and-container
|
||||
[file-id component components-v2]
|
||||
(if (= file-id (:id @refs/workspace-file))
|
||||
(let [data @refs/workspace-data]
|
||||
[(ctf/get-component-root data component)
|
||||
(if components-v2
|
||||
(ctf/get-component-page data component)
|
||||
component)])
|
||||
(let [data (dm/get-in @refs/workspace-libraries [file-id :data])]
|
||||
[(ctf/get-component-root data component)
|
||||
(if components-v2
|
||||
(ctf/get-component-page data component)
|
||||
component)])))
|
||||
|
||||
(mf/defc components-item
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [component renaming listing-thumbs? selected
|
||||
file-id on-asset-click on-context-menu on-drag-start do-rename
|
||||
cancel-rename selected-full selected-paths]}]
|
||||
(let [item-ref (mf/use-ref)
|
||||
|
||||
dragging* (mf/use-state false)
|
||||
dragging? (deref dragging*)
|
||||
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
component-id (:id component)
|
||||
|
||||
;; NOTE: we don't use reactive deref for it because we don't
|
||||
;; really need rerender on any change on the file change. If
|
||||
;; the component changes, it will trigger rerender anyway.
|
||||
[root-shape container]
|
||||
(get-component-root-and-container file-id component components-v2)
|
||||
|
||||
unselect-all
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (dw/unselect-all-assets))))
|
||||
|
||||
on-component-click
|
||||
(mf/use-fn
|
||||
(mf/deps component selected)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(on-asset-click component-id unselect-all event)))
|
||||
|
||||
on-component-double-click
|
||||
(mf/use-fn
|
||||
(mf/deps file-id component-id)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dw/go-to-main-instance file-id component-id))))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps component dragging* selected selected-full selected-paths)
|
||||
(fn [event]
|
||||
(cmm/on-drop-asset event component dragging* selected selected-full
|
||||
selected-paths dwl/rename-component)))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-fn
|
||||
(mf/deps component dragging* selected selected-paths)
|
||||
(fn [event]
|
||||
(cmm/on-drag-enter-asset event component dragging* selected selected-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-fn
|
||||
(mf/deps dragging*)
|
||||
(fn [event]
|
||||
(cmm/on-drag-leave-asset event dragging*)))
|
||||
|
||||
on-component-drag-start
|
||||
(mf/use-fn
|
||||
(mf/deps file-id component selected item-ref on-drag-start read-only?)
|
||||
(fn [event]
|
||||
(if read-only?
|
||||
(dom/prevent-default event)
|
||||
(cmm/on-asset-drag-start event file-id component selected item-ref :components on-drag-start))))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps component-id)
|
||||
(partial on-context-menu component-id))]
|
||||
|
||||
(if ^boolean new-css-system
|
||||
[:div {:ref item-ref
|
||||
:class (dom/classnames
|
||||
(css :selected) (contains? selected (:id component))
|
||||
(css :grid-cell) listing-thumbs?
|
||||
(css :enum-item) (not listing-thumbs?))
|
||||
:id (dm/str "component-shape-id-" (:id component))
|
||||
:draggable (not read-only?)
|
||||
:on-click on-component-click
|
||||
:on-double-click on-component-double-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-drag-start on-component-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
(when (and (some? root-shape)
|
||||
(some? container))
|
||||
[:*
|
||||
[:& component-svg {:root-shape root-shape
|
||||
:objects (:objects container)}]
|
||||
(let [renaming? (= renaming (:id component))]
|
||||
[:*
|
||||
[:& editable-label
|
||||
{:class-name (dom/classnames
|
||||
(css :cell-name) listing-thumbs?
|
||||
(css :item-name) (not listing-thumbs?)
|
||||
(css :editing) renaming?)
|
||||
:value (cph/merge-path-item (:path component) (:name component))
|
||||
:tooltip (cph/merge-path-item (:path component) (:name component))
|
||||
:display-value (:name component)
|
||||
:editing? renaming?
|
||||
:disable-dbl-click? true
|
||||
:on-change do-rename
|
||||
:on-cancel cancel-rename}]
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div {:class (dom/classnames (css :dragging) true)}])])])]
|
||||
|
||||
[:div {:ref item-ref
|
||||
:class (dom/classnames
|
||||
:selected (contains? selected (:id component))
|
||||
:grid-cell listing-thumbs?
|
||||
:enum-item (not listing-thumbs?))
|
||||
:id (dm/str "component-shape-id-" (:id component))
|
||||
:draggable (not read-only?)
|
||||
:on-click on-component-click
|
||||
:on-double-click on-component-double-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-drag-start on-component-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when (and (some? root-shape)
|
||||
(some? container))
|
||||
[:*
|
||||
[:& component-svg {:root-shape root-shape
|
||||
:objects (:objects container)}]
|
||||
(let [renaming? (= renaming (:id component))]
|
||||
[:*
|
||||
[:& editable-label
|
||||
{:class-name (dom/classnames
|
||||
:cell-name listing-thumbs?
|
||||
:item-name (not listing-thumbs?)
|
||||
:editing renaming?)
|
||||
:value (cph/merge-path-item (:path component) (:name component))
|
||||
:tooltip (cph/merge-path-item (:path component) (:name component))
|
||||
:display-value (:name component)
|
||||
:editing? renaming?
|
||||
:disable-dbl-click? true
|
||||
:on-change do-rename
|
||||
:on-cancel cancel-rename}]
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div.dragging])])])])))
|
||||
|
||||
(mf/defc components-group
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file-id prefix groups open-groups renaming listing-thumbs? selected on-asset-click
|
||||
on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu
|
||||
selected-full]}]
|
||||
|
||||
(let [group-open? (get open-groups prefix true)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
dragging* (mf/use-state false)
|
||||
dragging? (deref dragging*)
|
||||
|
||||
selected-paths (mf/with-memo [selected-full]
|
||||
(into #{}
|
||||
(comp (map :path) (d/nilv ""))
|
||||
selected-full))
|
||||
on-drag-enter
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* prefix selected-paths)
|
||||
(fn [event]
|
||||
(cmm/on-drag-enter-asset-group event dragging* prefix selected-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-fn
|
||||
(mf/deps dragging*)
|
||||
(fn [event]
|
||||
(cmm/on-drag-leave-asset event dragging*)))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* prefix selected-paths selected-full)
|
||||
(fn [event]
|
||||
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full dwl/rename-component)))]
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :component-group) true)
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
[:& grp/asset-group-title
|
||||
{:file-id file-id
|
||||
:section :components
|
||||
:path prefix
|
||||
:group-open? group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup}]
|
||||
|
||||
|
||||
(when group-open?
|
||||
[:*
|
||||
(let [components (get groups "" [])]
|
||||
[:div {:class-name (dom/classnames
|
||||
(css :asset-grid) listing-thumbs?
|
||||
(css :asset-enum) (not listing-thumbs?)
|
||||
(css :drop-space) (and
|
||||
(empty? components)
|
||||
(some? groups)
|
||||
(not dragging?)))
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div {:class (dom/classnames (css :grid-placeholder) true)} "\u00A0"])
|
||||
|
||||
|
||||
(when (and (empty? components)
|
||||
(some? groups))
|
||||
[:div {:class (dom/classnames (css :drop-space) true)}])
|
||||
|
||||
(for [component components]
|
||||
[:& components-item
|
||||
{:component component
|
||||
:key (dm/str "component-" (:id component))
|
||||
:renaming renaming
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:file-id file-id
|
||||
:selected selected
|
||||
:selected-full selected-full
|
||||
:selected-paths selected-paths
|
||||
:on-asset-click on-asset-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-drag-start on-drag-start
|
||||
:on-group on-group
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename}])])
|
||||
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& components-group {:file-id file-id
|
||||
:key path-item
|
||||
:prefix (cph/merge-path-item prefix path-item)
|
||||
:groups content
|
||||
:open-groups open-groups
|
||||
:renaming renaming
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:selected selected
|
||||
:on-asset-click on-asset-click
|
||||
:on-drag-start on-drag-start
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full}]))])]
|
||||
|
||||
|
||||
[:div {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
[:& grp/asset-group-title
|
||||
{:file-id file-id
|
||||
:section :components
|
||||
:path prefix
|
||||
:group-open? group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup}]
|
||||
|
||||
(when group-open?
|
||||
[:*
|
||||
(let [components (get groups "" [])]
|
||||
[:div {:class-name (dom/classnames
|
||||
:asset-grid listing-thumbs?
|
||||
:big listing-thumbs?
|
||||
:asset-enum (not listing-thumbs?)
|
||||
:drop-space (and
|
||||
(empty? components)
|
||||
(some? groups)
|
||||
(not dragging?)))
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div.grid-placeholder "\u00A0"])
|
||||
|
||||
(when (and (empty? components)
|
||||
(some? groups))
|
||||
[:div.drop-space])
|
||||
|
||||
(for [component components]
|
||||
[:& components-item
|
||||
{:component component
|
||||
:key (dm/str "component-" (:id component))
|
||||
:renaming renaming
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:file-id file-id
|
||||
:selected selected
|
||||
:selected-full selected-full
|
||||
:selected-paths selected-paths
|
||||
:on-asset-click on-asset-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-drag-start on-drag-start
|
||||
:on-group on-group
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename}])])
|
||||
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& components-group {:file-id file-id
|
||||
:key path-item
|
||||
:prefix (cph/merge-path-item prefix path-item)
|
||||
:groups content
|
||||
:open-groups open-groups
|
||||
:renaming renaming
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:selected selected
|
||||
:on-asset-click on-asset-click
|
||||
:on-drag-start on-drag-start
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full}]))])])))
|
||||
|
||||
(mf/defc components-section
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file-id local? components listing-thumbs? open? reverse-sort? selected
|
||||
on-asset-click on-assets-delete on-clear-selection open-status-ref]}]
|
||||
|
||||
(let [input-ref (mf/use-ref nil)
|
||||
|
||||
state* (mf/use-state {})
|
||||
state (deref state*)
|
||||
|
||||
current-component-id (:component-id state)
|
||||
renaming? (:renaming state)
|
||||
|
||||
open-groups-ref (mf/with-memo [open-status-ref]
|
||||
(-> (l/in [:groups :components])
|
||||
(l/derived open-status-ref)))
|
||||
|
||||
open-groups (mf/deref open-groups-ref)
|
||||
|
||||
menu-state (mf/use-state cmm/initial-context-menu-state)
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
toggle-list-style (mf/use-ctx cmm/assets-toggle-list-style)
|
||||
|
||||
selected (:components selected)
|
||||
selected-full (into #{} (filter #(contains? selected (:id %))) components)
|
||||
multi-components? (> (count selected) 1)
|
||||
multi-assets? (or (seq (:graphics selected))
|
||||
(seq (:colors selected))
|
||||
(seq (:typographies selected)))
|
||||
|
||||
groups (mf/with-memo [components reverse-sort?]
|
||||
(grp/group-assets components reverse-sort?))
|
||||
|
||||
add-component
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (dw/set-assets-section-open file-id :components true))
|
||||
(dom/click (mf/ref-val input-ref))))
|
||||
|
||||
on-file-selected
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn [blobs]
|
||||
(let [params {:file-id file-id
|
||||
:blobs (seq blobs)}]
|
||||
(st/emit! (dwm/upload-media-components params)
|
||||
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
||||
:asset-type "components"})))))
|
||||
|
||||
on-duplicate
|
||||
(mf/use-fn
|
||||
(mf/deps current-component-id selected)
|
||||
(fn []
|
||||
(if (empty? selected)
|
||||
(st/emit! (dwl/duplicate-component file-id current-component-id))
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit! (map (partial dwl/duplicate-component file-id) selected))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
on-delete
|
||||
(mf/use-fn
|
||||
(mf/deps current-component-id file-id multi-components? multi-assets? on-assets-delete)
|
||||
(fn []
|
||||
(let [undo-id (js/Symbol)]
|
||||
(if (or multi-components? multi-assets?)
|
||||
(on-assets-delete)
|
||||
(st/emit! (dwu/start-undo-transaction undo-id)
|
||||
(dwl/delete-component {:id current-component-id})
|
||||
(dwl/sync-file file-id file-id :components current-component-id)
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
on-close-menu
|
||||
(mf/use-fn #(swap! menu-state cmm/close-context-menu))
|
||||
|
||||
on-rename
|
||||
(mf/use-fn #(swap! state* assoc :renaming true))
|
||||
|
||||
cancel-rename
|
||||
(mf/use-fn #(swap! state* dissoc :renaming))
|
||||
|
||||
do-rename
|
||||
(mf/use-fn
|
||||
(mf/deps current-component-id)
|
||||
(fn [new-name]
|
||||
(swap! state* dissoc :renaming)
|
||||
(st/emit!
|
||||
(dwl/rename-component-and-main-instance current-component-id new-name))))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps selected on-clear-selection read-only?)
|
||||
(fn [component-id event]
|
||||
(dom/prevent-default event)
|
||||
(let [pos (dom/get-client-position event)]
|
||||
(when (and local? (not read-only?))
|
||||
(when-not (contains? selected component-id)
|
||||
(on-clear-selection))
|
||||
|
||||
(swap! state* assoc :component-id component-id)
|
||||
(swap! menu-state cmm/open-context-menu pos)))))
|
||||
|
||||
create-group
|
||||
(mf/use-fn
|
||||
(mf/deps current-component-id components selected on-clear-selection)
|
||||
(fn [group-name]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> components
|
||||
(filter #(if multi-components?
|
||||
(contains? selected (:id %))
|
||||
(= current-component-id (:id %))))
|
||||
(map #(dwl/rename-component
|
||||
(:id %)
|
||||
(cmm/add-group % group-name)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
rename-group
|
||||
(mf/use-fn
|
||||
(mf/deps components)
|
||||
(fn [path last-path]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> components
|
||||
(filter #(str/starts-with? (:path %) path))
|
||||
(map #(dwl/rename-component
|
||||
(:id %)
|
||||
(cmm/rename-group % path last-path)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
on-group
|
||||
(mf/use-fn
|
||||
(mf/deps components selected create-group)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(modal/show! :name-group-dialog {:accept create-group})))
|
||||
|
||||
on-rename-group
|
||||
(mf/use-fn
|
||||
(mf/deps components)
|
||||
(fn [event path last-path]
|
||||
(dom/stop-propagation event)
|
||||
(modal/show! :name-group-dialog {:path path
|
||||
:last-path last-path
|
||||
:accept rename-group})))
|
||||
|
||||
on-ungroup
|
||||
(mf/use-fn
|
||||
(mf/deps components)
|
||||
(fn [path]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> components
|
||||
(filter #(str/starts-with? (:path %) path))
|
||||
(map #(dwl/rename-component (:id %) (cmm/ungroup % path)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
on-drag-start
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn [component event]
|
||||
(dnd/set-data! event "penpot/component" {:file-id file-id
|
||||
:component component})
|
||||
(dnd/set-allowed-effect! event "move")))
|
||||
|
||||
on-show-main
|
||||
(mf/use-fn
|
||||
(mf/deps current-component-id file-id)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dw/go-to-main-instance file-id current-component-id))))
|
||||
|
||||
on-asset-click
|
||||
(mf/use-fn (mf/deps groups on-asset-click) (partial on-asset-click groups))]
|
||||
|
||||
[:& cmm/asset-section {:file-id file-id
|
||||
:title (tr "workspace.assets.components")
|
||||
:section :components
|
||||
:assets-count (count components)
|
||||
:open? open?}
|
||||
(if ^boolean new-css-system
|
||||
[:& cmm/asset-section-block {:role :title-button}
|
||||
|
||||
(when open?
|
||||
[:div {:class (dom/classnames (css :listing-options) true)}
|
||||
(let [option-selected (if listing-thumbs?
|
||||
"grid"
|
||||
"list")]
|
||||
[:& radio-buttons {:selected option-selected
|
||||
:on-change toggle-list-style
|
||||
:name "listing-style"}
|
||||
[:& radio-button {:icon (mf/html i/view-as-list-refactor)
|
||||
:value "list"
|
||||
:id :list}]
|
||||
[:& radio-button {:icon (mf/html i/flex-grid-refactor)
|
||||
:value "grid"
|
||||
:id :grid}]])])
|
||||
(when (and components-v2 (not read-only?) local?)
|
||||
[:div {:on-click add-component
|
||||
:class (dom/classnames (css :add-component) true)}
|
||||
i/add-refactor
|
||||
[:& file-uploader {:accept cm/str-image-types
|
||||
:multi true
|
||||
:ref input-ref
|
||||
:on-selected on-file-selected}]])]
|
||||
(when local?
|
||||
[:& cmm/asset-section-block {:role :title-button}
|
||||
(when (and components-v2 (not read-only?))
|
||||
[:div.assets-button {:on-click add-component}
|
||||
i/plus
|
||||
[:& file-uploader {:accept cm/str-image-types
|
||||
:multi true
|
||||
:ref input-ref
|
||||
:on-selected on-file-selected}]])]))
|
||||
[:& cmm/asset-section-block {:role :content}
|
||||
[:& components-group {:file-id file-id
|
||||
:prefix ""
|
||||
:groups groups
|
||||
:open-groups open-groups
|
||||
:renaming (when ^boolean renaming? current-component-id)
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:selected selected
|
||||
:on-asset-click on-asset-click
|
||||
:on-drag-start on-drag-start
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-group on-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full}]
|
||||
(when local?
|
||||
[:& cmm/assets-context-menu
|
||||
{:on-close on-close-menu
|
||||
:state @menu-state
|
||||
:options (if new-css-system
|
||||
[(when-not (or multi-components? multi-assets?)
|
||||
{:option-name (tr "workspace.assets.rename")
|
||||
:id "assets-rename-component"
|
||||
:option-handler on-rename})
|
||||
(when-not multi-assets?
|
||||
{:option-name (if components-v2
|
||||
(tr "workspace.assets.duplicate-main")
|
||||
(tr "workspace.assets.duplicate"))
|
||||
:id "assets-duplicate-component"
|
||||
:option-handler on-duplicate})
|
||||
|
||||
{:option-name (tr "workspace.assets.delete")
|
||||
:id "assets-delete-component"
|
||||
:option-handler on-delete}
|
||||
(when-not multi-assets?
|
||||
{:option-name (tr "workspace.assets.group")
|
||||
:id "assets-group-component"
|
||||
:option-handler on-group})
|
||||
|
||||
|
||||
(when (and components-v2 (not multi-assets?))
|
||||
{:option-name (tr "workspace.shape.menu.show-main")
|
||||
:id "assets-show-main-component"
|
||||
:option-handler on-show-main})]
|
||||
|
||||
[(when-not (or multi-components? multi-assets?)
|
||||
[(tr "workspace.assets.rename") on-rename])
|
||||
(when-not multi-assets?
|
||||
[(if components-v2
|
||||
(tr "workspace.assets.duplicate-main")
|
||||
(tr "workspace.assets.duplicate")) on-duplicate])
|
||||
[(tr "workspace.assets.delete") on-delete]
|
||||
(when-not multi-assets?
|
||||
[(tr "workspace.assets.group") on-group])
|
||||
(when (and components-v2 (not multi-assets?))
|
||||
[(tr "workspace.shape.menu.show-main") on-show-main])])}])]]))
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"assets_components_button-primary_lsoWq","button-secondary":"assets_components_button-secondary_P8v5X","button-tertiary":"assets_components_button-tertiary_7wMqf","add-component":"assets_components_add-component_X9o2C","button-tag":"assets_components_button-tag_ibmtY","button-icon":"assets_components_button-icon_4Lapr","button-icon-small":"assets_components_button-icon-small_7WrRR","component-group":"assets_components_component-group_AYXVI","asset-enum":"assets_components_asset-enum_iLlfH","enum-item":"assets_components_enum-item_l4zuE","item-name":"assets_components_item-name_Hwadc","editing":"assets_components_editing_3RdZy","asset-grid":"assets_components_asset-grid_mK75F","grid-cell":"assets_components_grid-cell_ctU6T","cell-name":"assets_components_cell-name_DUUMt","asset-element":"assets_components_asset-element_UsbdX","drop-space":"assets_components_drop-space_QhD1-","selected":"assets_components_selected_QLPO7","grid-placeholder":"assets_components_grid-placeholder_a3PoY","listing-options":"assets_components_listing-options_-vPIQ","listing-option-btn":"assets_components_listing-option-btn_-d9cg","first":"assets_components_first_sri1T","dragging":"assets_components_dragging_bWqQC"}
|
|
@ -0,0 +1,249 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.component-group {
|
||||
.drop-space {
|
||||
height: $s-12;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--assets-item-background-color);
|
||||
}
|
||||
.asset-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-auto-rows: calc(10vh + $s-16);
|
||||
gap: $s-4;
|
||||
margin-left: $s-8;
|
||||
margin-right: $s-12;
|
||||
.grid-cell {
|
||||
@include flexCenter;
|
||||
position: relative;
|
||||
padding: $s-8;
|
||||
border: $s-2 solid transparent;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--assets-item-background-color);
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
img {
|
||||
height: auto;
|
||||
width: auto;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
svg {
|
||||
height: 10vh;
|
||||
}
|
||||
.cell-name {
|
||||
@include titleTipography;
|
||||
@include textEllipsis;
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding: $s-2;
|
||||
|
||||
&.editing {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
border: $s-1 solid var(--input-border-color-focus);
|
||||
border-radius: $br-8;
|
||||
background-color: var(--input-background-color);
|
||||
input {
|
||||
@include textEllipsis;
|
||||
@include titleTipography;
|
||||
@include removeInputStyle;
|
||||
flex-grow: 1;
|
||||
height: $s-28;
|
||||
max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
|
||||
padding-left: $s-6;
|
||||
margin: 0;
|
||||
border-radius: $br-8;
|
||||
color: var(--input-foreground-color);
|
||||
}
|
||||
span {
|
||||
@include flexCenter;
|
||||
height: $s-28;
|
||||
background-color: transparent;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--input-foreground-color);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--assets-item-background-color-hover);
|
||||
.cell-name {
|
||||
display: block;
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
background: linear-gradient(to top, rgba(52, 57, 59, 1) 0%, rgba(52, 57, 59, 0) 100%);
|
||||
&.editing {
|
||||
display: flex;
|
||||
background: var(--input-background-color);
|
||||
input {
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
span svg {
|
||||
stroke: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
border: $s-1 solid var(--assets-item-border-color);
|
||||
}
|
||||
}
|
||||
.grid-placeholder {
|
||||
width: 100%;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--assets-item-background-color);
|
||||
}
|
||||
}
|
||||
.asset-enum {
|
||||
margin: 0 $s-12;
|
||||
.enum-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-36;
|
||||
margin-bottom: $s-4;
|
||||
padding: $s-2;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--assets-item-background-color);
|
||||
cursor: pointer;
|
||||
|
||||
svg,
|
||||
img {
|
||||
@include flexCenter;
|
||||
padding: $s-2;
|
||||
height: $s-32;
|
||||
width: $s-32;
|
||||
border-radius: $br-6;
|
||||
background-color: var(--assets-item-background-color);
|
||||
}
|
||||
|
||||
.item-name {
|
||||
@include titleTipography;
|
||||
@include textEllipsis;
|
||||
padding-left: $s-8;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
&.editing {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
border: $s-1 solid var(--input-border-color-focus);
|
||||
border-radius: $br-8;
|
||||
background-color: var(--input-background-color);
|
||||
input {
|
||||
@include textEllipsis;
|
||||
@include titleTipography;
|
||||
@include removeInputStyle;
|
||||
flex-grow: 1;
|
||||
height: $s-28;
|
||||
max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
|
||||
padding-left: $s-6;
|
||||
margin: 0;
|
||||
border-radius: $br-8;
|
||||
color: var(--input-foreground-color);
|
||||
}
|
||||
span {
|
||||
@include flexCenter;
|
||||
height: $s-28;
|
||||
background-color: transparent;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--input-foreground-color);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--assets-item-background-color-hover);
|
||||
.item-name {
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
&.editing {
|
||||
background: var(--input-background-color);
|
||||
input {
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
span svg {
|
||||
stroke: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
border: $s-1 solid var(--assets-item-border-color);
|
||||
}
|
||||
}
|
||||
.grid-placeholder {
|
||||
height: $s-2;
|
||||
width: 100%;
|
||||
background-color: var(--color-accent-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
.listing-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.listing-option-btn {
|
||||
@include flexCenter;
|
||||
cursor: pointer;
|
||||
|
||||
&.first {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
svg {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.add-component {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
margin-left: $s-2;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
:global(.three-row) {
|
||||
.asset-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
:global(.four-row) {
|
||||
.asset-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.dragging {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: $s-8;
|
||||
background-color: var(--assets-item-background-color-drag);
|
||||
border: $s-2 solid var(--assets-item-border-color-drag);
|
||||
}
|
|
@ -0,0 +1,420 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.assets.file-library
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.libraries :refer [create-file-library-ref]]
|
||||
[app.main.ui.workspace.sidebar.assets.colors :refer [colors-section]]
|
||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||
[app.main.ui.workspace.sidebar.assets.components :refer [components-section]]
|
||||
[app.main.ui.workspace.sidebar.assets.graphics :refer [graphics-section]]
|
||||
[app.main.ui.workspace.sidebar.assets.typographies :refer [typographies-section]]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.keyboard :as kbd]
|
||||
[app.util.router :as rt]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def lens:open-status
|
||||
(l/derived (l/in [:workspace-assets :open-status]) st/state))
|
||||
|
||||
(def lens:selected
|
||||
(-> (l/in [:workspace-assets :selected])
|
||||
(l/derived st/state)))
|
||||
|
||||
(mf/defc file-library-title
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [open? local? shared? project-id file-id page-id file-name]}]
|
||||
(let [router (mf/deref refs/router)
|
||||
url (rt/resolve router :workspace
|
||||
{:project-id project-id
|
||||
:file-id file-id}
|
||||
{:page-id page-id})
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
toggle-open
|
||||
(mf/use-fn
|
||||
(mf/deps file-id open?)
|
||||
(fn []
|
||||
(st/emit! (dw/set-assets-section-open file-id :library (not open?)))))]
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :library-title) true)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-open
|
||||
:title (if local?
|
||||
(mf/html [:div {:class (dom/classnames (css :special-title) true)} (tr "workspace.assets.local-library")
|
||||
[:span {:class (dom/classnames (css :special-subtitle) true)} file-name]])
|
||||
|
||||
(mf/html [:div {:class (dom/classnames (css :special-title) true)} file-name]))}
|
||||
(when-not local?
|
||||
[:span.tool-link.tooltip.tooltip-left {:alt "Open library file"}
|
||||
[:a {:class (dom/classnames (css :file-link) true)
|
||||
:href (str "#" url)
|
||||
:target "_blank"
|
||||
:on-click dom/stop-propagation}
|
||||
i/open-link-refactor]])]]
|
||||
|
||||
[:div.tool-window-bar.library-bar
|
||||
{:on-click toggle-open}
|
||||
[:div.collapse-library
|
||||
{:class (dom/classnames :open open?)}
|
||||
i/arrow-slide]
|
||||
|
||||
(if local?
|
||||
[:*
|
||||
[:span file-name " (" (tr "workspace.assets.local-library") ")"]
|
||||
(when shared?
|
||||
[:span.tool-badge (tr "workspace.assets.shared")])]
|
||||
[:*
|
||||
[:span file-name]
|
||||
[:span.tool-link.tooltip.tooltip-left {:alt "Open library file"}
|
||||
[:a {:href (str "#" url)
|
||||
:target "_blank"
|
||||
:on-click dom/stop-propagation}
|
||||
i/chain]]])])))
|
||||
|
||||
(mf/defc file-library-content
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file local? open-status-ref on-clear-selection]}]
|
||||
(let [components-v2 (mf/use-ctx ctx/components-v2)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
open-status (mf/deref open-status-ref)
|
||||
|
||||
file-id (:id file)
|
||||
project-id (:project-id file)
|
||||
|
||||
filters (mf/use-ctx cmm/assets-filters)
|
||||
filters-section (:section filters)
|
||||
|
||||
filters-term (:term filters)
|
||||
filters-ordering (:ordering filters)
|
||||
filters-list-style (:list-style filters)
|
||||
|
||||
reverse-sort? (= :desc filters-ordering)
|
||||
listing-thumbs? (= :thumbs filters-list-style)
|
||||
|
||||
toggle-ordering (mf/use-ctx cmm/assets-toggle-ordering)
|
||||
toggle-list-style (mf/use-ctx cmm/assets-toggle-list-style)
|
||||
|
||||
library-ref (mf/with-memo [file-id]
|
||||
(create-file-library-ref file-id))
|
||||
|
||||
library (mf/deref library-ref)
|
||||
colors (:colors library)
|
||||
components (:components library)
|
||||
media (:media library)
|
||||
typographies (:typographies library)
|
||||
|
||||
colors (mf/with-memo [filters colors]
|
||||
(cmm/apply-filters colors filters))
|
||||
components (mf/with-memo [filters components]
|
||||
(cmm/apply-filters components filters))
|
||||
media (mf/with-memo [filters media]
|
||||
(cmm/apply-filters media filters))
|
||||
typographies (mf/with-memo [filters typographies]
|
||||
(cmm/apply-filters typographies filters))
|
||||
|
||||
show-components? (and (or (= filters-section "all")
|
||||
(= filters-section "components"))
|
||||
(or (pos? (count components))
|
||||
(str/empty? filters-term)))
|
||||
show-graphics? (and (or (= filters-section "all")
|
||||
(= filters-section "graphics"))
|
||||
(or (pos? (count media))
|
||||
(and (str/empty? filters-term)
|
||||
(not components-v2))))
|
||||
show-colors? (and (or (= filters-section "all")
|
||||
(= filters-section "colors"))
|
||||
(or (> (count colors) 0)
|
||||
(str/empty? filters-term)))
|
||||
show-typography? (and (or (= filters-section "all")
|
||||
(= filters-section "typographies"))
|
||||
(or (pos? (count typographies))
|
||||
(str/empty? filters-term)))
|
||||
|
||||
|
||||
selected-lens (mf/with-memo [file-id]
|
||||
(-> (l/key file-id)
|
||||
(l/derived lens:selected)))
|
||||
|
||||
selected (mf/deref selected-lens)
|
||||
selected-count (+ (count (get selected :components))
|
||||
(count (get selected :graphics))
|
||||
(count (get selected :colors))
|
||||
(count (get selected :typographies)))
|
||||
|
||||
extend-selected
|
||||
(fn [type asset-groups asset-id]
|
||||
(letfn [(flatten-groups [groups]
|
||||
(reduce concat [(get groups "" [])
|
||||
(into []
|
||||
(->> (filter #(seq (first %)) groups)
|
||||
(map second)
|
||||
(mapcat flatten-groups)))]))]
|
||||
|
||||
(let [selected' (get selected type)]
|
||||
(if (zero? (count selected'))
|
||||
(st/emit! (dw/select-single-asset file-id asset-id type))
|
||||
(let [all-assets (flatten-groups asset-groups)
|
||||
click-index (d/index-of-pred all-assets #(= (:id %) asset-id))
|
||||
first-index (->> (get selected type)
|
||||
(map (fn [asset] (d/index-of-pred all-assets #(= (:id %) asset))))
|
||||
(sort)
|
||||
(first))
|
||||
|
||||
min-index (min first-index click-index)
|
||||
max-index (max first-index click-index)
|
||||
ids (->> (d/enumerate all-assets)
|
||||
(into #{} (comp (filter #(<= min-index (first %) max-index))
|
||||
(map (comp :id second)))))]
|
||||
|
||||
(st/emit! (dw/select-assets file-id ids type)))))))
|
||||
|
||||
on-asset-click
|
||||
(mf/use-fn
|
||||
(mf/deps file-id extend-selected)
|
||||
(fn [asset-type asset-groups asset-id default-click event]
|
||||
(cond
|
||||
(kbd/mod? event)
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dw/toggle-selected-assets file-id asset-id asset-type)))
|
||||
|
||||
(kbd/shift? event)
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(extend-selected asset-type asset-groups asset-id))
|
||||
|
||||
:else
|
||||
(when default-click
|
||||
(default-click event)))))
|
||||
|
||||
on-component-click
|
||||
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :components))
|
||||
|
||||
on-graphics-click
|
||||
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :graphics))
|
||||
|
||||
on-colors-click
|
||||
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :colors))
|
||||
|
||||
on-typography-click
|
||||
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :typographies))
|
||||
|
||||
on-assets-delete
|
||||
(mf/use-fn
|
||||
(mf/deps selected file-id)
|
||||
(fn []
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit! (map #(dwl/delete-component {:id %})
|
||||
(:components selected)))
|
||||
(run! st/emit! (map #(dwl/delete-media {:id %})
|
||||
(:graphics selected)))
|
||||
(run! st/emit! (map #(dwl/delete-color {:id %})
|
||||
(:colors selected)))
|
||||
(run! st/emit! (map #(dwl/delete-typography %)
|
||||
(:typographies selected)))
|
||||
|
||||
(when (or (seq (:components selected))
|
||||
(seq (:colors selected))
|
||||
(seq (:typographies selected)))
|
||||
(st/emit! (dwl/sync-file file-id file-id)))
|
||||
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))]
|
||||
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :library-content) true)}
|
||||
(when ^boolean show-components?
|
||||
[:& components-section
|
||||
{:file-id file-id
|
||||
:local? local?
|
||||
:components components
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:open? (get open-status :components true)
|
||||
:open-status-ref open-status-ref
|
||||
:reverse-sort? reverse-sort?
|
||||
:selected selected
|
||||
:on-asset-click on-component-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection}])
|
||||
|
||||
(when ^boolean show-graphics?
|
||||
[:& graphics-section
|
||||
{:file-id file-id
|
||||
:project-id project-id
|
||||
:local? local?
|
||||
:objects media
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:open? (get open-status :graphics true)
|
||||
:open-status-ref open-status-ref
|
||||
:reverse-sort? reverse-sort?
|
||||
:selected selected
|
||||
:on-asset-click on-graphics-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection}])
|
||||
|
||||
(when ^boolean show-colors?
|
||||
[:& colors-section
|
||||
{:file-id file-id
|
||||
:local? local?
|
||||
:colors colors
|
||||
:open? (get open-status :colors true)
|
||||
:open-status-ref open-status-ref
|
||||
:reverse-sort? reverse-sort?
|
||||
:selected selected
|
||||
:on-asset-click on-colors-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection}])
|
||||
|
||||
(when ^boolean show-typography?
|
||||
[:& typographies-section
|
||||
{:file file
|
||||
:file-id (:id file)
|
||||
:local? local?
|
||||
:typographies typographies
|
||||
:open? (get open-status :typographies true)
|
||||
:open-status-ref open-status-ref
|
||||
:reverse-sort? reverse-sort?
|
||||
:selected selected
|
||||
:on-asset-click on-typography-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection}])
|
||||
|
||||
(when (and (not ^boolean show-components?)
|
||||
(not ^boolean show-graphics?)
|
||||
(not ^boolean show-colors?)
|
||||
(not ^boolean show-typography?))
|
||||
[:div {:class (css :asset-title)} (tr "workspace.assets.not-found")])]
|
||||
|
||||
[:div.tool-window-content
|
||||
[:div.listing-options
|
||||
(when (> selected-count 0)
|
||||
[:span.selected-count
|
||||
(tr "workspace.assets.selected-count" (i18n/c selected-count))])
|
||||
[:div.listing-option-btn.first {:on-click toggle-ordering}
|
||||
(if reverse-sort?
|
||||
i/sort-ascending
|
||||
i/sort-descending)]
|
||||
[:div.listing-option-btn {:on-click toggle-list-style}
|
||||
(if listing-thumbs?
|
||||
i/listing-enum
|
||||
i/listing-thumbs)]]
|
||||
|
||||
(when ^boolean show-components?
|
||||
[:& components-section
|
||||
{:file-id file-id
|
||||
:local? local?
|
||||
:components components
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:open? (get open-status :components true)
|
||||
:open-status-ref open-status-ref
|
||||
:reverse-sort? reverse-sort?
|
||||
:selected selected
|
||||
:on-asset-click on-component-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection}])
|
||||
|
||||
(when ^boolean show-graphics?
|
||||
[:& graphics-section
|
||||
{:file-id file-id
|
||||
:project-id project-id
|
||||
:local? local?
|
||||
:objects media
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:open? (get open-status :graphics true)
|
||||
:open-status-ref open-status-ref
|
||||
:reverse-sort? reverse-sort?
|
||||
:selected selected
|
||||
:on-asset-click on-graphics-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection}])
|
||||
|
||||
(when ^boolean show-colors?
|
||||
[:& colors-section
|
||||
{:file-id file-id
|
||||
:local? local?
|
||||
:colors colors
|
||||
:open? (get open-status :colors true)
|
||||
:open-status-ref open-status-ref
|
||||
:reverse-sort? reverse-sort?
|
||||
:selected selected
|
||||
:on-asset-click on-colors-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection}])
|
||||
|
||||
(when ^boolean show-typography?
|
||||
[:& typographies-section
|
||||
{:file file
|
||||
:file-id (:id file)
|
||||
:local? local?
|
||||
:typographies typographies
|
||||
:open? (get open-status :typographies true)
|
||||
:open-status-ref open-status-ref
|
||||
:reverse-sort? reverse-sort?
|
||||
:selected selected
|
||||
:on-asset-click on-typography-click
|
||||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection}])
|
||||
|
||||
(when (and (not ^boolean show-components?)
|
||||
(not ^boolean show-graphics?)
|
||||
(not ^boolean show-colors?)
|
||||
(not ^boolean show-typography?))
|
||||
[:div.asset-section
|
||||
[:div.asset-title (tr "workspace.assets.not-found")]])])))
|
||||
|
||||
(mf/defc file-library
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file local? default-open? filters]}]
|
||||
(let [file-id (:id file)
|
||||
file-name (:name file)
|
||||
shared? (:is-shared file)
|
||||
project-id (:project-id file)
|
||||
page-id (dm/get-in file [:data :pages 0])
|
||||
|
||||
open-status-ref (mf/with-memo [file-id]
|
||||
(-> (l/key file-id)
|
||||
(l/derived lens:open-status)))
|
||||
open-status (mf/deref open-status-ref)
|
||||
open? (d/nilv (:library open-status) default-open?)
|
||||
|
||||
unselect-all
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn []
|
||||
(st/emit! (dw/unselect-all-assets file-id))))]
|
||||
|
||||
[:div.tool-window {:on-context-menu dom/prevent-default
|
||||
:on-click unselect-all}
|
||||
[:& file-library-title
|
||||
{:project-id project-id
|
||||
:file-id file-id
|
||||
:page-id page-id
|
||||
:file-name file-name
|
||||
:open? open?
|
||||
:local? local?
|
||||
:shared? shared?}]
|
||||
(when ^boolean open?
|
||||
[:& file-library-content
|
||||
{:file file
|
||||
:local? local?
|
||||
:filters filters
|
||||
:on-clear-selection unselect-all
|
||||
:open-status-ref open-status-ref}])]))
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"assets_file_library_button-primary_o8czr","button-secondary":"assets_file_library_button-secondary_BCBmw","button-tertiary":"assets_file_library_button-tertiary_JiCQn","library-title":"assets_file_library_library-title_FvGs6","file-link":"assets_file_library_file-link_CtN0K","button-tag":"assets_file_library_button-tag_cyg7Q","button-icon":"assets_file_library_button-icon_R-4R0","button-icon-small":"assets_file_library_button-icon-small_9UOdy","asset-element":"assets_file_library_asset-element_6ian7","file-name":"assets_file_library_file-name_Pc8ng","special-title":"assets_file_library_special-title_-Pqzq","special-subtitle":"assets_file_library_special-subtitle_9xOl9","library-content":"assets_file_library_library-content_Yto-8","asset-title":"assets_file_library_asset-title_ozD8M"}
|
|
@ -0,0 +1,51 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.library-title {
|
||||
.file-name {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex-grow: 100;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.special-title {
|
||||
color: var(--title-foreground-color-hover);
|
||||
}
|
||||
.special-subtitle {
|
||||
padding-left: $s-4;
|
||||
color: var(--title-foreground-color);
|
||||
text-transform: initial;
|
||||
}
|
||||
.file-link {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
margin-right: $s-12;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
fill: var(--title-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.library-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.asset-title {
|
||||
@include titleTipography;
|
||||
margin-left: $s-28;
|
||||
}
|
553
frontend/src/app/main/ui/workspace/sidebar/assets/graphics.cljs
Normal file
553
frontend/src/app/main/ui/workspace/sidebar/assets/graphics.cljs
Normal file
|
@ -0,0 +1,553 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.assets.graphics
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.media :as cm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.config :as cf]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.media :as dwm]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.editable-label :refer [editable-label]]
|
||||
[app.main.ui.components.file-uploader :refer [file-uploader]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||
[app.main.ui.workspace.sidebar.assets.groups :as grp]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.dom.dnd :as dnd]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[potok.core :as ptk]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc graphics-item
|
||||
[{:keys [object renaming listing-thumbs? selected-objects file-id
|
||||
on-asset-click on-context-menu on-drag-start do-rename cancel-rename
|
||||
selected-full selected-graphics-paths]}]
|
||||
(let [item-ref (mf/use-ref)
|
||||
visible? (h/use-visible item-ref :once? true)
|
||||
object-id (:id object)
|
||||
|
||||
dragging* (mf/use-state false)
|
||||
dragging? (deref dragging*)
|
||||
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps object dragging* selected-objects selected-full selected-graphics-paths)
|
||||
(fn [event]
|
||||
(cmm/on-drop-asset event object dragging* selected-objects selected-full
|
||||
selected-graphics-paths dwl/rename-media)))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-fn
|
||||
(mf/deps object dragging* selected-objects selected-graphics-paths)
|
||||
(fn [event]
|
||||
(cmm/on-drag-enter-asset event object dragging* selected-objects selected-graphics-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-fn
|
||||
(mf/deps dragging*)
|
||||
(fn [event]
|
||||
(cmm/on-drag-leave-asset event dragging*)))
|
||||
|
||||
on-grahic-drag-start
|
||||
(mf/use-fn
|
||||
(mf/deps object file-id selected-objects item-ref on-drag-start read-only?)
|
||||
(fn [event]
|
||||
(if read-only?
|
||||
(dom/prevent-default event)
|
||||
(cmm/on-asset-drag-start event file-id object selected-objects item-ref :graphics on-drag-start))))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps object-id)
|
||||
(partial on-context-menu object-id))
|
||||
|
||||
on-asset-click
|
||||
(mf/use-fn
|
||||
(mf/deps object-id on-asset-click)
|
||||
(partial on-asset-click object-id nil))]
|
||||
(if ^boolean new-css-system
|
||||
[:div {:ref item-ref
|
||||
:class-name (dom/classnames
|
||||
(css :selected) (contains? selected-objects object-id)
|
||||
(css :grid-cell) listing-thumbs?
|
||||
(css :enum-item) (not listing-thumbs?))
|
||||
:draggable (not read-only?)
|
||||
:on-click on-asset-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-drag-start on-grahic-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when visible?
|
||||
[:*
|
||||
[:img {:src (when visible? (cf/resolve-file-media object true))
|
||||
:class (css :graphic-image)
|
||||
:draggable false}] ;; Also need to add css pointer-events: none
|
||||
|
||||
(let [renaming? (= renaming (:id object))]
|
||||
[:*
|
||||
[:& editable-label
|
||||
{:class-name (dom/classnames
|
||||
(css :cell-name) listing-thumbs?
|
||||
(css :item-name) (not listing-thumbs?)
|
||||
(css :editing) renaming?)
|
||||
:value (cph/merge-path-item (:path object) (:name object))
|
||||
:tooltip (cph/merge-path-item (:path object) (:name object))
|
||||
:display-value (:name object)
|
||||
:editing? renaming?
|
||||
:disable-dbl-click? true
|
||||
:on-change do-rename
|
||||
:on-cancel cancel-rename}]
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div {:class (dom/classnames (css :dragging) true)}])])])]
|
||||
|
||||
[:div {:ref item-ref
|
||||
:class-name (dom/classnames
|
||||
:selected (contains? selected-objects object-id)
|
||||
:grid-cell listing-thumbs?
|
||||
:enum-item (not listing-thumbs?))
|
||||
:draggable (not read-only?)
|
||||
:on-click on-asset-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-drag-start on-grahic-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when visible?
|
||||
[:*
|
||||
[:img {:src (when visible? (cf/resolve-file-media object true))
|
||||
:draggable false}] ;; Also need to add css pointer-events: none
|
||||
|
||||
(let [renaming? (= renaming (:id object))]
|
||||
[:*
|
||||
[:& editable-label
|
||||
{:class-name (dom/classnames
|
||||
:cell-name listing-thumbs?
|
||||
:item-name (not listing-thumbs?)
|
||||
:editing renaming?)
|
||||
:value (cph/merge-path-item (:path object) (:name object))
|
||||
:tooltip (cph/merge-path-item (:path object) (:name object))
|
||||
:display-value (:name object)
|
||||
:editing? renaming?
|
||||
:disable-dbl-click? true
|
||||
:on-change do-rename
|
||||
:on-cancel cancel-rename}]
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div.dragging])])])])))
|
||||
|
||||
(mf/defc graphics-group
|
||||
[{:keys [file-id prefix groups open-groups renaming listing-thumbs? selected-objects on-asset-click
|
||||
on-drag-start do-rename cancel-rename on-rename-group on-ungroup
|
||||
on-context-menu selected-full]}]
|
||||
(let [group-open? (get open-groups prefix true)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
dragging* (mf/use-state false)
|
||||
dragging? (deref dragging*)
|
||||
|
||||
selected-paths
|
||||
(mf/with-memo [selected-full]
|
||||
(into #{}
|
||||
(comp (map :path) (d/nilv ""))
|
||||
selected-full))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* prefix selected-paths)
|
||||
(fn [event]
|
||||
(cmm/on-drag-enter-asset-group event dragging* prefix selected-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-fn
|
||||
(mf/deps dragging*)
|
||||
(fn [event]
|
||||
(cmm/on-drag-leave-asset event dragging*)))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* prefix selected-paths selected-full)
|
||||
(fn [event]
|
||||
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full dwl/rename-media)))]
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :graphics-group) true)
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
[:& grp/asset-group-title
|
||||
{:file-id file-id
|
||||
:section :graphics
|
||||
:path prefix
|
||||
:group-open? group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup}]
|
||||
(when group-open?
|
||||
[:*
|
||||
(let [objects (get groups "" [])]
|
||||
[:div {:class-name (dom/classnames
|
||||
(css :asset-grid) listing-thumbs?
|
||||
(css :asset-enum) (not listing-thumbs?)
|
||||
(css :drop-space) (and
|
||||
(empty? objects)
|
||||
(some? groups)
|
||||
(not dragging?)))
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div {:class (dom/classnames (css :grid-placeholder) true)} "\u00A0"])
|
||||
|
||||
(when (and (empty? objects)
|
||||
(some? groups))
|
||||
[:div {:class (dom/classnames (css :drop-space) true)}])
|
||||
|
||||
(for [object objects]
|
||||
[:& graphics-item
|
||||
{:key (dm/str "object-" (:id object))
|
||||
:file-id file-id
|
||||
:object object
|
||||
:renaming renaming
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:selected-objects selected-objects
|
||||
:on-asset-click on-asset-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-drag-start on-drag-start
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename
|
||||
:selected-full selected-full
|
||||
:selected-paths selected-paths}])])
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& graphics-group {:file-id file-id
|
||||
:key path-item
|
||||
:prefix (cph/merge-path-item prefix path-item)
|
||||
:groups content
|
||||
:open-groups open-groups
|
||||
:renaming renaming
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:selected-objects selected-objects
|
||||
:on-asset-click on-asset-click
|
||||
:on-drag-start on-drag-start
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full
|
||||
:selected-paths selected-paths}]))])]
|
||||
|
||||
[:div {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
[:& grp/asset-group-title {:file-id file-id
|
||||
:section :graphics
|
||||
:path prefix
|
||||
:group-open? group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup}]
|
||||
(when group-open?
|
||||
[:*
|
||||
(let [objects (get groups "" [])]
|
||||
[:div {:class-name (dom/classnames
|
||||
:asset-grid listing-thumbs?
|
||||
:asset-enum (not listing-thumbs?)
|
||||
:drop-space (and
|
||||
(empty? objects)
|
||||
(some? groups)
|
||||
(not dragging?)))
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div.grid-placeholder "\u00A0"])
|
||||
|
||||
(when (and (empty? objects)
|
||||
(some? groups))
|
||||
[:div.drop-space])
|
||||
|
||||
(for [object objects]
|
||||
[:& graphics-item {:key (dm/str "object-" (:id object))
|
||||
:file-id file-id
|
||||
:object object
|
||||
:renaming renaming
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:selected-objects selected-objects
|
||||
:on-asset-click on-asset-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-drag-start on-drag-start
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename
|
||||
:selected-full selected-full
|
||||
:selected-paths selected-paths}])])
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& graphics-group {:file-id file-id
|
||||
:key path-item
|
||||
:prefix (cph/merge-path-item prefix path-item)
|
||||
:groups content
|
||||
:open-groups open-groups
|
||||
:renaming renaming
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:selected-objects selected-objects
|
||||
:on-asset-click on-asset-click
|
||||
:on-drag-start on-drag-start
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full
|
||||
:selected-paths selected-paths}]))])])))
|
||||
|
||||
(mf/defc graphics-section
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file-id project-id local? objects listing-thumbs? open? open-status-ref selected reverse-sort?
|
||||
on-asset-click on-assets-delete on-clear-selection]}]
|
||||
(let [input-ref (mf/use-ref nil)
|
||||
state (mf/use-state {:renaming nil :object-id nil})
|
||||
|
||||
menu-state (mf/use-state cmm/initial-context-menu-state)
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
|
||||
open-groups-ref (mf/with-memo [open-status-ref]
|
||||
(-> (l/in [:groups :graphics])
|
||||
(l/derived open-status-ref)))
|
||||
open-groups (mf/deref open-groups-ref)
|
||||
|
||||
selected (:graphics selected)
|
||||
selected-full (into #{} (filter #(contains? selected (:id %))) objects)
|
||||
multi-objects? (> (count selected) 1)
|
||||
multi-assets? (or (seq (:components selected))
|
||||
(seq (:colors selected))
|
||||
(seq (:typographies selected)))
|
||||
|
||||
objects (mf/with-memo [objects]
|
||||
(mapv dwl/extract-path-if-missing objects))
|
||||
|
||||
groups (mf/with-memo [objects reverse-sort?]
|
||||
(grp/group-assets objects reverse-sort?))
|
||||
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
team-id (mf/use-ctx ctx/current-team-id)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
add-graphic
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (dw/set-assets-section-open file-id :graphics true))
|
||||
(dom/click (mf/ref-val input-ref))))
|
||||
|
||||
on-file-selected
|
||||
(mf/use-fn
|
||||
(mf/deps file-id project-id team-id)
|
||||
(fn [blobs]
|
||||
(let [params {:file-id file-id
|
||||
:blobs (seq blobs)}]
|
||||
(st/emit! (dwm/upload-media-asset params)
|
||||
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
||||
:asset-type "graphics"
|
||||
:file-id file-id
|
||||
:project-id project-id
|
||||
:team-id team-id})))))
|
||||
on-delete
|
||||
(mf/use-fn
|
||||
(mf/deps @state multi-objects? multi-assets?)
|
||||
(fn []
|
||||
(if (or multi-objects? multi-assets?)
|
||||
(on-assets-delete)
|
||||
(st/emit! (dwl/delete-media {:id (:object-id @state)})))))
|
||||
|
||||
on-rename
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(swap! state (fn [state]
|
||||
(assoc state :renaming (:component-id state))))))
|
||||
cancel-rename
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(swap! state assoc :renaming nil)))
|
||||
|
||||
do-rename
|
||||
(mf/use-fn
|
||||
(mf/deps @state)
|
||||
(fn [new-name]
|
||||
(st/emit! (dwl/rename-media (:renaming @state) new-name))
|
||||
(swap! state assoc :renaming nil)))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps selected on-clear-selection read-only?)
|
||||
(fn [object-id event]
|
||||
(dom/prevent-default event)
|
||||
(let [pos (dom/get-client-position event)]
|
||||
(when (and local? (not read-only?))
|
||||
(when-not (contains? selected object-id)
|
||||
(on-clear-selection))
|
||||
(swap! state assoc :object-id object-id)
|
||||
(swap! menu-state cmm/open-context-menu pos)))))
|
||||
|
||||
on-close-menu
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(swap! menu-state cmm/close-context-menu)))
|
||||
|
||||
create-group
|
||||
(mf/use-fn
|
||||
(mf/deps objects selected on-clear-selection (:object-id @state))
|
||||
(fn [group-name]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> objects
|
||||
(filter #(if multi-objects?
|
||||
(contains? selected (:id %))
|
||||
(= (:object-id @state) (:id %))))
|
||||
(map #(dwl/rename-media (:id %) (cmm/add-group % group-name)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
rename-group
|
||||
(mf/use-fn
|
||||
(mf/deps objects)
|
||||
(fn [path last-path]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> objects
|
||||
(filter #(str/starts-with? (:path %) path))
|
||||
(map #(dwl/rename-media (:id %) (cmm/rename-group % path last-path)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
on-group
|
||||
(mf/use-fn
|
||||
(mf/deps objects selected create-group)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(modal/show! :name-group-dialog {:accept create-group})))
|
||||
|
||||
on-rename-group
|
||||
(mf/use-fn
|
||||
(mf/deps objects)
|
||||
(fn [event path last-path]
|
||||
(dom/stop-propagation event)
|
||||
(modal/show! :name-group-dialog {:path path
|
||||
:last-path last-path
|
||||
:accept rename-group})))
|
||||
on-ungroup
|
||||
(mf/use-fn
|
||||
(mf/deps objects)
|
||||
(fn [path]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> objects
|
||||
(filter #(str/starts-with? (:path %) path))
|
||||
(map #(dwl/rename-media (:id %) (cmm/ungroup % path)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
on-drag-start
|
||||
(mf/use-fn
|
||||
(fn [{:keys [name id mtype]} event]
|
||||
(dnd/set-data! event "text/asset-id" (str id))
|
||||
(dnd/set-data! event "text/asset-name" name)
|
||||
(dnd/set-data! event "text/asset-type" mtype)
|
||||
(dnd/set-allowed-effect! event "move")))
|
||||
|
||||
on-asset-click
|
||||
(mf/use-fn (mf/deps groups on-asset-click) (partial on-asset-click groups))]
|
||||
|
||||
[:& cmm/asset-section {:file-id file-id
|
||||
:title (tr "workspace.assets.graphics")
|
||||
:section :graphics
|
||||
:assets-count (count objects)
|
||||
:open? open?}
|
||||
(if new-css-system
|
||||
(when local?
|
||||
[:& cmm/asset-section-block {:role :title-button}
|
||||
(when (and (not components-v2) (not read-only?))
|
||||
[:button {:class (dom/classnames (css :assets-btn) true)
|
||||
:on-click add-graphic}
|
||||
i/add-refactor
|
||||
[:& file-uploader {:accept cm/str-image-types
|
||||
:multi true
|
||||
:ref input-ref
|
||||
:on-selected on-file-selected}]])])
|
||||
(when local?
|
||||
[:& cmm/asset-section-block {:role :title-button}
|
||||
(when (and (not components-v2) (not read-only?))
|
||||
[:div.assets-button {:on-click add-graphic}
|
||||
i/plus
|
||||
[:& file-uploader {:accept cm/str-image-types
|
||||
:multi true
|
||||
:ref input-ref
|
||||
:on-selected on-file-selected}]])]))
|
||||
|
||||
[:& cmm/asset-section-block {:role :content}
|
||||
[:& graphics-group {:file-id file-id
|
||||
:prefix ""
|
||||
:groups groups
|
||||
:open-groups open-groups
|
||||
:renaming (:renaming @state)
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:selected selected
|
||||
:on-asset-click on-asset-click
|
||||
:on-drag-start on-drag-start
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full}]
|
||||
(when local?
|
||||
[:& cmm/assets-context-menu
|
||||
{:on-close on-close-menu
|
||||
:state @menu-state
|
||||
:options (if new-css-system
|
||||
[(when-not (or multi-objects? multi-assets?)
|
||||
{:option-name (tr "workspace.assets.rename")
|
||||
:id "assets-rename-graphics"
|
||||
:option-handler on-rename})
|
||||
{:option-name (tr "workspace.assets.delete")
|
||||
:id "assets-delete-graphics"
|
||||
:option-handler on-delete}
|
||||
(when-not multi-assets?
|
||||
{:option-name (tr "workspace.assets.group")
|
||||
:id "assets-group-graphics"
|
||||
:option-handler on-group})]
|
||||
|
||||
[(when-not (or multi-objects? multi-assets?)
|
||||
[(tr "workspace.assets.rename") on-rename])
|
||||
[(tr "workspace.assets.delete") on-delete]
|
||||
(when-not multi-assets?
|
||||
[(tr "workspace.assets.group") on-group])])}])]]))
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"assets_graphics_button-primary_6qIO6","button-secondary":"assets_graphics_button-secondary_0qkG4","button-tertiary":"assets_graphics_button-tertiary_bWZ1s","assets-btn":"assets_graphics_assets-btn_BIoeo","add-component":"assets_graphics_add-component_bgwrr","button-tag":"assets_graphics_button-tag_K3ckf","button-icon":"assets_graphics_button-icon_En5qq","button-icon-small":"assets_graphics_button-icon-small_xNHzC","asset-element":"assets_graphics_asset-element_-VwmF","graphics-group":"assets_graphics_graphics-group_kibPf","drop-space":"assets_graphics_drop-space_2UAKf","asset-grid":"assets_graphics_asset-grid_6ET0K","grid-cell":"assets_graphics_grid-cell_EHW4x","cell-name":"assets_graphics_cell-name_JgbUS","editing":"assets_graphics_editing_O-Ozt","editable-label-input":"assets_graphics_editable-label-input_Yc2zA","editable-label-close":"assets_graphics_editable-label-close_16VT8","selected":"assets_graphics_selected_Q9YJC","dragging":"assets_graphics_dragging_oVA41","asset-enum":"assets_graphics_asset-enum_TS6Je","enum-item":"assets_graphics_enum-item_UFh4c","item-name":"assets_graphics_item-name_HGIQs","grid-placeholder":"assets_graphics_grid-placeholder_9brkO","listing-options":"assets_graphics_listing-options_Jw51P","listing-option-btn":"assets_graphics_listing-option-btn_3IkTO","first":"assets_graphics_first_kU3zf"}
|
190
frontend/src/app/main/ui/workspace/sidebar/assets/graphics.scss
Normal file
190
frontend/src/app/main/ui/workspace/sidebar/assets/graphics.scss
Normal file
|
@ -0,0 +1,190 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.graphics-group {
|
||||
.drop-space {
|
||||
height: $s-12;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--assets-item-background-color);
|
||||
}
|
||||
.asset-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: $s-4;
|
||||
margin-left: $s-8;
|
||||
margin-right: $s-12;
|
||||
.grid-cell {
|
||||
@include flexCenter;
|
||||
position: relative;
|
||||
padding: $s-8;
|
||||
border: $s-2 solid transparent;
|
||||
border-radius: $br-8;
|
||||
aspect-ratio: 1/1;
|
||||
background-color: var(--assets-item-background-color);
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
img {
|
||||
height: auto;
|
||||
width: auto;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
svg {
|
||||
height: 10vh;
|
||||
}
|
||||
.cell-name {
|
||||
@include titleTipography;
|
||||
@include textEllipsis;
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding: $s-2;
|
||||
|
||||
&.editing {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.editable-label-input {
|
||||
height: unset;
|
||||
width: 100%;
|
||||
padding: $s-2;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.editable-label-close {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--assets-item-background-color-hover);
|
||||
.cell-name {
|
||||
display: block;
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
background: linear-gradient(to top, rgba(52, 57, 59, 1) 0%, rgba(52, 57, 59, 0) 100%);
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
border: $s-1 solid var(--assets-item-border-color);
|
||||
}
|
||||
|
||||
.dragging {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: $s-8;
|
||||
background-color: var(--assets-item-background-color-drag);
|
||||
border: $s-2 solid var(--assets-item-border-color-drag);
|
||||
}
|
||||
}
|
||||
}
|
||||
.asset-enum {
|
||||
margin: 0 $s-12;
|
||||
|
||||
.enum-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-36;
|
||||
margin-bottom: $s-4;
|
||||
padding: $s-2;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--assets-item-background-color);
|
||||
cursor: pointer;
|
||||
|
||||
svg,
|
||||
img {
|
||||
@include flexCenter;
|
||||
padding: $s-2;
|
||||
height: $s-32;
|
||||
width: $s-32;
|
||||
border-radius: $br-6;
|
||||
background-color: var(--assets-component-background-color);
|
||||
}
|
||||
|
||||
.item-name {
|
||||
@include titleTipography;
|
||||
@include textEllipsis;
|
||||
padding-left: $s-8;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
|
||||
&.editing {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.editable-label-input {
|
||||
height: $s-24;
|
||||
}
|
||||
|
||||
.editable-label-close {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--assets-item-background-color-hover);
|
||||
.item-name {
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
border: $s-1 solid var(--assets-item-border-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
.grid-placeholder {
|
||||
height: $s-2;
|
||||
background-color: var(--color-accent-primary);
|
||||
margin-bottom: $s-2;
|
||||
}
|
||||
}
|
||||
.listing-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.listing-option-btn {
|
||||
@include flexCenter;
|
||||
cursor: pointer;
|
||||
|
||||
&.first {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
svg {
|
||||
height: $s-16;
|
||||
width: $s-16;
|
||||
}
|
||||
}
|
||||
}
|
||||
.add-component {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
margin-left: $s-2;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
|
||||
.assets-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: calc($s-24 + $s-4);
|
||||
padding: 0;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
171
frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs
Normal file
171
frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs
Normal file
|
@ -0,0 +1,171 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.assets.groups
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.forms :as fm]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[cljs.spec.alpha :as s]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc asset-group-title
|
||||
[{:keys [file-id section path group-open? on-rename on-ungroup]}]
|
||||
(when-not (empty? path)
|
||||
(let [[other-path last-path truncated] (cph/compact-path path 35 true)
|
||||
menu-state (mf/use-state cmm/initial-context-menu-state)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
on-fold-group
|
||||
(mf/use-fn
|
||||
(mf/deps file-id section path group-open?)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dw/set-assets-group-open file-id
|
||||
section
|
||||
path
|
||||
(not group-open?)))))
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(let [pos (dom/get-client-position event)]
|
||||
(swap! menu-state cmm/open-context-menu pos))))
|
||||
|
||||
on-close-menu
|
||||
(mf/use-fn #(swap! menu-state cmm/close-context-menu))]
|
||||
(if new-css-system
|
||||
[:div {:class (dom/classnames (css :group-title) true)
|
||||
:on-context-menu on-context-menu}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not group-open?)
|
||||
:on-collapsed on-fold-group
|
||||
:title (mf/html [:* (when-not (empty? other-path)
|
||||
[:span {:class (dom/classnames (css :pre-path) true)
|
||||
:title (when truncated path)}
|
||||
other-path "\u00A0\u2022\u00A0"])
|
||||
[:span {:class (dom/classnames (css :path) true)
|
||||
:title (when truncated path)}
|
||||
last-path]])}]
|
||||
[:& cmm/assets-context-menu
|
||||
{:on-close on-close-menu
|
||||
:state @menu-state
|
||||
:options [{:option-name (tr "workspace.assets.rename")
|
||||
:id "assets-rename-group"
|
||||
:option-handler #(on-rename % path last-path)}
|
||||
{:option-name (tr "workspace.assets.ungroup")
|
||||
:id "assets-ungroup-group"
|
||||
:option-handler #(on-ungroup path)}]}]]
|
||||
|
||||
|
||||
[:div.group-title {:class (when-not group-open? "closed")
|
||||
:on-click on-fold-group
|
||||
:on-context-menu on-context-menu}
|
||||
[:span i/arrow-slide]
|
||||
(when-not (empty? other-path)
|
||||
[:span.dim {:title (when truncated path)}
|
||||
other-path "\u00A0/\u00A0"])
|
||||
[:span {:title (when truncated path)}
|
||||
last-path]
|
||||
[:& cmm/assets-context-menu
|
||||
{:on-close on-close-menu
|
||||
:state @menu-state
|
||||
:options [[(tr "workspace.assets.rename") #(on-rename % path last-path)]
|
||||
[(tr "workspace.assets.ungroup") #(on-ungroup path)]]}]]))))
|
||||
|
||||
(defn group-assets
|
||||
"Convert a list of assets in a nested structure like this:
|
||||
|
||||
{'': [{assetA} {assetB}]
|
||||
'group1': {'': [{asset1A} {asset1B}]
|
||||
'subgroup11': {'': [{asset11A} {asset11B} {asset11C}]}
|
||||
'subgroup12': {'': [{asset12A}]}}
|
||||
'group2': {'subgroup21': {'': [{asset21A}}}}
|
||||
"
|
||||
[assets reverse-sort?]
|
||||
(when-not (empty? assets)
|
||||
(reduce (fn [groups {:keys [path] :as asset}]
|
||||
(let [path (cph/split-path (or path ""))]
|
||||
(update-in groups
|
||||
(conj path "")
|
||||
(fn [group]
|
||||
(if group
|
||||
(conj group asset)
|
||||
[asset])))))
|
||||
(sorted-map-by (fn [key1 key2]
|
||||
(if reverse-sort?
|
||||
(compare key2 key1)
|
||||
(compare key1 key2))))
|
||||
assets)))
|
||||
|
||||
(s/def ::asset-name ::us/not-empty-string)
|
||||
(s/def ::name-group-form
|
||||
(s/keys :req-un [::asset-name]))
|
||||
|
||||
(mf/defc name-group-dialog
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :name-group-dialog}
|
||||
[{:keys [path last-path accept] :as ctx
|
||||
:or {path "" last-path ""}}]
|
||||
(let [initial (mf/use-memo
|
||||
(mf/deps last-path)
|
||||
(constantly {:asset-name last-path}))
|
||||
form (fm/use-form :spec ::name-group-form
|
||||
:initial initial)
|
||||
|
||||
create? (empty? path)
|
||||
|
||||
on-close (mf/use-fn #(modal/hide!))
|
||||
|
||||
on-accept
|
||||
(mf/use-fn
|
||||
(mf/deps form)
|
||||
(fn [_]
|
||||
(let [asset-name (get-in @form [:clean-data :asset-name])]
|
||||
(if create?
|
||||
(accept asset-name)
|
||||
(accept path asset-name))
|
||||
(modal/hide!))))]
|
||||
|
||||
[:div.modal-overlay
|
||||
[:div.modal-container.confirm-dialog
|
||||
[:div.modal-header
|
||||
[:div.modal-header-title
|
||||
[:h2 (if create?
|
||||
(tr "workspace.assets.create-group")
|
||||
(tr "workspace.assets.rename-group"))]]
|
||||
[:div.modal-close-button
|
||||
{:on-click on-close} i/close]]
|
||||
|
||||
[:div.modal-content.generic-form
|
||||
[:& fm/form {:form form :on-submit on-accept}
|
||||
[:& fm/input {:name :asset-name
|
||||
:auto-focus? true
|
||||
:label (tr "workspace.assets.group-name")
|
||||
:hint (tr "workspace.assets.create-group-hint")}]]]
|
||||
|
||||
[:div.modal-footer
|
||||
[:div.action-buttons
|
||||
[:input.cancel-button
|
||||
{:type "button"
|
||||
:value (tr "labels.cancel")
|
||||
:on-click on-close}]
|
||||
|
||||
[:input.accept-button.primary
|
||||
{:type "button"
|
||||
:class (when-not (:valid @form) "btn-disabled")
|
||||
:disabled (not (:valid @form))
|
||||
:value (if create? (tr "labels.create") (tr "labels.rename"))
|
||||
:on-click on-accept}]]]]]))
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"assets_groups_button-primary_2o3Db","button-secondary":"assets_groups_button-secondary_-qdxB","button-tertiary":"assets_groups_button-tertiary_1f4Jy","button-tag":"assets_groups_button-tag_yIgd9","button-icon":"assets_groups_button-icon_MSptS","button-icon-small":"assets_groups_button-icon-small_73Ir0","asset-element":"assets_groups_asset-element_RgKXH","group-title":"assets_groups_group-title_cV4AQ","pre-path":"assets_groups_pre-path_1rE71","path":"assets_groups_path_m0esc"}
|
|
@ -0,0 +1,19 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.group-title {
|
||||
padding-left: $s-16;
|
||||
.pre-path {
|
||||
text-transform: initial;
|
||||
color: var(--title-foreground-color);
|
||||
}
|
||||
.path {
|
||||
text-transform: initial;
|
||||
color: var(--title-foreground-color-hover);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,553 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.assets.typographies
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||
[app.main.ui.workspace.sidebar.assets.groups :as grp]
|
||||
[app.main.ui.workspace.sidebar.options.menus.typography :refer [typography-entry]]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def lens:typography-section-state
|
||||
(l/derived (fn [gstate]
|
||||
{:rename-typography (:rename-typography gstate)
|
||||
:edit-typography (:edit-typography gstate)})
|
||||
refs/workspace-global
|
||||
=))
|
||||
|
||||
(mf/defc typography-item
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [typography file-id local? handle-change selected apply-typography editing-id renaming-id on-asset-click
|
||||
on-context-menu selected-full selected-paths move-typography rename?]}]
|
||||
(let [item-ref (mf/use-ref)
|
||||
typography-id (:id typography)
|
||||
|
||||
dragging* (mf/use-state false)
|
||||
dragging? (deref dragging*)
|
||||
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
editing? (= editing-id (:id typography))
|
||||
renaming? (= renaming-id (:id typography))
|
||||
|
||||
open* (mf/use-state editing?)
|
||||
open? (deref open*)
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps typography dragging* selected selected-full selected-paths move-typography)
|
||||
(fn [event]
|
||||
(cmm/on-drop-asset event typography dragging* selected selected-full
|
||||
selected-paths move-typography)))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-fn
|
||||
(mf/deps typography dragging* selected selected-paths)
|
||||
(fn [event]
|
||||
(cmm/on-drag-enter-asset event typography dragging* selected selected-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-fn
|
||||
(mf/deps dragging*)
|
||||
(fn [event]
|
||||
(cmm/on-drag-leave-asset event dragging*)))
|
||||
|
||||
on-typography-drag-start
|
||||
(mf/use-fn
|
||||
(mf/deps typography file-id selected item-ref read-only?)
|
||||
(fn [event]
|
||||
(if read-only?
|
||||
(dom/prevent-default event)
|
||||
(cmm/on-asset-drag-start event file-id typography selected item-ref :typographies identity))))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps on-context-menu typography-id)
|
||||
(partial on-context-menu typography-id))
|
||||
|
||||
handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps typography)
|
||||
(partial handle-change typography))
|
||||
|
||||
apply-typography
|
||||
(mf/use-fn
|
||||
(mf/deps typography)
|
||||
(partial apply-typography typography))
|
||||
|
||||
on-asset-click
|
||||
(mf/use-fn
|
||||
(mf/deps typography apply-typography on-asset-click)
|
||||
(partial on-asset-click typography-id apply-typography))]
|
||||
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :typography-item) true)
|
||||
:ref item-ref
|
||||
:draggable (and (not read-only?) (not open?))
|
||||
:on-drag-start on-typography-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
[:& typography-entry
|
||||
{:typography typography
|
||||
:local? local?
|
||||
:on-context-menu on-context-menu
|
||||
:on-change handle-change
|
||||
:selected? (contains? selected typography-id)
|
||||
:on-click on-asset-click
|
||||
:editing? editing?
|
||||
:renaming? renaming?
|
||||
:focus-name? rename?
|
||||
:external-open* open*
|
||||
:file-id file-id}]
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div {:class (dom/classnames (css :dragging) true)}])]
|
||||
|
||||
[:div.typography-container {:ref item-ref
|
||||
:draggable (and (not read-only?) (not open?))
|
||||
:on-drag-start on-typography-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
[:& typography-entry
|
||||
{:typography typography
|
||||
:local? local?
|
||||
:on-context-menu on-context-menu
|
||||
:on-change handle-change
|
||||
:selected? (contains? selected typography-id)
|
||||
:on-click on-asset-click
|
||||
:editing? editing?
|
||||
:focus-name? rename?
|
||||
:external-open* open*
|
||||
:file-id file-id}]
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div.dragging])])))
|
||||
|
||||
(mf/defc typographies-group
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file-id prefix groups open-groups file local? selected local-data
|
||||
editing-id renaming-id on-asset-click handle-change apply-typography on-rename-group
|
||||
on-ungroup on-context-menu selected-full]}]
|
||||
(let [group-open? (get open-groups prefix true)
|
||||
dragging* (mf/use-state false)
|
||||
dragging? (deref dragging*)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
selected-paths (mf/with-memo [selected-full]
|
||||
(into #{}
|
||||
(comp (map :path) (d/nilv ""))
|
||||
selected-full))
|
||||
move-typography
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(partial dwl/rename-typography file-id))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* prefix selected-paths)
|
||||
(fn [event]
|
||||
(cmm/on-drag-enter-asset-group event dragging* prefix selected-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-fn
|
||||
(mf/deps dragging*)
|
||||
(fn [event]
|
||||
(cmm/on-drag-leave-asset event dragging*)))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* prefix selected-paths selected-full move-typography)
|
||||
(fn [event]
|
||||
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full move-typography)))]
|
||||
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :typographies-group) true)
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
[:& grp/asset-group-title {:file-id file-id
|
||||
:section :typographies
|
||||
:path prefix
|
||||
:group-open? group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup}]
|
||||
|
||||
(when group-open?
|
||||
[:*
|
||||
(let [typographies (get groups "" [])]
|
||||
[:div {:class (dom/classnames (css :assets-list) true)
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div {:class (css :grid-placeholder)} "\u00A0"])
|
||||
|
||||
(when (and
|
||||
(empty? typographies)
|
||||
(some? groups))
|
||||
[:div {:class (css :drop-space)}])
|
||||
(for [{:keys [id] :as typography} typographies]
|
||||
[:& typography-item {:typography typography
|
||||
:key (dm/str "typography-" id)
|
||||
:file-id file-id
|
||||
:local? local?
|
||||
:handle-change handle-change
|
||||
:selected selected
|
||||
:apply-typography apply-typography
|
||||
:editing-id editing-id
|
||||
:renaming-id renaming-id
|
||||
:rename? (= (:rename-typography local-data) id)
|
||||
:on-asset-click on-asset-click
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full
|
||||
:selected-paths selected-paths
|
||||
:move-typography move-typography}])])
|
||||
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& typographies-group {:file-id file-id
|
||||
:prefix (cph/merge-path-item prefix path-item)
|
||||
:key (dm/str "group-" path-item)
|
||||
:groups content
|
||||
:open-groups open-groups
|
||||
:file file
|
||||
:local? local?
|
||||
:selected selected
|
||||
:editing-id editing-id
|
||||
:renaming-id renaming-id
|
||||
:local-data local-data
|
||||
:on-asset-click on-asset-click
|
||||
:handle-change handle-change
|
||||
:apply-typography apply-typography
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full}]))])]
|
||||
[:div {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
[:& grp/asset-group-title {:file-id file-id
|
||||
:section :typographies
|
||||
:path prefix
|
||||
:group-open? group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup}]
|
||||
(when group-open?
|
||||
[:*
|
||||
(let [typographies (get groups "" [])]
|
||||
[:div.asset-list {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over dom/prevent-default
|
||||
:on-drop on-drop}
|
||||
|
||||
(when ^boolean dragging?
|
||||
[:div.grid-placeholder "\u00A0"])
|
||||
|
||||
(when (and
|
||||
(empty? typographies)
|
||||
(some? groups))
|
||||
[:div.drop-space])
|
||||
(for [{:keys [id] :as typography} typographies]
|
||||
[:& typography-item {:typography typography
|
||||
:key (dm/str "typography-" id)
|
||||
:file-id file-id
|
||||
:local? local?
|
||||
:handle-change handle-change
|
||||
:selected selected
|
||||
:apply-typography apply-typography
|
||||
:editing-id editing-id
|
||||
:rename? (= (:rename-typography local-data) id)
|
||||
:on-asset-click on-asset-click
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full
|
||||
:selected-paths selected-paths
|
||||
:move-typography move-typography}])])
|
||||
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& typographies-group {:file-id file-id
|
||||
:prefix (cph/merge-path-item prefix path-item)
|
||||
:key (dm/str "group-" path-item)
|
||||
:groups content
|
||||
:open-groups open-groups
|
||||
:file file
|
||||
:local? local?
|
||||
:selected selected
|
||||
:editing-id editing-id
|
||||
:local-data local-data
|
||||
:on-asset-click on-asset-click
|
||||
:handle-change handle-change
|
||||
:apply-typography apply-typography
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full}]))])])))
|
||||
|
||||
(mf/defc typographies-section
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file file-id local? typographies open? open-status-ref selected reverse-sort?
|
||||
on-asset-click on-assets-delete on-clear-selection]}]
|
||||
(let [state (mf/use-state {:detail-open? false :id nil})
|
||||
local-data (mf/deref lens:typography-section-state)
|
||||
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
menu-state (mf/use-state cmm/initial-context-menu-state)
|
||||
typographies (mf/with-memo [typographies]
|
||||
(mapv dwl/extract-path-if-missing typographies))
|
||||
|
||||
groups (mf/with-memo [typographies reverse-sort?]
|
||||
(grp/group-assets typographies reverse-sort?))
|
||||
|
||||
selected (:typographies selected)
|
||||
selected-full (mf/with-memo [selected typographies]
|
||||
(into #{} (filter #(contains? selected (:id %))) typographies))
|
||||
|
||||
multi-typographies? (> (count selected) 1)
|
||||
multi-assets? (or (seq (:components selected))
|
||||
(seq (:graphics selected))
|
||||
(seq (:colors selected)))
|
||||
|
||||
open-groups-ref (mf/with-memo [open-status-ref]
|
||||
(-> (l/in [:groups :typographies])
|
||||
(l/derived open-status-ref)))
|
||||
|
||||
open-groups (mf/deref open-groups-ref)
|
||||
|
||||
add-typography
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn [_]
|
||||
(st/emit! (dwt/add-typography file-id))))
|
||||
|
||||
handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn [typography changes]
|
||||
(st/emit! (dwl/update-typography (merge typography changes) file-id))))
|
||||
|
||||
apply-typography
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn [typography _event]
|
||||
(st/emit! (dwt/apply-typography typography file-id))))
|
||||
|
||||
create-group
|
||||
(mf/use-fn
|
||||
(mf/deps typographies selected on-clear-selection file-id (:id @state))
|
||||
(fn [group-name]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> typographies
|
||||
(filter #(if multi-typographies?
|
||||
(contains? selected (:id %))
|
||||
(= (:id @state) (:id %))))
|
||||
(map #(dwl/update-typography
|
||||
(assoc % :name
|
||||
(cmm/add-group % group-name))
|
||||
file-id))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
rename-group
|
||||
(mf/use-fn
|
||||
(mf/deps typographies)
|
||||
(fn [path last-path]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> typographies
|
||||
(filter #(str/starts-with? (:path %) path))
|
||||
(map #(dwl/update-typography
|
||||
(assoc % :name
|
||||
(cmm/rename-group % path last-path))
|
||||
file-id))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
on-group
|
||||
(mf/use-fn
|
||||
(mf/deps typographies selected create-group)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(modal/show! :name-group-dialog {:accept create-group})))
|
||||
|
||||
on-rename-group
|
||||
(mf/use-fn
|
||||
(mf/deps typographies)
|
||||
(fn [event path last-path]
|
||||
(dom/stop-propagation event)
|
||||
(modal/show! :name-group-dialog {:path path
|
||||
:last-path last-path
|
||||
:accept rename-group})))
|
||||
on-ungroup
|
||||
(mf/use-fn
|
||||
(mf/deps typographies)
|
||||
(fn [path]
|
||||
(on-clear-selection)
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(apply st/emit!
|
||||
(->> typographies
|
||||
(filter #(str/starts-with? (:path %) path))
|
||||
(map #(dwl/rename-typography
|
||||
file-id
|
||||
(:id %)
|
||||
(cmm/ungroup % path)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps selected on-clear-selection read-only?)
|
||||
(fn [id event]
|
||||
(dom/prevent-default event)
|
||||
(let [pos (dom/get-client-position event)]
|
||||
(when (and local? (not read-only?))
|
||||
(when-not (contains? selected id)
|
||||
(on-clear-selection))
|
||||
(swap! state assoc :id id)
|
||||
(swap! menu-state cmm/open-context-menu pos)))))
|
||||
|
||||
on-close-menu
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(swap! menu-state cmm/close-context-menu)))
|
||||
|
||||
handle-rename-typography-clicked
|
||||
(fn []
|
||||
(st/emit! #(assoc-in % [:workspace-global :rename-typography] (:id @state))))
|
||||
|
||||
handle-edit-typography-clicked
|
||||
(fn []
|
||||
(st/emit! #(assoc-in % [:workspace-global :edit-typography] (:id @state))))
|
||||
|
||||
handle-delete-typography
|
||||
(mf/use-fn
|
||||
(mf/deps @state multi-typographies? multi-assets?)
|
||||
(fn []
|
||||
(let [undo-id (js/Symbol)]
|
||||
(if (or multi-typographies? multi-assets?)
|
||||
(on-assets-delete)
|
||||
(st/emit! (dwu/start-undo-transaction undo-id)
|
||||
(dwl/delete-typography (:id @state))
|
||||
(dwl/sync-file file-id file-id :typographies (:id @state))
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
editing-id (if new-css-system
|
||||
(:edit-typography local-data)
|
||||
(or (:rename-typography local-data)
|
||||
(:edit-typography local-data)))
|
||||
|
||||
renaming-id (:rename-typography local-data)
|
||||
|
||||
on-asset-click
|
||||
(mf/use-fn
|
||||
(mf/deps groups on-asset-click)
|
||||
(partial on-asset-click groups))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps local-data new-css-system)
|
||||
(fn []
|
||||
(when (and (not new-css-system)(:rename-typography local-data))
|
||||
(st/emit! #(update % :workspace-global dissoc :rename-typography)))
|
||||
(when (:edit-typography local-data)
|
||||
(st/emit! #(update % :workspace-global dissoc :edit-typography)))))
|
||||
|
||||
[:& cmm/asset-section {:file-id file-id
|
||||
:title (tr "workspace.assets.typography")
|
||||
:section :typographies
|
||||
:assets-count (count typographies)
|
||||
:open? open?}
|
||||
(if ^boolean new-css-system
|
||||
(when local?
|
||||
[:& cmm/asset-section-block {:role :title-button}
|
||||
(when-not read-only?
|
||||
[:button {:class (dom/classnames (css :assets-btn) true)
|
||||
:on-click add-typography}
|
||||
i/add-refactor])])
|
||||
|
||||
(when local?
|
||||
[:& cmm/asset-section-block {:role :title-button}
|
||||
(when-not read-only?
|
||||
[:div.assets-button {:on-click add-typography}
|
||||
i/plus])]))
|
||||
|
||||
[:& cmm/asset-section-block {:role :content}
|
||||
[:& typographies-group {:file-id file-id
|
||||
:prefix ""
|
||||
:groups groups
|
||||
:open-groups open-groups
|
||||
:state state
|
||||
:file file
|
||||
:local? local?
|
||||
:selected selected
|
||||
:editing-id editing-id
|
||||
:renaming-id renaming-id
|
||||
:local-data local-data
|
||||
:on-asset-click on-asset-click
|
||||
:handle-change handle-change
|
||||
:apply-typography apply-typography
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full}]
|
||||
|
||||
(when local?
|
||||
[:& cmm/assets-context-menu
|
||||
{:on-close on-close-menu
|
||||
:state @menu-state
|
||||
:options (if new-css-system
|
||||
[(when-not (or multi-typographies? multi-assets?)
|
||||
{:option-name (tr "workspace.assets.rename")
|
||||
:id "assets-rename-typography"
|
||||
:option-handler handle-rename-typography-clicked})
|
||||
|
||||
(when-not (or multi-typographies? multi-assets?)
|
||||
{:option-name (tr "workspace.assets.edit")
|
||||
:id "assets-edit-typography"
|
||||
:option-handler handle-edit-typography-clicked})
|
||||
|
||||
{:option-name (tr "workspace.assets.delete")
|
||||
:id "assets-delete-typography"
|
||||
:option-handler handle-delete-typography}
|
||||
|
||||
(when-not multi-assets?
|
||||
{:option-name (tr "workspace.assets.group")
|
||||
:id "assets-group-typography"
|
||||
:option-handler on-group})]
|
||||
|
||||
|
||||
[(when-not (or multi-typographies? multi-assets?)
|
||||
[(tr "workspace.assets.rename") handle-rename-typography-clicked])
|
||||
(when-not (or multi-typographies? multi-assets?)
|
||||
[(tr "workspace.assets.edit") handle-edit-typography-clicked])
|
||||
[(tr "workspace.assets.delete") handle-delete-typography]
|
||||
(when-not multi-assets?
|
||||
[(tr "workspace.assets.group") on-group])])}])]]))
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"assets_typographies_button-primary_njVYq","button-secondary":"assets_typographies_button-secondary_Wzmmw","button-tertiary":"assets_typographies_button-tertiary_k3V5a","assets-btn":"assets_typographies_assets-btn_wCF-m","button-tag":"assets_typographies_button-tag_grTbB","button-icon":"assets_typographies_button-icon_7peoi","button-icon-small":"assets_typographies_button-icon-small_oHD9w","asset-element":"assets_typographies_asset-element_hvNzY","typographies-group":"assets_typographies_typographies-group_iCR4V","assets-list":"assets_typographies_assets-list_wS3At","drop-space":"assets_typographies_drop-space_kGrjB","grid-placeholder":"assets_typographies_grid-placeholder_FvcCI","typography-item":"assets_typographies_typography-item_qkADe","dragging":"assets_typographies_dragging_Ns4o7"}
|
|
@ -0,0 +1,51 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.assets-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: calc($s-24 + $s-4);
|
||||
padding: 0;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
.typographies-group {
|
||||
.assets-list {
|
||||
padding: 0 0 0 $s-12;
|
||||
.drop-space {
|
||||
height: $s-12;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--assets-item-background-color);
|
||||
}
|
||||
.grid-placeholder {
|
||||
height: $s-2;
|
||||
width: 100%;
|
||||
background-color: var(--color-accent-primary);
|
||||
}
|
||||
.typography-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: $s-4;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--assets-item-background-color);
|
||||
}
|
||||
.dragging {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: $s-2 solid var(--assets-item-border-color-drag);
|
||||
border-radius: $s-8;
|
||||
background-color: var(--assets-item-background-color-drag);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,9 +18,9 @@
|
|||
(mf/defc collapsed-button
|
||||
{::mf/wrap-props false}
|
||||
[]
|
||||
(let [new-css? (mf/use-ctx ctx/new-css-system)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
on-click (mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))]
|
||||
(if ^boolean new-css?
|
||||
(if ^boolean new-css-system
|
||||
[:div {:class (dom/classnames (css :collapsed-sidebar) true)}
|
||||
[:div {:class (dom/classnames (css :collapsed-title) true)}
|
||||
[:button {:class (dom/classnames (css :collapsed-button) true)
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"sidebar_collapsable_button_button-primary_qaRce","button-secondary":"sidebar_collapsable_button_button-secondary_OqDpe","button-icon":"sidebar_collapsable_button_button-icon_P4-xy","button-icon-small":"sidebar_collapsable_button_button-icon-small_lQUE3","collapsed-sidebar":"sidebar_collapsable_button_collapsed-sidebar_uQnGJ","collapsed-title":"sidebar_collapsable_button_collapsed-title_Jb62g","collapsed-button":"sidebar_collapsable_button_collapsed-button_LT5ME"}
|
||||
{"button-primary":"sidebar_collapsable_button_button-primary_qaRce","button-secondary":"sidebar_collapsable_button_button-secondary_OqDpe","button-tertiary":"sidebar_collapsable_button_button-tertiary_NuJrA","button-tag":"sidebar_collapsable_button_button-tag_unQKq","button-icon":"sidebar_collapsable_button_button-icon_P4-xy","button-icon-small":"sidebar_collapsable_button_button-icon-small_lQUE3","asset-element":"sidebar_collapsable_button_asset-element_BboJ7","collapsed-sidebar":"sidebar_collapsable_button_collapsed-sidebar_uQnGJ","collapsed-title":"sidebar_collapsable_button_collapsed-title_Jb62g","collapsed-button":"sidebar_collapsable_button_collapsed-button_LT5ME"}
|
|
@ -1 +1 @@
|
|||
{"button-primary":"sidebar_layer_item_button-primary_74ST4","button-secondary":"sidebar_layer_item_button-secondary_e4u9V","button-icon":"sidebar_layer_item_button-icon_-D7KH","button-icon-small":"sidebar_layer_item_button-icon-small_1RfDl","layer-row":"sidebar_layer_item_layer-row_KibLX","element-list-body":"sidebar_layer_item_element-list-body_832JO","element-actions":"sidebar_layer_item_element-actions_ACGJI","toggle-element":"sidebar_layer_item_toggle-element_4bhRW","block-element":"sidebar_layer_item_block-element_RhKz-","button-content":"sidebar_layer_item_button-content_bPwop","icon-shape":"sidebar_layer_item_icon-shape_g9Wxn","toggle-content":"sidebar_layer_item_toggle-content_MKhsv","filtered":"sidebar_layer_item_filtered_V5CHf","inverse":"sidebar_layer_item_inverse_zzZ54","absolute":"sidebar_layer_item_absolute_mYIKg","selected":"sidebar_layer_item_selected_O7P-j","element-children":"sidebar_layer_item_element-children_3iA4Q","parent-selected":"sidebar_layer_item_parent-selected_uIIyQ","hidden":"sidebar_layer_item_hidden_JRbJO","type-comp":"sidebar_layer_item_type-comp_FBSRt","tab-indentation":"sidebar_layer_item_tab-indentation_e-2dQ"}
|
||||
{"button-primary":"sidebar_layer_item_button-primary_74ST4","button-secondary":"sidebar_layer_item_button-secondary_e4u9V","button-tertiary":"sidebar_layer_item_button-tertiary_Mo--6","button-tag":"sidebar_layer_item_button-tag_lFKoD","button-icon":"sidebar_layer_item_button-icon_-D7KH","button-icon-small":"sidebar_layer_item_button-icon-small_1RfDl","layer-row":"sidebar_layer_item_layer-row_KibLX","element-list-body":"sidebar_layer_item_element-list-body_832JO","element-actions":"sidebar_layer_item_element-actions_ACGJI","toggle-element":"sidebar_layer_item_toggle-element_4bhRW","block-element":"sidebar_layer_item_block-element_RhKz-","button-content":"sidebar_layer_item_button-content_bPwop","icon-shape":"sidebar_layer_item_icon-shape_g9Wxn","toggle-content":"sidebar_layer_item_toggle-content_MKhsv","asset-element":"sidebar_layer_item_asset-element_AXTD0","filtered":"sidebar_layer_item_filtered_V5CHf","inverse":"sidebar_layer_item_inverse_zzZ54","absolute":"sidebar_layer_item_absolute_mYIKg","selected":"sidebar_layer_item_selected_O7P-j","element-children":"sidebar_layer_item_element-children_3iA4Q","parent-selected":"sidebar_layer_item_parent-selected_uIIyQ","hidden":"sidebar_layer_item_hidden_JRbJO","type-comp":"sidebar_layer_item_type-comp_FBSRt","tab-indentation":"sidebar_layer_item_tab-indentation_e-2dQ"}
|
|
@ -1 +1 @@
|
|||
{"button-primary":"sidebar_layer_name_button-primary_V-6Cp","button-secondary":"sidebar_layer_name_button-secondary_Q14Qj","button-icon":"sidebar_layer_name_button-icon_UQXjw","button-icon-small":"sidebar_layer_name_button-icon-small_At5P8","element-name":"sidebar_layer_name_element-name_hZ-lA","selected":"sidebar_layer_name_selected_MKxdm","type-comp":"sidebar_layer_name_type-comp_TNGM-","hidden":"sidebar_layer_name_hidden_e-K3G","element-name-input":"sidebar_layer_name_element-name-input_Wpnkf"}
|
||||
{"button-primary":"sidebar_layer_name_button-primary_V-6Cp","button-secondary":"sidebar_layer_name_button-secondary_Q14Qj","button-tertiary":"sidebar_layer_name_button-tertiary_dA-v0","button-tag":"sidebar_layer_name_button-tag_fr2K0","button-icon":"sidebar_layer_name_button-icon_UQXjw","button-icon-small":"sidebar_layer_name_button-icon-small_At5P8","asset-element":"sidebar_layer_name_asset-element_WVekz","element-name":"sidebar_layer_name_element-name_hZ-lA","selected":"sidebar_layer_name_selected_MKxdm","type-comp":"sidebar_layer_name_type-comp_TNGM-","hidden":"sidebar_layer_name_hidden_e-K3G","element-name-input":"sidebar_layer_name_element-name-input_Wpnkf"}
|
|
@ -28,6 +28,7 @@
|
|||
.element-name-input {
|
||||
@include textEllipsis;
|
||||
@include titleTipography;
|
||||
@include removeInputStyle;
|
||||
flex-grow: 1;
|
||||
height: $s-28;
|
||||
max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
|
||||
|
@ -35,7 +36,5 @@
|
|||
padding-left: $s-6;
|
||||
border-radius: $br-8;
|
||||
border: 1px solid var(--input-border-color-focus);
|
||||
outline: none;
|
||||
background-color: transparent;
|
||||
color: var(--layer-row-foreground-color);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
[app.main.data.workspace :as dw]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.search-bar :refer [search-bar]]
|
||||
[app.main.ui.components.shape-icon-refactor :as sic]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.icons :as i]
|
||||
|
@ -128,9 +130,14 @@
|
|||
(swap! filter-state assoc :search-text "" :num-items 100)))
|
||||
|
||||
update-search-text
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps new-css-system)
|
||||
(fn [event]
|
||||
(let [value (-> event dom/get-target dom/get-value)]
|
||||
;; NOTE: When old-css-system is removed this function will recibe value and event
|
||||
;; Let won't be necessary any more
|
||||
(let [value (if new-css-system
|
||||
event
|
||||
(dom/get-target-val event))]
|
||||
(swap! filter-state assoc :search-text value :num-items 100))))
|
||||
|
||||
toggle-search
|
||||
|
@ -226,12 +233,9 @@
|
|||
(fn [event]
|
||||
(let [enter? (kbd/enter? event)
|
||||
esc? (kbd/esc? event)
|
||||
input-node (dom/event->target event)]
|
||||
|
||||
(when enter?
|
||||
(dom/blur! input-node))
|
||||
(when esc?
|
||||
(dom/blur! input-node)))))]
|
||||
node (dom/event->target event)]
|
||||
(when ^boolean enter? (dom/blur! node))
|
||||
(when ^boolean esc? (dom/blur! node)))))]
|
||||
|
||||
[filtered-objects
|
||||
handle-show-more
|
||||
|
@ -243,33 +247,33 @@
|
|||
(css :search) true)
|
||||
(dom/classnames :tool-window-bar true
|
||||
:search true))}
|
||||
[:span {:class (if new-css-system
|
||||
(dom/classnames (css :search-box) true)
|
||||
(dom/classnames :search-box true))}
|
||||
[:button
|
||||
{:on-click toggle-filters
|
||||
:class (if new-css-system
|
||||
(dom/classnames :active active?
|
||||
(css :filter-button) true)
|
||||
(dom/classnames :active active?
|
||||
:filter true))}
|
||||
(if new-css-system
|
||||
i/filter-refactor
|
||||
i/icon-filter)]
|
||||
[:div {:class (dom/classnames (css :search-input-wrapper) new-css-system)}
|
||||
[:input {:on-change update-search-text
|
||||
:value (:search-text @filter-state)
|
||||
:auto-focus (:show-search-box @filter-state)
|
||||
:placeholder (tr "workspace.sidebar.layers.search")
|
||||
:on-key-down handle-key-down}]
|
||||
(when (not (= "" (:search-text @filter-state)))
|
||||
[:button {:class (if new-css-system
|
||||
(dom/classnames (css :clear) true)
|
||||
(dom/classnames :clear true))
|
||||
:on-click clear-search-text}
|
||||
(if new-css-system
|
||||
i/delete-text-refactor
|
||||
i/exclude)])]]
|
||||
(if new-css-system
|
||||
[:& search-bar
|
||||
{:on-change update-search-text
|
||||
:value (:search-text @filter-state)
|
||||
:on-clear clear-search-text
|
||||
:placeholder (tr "workspace.sidebar.layers.search")}
|
||||
[:button
|
||||
{:on-click toggle-filters
|
||||
:class (dom/classnames :active active?
|
||||
(css :filter-button) true)}
|
||||
i/filter-refactor]]
|
||||
|
||||
[:span.search-box
|
||||
[:button.filter
|
||||
{:on-click toggle-filters
|
||||
:class (dom/classnames :active active?)}
|
||||
i/icon-filter]
|
||||
[:div
|
||||
[:input {:on-change update-search-text
|
||||
:value (:search-text @filter-state)
|
||||
:auto-focus (:show-search-box @filter-state)
|
||||
:placeholder (tr "workspace.sidebar.layers.search")
|
||||
:on-key-down handle-key-down}]
|
||||
(when (not (= "" (:search-text @filter-state)))
|
||||
[:button.clear {:on-click clear-search-text}
|
||||
i/exclude])]])
|
||||
|
||||
[:button {:class (dom/classnames (css :close-search) new-css-system)
|
||||
:on-click toggle-search}
|
||||
(if new-css-system
|
||||
|
@ -397,20 +401,18 @@
|
|||
[:span {:on-click (add-filter :text)} i/text (tr "workspace.sidebar.layers.texts")]
|
||||
[:span {:on-click (add-filter :image)} i/image (tr "workspace.sidebar.layers.images")]
|
||||
[:span {:on-click (add-filter :shape)} i/curve (tr "workspace.sidebar.layers.shapes")]]))]
|
||||
[:div {:class (if new-css-system
|
||||
(dom/classnames (css :tool-window-bar) true)
|
||||
(dom/classnames :tool-window-bar true))}
|
||||
[:span {:class (if new-css-system
|
||||
(dom/classnames (css :page-name) true)
|
||||
(dom/classnames :page-name true))}
|
||||
(:name page)]
|
||||
[:button {:class (if new-css-system
|
||||
(dom/classnames (css :icon-search) true)
|
||||
(dom/classnames :icon-search true))
|
||||
:on-click toggle-search}
|
||||
(if new-css-system
|
||||
i/search-refactor
|
||||
i/search)]]))]))
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (dom/classnames (css :tool-window-bar) true)}
|
||||
[:& title-bar {:collapsable? false
|
||||
:title (:name page)
|
||||
:on-btn-click toggle-search
|
||||
:btn-children i/search-refactor}]]
|
||||
[:div.tool-window-bar
|
||||
[:span.page-name
|
||||
(:name page)]
|
||||
[:button.icon-search {:on-click toggle-search}
|
||||
i/search]])))]))
|
||||
|
||||
(mf/defc layers-toolbox
|
||||
{:wrap [mf/memo]}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"sidebar_layers_button-primary_q9e2I","layers":"sidebar_layers_layers_87ZOo","tool-window-bar":"sidebar_layers_tool-window-bar_lg54C","search":"sidebar_layers_search_zjs2x","close-search":"sidebar_layers_close-search_baIhK","icon-search":"sidebar_layers_icon-search_6kWUn","button-secondary":"sidebar_layers_button-secondary_H4lpi","active-filters":"sidebar_layers_active-filters_-JMMP","layer-filter":"sidebar_layers_layer-filter_rHZTz","search-box":"sidebar_layers_search-box_JtqOV","search-input-wrapper":"sidebar_layers_search-input-wrapper_oJa-7","clear":"sidebar_layers_clear_sLcl1","button-icon":"sidebar_layers_button-icon_SD8PP","button-icon-small":"sidebar_layers_button-icon-small_v5L-u","filters-container":"sidebar_layers_filters-container_c1Ux9","filter-menu-item":"sidebar_layers_filter-menu-item_aZd0D","filter-menu-item-tick":"sidebar_layers_filter-menu-item-tick_JNdIK","filter-menu-item-name-wrapper":"sidebar_layers_filter-menu-item-name-wrapper_DtGkH","filter-menu-item-icon":"sidebar_layers_filter-menu-item-icon_Oi3Ix","layer-filter-icon":"sidebar_layers_layer-filter-icon_0yKrb","layer-filter-close":"sidebar_layers_layer-filter-close_3mV4i","focus-title":"sidebar_layers_focus-title_35PvQ","back-button-icon":"sidebar_layers_back-button-icon_mHv6g","page-name":"sidebar_layers_page-name_8ZDRR","filter-button":"sidebar_layers_filter-button_KXxHh","focus-name":"sidebar_layers_focus-name_Fderf","focus-mode-tag-wrapper":"sidebar_layers_focus-mode-tag-wrapper_OHXCG","focus-mode-tag":"sidebar_layers_focus-mode-tag_J5ItD","layer-filter-name":"sidebar_layers_layer-filter-name_Y4PuB","filter-menu-item-name":"sidebar_layers_filter-menu-item-name_rxeut","selected":"sidebar_layers_selected_V5Vv3","tool-window-content":"sidebar_layers_tool-window-content_YnpDB","element-list":"sidebar_layers_element-list_nAntB"}
|
||||
{"button-primary":"sidebar_layers_button-primary_q9e2I","button-secondary":"sidebar_layers_button-secondary_H4lpi","button-tertiary":"sidebar_layers_button-tertiary_5mq-9","layers":"sidebar_layers_layers_87ZOo","tool-window-bar":"sidebar_layers_tool-window-bar_lg54C","search":"sidebar_layers_search_zjs2x","close-search":"sidebar_layers_close-search_baIhK","icon-search":"sidebar_layers_icon-search_6kWUn","button-tag":"sidebar_layers_button-tag_FT7oa","active-filters":"sidebar_layers_active-filters_-JMMP","layer-filter":"sidebar_layers_layer-filter_rHZTz","button-icon":"sidebar_layers_button-icon_SD8PP","button-icon-small":"sidebar_layers_button-icon-small_v5L-u","filters-container":"sidebar_layers_filters-container_c1Ux9","filter-menu-item":"sidebar_layers_filter-menu-item_aZd0D","filter-menu-item-tick":"sidebar_layers_filter-menu-item-tick_JNdIK","filter-menu-item-name-wrapper":"sidebar_layers_filter-menu-item-name-wrapper_DtGkH","filter-menu-item-icon":"sidebar_layers_filter-menu-item-icon_Oi3Ix","layer-filter-icon":"sidebar_layers_layer-filter-icon_0yKrb","layer-filter-close":"sidebar_layers_layer-filter-close_3mV4i","focus-title":"sidebar_layers_focus-title_35PvQ","back-button-icon":"sidebar_layers_back-button-icon_mHv6g","asset-element":"sidebar_layers_asset-element_-dbA7","page-name":"sidebar_layers_page-name_8ZDRR","filter-button":"sidebar_layers_filter-button_KXxHh","focus-name":"sidebar_layers_focus-name_Fderf","focus-mode-tag-wrapper":"sidebar_layers_focus-mode-tag-wrapper_OHXCG","focus-mode-tag":"sidebar_layers_focus-mode-tag_J5ItD","layer-filter-name":"sidebar_layers_layer-filter-name_Y4PuB","filter-menu-item-name":"sidebar_layers_filter-menu-item-name_rxeut","selected":"sidebar_layers_selected_V5Vv3","tool-window-content":"sidebar_layers_tool-window-content_YnpDB","element-list":"sidebar_layers_element-list_nAntB"}
|
|
@ -20,13 +20,14 @@
|
|||
min-height: $s-32;
|
||||
margin-top: $s-2;
|
||||
margin-bottom: $s-4;
|
||||
padding-right: $s-8;
|
||||
.page-name {
|
||||
@include tabTitleTipography;
|
||||
padding: 0 $s-12;
|
||||
color: var(--title-foreground-color);
|
||||
}
|
||||
.icon-search {
|
||||
@extend .button-primary;
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: calc($s-24 + $s-4);
|
||||
border-radius: $br-8;
|
||||
|
@ -38,94 +39,41 @@
|
|||
}
|
||||
&.search {
|
||||
padding: 0 $s-8 0 $s-12;
|
||||
.search-box {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: $s-2;
|
||||
gap: $s-4;
|
||||
.filter-button {
|
||||
@include flexCenter;
|
||||
@include buttonStyle;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin-right: $s-4;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--color-background-primary);
|
||||
.filter-button {
|
||||
@include flexCenter;
|
||||
@include buttonStyle;
|
||||
height: $s-32;
|
||||
width: $s-32;
|
||||
margin: 0;
|
||||
border: 1px solid var(--color-background-tertiary);
|
||||
border-radius: $br-8 $br-2 $br-2 $br-8;
|
||||
background-color: var(--color-background-tertiary);
|
||||
width: $s-32;
|
||||
margin: 0;
|
||||
border: 1px solid var(--color-background-tertiary);
|
||||
border-radius: $br-8 $br-2 $br-2 $br-8;
|
||||
background-color: var(--color-background-tertiary);
|
||||
svg {
|
||||
height: $s-16;
|
||||
width: $s-16;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
&:focus {
|
||||
border: 1px solid var(--input-border-color-focus);
|
||||
outline: 0;
|
||||
background-color: var(--input-background-color-active);
|
||||
color: var(--input-foreground-color-active);
|
||||
svg {
|
||||
height: $s-16;
|
||||
width: $s-16;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
&:focus {
|
||||
border: 1px solid var(--input-border-color-focus);
|
||||
outline: 0;
|
||||
background-color: var(--input-background-color-active);
|
||||
color: var(--input-foreground-color-active);
|
||||
svg {
|
||||
background-color: var(--input-background-color-active);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
border: 1px solid var(--input-background-color-hover);
|
||||
background-color: var(--input-background-color-hover);
|
||||
svg {
|
||||
background-color: var(--input-background-color-hover);
|
||||
stroke: var(--button-foreground-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.search-input-wrapper {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
border: 1px solid var(--color-background-tertiary);
|
||||
border-radius: $br-2 $br-8 $br-8 $br-2;
|
||||
background-color: var(--color-background-tertiary);
|
||||
input {
|
||||
width: 100%;
|
||||
margin: $s-8;
|
||||
border: 0;
|
||||
background-color: var(--input-background-color);
|
||||
font-size: $fs-12;
|
||||
color: var(--input-foreground-color);
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
border: 1px solid var(--input-background-color-hover);
|
||||
&:hover {
|
||||
border: 1px solid var(--input-background-color-hover);
|
||||
background-color: var(--input-background-color-hover);
|
||||
svg {
|
||||
background-color: var(--input-background-color-hover);
|
||||
input {
|
||||
background-color: var(--input-background-color-hover);
|
||||
}
|
||||
}
|
||||
&:focus-within {
|
||||
background-color: var(--input-background-color-active);
|
||||
color: var(--input-foreground-color-active);
|
||||
border: 1px solid var(--input-border-color-focus);
|
||||
input {
|
||||
background-color: var(--input-background-color-active);
|
||||
}
|
||||
}
|
||||
|
||||
.clear {
|
||||
@extend .button-secondary;
|
||||
border-radius: $br-8;
|
||||
height: 100%;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
color: transparent;
|
||||
}
|
||||
stroke: var(--button-foreground-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.close-search {
|
||||
@extend .button-primary;
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
min-width: $s-28;
|
||||
|
@ -184,7 +132,7 @@
|
|||
gap: $s-4;
|
||||
margin: 0 $s-12;
|
||||
.layer-filter {
|
||||
@extend .button-secondary;
|
||||
@extend .button-tag;
|
||||
@include buttonStyle;
|
||||
gap: $s-6;
|
||||
height: $s-24;
|
||||
|
@ -296,7 +244,6 @@
|
|||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: $br-8;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scrollbar-gutter: stable;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.typography
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
["react-virtualized" :as rvt]
|
||||
[app.common.data :as d]
|
||||
|
@ -19,6 +20,9 @@
|
|||
[app.main.store :as st]
|
||||
[app.main.ui.components.editable-select :refer [editable-select]]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||
[app.main.ui.components.radio-buttons :refer [nilable-option radio-buttons]]
|
||||
[app.main.ui.components.search-bar :refer [search-bar]]
|
||||
[app.main.ui.components.select :refer [select]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
|
||||
|
@ -57,7 +61,8 @@
|
|||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [font current? on-click style]}]
|
||||
(let [item-ref (mf/use-ref)
|
||||
on-click (mf/use-callback (mf/deps font) #(on-click font))]
|
||||
on-click (mf/use-callback (mf/deps font) #(on-click font))
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps current?)
|
||||
|
@ -67,12 +72,23 @@
|
|||
(when-not (dom/is-in-viewport? element)
|
||||
(dom/scroll-into-view! element))))))
|
||||
|
||||
[:div.font-item {:ref item-ref
|
||||
:style style
|
||||
:class (when current? "selected")
|
||||
:on-click on-click}
|
||||
[:span.icon (when current? i/tick)]
|
||||
[:span.label (:name font)]]))
|
||||
(if new-css-system
|
||||
[:div {:class (css :font-wrapper)
|
||||
:style style
|
||||
:ref item-ref
|
||||
:on-click on-click}
|
||||
[:div {:class (dom/classnames
|
||||
(css :font-item) true
|
||||
(css :selected) current?)}
|
||||
[:span {:class (css :label)} (:name font)]
|
||||
[:span {:class (css :icon)} (when current? i/tick-refactor)]]]
|
||||
|
||||
[:div.font-item {:ref item-ref
|
||||
:style style
|
||||
:class (when current? "selected")
|
||||
:on-click on-click}
|
||||
[:span.icon (when current? i/tick)]
|
||||
[:span.label (:name font)]])))
|
||||
|
||||
(declare row-renderer)
|
||||
|
||||
|
@ -87,25 +103,17 @@
|
|||
(comp (filter #(contains? backends (:backend %)))))]
|
||||
(into [] xform fonts)))
|
||||
|
||||
;; (defn- toggle-backend
|
||||
;; [backends id]
|
||||
;; (if (contains? backends id)
|
||||
;; (disj backends id)
|
||||
;; (conj backends id)))
|
||||
|
||||
(mf/defc font-selector
|
||||
[{:keys [on-select on-close current-font show-recent] :as props}]
|
||||
(let [selected (mf/use-state current-font)
|
||||
state (mf/use-state {:term "" :backends #{}})
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
selected (mf/use-state current-font)
|
||||
state (mf/use-state {:term "" :backends #{}})
|
||||
|
||||
flist (mf/use-ref)
|
||||
input (mf/use-ref)
|
||||
flist (mf/use-ref)
|
||||
input (mf/use-ref)
|
||||
|
||||
fonts (mf/use-memo (mf/deps @state) #(filter-fonts @state @fonts/fonts))
|
||||
fontsdb (mf/deref fonts/fontsdb)
|
||||
;; Filtering deleted fonts
|
||||
recent-fonts (->> (mf/deref refs/workspace-recent-fonts)
|
||||
(into [] (filter #(some? (get fontsdb (:id %))))))
|
||||
fonts (mf/use-memo (mf/deps @state) #(filter-fonts @state @fonts/fonts))
|
||||
recent-fonts (mf/deref refs/workspace-recent-fonts)
|
||||
|
||||
select-next
|
||||
(mf/use-callback
|
||||
|
@ -136,9 +144,11 @@
|
|||
|
||||
on-filter-change
|
||||
(mf/use-callback
|
||||
(mf/deps)
|
||||
(mf/deps new-css-system)
|
||||
(fn [event]
|
||||
(let [value (dom/get-target-val event)]
|
||||
(let [value (if new-css-system
|
||||
event
|
||||
(dom/get-target-val event))]
|
||||
(swap! state assoc :term value))))
|
||||
|
||||
on-select-and-close
|
||||
|
@ -184,60 +194,71 @@
|
|||
#(let [offset (.getOffsetForRow ^js inst #js {:alignment "center" :index index})]
|
||||
(.scrollToPosition ^js inst offset))))))
|
||||
|
||||
[:div.font-selector
|
||||
[:div.font-selector-dropdown
|
||||
[:header
|
||||
[:input {:placeholder (tr "workspace.options.search-font")
|
||||
:value (:term @state)
|
||||
:ref input
|
||||
:spell-check false
|
||||
:on-change on-filter-change}]
|
||||
(when (and recent-fonts show-recent)
|
||||
[:hr]
|
||||
[*
|
||||
[:p.title (tr "workspace.options.recent-fonts")]
|
||||
(for [[idx font] (d/enumerate recent-fonts)]
|
||||
[:& font-item {:key (dm/str "font-" idx)
|
||||
:font font
|
||||
:style {}
|
||||
:on-click on-select-and-close
|
||||
:current? (= (:id font) (:id @selected))}])])
|
||||
(if new-css-system
|
||||
[:div {:class (css :font-selector)}
|
||||
[:div {:class (css :font-selector-dropdown)}
|
||||
[:div {:class (css :header)}
|
||||
[:& search-bar {:on-change on-filter-change
|
||||
:value (:term @state)
|
||||
:placeholder (tr "workspace.options.search-font")}]
|
||||
(when (and recent-fonts show-recent)
|
||||
[*
|
||||
[:p {:class :title} (tr "workspace.options.recent-fonts")]
|
||||
(for [[idx font] (d/enumerate recent-fonts)]
|
||||
[:& font-item {:key (dm/str "font-" idx)
|
||||
:font font
|
||||
:style {}
|
||||
:on-click on-select-and-close
|
||||
:current? (= (:id font) (:id @selected))}])])]
|
||||
|
||||
#_[:div.options
|
||||
{:on-click #(swap! state assoc :show-options true)
|
||||
:class (when (seq (:backends @state)) "active")}
|
||||
i/picker-hsv]
|
||||
[:div {:class (css :fonts-list)}
|
||||
[:> rvt/AutoSizer {}
|
||||
(fn [props]
|
||||
(let [width (unchecked-get props "width")
|
||||
height (unchecked-get props "height")
|
||||
render #(row-renderer fonts @selected on-select-and-close %)]
|
||||
(mf/html
|
||||
[:> rvt/List #js {:height height
|
||||
:ref flist
|
||||
:width width
|
||||
:rowCount (count fonts)
|
||||
:rowHeight 36
|
||||
:rowRenderer render}])))]]]]
|
||||
|
||||
#_[:& dropdown {:show (:show-options @state false)
|
||||
:on-close #(swap! state dissoc :show-options)}
|
||||
(let [backends (:backends @state)]
|
||||
[:div.backend-filters.dropdown {:ref ddown}
|
||||
[:div.backend-filter
|
||||
{:class (when (backends :custom) "selected")
|
||||
:on-click #(swap! state update :backends toggle-backend :custom)}
|
||||
[:div.checkbox-icon i/tick]
|
||||
[:div.backend-name (tr "labels.custom-fonts")]]
|
||||
[:div.backend-filter
|
||||
{:class (when (backends :google) "selected")
|
||||
:on-click #(swap! state update :backends toggle-backend :google)}
|
||||
[:div.checkbox-icon i/tick]
|
||||
[:div.backend-name "Google Fonts"]]])]]
|
||||
[:div.font-selector
|
||||
[:div.font-selector-dropdown
|
||||
[:header
|
||||
[:input {:placeholder (tr "workspace.options.search-font")
|
||||
:value (:term @state)
|
||||
:ref input
|
||||
:spell-check false
|
||||
:on-change on-filter-change}]
|
||||
(when (and recent-fonts show-recent)
|
||||
[:hr]
|
||||
[*
|
||||
[:p.title (tr "workspace.options.recent-fonts")]
|
||||
(for [[idx font] (d/enumerate recent-fonts)]
|
||||
[:& font-item {:key (dm/str "font-" idx)
|
||||
:font font
|
||||
:style {}
|
||||
:on-click on-select-and-close
|
||||
:current? (= (:id font) (:id @selected))}])])]
|
||||
|
||||
[:hr]
|
||||
[:hr]
|
||||
|
||||
[:div.fonts-list
|
||||
[:> rvt/AutoSizer {}
|
||||
(fn [props]
|
||||
(let [width (unchecked-get props "width")
|
||||
height (unchecked-get props "height")
|
||||
render #(row-renderer fonts @selected on-select-and-close %)]
|
||||
(mf/html
|
||||
[:> rvt/List #js {:height height
|
||||
:ref flist
|
||||
:width width
|
||||
:rowCount (count fonts)
|
||||
:rowHeight 32
|
||||
:rowRenderer render}])))]]]]))
|
||||
[:div.fonts-list
|
||||
[:> rvt/AutoSizer {}
|
||||
(fn [props]
|
||||
(let [width (unchecked-get props "width")
|
||||
height (unchecked-get props "height")
|
||||
render #(row-renderer fonts @selected on-select-and-close %)]
|
||||
(mf/html
|
||||
[:> rvt/List #js {:height height
|
||||
:ref flist
|
||||
:width width
|
||||
:rowCount (count fonts)
|
||||
:rowHeight 32
|
||||
:rowRenderer render}])))]]]])))
|
||||
(defn row-renderer
|
||||
[fonts selected on-select props]
|
||||
(let [index (unchecked-get props "index")
|
||||
|
@ -259,12 +280,11 @@
|
|||
font-id (or font-id (:font-id txt/default-text-attrs))
|
||||
font-size (or font-size (:font-size txt/default-text-attrs))
|
||||
font-variant-id (or font-variant-id (:font-variant-id txt/default-text-attrs))
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
fonts (mf/deref fonts/fontsdb)
|
||||
font (get fonts font-id)
|
||||
;; Filtering deleted fonts
|
||||
recent-fonts (->> (mf/deref refs/workspace-recent-fonts)
|
||||
(into [] (filter #(some? (get fonts (:id %))))))
|
||||
recent-fonts (mf/deref refs/workspace-recent-fonts)
|
||||
last-font (mf/use-ref nil)
|
||||
|
||||
open-selector? (mf/use-state false)
|
||||
|
@ -319,57 +339,110 @@
|
|||
(when (some? on-blur)
|
||||
(on-blur))
|
||||
(when (mf/ref-val last-font)
|
||||
(st/emit! (fts/add-recent-font (mf/ref-val last-font))))
|
||||
))]
|
||||
(st/emit! (fts/add-recent-font (mf/ref-val last-font))))))]
|
||||
(if new-css-system
|
||||
[:*
|
||||
(when @open-selector?
|
||||
[:& font-selector
|
||||
{:current-font font
|
||||
:on-close on-font-selector-close
|
||||
:on-select on-font-select
|
||||
:show-recent show-recent}])
|
||||
|
||||
[:*
|
||||
(when @open-selector?
|
||||
[:& font-selector
|
||||
{:current-font font
|
||||
:on-close on-font-selector-close
|
||||
:on-select on-font-select
|
||||
:show-recent show-recent}])
|
||||
[:div
|
||||
{:class (css :font-option)
|
||||
:on-click #(reset! open-selector? true)}
|
||||
(cond
|
||||
(= :multiple font-id)
|
||||
"--"
|
||||
|
||||
[:div.row-flex
|
||||
[:div.input-select.font-option
|
||||
{:on-click #(reset! open-selector? true)}
|
||||
(cond
|
||||
(= :multiple font-id)
|
||||
"--"
|
||||
(some? font)
|
||||
[:*
|
||||
[:span {:class (css :name)}
|
||||
(:name font)]
|
||||
[:span {:class (css :icon)}
|
||||
i/arrow-refactor]]
|
||||
|
||||
(some? font)
|
||||
(:name font)
|
||||
:else
|
||||
(tr "dashboard.fonts.deleted-placeholder"))]
|
||||
|
||||
:else
|
||||
(tr "dashboard.fonts.deleted-placeholder"))]]
|
||||
[:div {:class (css :font-modifiers)}
|
||||
[:div {:class (css :font-size-options)}
|
||||
(let [sizes [8 9 10 11 12 14 16 18 24 36 48 72]
|
||||
basic-size-options (map (fn [number]
|
||||
{:value (dm/str number) :key (dm/str "size-" number) :label (dm/str number)}) sizes)
|
||||
size-options (if (= font-size :multiple)
|
||||
(conj {:value :key :mulitple-sizes :multiple :label "--"} basic-size-options)
|
||||
basic-size-options)]
|
||||
|
||||
[:& select
|
||||
{:class (css :font-size-select)
|
||||
:default-value (attr->string font-size)
|
||||
:options size-options
|
||||
:on-change on-font-size-change
|
||||
:on-blur on-blur}])]
|
||||
|
||||
[:div {:class (css :font-variant-options)}
|
||||
(let [basic-variant-options (map (fn [variant]
|
||||
{:value (:id variant) :key (pr-str variant) :label (:name variant)}) (:variants font))
|
||||
variant-options (if (= font-size :multiple)
|
||||
(conj {:value :multiple :key :multiple-variants :label "--"} basic-variant-options)
|
||||
basic-variant-options)]
|
||||
;; TODO Add disabled mode
|
||||
[:& select
|
||||
{:class (css :font-variant-select)
|
||||
:default-value (attr->string font-variant-id)
|
||||
:options variant-options
|
||||
:on-change on-font-variant-change
|
||||
:on-blur on-blur}])]]]
|
||||
|
||||
[:*
|
||||
(when @open-selector?
|
||||
[:& font-selector
|
||||
{:current-font font
|
||||
:on-close on-font-selector-close
|
||||
:on-select on-font-select
|
||||
:show-recent show-recent}])
|
||||
|
||||
[:div.row-flex
|
||||
[:div.input-select.font-option
|
||||
{:on-click #(reset! open-selector? true)}
|
||||
(cond
|
||||
(= :multiple font-id)
|
||||
"--"
|
||||
|
||||
(some? font)
|
||||
(:name font)
|
||||
|
||||
:else
|
||||
(tr "dashboard.fonts.deleted-placeholder"))]]
|
||||
|
||||
|
||||
[:div.row-flex
|
||||
(let [size-options [8 9 10 11 12 14 16 18 24 36 48 72]
|
||||
size-options (if (= font-size :multiple) (into [""] size-options) size-options)]
|
||||
[:& editable-select
|
||||
{:value (attr->string font-size)
|
||||
:class "input-option size-option"
|
||||
:options size-options
|
||||
:type "number"
|
||||
:placeholder "--"
|
||||
:min 3
|
||||
:max 1000
|
||||
:on-change on-font-size-change
|
||||
:on-blur on-blur}])
|
||||
|
||||
[:select.input-select.variant-option
|
||||
{:disabled (= font-id :multiple)
|
||||
:value (attr->string font-variant-id)
|
||||
:on-change on-font-variant-change
|
||||
:on-blur on-blur}
|
||||
(when (or (= font-id :multiple) (= font-variant-id :multiple))
|
||||
[:option {:value ""} "--"])
|
||||
(for [variant (:variants font)]
|
||||
[:option {:value (:id variant)
|
||||
:key (pr-str variant)}
|
||||
(:name variant)])]]]))
|
||||
[:div.row-flex
|
||||
(let [size-options [8 9 10 11 12 14 16 18 24 36 48 72]
|
||||
size-options (if (= font-size :multiple) (into [""] size-options) size-options)]
|
||||
[:& editable-select
|
||||
{:value (attr->string font-size)
|
||||
:class "input-option size-option"
|
||||
:options size-options
|
||||
:type "number"
|
||||
:placeholder "--"
|
||||
:min 3
|
||||
:max 1000
|
||||
:on-change on-font-size-change
|
||||
:on-blur on-blur}])
|
||||
|
||||
[:select.input-select.variant-option
|
||||
{:disabled (= font-id :multiple)
|
||||
:value (attr->string font-variant-id)
|
||||
:on-change on-font-variant-change
|
||||
:on-blur on-blur}
|
||||
(when (or (= font-id :multiple) (= font-variant-id :multiple))
|
||||
[:option {:value ""} "--"])
|
||||
(for [variant (:variants font)]
|
||||
[:option {:value (:id variant)
|
||||
:key (pr-str variant)}
|
||||
(:name variant)])]]])))
|
||||
|
||||
(mf/defc spacing-options
|
||||
{::mf/wrap-props false}
|
||||
|
@ -379,101 +452,243 @@
|
|||
|
||||
line-height (or line-height "1.2")
|
||||
letter-spacing (or letter-spacing "0")
|
||||
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
line-height-nillable (if (= (str line-height) "1.2") false true)
|
||||
|
||||
handle-change
|
||||
(fn [value attr]
|
||||
(on-change {attr (str value)}))]
|
||||
(if new-css-system
|
||||
[:div {:class (css :spacing-options)}
|
||||
[:div {:class (css :line-height)}
|
||||
[:span {:class (css :icon)
|
||||
:alt (tr "workspace.options.text-options.line-height")}
|
||||
i/text-lineheight-refactor]
|
||||
|
||||
[:div.spacing-options
|
||||
[:div.input-icon
|
||||
[:span.icon-before.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.line-height")}
|
||||
i/line-height]
|
||||
[:> numeric-input
|
||||
{:min -200
|
||||
:max 200
|
||||
:step 0.1
|
||||
:default "1.2"
|
||||
:value (attr->string line-height)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:nillable line-height-nillable
|
||||
:on-change #(handle-change % :line-height)
|
||||
:on-blur on-blur}]]
|
||||
[:> numeric-input
|
||||
{:min -200
|
||||
:max 200
|
||||
:step 0.1
|
||||
:default "1.2"
|
||||
:klass (css :line-height-input)
|
||||
:value (attr->string line-height)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:nillable line-height-nillable
|
||||
:on-change #(handle-change % :line-height)
|
||||
:on-blur on-blur}]]
|
||||
|
||||
[:div.input-icon
|
||||
[:span.icon-before.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.letter-spacing")}
|
||||
i/letter-spacing]
|
||||
[:> numeric-input
|
||||
{:min -200
|
||||
:max 200
|
||||
:step 0.1
|
||||
:value (attr->string letter-spacing)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change #(handle-change % :letter-spacing)
|
||||
:on-blur on-blur}]]]))
|
||||
[:div {:class (css :letter-spacing)}
|
||||
[:span
|
||||
{:class (css :icon)
|
||||
:alt (tr "workspace.options.text-options.letter-spacing")}
|
||||
i/text-letterspacing-refactor]
|
||||
[:> numeric-input
|
||||
{:min -200
|
||||
:max 200
|
||||
:step 0.1
|
||||
:klass (css :letter-spacing-input)
|
||||
:value (attr->string letter-spacing)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change #(handle-change % :letter-spacing)
|
||||
:on-blur on-blur}]]]
|
||||
|
||||
[:div.spacing-options
|
||||
[:div.input-icon
|
||||
[:span.icon-before.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.line-height")}
|
||||
i/line-height]
|
||||
[:> numeric-input
|
||||
{:min -200
|
||||
:max 200
|
||||
:step 0.1
|
||||
:default "1.2"
|
||||
:value (attr->string line-height)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:nillable line-height-nillable
|
||||
:on-change #(handle-change % :line-height)
|
||||
:on-blur on-blur}]]
|
||||
|
||||
[:div.input-icon
|
||||
[:span.icon-before.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.letter-spacing")}
|
||||
i/letter-spacing]
|
||||
[:> numeric-input
|
||||
{:min -200
|
||||
:max 200
|
||||
:step 0.1
|
||||
:value (attr->string letter-spacing)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change #(handle-change % :letter-spacing)
|
||||
:on-blur on-blur}]]])))
|
||||
|
||||
(mf/defc text-transform-options
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [values on-change on-blur]}]
|
||||
(let [text-transform (or (:text-transform values) "none")
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
handle-change
|
||||
(fn [_ type]
|
||||
(on-change {:text-transform type})
|
||||
(fn [type]
|
||||
(if (= text-transform type)
|
||||
(on-change {:text-transform "unset"})
|
||||
(on-change {:text-transform type}))
|
||||
(when (some? on-blur) (on-blur)))]
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.none")
|
||||
:class (dom/classnames :current (= "none" text-transform))
|
||||
:on-focus #(dom/prevent-default %)
|
||||
:on-click #(handle-change % "none")}
|
||||
i/minus]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.uppercase")
|
||||
:class (dom/classnames :current (= "uppercase" text-transform))
|
||||
:on-click #(handle-change % "uppercase")}
|
||||
i/uppercase]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.lowercase")
|
||||
:class (dom/classnames :current (= "lowercase" text-transform))
|
||||
:on-click #(handle-change % "lowercase")}
|
||||
i/lowercase]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.titlecase")
|
||||
:class (dom/classnames :current (= "capitalize" text-transform))
|
||||
:on-click #(handle-change % "capitalize")}
|
||||
i/titlecase]]))
|
||||
(if new-css-system
|
||||
[:div {:class (css :text-transform)}
|
||||
[:& radio-buttons {:selected text-transform
|
||||
:on-change handle-change
|
||||
:name "text-transform"}
|
||||
[:& nilable-option {:icon (mf/html i/text-uppercase-refactor)
|
||||
:value "uppercase"
|
||||
:id :uppercase}]
|
||||
[:& nilable-option {:icon (mf/html i/text-lowercase-refactor)
|
||||
:value "lowercase"
|
||||
:id :lowercase}]
|
||||
[:& nilable-option {:icon "Aa"
|
||||
:value "capitalize"
|
||||
:id :capitalize}]]]
|
||||
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.none")
|
||||
:class (dom/classnames :current (= "none" text-transform))
|
||||
:on-focus #(dom/prevent-default %)
|
||||
:on-click #(handle-change "none")}
|
||||
i/minus]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.uppercase")
|
||||
:class (dom/classnames :current (= "uppercase" text-transform))
|
||||
:on-click #(handle-change "uppercase")}
|
||||
i/uppercase]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.lowercase")
|
||||
:class (dom/classnames :current (= "lowercase" text-transform))
|
||||
:on-click #(handle-change "lowercase")}
|
||||
i/lowercase]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.titlecase")
|
||||
:class (dom/classnames :current (= "capitalize" text-transform))
|
||||
:on-click #(handle-change "capitalize")}
|
||||
i/titlecase]])))
|
||||
|
||||
(mf/defc typography-options
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [ids editor values on-change on-blur show-recent]}]
|
||||
(let [opts #js {:editor editor
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
opts #js {:editor editor
|
||||
:ids ids
|
||||
:values values
|
||||
:on-change on-change
|
||||
:on-blur on-blur
|
||||
:show-recent show-recent}]
|
||||
[:div.element-set-content
|
||||
[:> font-options opts]
|
||||
[:div.row-flex
|
||||
[:> spacing-options opts]]
|
||||
[:div.row-flex
|
||||
[:> text-transform-options opts]]]))
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (css :typography-options)}
|
||||
[:> font-options opts]
|
||||
[:div {:class (css :typography-variations)}
|
||||
[:> spacing-options opts]
|
||||
[:> text-transform-options opts]]]
|
||||
|
||||
[:div.element-set-content
|
||||
[:> font-options opts]
|
||||
[:div.row-flex
|
||||
[:> spacing-options opts]]
|
||||
[:div.row-flex
|
||||
[:> text-transform-options opts]]])))
|
||||
|
||||
|
||||
(mf/defc typography-advanced-options
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [visible? typography editable? name-input-ref on-close on-change on-name-blur local? navigate-to-library]}]
|
||||
(let [ref (mf/use-ref nil)]
|
||||
(mf/use-effect
|
||||
(mf/deps visible?)
|
||||
(fn []
|
||||
(when-let [node (mf/ref-val ref)]
|
||||
(when visible?
|
||||
(dom/scroll-into-view-if-needed! node)))))
|
||||
|
||||
(when visible?
|
||||
[:div {:ref ref
|
||||
:class (css :advanced-options-wrapper)}
|
||||
(if ^boolean editable?
|
||||
[:*
|
||||
[:div {:class (css :font-name-wrapper)}
|
||||
[:div
|
||||
{:class (dom/classnames (css :typography-sample-input) true)
|
||||
:style {:font-family (:font-family typography)
|
||||
:font-weight (:font-weight typography)
|
||||
:font-style (:font-style typography)}}
|
||||
(tr "workspace.assets.typography.sample")]
|
||||
|
||||
[:input
|
||||
{:class (css :adv-typography-name)
|
||||
:type "text"
|
||||
:ref name-input-ref
|
||||
:default-value (:name typography)
|
||||
:on-blur on-name-blur}]
|
||||
|
||||
[:div {:class (css :action-btn)
|
||||
:on-click on-close}
|
||||
i/tick-refactor]]
|
||||
|
||||
[:& typography-options {:values typography
|
||||
:on-change on-change
|
||||
:show-recent false}]]
|
||||
|
||||
[:div.element-set-content.typography-read-only-data
|
||||
[:div.row-flex.typography-name
|
||||
[:span {:title (:name typography)} (:name typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.font-id")]
|
||||
[:span (:font-id typography)]]
|
||||
|
||||
[:div.element-set-actions-button.actions-inside
|
||||
{:on-click on-close}
|
||||
i/actions]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.font-variant-id")]
|
||||
[:span (:font-variant-id typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.font-size")]
|
||||
[:span (:font-size typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.line-height")]
|
||||
[:span (:line-height typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.letter-spacing")]
|
||||
[:span (:letter-spacing typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.text-transform")]
|
||||
[:span (:text-transform typography)]]
|
||||
|
||||
(when-not local?
|
||||
[:div.row-flex
|
||||
[:a.go-to-lib-button
|
||||
{:on-click navigate-to-library}
|
||||
(tr "workspace.assets.typography.go-to-edit")]])])])))
|
||||
|
||||
|
||||
(mf/defc typography-entry
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file-id typography local? selected? on-click on-change on-detach on-context-menu editing? focus-name? external-open*]}]
|
||||
[{:keys [file-id typography local? selected? on-click on-change on-detach on-context-menu editing? renaming? focus-name? external-open*]}]
|
||||
(let [hover-detach* (mf/use-state false)
|
||||
hover-detach? (deref hover-detach*)
|
||||
|
||||
name-input-ref (mf/use-ref)
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
editable? (and local? (not read-only?))
|
||||
|
||||
open* (mf/use-state editing?)
|
||||
open? (deref open*)
|
||||
font-data (fonts/get-font-data (:font-id typography))
|
||||
name-only? (= (:name typography) (:name font-data))
|
||||
|
||||
on-name-blur
|
||||
(mf/use-callback
|
||||
|
@ -481,7 +696,8 @@
|
|||
(fn [event]
|
||||
(let [name (dom/get-target-val event)]
|
||||
(when-not (str/blank? name)
|
||||
(on-change {:name name})))))
|
||||
(on-change {:name name})
|
||||
(st/emit! #(update % :workspace-global dissoc :rename-typography))))))
|
||||
|
||||
on-pointer-enter
|
||||
(mf/use-fn #(reset! hover-detach* true))
|
||||
|
@ -500,9 +716,7 @@
|
|||
(mf/deps file-id)
|
||||
(fn []
|
||||
(when file-id
|
||||
(st/emit! (dw/navigate-to-library file-id)))))
|
||||
|
||||
]
|
||||
(st/emit! (dw/navigate-to-library file-id)))))]
|
||||
|
||||
(mf/with-effect [editing?]
|
||||
(when editing?
|
||||
|
@ -518,88 +732,145 @@
|
|||
#(when-let [node (mf/ref-val name-input-ref)]
|
||||
(dom/focus! node)
|
||||
(dom/select-text! node)))))
|
||||
(if new-css-system
|
||||
[:*
|
||||
[:div {:class (dom/classnames (css :typography-entry) true
|
||||
(css :selected) ^boolean selected?)
|
||||
:style {:display (when ^boolean open? "none")}}
|
||||
(if renaming?
|
||||
[:div {:class (css :font-name-wrapper)}
|
||||
[:div
|
||||
{:class (dom/classnames (css :typography-sample-input) true)
|
||||
:style {:font-family (:font-family typography)
|
||||
:font-weight (:font-weight typography)
|
||||
:font-style (:font-style typography)}}
|
||||
(tr "workspace.assets.typography.sample")]
|
||||
|
||||
[:*
|
||||
[:div.element-set-options-group.typography-entry
|
||||
{:class (when ^boolean selected? "selected")
|
||||
:style {:display (when ^boolean open? "none")}}
|
||||
[:div.typography-selection-wrapper
|
||||
{:class (when ^boolean on-click "is-selectable")
|
||||
:on-click on-click
|
||||
:on-context-menu on-context-menu}
|
||||
[:div.typography-sample
|
||||
{:style {:font-family (:font-family typography)
|
||||
:font-weight (:font-weight typography)
|
||||
:font-style (:font-style typography)}}
|
||||
(tr "workspace.assets.typography.sample")]
|
||||
[:div.typography-name {:title (:name typography)}(:name typography)]]
|
||||
[:div.element-set-actions
|
||||
(when ^boolean on-detach
|
||||
[:div.element-set-actions-button
|
||||
{:on-pointer-enter on-pointer-enter
|
||||
:on-pointer-leave on-pointer-leave
|
||||
:on-click on-detach}
|
||||
(if ^boolean hover-detach? i/unchain i/chain)])
|
||||
|
||||
[:div.element-set-actions-button
|
||||
{:on-click on-open}
|
||||
i/actions]]]
|
||||
|
||||
[:& advanced-options {:visible? open? :on-close on-close}
|
||||
(if ^boolean editable?
|
||||
[:*
|
||||
[:div.element-set-content
|
||||
[:div.row-flex
|
||||
[:input.element-name.adv-typography-name
|
||||
{:type "text"
|
||||
[:input
|
||||
{:class (css :adv-typography-name)
|
||||
:type "text"
|
||||
:ref name-input-ref
|
||||
:default-value (:name typography)
|
||||
:on-blur on-name-blur}]
|
||||
:on-blur on-name-blur}]]
|
||||
[:div
|
||||
{:class (dom/classnames (css :typography-selection-wrapper) true
|
||||
(css :is-selectable) ^boolean on-click)
|
||||
:on-click on-click
|
||||
:on-context-menu on-context-menu}
|
||||
[:div
|
||||
{:class (dom/classnames (css :typography-sample) true)
|
||||
:style {:font-family (:font-family typography)
|
||||
:font-weight (:font-weight typography)
|
||||
:font-style (:font-style typography)}}
|
||||
(tr "workspace.assets.typography.sample")]
|
||||
|
||||
[:div {:class (dom/classnames (css :typography-name) true)
|
||||
:title (:name typography)} (:name typography)]
|
||||
|
||||
(when-not name-only?
|
||||
[:div {:class (dom/classnames (css :typography-font) true)
|
||||
:title (:name font-data)}
|
||||
(:name font-data)])])
|
||||
|
||||
(when ^boolean on-detach
|
||||
[:div {:class (dom/classnames (css :element-set-actions) true)}
|
||||
[:div
|
||||
{:class (dom/classnames (css :element-set-actions-button) true)
|
||||
:on-pointer-enter on-pointer-enter
|
||||
:on-pointer-leave on-pointer-leave
|
||||
:on-click on-detach}
|
||||
(if ^boolean hover-detach? i/detach-refactor i/chain)]])]
|
||||
|
||||
[:& typography-advanced-options
|
||||
{:visible? open? :on-close on-close
|
||||
:typography typography
|
||||
:editable? editable?
|
||||
:name-input-ref name-input-ref
|
||||
:on-change on-change
|
||||
:on-name-blur on-name-blur
|
||||
:local? local?
|
||||
:navigate-to-library navigate-to-library}]]
|
||||
|
||||
|
||||
[:*
|
||||
[:div.element-set-options-group.typography-entry
|
||||
{:class (when ^boolean selected? "selected")
|
||||
:style {:display (when ^boolean open? "none")}}
|
||||
[:div.typography-selection-wrapper
|
||||
{:class (when ^boolean on-click "is-selectable")
|
||||
:on-click on-click
|
||||
:on-context-menu on-context-menu}
|
||||
[:div.typography-sample
|
||||
{:style {:font-family (:font-family typography)
|
||||
:font-weight (:font-weight typography)
|
||||
:font-style (:font-style typography)}}
|
||||
(tr "workspace.assets.typography.sample")]
|
||||
[:div.typography-name {:title (:name typography)} (:name typography)]]
|
||||
[:div.element-set-actions
|
||||
(when ^boolean on-detach
|
||||
[:div.element-set-actions-button
|
||||
{:on-click on-close}
|
||||
i/actions]]]
|
||||
{:on-pointer-enter on-pointer-enter
|
||||
:on-pointer-leave on-pointer-leave
|
||||
:on-click on-detach}
|
||||
(if ^boolean hover-detach? i/unchain i/chain)])
|
||||
|
||||
[:& typography-options {:values typography
|
||||
:on-change on-change
|
||||
:show-recent false}]]
|
||||
[:div.element-set-actions-button
|
||||
{:on-click on-open}
|
||||
i/actions]]]
|
||||
|
||||
[:div.element-set-content.typography-read-only-data
|
||||
[:div.row-flex.typography-name
|
||||
[:span {:title (:name typography)} (:name typography)]]
|
||||
[:& advanced-options {:visible? open? :on-close on-close}
|
||||
(if ^boolean editable?
|
||||
[:*
|
||||
[:div.element-set-content
|
||||
[:div.row-flex
|
||||
[:input.element-name.adv-typography-name
|
||||
{:type "text"
|
||||
:ref name-input-ref
|
||||
:default-value (:name typography)
|
||||
:on-blur on-name-blur}]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.font-id")]
|
||||
[:span (:font-id typography)]]
|
||||
[:div.element-set-actions-button
|
||||
{:on-click on-close}
|
||||
i/actions]]]
|
||||
|
||||
[:div.element-set-actions-button.actions-inside
|
||||
{:on-click on-close}
|
||||
i/actions]
|
||||
[:& typography-options {:values typography
|
||||
:on-change on-change
|
||||
:show-recent false}]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.font-variant-id")]
|
||||
[:span (:font-variant-id typography)]]
|
||||
[:div.element-set-content.typography-read-only-data
|
||||
[:div.row-flex.typography-name
|
||||
[:span {:title (:name typography)} (:name typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.font-size")]
|
||||
[:span (:font-size typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.line-height")]
|
||||
[:span (:line-height typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.letter-spacing")]
|
||||
[:span (:letter-spacing typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.text-transform")]
|
||||
[:span (:text-transform typography)]]
|
||||
|
||||
(when-not local?
|
||||
[:div.row-flex
|
||||
[:a.go-to-lib-button
|
||||
{:on-click navigate-to-library}
|
||||
(tr "workspace.assets.typography.go-to-edit")]])]
|
||||
[:span.label (tr "workspace.assets.typography.font-id")]
|
||||
[:span (:font-id typography)]]
|
||||
|
||||
)]]))
|
||||
[:div.element-set-actions-button.actions-inside
|
||||
{:on-click on-close}
|
||||
i/actions]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.font-variant-id")]
|
||||
[:span (:font-variant-id typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.font-size")]
|
||||
[:span (:font-size typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.line-height")]
|
||||
[:span (:line-height typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.letter-spacing")]
|
||||
[:span (:letter-spacing typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label (tr "workspace.assets.typography.text-transform")]
|
||||
[:span (:text-transform typography)]]
|
||||
|
||||
(when-not local?
|
||||
[:div.row-flex
|
||||
[:a.go-to-lib-button
|
||||
{:on-click navigate-to-library}
|
||||
(tr "workspace.assets.typography.go-to-edit")]])])]])))
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"menus_typography_button-primary_s1c9M","button-secondary":"menus_typography_button-secondary_RjAsk","button-tertiary":"menus_typography_button-tertiary_Qt18f","font-name-wrapper":"menus_typography_font-name-wrapper_Njxb6","action-btn":"menus_typography_action-btn_hCakz","button-tag":"menus_typography_button-tag_32-df","button-icon":"menus_typography_button-icon_jucwh","advanced-options-wrapper":"menus_typography_advanced-options-wrapper_k3FD6","typography-options":"menus_typography_typography-options_j1u8l","font-modifiers":"menus_typography_font-modifiers_P8cSa","font-variant-options":"menus_typography_font-variant-options_qlgLr","icon":"menus_typography_icon_eDU2Z","font-size-options":"menus_typography_font-size-options_sKQdL","font-option":"menus_typography_font-option_7mgxF","button-icon-small":"menus_typography_button-icon-small_g3fsU","font-selector":"menus_typography_font-selector_TzuGa","font-selector-dropdown":"menus_typography_font-selector-dropdown_4s6s8","font-wrapper":"menus_typography_font-wrapper_GPkHS","font-item":"menus_typography_font-item_YQffA","typography-variations":"menus_typography_typography-variations_wbNM3","spacing-options":"menus_typography_spacing-options_RUpAK","line-height":"menus_typography_line-height_S7zsF","letter-spacing":"menus_typography_letter-spacing_8R6p2","asset-element":"menus_typography_asset-element_-LlIX","text-transform":"menus_typography_text-transform_U7Y3U","typography-entry":"menus_typography_typography-entry_Y6lvA","typography-selection-wrapper":"menus_typography_typography-selection-wrapper_W6ewx","is-selectable":"menus_typography_is-selectable_O6-D2","typography-sample":"menus_typography_typography-sample_6ruld","typography-name":"menus_typography_typography-name_b14xj","typography-font":"menus_typography_typography-font_hJIgO","selected":"menus_typography_selected_Ka-O9","typography-sample-input":"menus_typography_typography-sample-input_u2i8b","adv-typography-name":"menus_typography_adv-typography-name_PvB1X","name":"menus_typography_name_1SJal","font-size-select":"menus_typography_font-size-select_yexav","font-variant-select":"menus_typography_font-variant-select_-OQsO","line-height-input":"menus_typography_line-height-input_SG7be","letter-spacing-input":"menus_typography_letter-spacing-input_LShRc","header":"menus_typography_header_e-rUh","title":"menus_typography_title_uPejx","fonts-list":"menus_typography_fonts-list_ki8X-","label":"menus_typography_label_S-7jI"}
|
|
@ -0,0 +1,304 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.typography-entry {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
border-radius: $br-8;
|
||||
|
||||
.typography-selection-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: $s-24 auto 1fr;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0 $s-12;
|
||||
|
||||
&.is-selectable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.typography-sample {
|
||||
@include flexCenter;
|
||||
min-width: $s-24;
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
}
|
||||
.typography-name,
|
||||
.typography-font {
|
||||
@include titleTipography;
|
||||
@include textEllipsis;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin-left: $s-6;
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
}
|
||||
.typography-font {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
min-width: 0;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
border: $s-1 solid var(--assets-item-border-color);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--assets-item-background-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.font-name-wrapper {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
border-radius: $br-8;
|
||||
border: $s-1 solid transparent;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--assets-item-background-color);
|
||||
margin-bottom: $s-4;
|
||||
padding: $s-8 $s-0 $s-8 $s-12;
|
||||
|
||||
.typography-sample-input {
|
||||
@include flexCenter;
|
||||
width: $s-24;
|
||||
height: 100%;
|
||||
font-size: $fs-16;
|
||||
}
|
||||
.adv-typography-name {
|
||||
@include removeInputStyle;
|
||||
color: var(--input-foreground-color);
|
||||
flex-grow: 1;
|
||||
margin: 0;
|
||||
}
|
||||
.action-btn {
|
||||
@extend .button-tertiary;
|
||||
@include flexCenter;
|
||||
width: $s-28;
|
||||
height: $s-28;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
}
|
||||
}
|
||||
&:focus-within {
|
||||
border: $s-1 solid var(--input-border-color-active);
|
||||
.adv-typography-name {
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--assets-item-background-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.advanced-options-wrapper {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: var(--title-background-color);
|
||||
|
||||
.typography-options {
|
||||
position: relative;
|
||||
.font-option {
|
||||
@include titleTipography;
|
||||
@extend .asset-element;
|
||||
padding-right: 0;
|
||||
cursor: pointer;
|
||||
.name {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-28;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
.font-modifiers {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.font-size-options {
|
||||
@extend .asset-element;
|
||||
@include titleTipography;
|
||||
padding: 0;
|
||||
flex-grow: 1;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-28;
|
||||
min-width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
.font-size-select {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
.font-variant-options {
|
||||
@extend .asset-element;
|
||||
@include titleTipography;
|
||||
padding: 0;
|
||||
flex-grow: 2;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-28;
|
||||
min-width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
.font-variant-select {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
option {
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
}
|
||||
&:hover {
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
option {
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.typography-variations {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
align-items: center;
|
||||
.spacing-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.line-height,
|
||||
.letter-spacing {
|
||||
@extend .asset-element;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
}
|
||||
}
|
||||
.line-height-input,
|
||||
.letter-spacing-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.text-transform {
|
||||
@extend .asset-element;
|
||||
width: fit-content;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.font-selector {
|
||||
@include flexCenter;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: $z-index-10;
|
||||
|
||||
.font-selector-dropdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
margin-bottom: $s-2;
|
||||
.title {
|
||||
@include tabTitleTipography;
|
||||
margin: 9px 17px;
|
||||
}
|
||||
}
|
||||
.fonts-list {
|
||||
position: absolute;
|
||||
top: $s-36;
|
||||
left: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
min-height: 100%;
|
||||
height: $s-216;
|
||||
width: 100%;
|
||||
padding: $s-2;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--dropdown-background-color);
|
||||
box-shadow: 0px 0px $s-12 0px var(--menu-shadow-color);
|
||||
}
|
||||
.font-wrapper {
|
||||
padding-bottom: $s-4;
|
||||
cursor: pointer;
|
||||
.font-item {
|
||||
@extend .asset-element;
|
||||
border-radius: $br-8;
|
||||
display: flex;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-28;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
.icon {
|
||||
svg {
|
||||
stroke: var(--assets-item-name-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
@include titleTipography;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
[app.main.data.workspace.path.shortcuts]
|
||||
[app.main.data.workspace.shortcuts]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.search-bar :refer [search-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -280,7 +281,7 @@
|
|||
(for [command-translate sorted-filtered]
|
||||
(let [sc-by-translate (first (filter #(= (:translation (second %)) command-translate) elements))
|
||||
[command comand-info] sc-by-translate
|
||||
content (or (:show-command comand-info)(:command comand-info))]
|
||||
content (or (:show-command comand-info) (:command comand-info))]
|
||||
[:li {:class (css :shortcuts-name)
|
||||
:key command-translate}
|
||||
[:span {:class (css :command-name)}
|
||||
|
@ -326,7 +327,7 @@
|
|||
:filter-term filter-term
|
||||
:match-section? match-section?
|
||||
:match-subsection? true}])
|
||||
|
||||
|
||||
[:ul {:class (dom/classnames (css :subsection-menu) new-css-system
|
||||
:subsection-menu (not new-css-system))}
|
||||
(for [sub-translated sorted-translations]
|
||||
|
@ -365,7 +366,7 @@
|
|||
translations (map #(translation-keyname :sc %) (keys subs-bodys))
|
||||
match-shortcut? (some #(matches-search % @filter-term) translations)
|
||||
visible? (some #(= % section-id) @open-sections)]
|
||||
|
||||
|
||||
(when (or match-section? match-subsection? match-shortcut?)
|
||||
[:div {:class (css :section)
|
||||
:on-click (manage-sections section-id)}
|
||||
|
@ -502,6 +503,11 @@
|
|||
(manage-sections-on-search value)
|
||||
(reset! filter-term value))))
|
||||
|
||||
on-search-term-change-2
|
||||
(mf/use-callback
|
||||
(fn [value]
|
||||
(manage-sections-on-search value)
|
||||
(reset! filter-term value)))
|
||||
on-search-clear-click
|
||||
(mf/use-callback
|
||||
(fn [_]
|
||||
|
@ -528,31 +534,17 @@
|
|||
(if new-css-system
|
||||
[:div {:class (css :shortcuts)}
|
||||
[:div {:class (css :shortcuts-header)}
|
||||
[:div {:class (css :shortcuts-title)} "Keyboard Shortcuts"]
|
||||
[:div {:class (css :shortcuts-title)} (tr "shortcuts.title")]
|
||||
[:div {:class (css :shortcuts-close-button)
|
||||
:on-click close-fn}
|
||||
i/close-refactor]]
|
||||
;; TODO Change this for search bar component
|
||||
[:div {:class (css :search-field)}
|
||||
[:div {:class (css :search-box)}
|
||||
[:span {:class (css :icon-wrapper)}
|
||||
i/search-refactor]
|
||||
[:input {:class (dom/classnames (css :input-text) true)
|
||||
:id "shortcut-search"
|
||||
:placeholder (tr "shortcuts.title")
|
||||
:type "text"
|
||||
:value @filter-term
|
||||
:on-change on-search-term-change
|
||||
:auto-complete "off"
|
||||
:on-key-down manage-key-down}]
|
||||
(when (not (str/empty? @filter-term))
|
||||
|
||||
[:button
|
||||
{:class (css :clear-btn)
|
||||
:on-click on-search-clear-click
|
||||
:on-key-down on-key-down}
|
||||
[:span {:class (css :clear-icon)}
|
||||
i/delete-text-refactor]])]]
|
||||
[:& search-bar {:on-change on-search-term-change-2
|
||||
:clear-action on-search-clear-click
|
||||
:value @filter-term
|
||||
:placeholder (tr "shortcuts.title")
|
||||
:icon (mf/html [:span {:class (css :search-icon)} i/search-refactor])}]]
|
||||
|
||||
(if match-any?
|
||||
[:div {:class (dom/classnames (css :shortcuts-list) true)}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"sidebar_shortcuts_button-primary_aIZ1F","shortcuts":"sidebar_shortcuts_shortcuts_cOJNo","shortcuts-header":"sidebar_shortcuts_shortcuts-header_0SZ19","shortcuts-close-button":"sidebar_shortcuts_shortcuts-close-button_gT7kn","button-secondary":"sidebar_shortcuts_button-secondary_dtWEN","button-icon":"sidebar_shortcuts_button-icon_rCHmV","button-icon-small":"sidebar_shortcuts_button-icon-small_9BnNh","shortcuts-list":"sidebar_shortcuts_shortcuts-list_z7osI","section-title":"sidebar_shortcuts_section-title_Dv7S-","collapsed-shortcuts":"sidebar_shortcuts_collapsed-shortcuts_XrOj5","subsection-title":"sidebar_shortcuts_subsection-title_--5j4","search-field":"sidebar_shortcuts_search-field_cDecA","search-box":"sidebar_shortcuts_search-box_vmYAl","clear-btn":"sidebar_shortcuts_clear-btn_vRbGu","clear-icon":"sidebar_shortcuts_clear-icon_ZL4ae","icon-wrapper":"sidebar_shortcuts_icon-wrapper_XaR8m","shortcuts-title":"sidebar_shortcuts_shortcuts-title_P38o9","input-text":"sidebar_shortcuts_input-text_e9n1x","section":"sidebar_shortcuts_section_Jxkqa","open":"sidebar_shortcuts_open_SxghD","subsection-name":"sidebar_shortcuts_subsection-name_rWvFY","section-name":"sidebar_shortcuts_section-name_SyF9-","subsection-menu":"sidebar_shortcuts_subsection-menu_FdH9L","sub-menu":"sidebar_shortcuts_sub-menu_95jTY","shortcuts-name":"sidebar_shortcuts_shortcuts-name_hPkq6","command-name":"sidebar_shortcuts_command-name_Cujed","keys":"sidebar_shortcuts_keys_-pUnF","key":"sidebar_shortcuts_key_QyU8q","space":"sidebar_shortcuts_space_aODdu","not-found":"sidebar_shortcuts_not-found_bKEb0"}
|
||||
{"button-primary":"sidebar_shortcuts_button-primary_aIZ1F","button-secondary":"sidebar_shortcuts_button-secondary_dtWEN","button-tertiary":"sidebar_shortcuts_button-tertiary_3VDIw","shortcuts":"sidebar_shortcuts_shortcuts_cOJNo","shortcuts-header":"sidebar_shortcuts_shortcuts-header_0SZ19","shortcuts-close-button":"sidebar_shortcuts_shortcuts-close-button_gT7kn","button-tag":"sidebar_shortcuts_button-tag_3LImZ","button-icon":"sidebar_shortcuts_button-icon_rCHmV","button-icon-small":"sidebar_shortcuts_button-icon-small_9BnNh","shortcuts-list":"sidebar_shortcuts_shortcuts-list_z7osI","section-title":"sidebar_shortcuts_section-title_Dv7S-","collapsed-shortcuts":"sidebar_shortcuts_collapsed-shortcuts_XrOj5","subsection-title":"sidebar_shortcuts_subsection-title_--5j4","search-field":"sidebar_shortcuts_search-field_cDecA","search-icon":"sidebar_shortcuts_search-icon_NSAwd","search-box":"sidebar_shortcuts_search-box_vmYAl","clear-btn":"sidebar_shortcuts_clear-btn_vRbGu","clear-icon":"sidebar_shortcuts_clear-icon_ZL4ae","icon-wrapper":"sidebar_shortcuts_icon-wrapper_XaR8m","asset-element":"sidebar_shortcuts_asset-element_-zk6N","shortcuts-title":"sidebar_shortcuts_shortcuts-title_P38o9","input-text":"sidebar_shortcuts_input-text_e9n1x","section":"sidebar_shortcuts_section_Jxkqa","open":"sidebar_shortcuts_open_SxghD","subsection-name":"sidebar_shortcuts_subsection-name_rWvFY","section-name":"sidebar_shortcuts_section-name_SyF9-","subsection-menu":"sidebar_shortcuts_subsection-menu_FdH9L","sub-menu":"sidebar_shortcuts_sub-menu_95jTY","shortcuts-name":"sidebar_shortcuts_shortcuts-name_hPkq6","command-name":"sidebar_shortcuts_command-name_Cujed","keys":"sidebar_shortcuts_keys_-pUnF","key":"sidebar_shortcuts_key_QyU8q","space":"sidebar_shortcuts_space_aODdu","not-found":"sidebar_shortcuts_not-found_bKEb0"}
|
|
@ -24,7 +24,7 @@
|
|||
}
|
||||
|
||||
.shortcuts-close-button {
|
||||
@extend .button-primary;
|
||||
@extend .button-tertiary;
|
||||
position: absolute;
|
||||
right: $s-2;
|
||||
top: $s-2;
|
||||
|
@ -45,7 +45,6 @@
|
|||
border-radius: $br-8;
|
||||
font-family: "worksans", sans-serif;
|
||||
background-color: var(--color-background-tertiary);
|
||||
|
||||
.search-box {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
@ -59,6 +58,7 @@
|
|||
}
|
||||
|
||||
.input-text {
|
||||
@include removeInputStyle;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
|
@ -66,7 +66,6 @@
|
|||
border: 0;
|
||||
font-size: $fs-12;
|
||||
color: var(--color-foreground-primary);
|
||||
background-color: transparent;
|
||||
&::placeholder {
|
||||
color: var(--color-foreground-secondary);
|
||||
}
|
||||
|
@ -87,6 +86,13 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.search-icon {
|
||||
@include flexCenter;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.main.data.workspace :as dw]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.hooks.resize :refer [use-resize-hook]]
|
||||
|
@ -239,22 +240,20 @@
|
|||
[:div {:class (dom/classnames (css :sitemap) true)
|
||||
:ref parent-ref
|
||||
:style #js {"--height" (str size "px")}}
|
||||
[:div {:class (dom/classnames (css :pages-tool-bar) true)}
|
||||
|
||||
[:button {:class (dom/classnames (css :page-tool-bar-title) true)
|
||||
:on-click toggle-pages}
|
||||
[:span {:class (dom/classnames (css :collapsable-button) true)
|
||||
:style {:transform (when (not @show-pages?) "rotate(-90deg)")}}
|
||||
i/arrow-refactor]
|
||||
(tr "workspace.sidebar.sitemap")]
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not @show-pages?)
|
||||
:on-collapsed toggle-pages
|
||||
:title (tr "workspace.sidebar.sitemap")
|
||||
:klass :title-spacing-sitemap}
|
||||
|
||||
(if workspace-read-only?
|
||||
[:div
|
||||
{:class (dom/classnames (css :view-only-mode) true)}
|
||||
(tr "labels.view-only")]
|
||||
[:*
|
||||
[:button {:class (dom/classnames (css :add-page) true)
|
||||
:on-click create}
|
||||
i/add-refactor]])]
|
||||
[:button {:class (dom/classnames (css :add-page) true)
|
||||
:on-click create}
|
||||
i/add-refactor])]
|
||||
|
||||
[:div {:class (dom/classnames (css :tool-window-content) true)}
|
||||
[:& pages-list {:file file :key (:id file)}]]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"sidebar_sitemap_button-primary_Z-bKW","sitemap":"sidebar_sitemap_sitemap_kvKKx","pages-tool-bar":"sidebar_sitemap_pages-tool-bar_n1yfA","add-page":"sidebar_sitemap_add-page_r8Ibb","button-secondary":"sidebar_sitemap_button-secondary_a56LZ","button-icon":"sidebar_sitemap_button-icon_MkibT","page-tool-bar-title":"sidebar_sitemap_page-tool-bar-title_D7h-S","collapsable-button":"sidebar_sitemap_collapsable-button_Xt79y","button-icon-small":"sidebar_sitemap_button-icon-small_Mhipv","tool-window-content":"sidebar_sitemap_tool-window-content_G-Nut","pages-list":"sidebar_sitemap_pages-list_cb1Mx","page-element":"sidebar_sitemap_page-element_iR9wf","element-list-body":"sidebar_sitemap_element-list-body_OIVac","page-actions":"sidebar_sitemap_page-actions_QTuKw","page-icon":"sidebar_sitemap_page-icon_ujSjM","view-only-mode":"sidebar_sitemap_view-only-mode_JrsYg","resize-area":"sidebar_sitemap_resize-area_JgdjZ","dnd-over-top":"sidebar_sitemap_dnd-over-top_kGfcb","dnd-over-bot":"sidebar_sitemap_dnd-over-bot_352W2","dnd-over":"sidebar_sitemap_dnd-over_Sf5e2","page-name":"sidebar_sitemap_page-name_601Ii","element-name":"sidebar_sitemap_element-name_iMex0","on-drag":"sidebar_sitemap_on-drag_v3GM8","selected":"sidebar_sitemap_selected_mCOlT","hidden":"sidebar_sitemap_hidden_viFSn"}
|
||||
{"button-primary":"sidebar_sitemap_button-primary_Z-bKW","button-secondary":"sidebar_sitemap_button-secondary_a56LZ","button-tertiary":"sidebar_sitemap_button-tertiary_E2hzd","sitemap":"sidebar_sitemap_sitemap_kvKKx","add-page":"sidebar_sitemap_add-page_r8Ibb","button-tag":"sidebar_sitemap_button-tag_u1NAz","button-icon":"sidebar_sitemap_button-icon_MkibT","button-icon-small":"sidebar_sitemap_button-icon-small_Mhipv","tool-window-content":"sidebar_sitemap_tool-window-content_G-Nut","pages-list":"sidebar_sitemap_pages-list_cb1Mx","page-element":"sidebar_sitemap_page-element_iR9wf","element-list-body":"sidebar_sitemap_element-list-body_OIVac","page-actions":"sidebar_sitemap_page-actions_QTuKw","page-icon":"sidebar_sitemap_page-icon_ujSjM","asset-element":"sidebar_sitemap_asset-element_I1-m4","view-only-mode":"sidebar_sitemap_view-only-mode_JrsYg","resize-area":"sidebar_sitemap_resize-area_JgdjZ","dnd-over-top":"sidebar_sitemap_dnd-over-top_kGfcb","dnd-over-bot":"sidebar_sitemap_dnd-over-bot_352W2","dnd-over":"sidebar_sitemap_dnd-over_Sf5e2","page-name":"sidebar_sitemap_page-name_601Ii","element-name":"sidebar_sitemap_element-name_iMex0","on-drag":"sidebar_sitemap_on-drag_v3GM8","selected":"sidebar_sitemap_selected_mCOlT","hidden":"sidebar_sitemap_hidden_viFSn"}
|
|
@ -14,63 +14,26 @@
|
|||
width: 100%;
|
||||
height: var(--height, 200px);
|
||||
|
||||
.pages-tool-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: $s-32;
|
||||
padding: 0 $s-8 0 0;
|
||||
margin: $s-2 0;
|
||||
.page-tool-bar-title {
|
||||
@include flexCenter;
|
||||
@include tabTitleTipography;
|
||||
@include buttonStyle;
|
||||
flex-grow: 1;
|
||||
gap: $s-4;
|
||||
justify-content: flex-start;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
color: var(--title-foreground-color);
|
||||
.collapsable-button {
|
||||
@include flexCenter;
|
||||
height: $s-24;
|
||||
width: $s-24;
|
||||
padding: 0 $s-4 0 $s-8;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
height: $s-12;
|
||||
width: $s-12;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
color: var(--title-foreground-color-hover);
|
||||
svg {
|
||||
stroke: var(--icon-foreground-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.add-page {
|
||||
@extend .button-primary;
|
||||
height: $s-32;
|
||||
width: calc($s-24 + $s-4);
|
||||
padding: 0;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
.view-only-mode {
|
||||
@include flexCenter;
|
||||
@include titleTipography;
|
||||
height: $s-20;
|
||||
padding: $s-4 $s-6;
|
||||
border: 1px solid var(--tag-background-color);
|
||||
border-radius: $br-6;
|
||||
color: var(--tag-background-color);
|
||||
.add-page {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: calc($s-24 + $s-4);
|
||||
padding: 0;
|
||||
border-radius: $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
.view-only-mode {
|
||||
@include flexCenter;
|
||||
@include titleTipography;
|
||||
height: $s-20;
|
||||
padding: $s-4 $s-6;
|
||||
border: 1px solid var(--tag-background-color);
|
||||
border-radius: $br-6;
|
||||
color: var(--tag-background-color);
|
||||
}
|
||||
.resize-area {
|
||||
position: absolute;
|
||||
bottom: -8px;
|
||||
|
@ -163,6 +126,7 @@
|
|||
input.element-name {
|
||||
@include textEllipsis;
|
||||
@include titleTipography;
|
||||
@include removeInputStyle;
|
||||
flex-grow: 1;
|
||||
height: $s-28;
|
||||
max-width: calc(var(--parent-size) - (var(--depth) * var(--layer-indentation-size)));
|
||||
|
@ -170,8 +134,6 @@
|
|||
padding-left: $s-6;
|
||||
border-radius: $br-8;
|
||||
border: 1px solid var(--input-border-color-focus);
|
||||
outline: none;
|
||||
background-color: transparent;
|
||||
color: var(--layer-row-foreground-color);
|
||||
}
|
||||
}
|
||||
|
@ -257,4 +219,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
:global(.title-spacing-sitemap) {
|
||||
padding-right: $s-8;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"button-primary":"workspace_text_palette_button-primary_1umSD","button-secondary":"workspace_text_palette_button-secondary_VOIWz","button-icon":"workspace_text_palette_button-icon_bcydd","text-palette":"workspace_text_palette_text-palette_0yeGp","left-arrow":"workspace_text_palette_left-arrow_iSjPL","right-arrow":"workspace_text_palette_right-arrow_cWHr6","button-icon-small":"workspace_text_palette_button-icon-small_wGyH7","disabled":"workspace_text_palette_disabled_EF36J","text-palette-content":"workspace_text_palette_text-palette-content_anJb5","text-palette-inside":"workspace_text_palette_text-palette-inside_LgHnf","typography-item":"workspace_text_palette_typography-item_d0vFL","typography-name":"workspace_text_palette_typography-name_NVBRv","typography-font":"workspace_text_palette_typography-font_paqmC","typography-data":"workspace_text_palette_typography-data_eKyme","mid-item":"workspace_text_palette_mid-item_uTcD2","small-item":"workspace_text_palette_small-item_1Y6mx"}
|
||||
{"button-primary":"workspace_text_palette_button-primary_1umSD","button-secondary":"workspace_text_palette_button-secondary_VOIWz","button-tertiary":"workspace_text_palette_button-tertiary_4AWFN","button-tag":"workspace_text_palette_button-tag_TMcKw","button-icon":"workspace_text_palette_button-icon_bcydd","text-palette":"workspace_text_palette_text-palette_0yeGp","left-arrow":"workspace_text_palette_left-arrow_iSjPL","right-arrow":"workspace_text_palette_right-arrow_cWHr6","button-icon-small":"workspace_text_palette_button-icon-small_wGyH7","asset-element":"workspace_text_palette_asset-element_edxQB","disabled":"workspace_text_palette_disabled_EF36J","text-palette-content":"workspace_text_palette_text-palette-content_anJb5","text-palette-inside":"workspace_text_palette_text-palette-inside_LgHnf","typography-item":"workspace_text_palette_typography-item_d0vFL","typography-name":"workspace_text_palette_typography-name_NVBRv","typography-font":"workspace_text_palette_typography-font_paqmC","typography-data":"workspace_text_palette_typography-data_eKyme","mid-item":"workspace_text_palette_mid-item_uTcD2","small-item":"workspace_text_palette_small-item_1Y6mx"}
|
|
@ -1 +1 @@
|
|||
{"button-primary":"workspace_text_palette_ctx_menu_button-primary_bkGXB","button-secondary":"workspace_text_palette_ctx_menu_button-secondary_mbPs7","button-icon":"workspace_text_palette_ctx_menu_button-icon_oklnh","button-icon-small":"workspace_text_palette_ctx_menu_button-icon-small_ebriD","workspace-context-menu":"workspace_text_palette_ctx_menu_workspace-context-menu_OShZn","palette-library":"workspace_text_palette_ctx_menu_palette-library_pDyi5","selected":"workspace_text_palette_ctx_menu_selected_k3kOd","icon-wrapper":"workspace_text_palette_ctx_menu_icon-wrapper_Xoj9o","file-library":"workspace_text_palette_ctx_menu_file-library_t-25M","library-name":"workspace_text_palette_ctx_menu_library-name_TGs9Z"}
|
||||
{"button-primary":"workspace_text_palette_ctx_menu_button-primary_bkGXB","button-secondary":"workspace_text_palette_ctx_menu_button-secondary_mbPs7","button-tertiary":"workspace_text_palette_ctx_menu_button-tertiary_Z74wM","button-tag":"workspace_text_palette_ctx_menu_button-tag_OmlzA","button-icon":"workspace_text_palette_ctx_menu_button-icon_oklnh","button-icon-small":"workspace_text_palette_ctx_menu_button-icon-small_ebriD","workspace-context-menu":"workspace_text_palette_ctx_menu_workspace-context-menu_OShZn","palette-library":"workspace_text_palette_ctx_menu_palette-library_pDyi5","selected":"workspace_text_palette_ctx_menu_selected_k3kOd","icon-wrapper":"workspace_text_palette_ctx_menu_icon-wrapper_Xoj9o","file-library":"workspace_text_palette_ctx_menu_file-library_t-25M","asset-element":"workspace_text_palette_ctx_menu_asset-element_-ynNV","library-name":"workspace_text_palette_ctx_menu_library-name_TGs9Z"}
|
Loading…
Add table
Add a link
Reference in a new issue