penpot/frontend/src/app/main/ui/inspect/right_sidebar.cljs

236 lines
9.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.inspect.right-sidebar
(:require-macros [app.main.style :as stl])
(:require
[app.common.types.component :as ctk]
[app.config :as cf]
[app.main.data.event :as ev]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.ds.controls.select :refer [select*]]
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
[app.main.ui.icons :as deprecated-icon]
[app.main.ui.inspect.attributes :refer [attributes]]
[app.main.ui.inspect.code :refer [code]]
[app.main.ui.inspect.selection-feedback :refer [resolve-shapes]]
[app.main.ui.inspect.styles :refer [styles-tab*]]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[app.util.shape-icon :as usi]
[potok.v2.core :as ptk]
[rumext.v2 :as mf]))
(defn- get-libraries
"Retrieve all libraries, including the local file, on workspace or viewer"
[from]
(if (= from :workspace)
(deref refs/libraries)
(let [viewer-data (deref refs/viewer-data)
local (get-in viewer-data [:file :data])
id (get local :id)
libraries (:libraries viewer-data)]
(-> libraries
(assoc id {:id id
:data local})))))
(mf/defc right-sidebar*
[{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
:or {from :viewer}}]
(let [color-space* (mf/use-state "hex")
color-space (deref color-space*)
section (mf/use-state #(if (contains? cf/flags :inspect-styles) :styles :info))
objects (or objects (:objects page))
shapes (or shapes
(resolve-shapes objects selected))
first-shape (first shapes)
page-id (or page-id (:id page))
file-id (or file-id (:id file))
libraries (get-libraries from)
main-instance? (ctk/main-instance? first-shape)
subtitle (cond
(or
(ctk/is-variant-container? first-shape)
(and (not (ctk/is-variant? first-shape)) main-instance?))
(tr "inspect.subtitle.main")
(and (ctk/is-variant? first-shape) main-instance?)
(tr "labels.variant")
(ctk/instance-head? first-shape)
(tr "inspect.subtitle.copy"))
handle-change-tab
(mf/use-fn
(mf/deps from on-change-section)
(fn [new-section]
(reset! section (keyword new-section))
(when on-change-section
(on-change-section (keyword new-section))
(st/emit!
(ptk/event ::ev/event {::ev/name "change-inspect-tab" :tab new-section})))))
handle-expand
(mf/use-fn
(mf/deps on-expand)
(fn []
(when on-expand (on-expand))))
navigate-to-help
(mf/use-fn
(fn []
(dom/open-new-window "https://help.penpot.app/user-guide/inspect/")))
handle-change-color-space
(mf/use-fn
(fn [color-space]
(reset! color-space* color-space)))
color-spaces
(mf/with-memo []
[{:label (tr "inspect.attributes.color.hex")
:id "hex"}
{:label (tr "inspect.attributes.color.rgba")
:id "rgba"}
{:label (tr "inspect.attributes.color.hsla")
:id "hsla"}])
tabs
(mf/with-memo []
(if (contains? cf/flags :inspect-styles)
[{:label (tr "labels.styles")
:id "styles"}
{:label (tr "inspect.tabs.computed")
:id "computed"}
{:label (tr "inspect.tabs.code")
:data-testid "code"
:id "code"}]
[{:label (tr "inspect.tabs.info")
:id "info"}
{:label (tr "inspect.tabs.code")
:data-testid "code"
:id "code"}]))]
(mf/use-effect
(mf/deps shapes handle-change-tab)
(fn []
(if (seq shapes)
(st/emit! (ptk/event ::ev/event {::ev/name "inspect-mode-click-element"}))
(handle-change-tab (if (contains? cf/flags :inspect-styles) :styles :info)))))
[:aside {:class (stl/css-case :settings-bar-right true
:viewer-code (= from :viewer))}
(if (seq shapes)
[:div {:class (stl/css :tool-windows)}
[:div {:class (stl/css-case :shape-info true :shape-info-subtitle (some? subtitle))}
(if (> (count shapes) 1)
[:*
[:div {:class (stl/css :layers-icon)}
[:> icon* {:icon-id i/layers :size "s"}]]
[:span {:class (stl/css :layer-title)} (tr "inspect.tabs.code.selected.multiple" (count shapes))]]
[:*
[:div {:class (stl/css :shape-icon)}
;; Use the shape icon utility to get the correct icon for the first shape
[:> icon* {:icon-id (usi/get-shape-icon first-shape) :size "s"}]]
;; Execution time translation strings:
;; (tr "inspect.tabs.code.selected.circle")
;; (tr "inspect.tabs.code.selected.component")
;; (tr "inspect.tabs.code.selected.curve")
;; (tr "inspect.tabs.code.selected.frame")
;; (tr "inspect.tabs.code.selected.group")
;; (tr "inspect.tabs.code.selected.image")
;; (tr "inspect.tabs.code.selected.mask")
;; (tr "inspect.tabs.code.selected.path")
;; (tr "inspect.tabs.code.selected.rect")
;; (tr "inspect.tabs.code.selected.svg-raw")
;; (tr "inspect.tabs.code.selected.text")
[:div
(if (some? subtitle)
[:*
[:div {:class (stl/css :layer-title :layer-title-with-subtitle)} (:name first-shape)]
[:div {:class (stl/css :layer-subtitle)} subtitle]]
[:div
[:div {:class (stl/css :layer-title)} (:name first-shape)]])]])]
[:div {:class (stl/css :inspect-content)}
(if (contains? cf/flags :inspect-styles)
[:div {:class (stl/css :inspect-tab-switcher)}
[:span {:class (stl/css :inspect-tab-switcher-label)} (tr "inspect.tabs.switcher.label")]
[:div {:class (stl/css :inspect-tab-switcher-controls)}
[:div {:class (stl/css :inspect-tab-switcher-controls-color-space)}
[:> select* {:options color-spaces
:default-selected "hex"
:variant "ghost"
:on-change handle-change-color-space}]]
[:div {:class (stl/css :inspect-tab-switcher-controls-tab)}
[:> select* {:options tabs
:default-selected (name @section)
:on-change handle-change-tab}]]]]
nil)
(if (contains? cf/flags :inspect-styles)
[:div {:class (stl/css :inspect-tab :viewer-tab-switcher :viewer-tab-switcher-layout)}
(case @section
:styles
[:> styles-tab* {:color-space color-space
:objects objects
:shapes shapes
:libraries libraries
:file-id file-id}]
:computed
[:& attributes {:page-id page-id
:objects objects
:file-id file-id
:frame frame
:shapes shapes
:from from
:libraries libraries
:share-id share-id}]
:code
[:& code {:frame frame
:shapes shapes
:on-expand handle-expand
:from from}])]
[:> tab-switcher* {:tabs tabs
:selected (name @section)
:on-change handle-change-tab
:class (stl/css :viewer-tab-switcher)}
(case @section
:info
[:& attributes {:page-id page-id
:objects objects
:file-id file-id
:frame frame
:shapes shapes
:from from
:libraries libraries
:share-id share-id}]
:code
[:& code {:frame frame
:shapes shapes
:on-expand handle-expand
:from from}])])]]
[:div {:class (stl/css :empty)}
[:div {:class (stl/css :code-info)}
[:span {:class (stl/css :placeholder-icon)}
deprecated-icon/code]
[:span {:class (stl/css :placeholder-label)}
(tr "inspect.empty.select")]]
[:div {:class (stl/css :help-info)}
[:span {:class (stl/css :placeholder-icon)}
deprecated-icon/help]
[:span {:class (stl/css :placeholder-label)}
(tr "inspect.empty.help")]]
[:button {:class (stl/css :more-info-btn)
:on-click navigate-to-help}
(tr "inspect.empty.more-info")]])]))