penpot/frontend/src/app/main/ui/workspace/palette.cljs
2023-08-07 12:52:36 +02:00

192 lines
8.5 KiB
Clojure

;; 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.palette
(:require-macros [app.main.style :refer [css]])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.main.data.events :as ev]
[app.main.data.workspace :as dw]
[app.main.data.workspace.colors :as mdc]
[app.main.data.workspace.shortcuts :as sc]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.hooks.resize :as r]
[app.main.ui.icons :as i]
[app.main.ui.workspace.color-palette :refer [color-palette]]
[app.main.ui.workspace.color-palette-ctx-menu :refer [color-palette-ctx-menu]]
[app.main.ui.workspace.text-palette :refer [text-palette]]
[app.main.ui.workspace.text-palette-ctx-menu :refer [text-palette-ctx-menu]]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[app.util.object :as obj]
[app.util.timers :as ts]
[goog.events :as events]
[okulary.core :as l]
[rumext.v2 :as mf]))
(def viewport
(l/derived :vport refs/workspace-local))
(defn calculate-palette-padding []
(let [left-sidebar (dom/get-element "left-sidebar-aside")
left-sidebar-size (d/parse-integer (dom/get-data left-sidebar "size"))
rulers? (:rules (mf/deref refs/workspace-layout))
rulers-width (if rulers? 26 4)
min-left-sidebar-width 27
calculate-padding-left (+ rulers-width (or left-sidebar-size
min-left-sidebar-width))]
#js {"paddingLeft" (dm/str calculate-padding-left "px")
"paddingRight" "280px"}))
(mf/defc palette
[{:keys [layout]}]
(let [color-palette? (:colorpalette layout)
text-palette? (:textpalette layout)
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)
container (mf/use-ref nil)
state (mf/use-state {:show-menu false :hide-palettes false})
selected (h/use-shared-state mdc/colorpalette-selected-broadcast-key :recent)
selected-text (mf/use-state :file)
on-select (mf/use-fn #(reset! selected %))
{:keys [on-pointer-down on-lost-pointer-capture on-pointer-move parent-ref size]}
(r/use-resize-hook :palette 72 54 80 :y true :bottom)
vport (mf/deref viewport)
vport-width (:width vport)
on-resize
(mf/use-callback
(fn [_]
(let [dom (mf/ref-val container)
width (obj/get dom "clientWidth")]
(swap! state assoc :width width))))
on-close-menu
(mf/use-callback
(fn [_]
(swap! state assoc :show-menu false)))
on-select-palette
(mf/use-fn
(mf/deps on-select)
(fn [event]
(let [node (dom/get-current-target event)
value (dom/get-attribute node "data-palette")]
(on-select (if (or (= "file" value) (= "recent" value))
(keyword value)
(parse-uuid value))))))
on-select-text-palette
(mf/use-fn
(mf/deps on-select)
(fn [lib]
(if (or (nil? lib) (= :file lib))
(reset! selected-text :file)
(reset! selected-text (:id lib)))))
toggle-palettes
(mf/use-callback
(fn [_]
(swap! state update :hide-palettes not)))
any-palette? (or color-palette? text-palette?)
size-classname (cond
(<= size 64) (css :small-palette)
(<= size 72) (css :mid-palette)
(<= size 80) (css :big-palette))]
(mf/with-effect []
(let [key1 (events/listen js/window "resize" on-resize)]
#(events/unlistenByKey key1)))
(mf/use-layout-effect
#(let [dom (mf/ref-val parent-ref)
width (obj/get dom "clientWidth")]
(swap! state assoc :width width)))
[:div {:class (dom/classnames (css :palette-wrapper) true)
:style (calculate-palette-padding)}
(when-not workspace-read-only?
[:div {:ref parent-ref
:class (dom/classnames (css :palettes) true
size-classname true
(css :wide) any-palette?
(css :hidden-bts) (:hide-palettes @state))
:style #js {"--height" (dm/str size "px")}}
[:div {:class (dom/classnames (css :resize-area) true)
:on-pointer-down on-pointer-down
:on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move}]
[:ul {:class (dom/classnames (css :palette-btn-list) true
(css :hidden-bts) (:hide-palettes @state)
size-classname true)}
[:li {:class (dom/classnames (css :palette-item) true)}
[:button
{:title (tr "workspace.toolbar.color-palette" (sc/get-tooltip :toggle-colorpalette))
:aria-label (tr "workspace.toolbar.color-palette" (sc/get-tooltip :toggle-colorpalette))
:class (dom/classnames (css :palette-btn) true
(css :selected) color-palette?)
:on-click (fn [event]
(let [node (dom/get-current-target event)]
(r/set-resize-type! :top)
(dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
(ts/schedule 300 #(st/emit! (dw/remove-layout-flag :textpalette)
(-> (dw/toggle-layout-flag :colorpalette)
(vary-meta assoc ::ev/origin "workspace-left-toolbar"))))
(dom/blur! node)))}
i/drop-refactor]]
[:li {:class (dom/classnames (css :palette-item) true)}
[:button
{:title (tr "workspace.toolbar.text-palette" (sc/get-tooltip :toggle-textpalette))
:aria-label (tr "workspace.toolbar.text-palette" (sc/get-tooltip :toggle-textpalette))
:class (dom/classnames (css :palette-btn) true
(css :selected) text-palette?)
:on-click (fn [event]
(let [node (dom/get-current-target event)]
(r/set-resize-type! :top)
(dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
(ts/schedule 300 #(st/emit! (dw/remove-layout-flag :colorpalette)
(-> (dw/toggle-layout-flag :textpalette)
(vary-meta assoc ::ev/origin "workspace-left-toolbar"))))
(dom/blur! node)))}
i/text-palette-refactor]]]
(if any-palette?
[:*
[:button {:class (dom/classnames (css :palette-actions) true)
:on-click #(swap! state update :show-menu not)}
i/menu-refactor]
[:div {:class (dom/classnames (css :palette) true)
:ref container}
(when text-palette?
[:*
[:& text-palette-ctx-menu {:show-menu? (:show-menu @state)
:close-menu on-close-menu
:on-select-palette on-select-text-palette
:selected @selected-text}]
[:& text-palette {:size size
:selected @selected-text
:width vport-width}]])
(when color-palette?
[:* [:& color-palette-ctx-menu {:show-menu? (:show-menu @state)
:close-menu on-close-menu
:on-select-palette on-select-palette
:selected @selected}]
[:& color-palette {:size size
:selected @selected
:width vport-width}]])]]
[:div {:class (dom/classnames (css :handler) true)
:on-click toggle-palettes}
[:div {:class (dom/classnames (css :handler-btn) true)}]])])]))