mirror of
https://github.com/penpot/penpot.git
synced 2025-06-01 10:51:37 +02:00
✨ Resizeable panels
This commit is contained in:
parent
acc3d00fd5
commit
1599b2644a
19 changed files with 307 additions and 118 deletions
|
@ -11,6 +11,13 @@ body {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
font-family: "worksans", sans-serif;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#app {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
$width-settings-bar: 16rem;
|
||||
$width-left-toolbar: 48px;
|
||||
$width-settings-bar: 256px;
|
||||
|
||||
.handoff-layout {
|
||||
height: 100vh;
|
||||
|
|
|
@ -10,10 +10,7 @@
|
|||
background-color: $color-gray-50;
|
||||
border-top: 1px solid $color-gray-60;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
z-index: 11;
|
||||
|
||||
& .right-arrow,
|
||||
|
@ -46,16 +43,21 @@
|
|||
@include animation(0, 0.5s, fadeOutDown);
|
||||
}
|
||||
|
||||
&.left-sidebar-open {
|
||||
left: 303px;
|
||||
width: calc(100% - 303px);
|
||||
}
|
||||
|
||||
& .context-menu-items {
|
||||
bottom: 1.5rem;
|
||||
top: initial;
|
||||
min-width: 10rem;
|
||||
}
|
||||
|
||||
& .resize-area {
|
||||
position: absolute;
|
||||
height: 8px;
|
||||
width: 100%;
|
||||
z-index: 10;
|
||||
cursor: ns-resize;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.color-palette-actions {
|
||||
|
@ -119,7 +121,6 @@
|
|||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 5rem;
|
||||
padding: 0.25rem;
|
||||
|
||||
&.size-small {
|
||||
|
|
|
@ -5,16 +5,8 @@
|
|||
// Copyright (c) 2015-2020 Andrey Antukh <niwi@niwi.nz>
|
||||
// Copyright (c) 2015-2020 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
$width-left-toolbar: 48px;
|
||||
|
||||
.left-toolbar {
|
||||
background-color: $color-gray-50;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
width: $width-left-toolbar;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
.left-toolbar-inside {
|
||||
|
@ -23,7 +15,6 @@ $width-left-toolbar: 48px;
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: visible;
|
||||
padding-top: 48px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,29 +5,14 @@
|
|||
// Copyright (c) 2015-2020 Andrey Antukh <niwi@niwi.nz>
|
||||
// Copyright (c) 2015-2020 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
$width-settings-bar: 16rem;
|
||||
// This width is also used in update-viewport-size at frontend/src/app/main/data/workspace.cljs
|
||||
|
||||
.settings-bar {
|
||||
background-color: $color-gray-50;
|
||||
border-left: 1px solid $color-gray-60;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
width: $width-settings-bar;
|
||||
|
||||
&.expanded {
|
||||
width: $width-settings-bar * 3;
|
||||
}
|
||||
|
||||
z-index: 10;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
|
||||
&.settings-bar-left {
|
||||
border-left: none;
|
||||
border-right: 1px solid $color-gray-60;
|
||||
left: 48px;
|
||||
}
|
||||
|
||||
.settings-bar-inside {
|
||||
|
@ -64,7 +49,6 @@ $width-settings-bar: 16rem;
|
|||
}
|
||||
|
||||
flex-direction: column;
|
||||
padding-top: 48px;
|
||||
height: 100%;
|
||||
|
||||
.tool-window {
|
||||
|
@ -163,6 +147,22 @@ $width-settings-bar: 16rem;
|
|||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
& .resize-area {
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 100%;
|
||||
z-index: 10;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
|
||||
&.settings-bar-left .resize-area {
|
||||
right: -8px;
|
||||
}
|
||||
|
||||
&.settings-bar-right .resize-area {
|
||||
left: -8px;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-window-content {
|
||||
|
@ -204,6 +204,7 @@ $width-settings-bar: 16rem;
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.element-list.pages-list {
|
||||
|
|
|
@ -5,14 +5,12 @@
|
|||
// Copyright (c) UXBOX Labs SL
|
||||
|
||||
.workspace-header {
|
||||
position: relative;
|
||||
align-items: center;
|
||||
background-color: $color-gray-50;
|
||||
border-bottom: 1px solid $color-gray-60;
|
||||
display: flex;
|
||||
height: 48px;
|
||||
padding: $size-1 $size-4 $size-1 55px;
|
||||
position: relative;
|
||||
z-index: 12;
|
||||
justify-content: space-between;
|
||||
|
||||
.main-icon {
|
||||
|
|
|
@ -5,10 +5,70 @@
|
|||
// Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
||||
// Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
$width-left-toolbar: 48px;
|
||||
|
||||
$width-settings-bar: 256px;
|
||||
$width-settings-bar-min: 255px;
|
||||
$width-settings-bar-max: 500px;
|
||||
|
||||
$height-palette: 79px;
|
||||
$height-palette-min: 54px;
|
||||
$height-palette-max: 80px;
|
||||
|
||||
#workspace {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
user-select: none;
|
||||
|
||||
display: grid;
|
||||
grid-template-areas: "header header header header"
|
||||
"toolbar left-sidebar viewport right-sidebar"
|
||||
"toolbar left-sidebar color-palette right-sidebar";
|
||||
|
||||
grid-template-rows: auto 1fr auto;
|
||||
grid-template-columns: auto auto 1fr auto;
|
||||
|
||||
.workspace-header {
|
||||
grid-area: header;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.left-toolbar {
|
||||
grid-area: toolbar;
|
||||
width: $width-left-toolbar;
|
||||
}
|
||||
|
||||
.settings-bar.settings-bar-left {
|
||||
min-width: $width-settings-bar;
|
||||
max-width: 500px;
|
||||
width: var(--width, $width-settings-bar);
|
||||
grid-area: left-sidebar;
|
||||
}
|
||||
|
||||
.settings-bar.settings-bar-right {
|
||||
min-width: $width-settings-bar;
|
||||
max-width: 500px;
|
||||
width: var(--width, $width-settings-bar);
|
||||
grid-area: right-sidebar;
|
||||
}
|
||||
|
||||
.workspace-loader {
|
||||
grid-area: viewport;
|
||||
}
|
||||
|
||||
.workspace-content {
|
||||
grid-area: viewport;
|
||||
}
|
||||
|
||||
.color-palette {
|
||||
grid-area: color-palette;
|
||||
min-height: $height-palette-min;
|
||||
max-height: $height-palette-max;
|
||||
height: var(--height, $height-palette);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.workspace-context-menu {
|
||||
background-color: $color-white;
|
||||
border-radius: $br-small;
|
||||
|
@ -97,7 +157,6 @@
|
|||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
|
||||
svg#loader-pencil {
|
||||
fill: $color-gray-50;
|
||||
|
@ -107,12 +166,8 @@
|
|||
.workspace-content {
|
||||
background-color: $color-canvas;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: calc(100% - #{$width-left-toolbar} - 2 * #{$width-settings-bar});
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: fixed;
|
||||
right: $width-settings-bar;
|
||||
|
||||
&.scrolling {
|
||||
cursor: grab;
|
||||
|
@ -171,14 +226,12 @@
|
|||
}
|
||||
|
||||
.workspace-viewport {
|
||||
height: calc(100% - 40px);
|
||||
overflow: hidden;
|
||||
transition: none;
|
||||
width: 100%;
|
||||
|
||||
display: grid;
|
||||
grid-template-rows: 20px 100%;
|
||||
grid-template-columns: 20px 100%;
|
||||
grid-template-rows: 20px 1fr;
|
||||
grid-template-columns: 20px 1fr;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.viewport {
|
||||
|
@ -209,10 +262,14 @@
|
|||
|
||||
.render-shapes {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.viewport-controls {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -481,7 +481,7 @@
|
|||
(cond
|
||||
(or (not (mth/finite? (:width srect)))
|
||||
(not (mth/finite? (:height srect))))
|
||||
(assoc local :vbox (assoc size :x 0 :y 0 :left-offset 0))
|
||||
(assoc local :vbox (assoc size :x 0 :y 0))
|
||||
|
||||
(or (> (:width srect) width)
|
||||
(> (:height srect) height))
|
||||
|
@ -522,25 +522,44 @@
|
|||
(update :y y)))))))
|
||||
|
||||
(defn update-viewport-size
|
||||
[{:keys [width height] :as size}]
|
||||
[resize-type {:keys [width height] :as size}]
|
||||
(ptk/reify ::update-viewport-size
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-local
|
||||
(fn [{:keys [vport left-sidebar? zoom] :as local}]
|
||||
(fn [{:keys [vport] :as local}]
|
||||
(if (or (mth/almost-zero? width) (mth/almost-zero? height))
|
||||
;; If we have a resize to zero just keep the old value
|
||||
local
|
||||
(let [wprop (/ (:width vport) width)
|
||||
hprop (/ (:height vport) height)
|
||||
left-offset (if left-sidebar? 0 (/ (* -1 15 16) zoom))]
|
||||
(-> local ;; This matches $width-settings-bar
|
||||
(assoc :vport size) ;; in frontend/resources/styles/main/partials/sidebar.scss
|
||||
(update :vbox (fn [vbox]
|
||||
(-> vbox
|
||||
(update :width #(/ % wprop))
|
||||
(update :height #(/ % hprop))
|
||||
(assoc :left-offset left-offset))))))))))))
|
||||
|
||||
vbox (:vbox local)
|
||||
vbox-x (:x vbox)
|
||||
vbox-y (:y vbox)
|
||||
vbox-width (:width vbox)
|
||||
vbox-height (:height vbox)
|
||||
|
||||
vbox-width' (/ vbox-width wprop)
|
||||
vbox-height' (/ vbox-height hprop)
|
||||
|
||||
vbox-x'
|
||||
(case resize-type
|
||||
:left (+ vbox-x (- vbox-width vbox-width'))
|
||||
:right vbox-x
|
||||
(+ vbox-x (/ (- vbox-width vbox-width') 2)))
|
||||
|
||||
vbox-y'
|
||||
(case resize-type
|
||||
:top (+ vbox-y (- vbox-height vbox-height'))
|
||||
:bottom vbox-y
|
||||
(+ vbox-y (/ (- vbox-height vbox-height') 2)))]
|
||||
(-> local
|
||||
(assoc :vport size)
|
||||
(assoc-in [:vbox :x] vbox-x')
|
||||
(assoc-in [:vbox :y] vbox-y')
|
||||
(assoc-in [:vbox :width] vbox-width')
|
||||
(assoc-in [:vbox :height] vbox-height')))))))))
|
||||
|
||||
(defn start-panning []
|
||||
(ptk/reify ::start-panning
|
||||
|
@ -596,14 +615,12 @@
|
|||
|
||||
(defn- impl-update-zoom
|
||||
[{:keys [vbox] :as local} center zoom]
|
||||
(let [vbox (update vbox :x + (:left-offset vbox))
|
||||
new-zoom (if (fn? zoom) (zoom (:zoom local)) zoom)
|
||||
(let [new-zoom (if (fn? zoom) (zoom (:zoom local)) zoom)
|
||||
old-zoom (:zoom local)
|
||||
center (if center center (gsh/center-rect vbox))
|
||||
scale (/ old-zoom new-zoom)
|
||||
mtx (gmt/scale-matrix (gpt/point scale) center)
|
||||
vbox' (gsh/transform-rect vbox mtx)
|
||||
vbox' (update vbox' :x - (:left-offset vbox))]
|
||||
vbox' (gsh/transform-rect vbox mtx)]
|
||||
(-> local
|
||||
(assoc :zoom new-zoom)
|
||||
(update :vbox merge (select-keys vbox' [:x :y :width :height])))))
|
||||
|
|
100
frontend/src/app/main/ui/hooks/resize.cljs
Normal file
100
frontend/src/app/main/ui/hooks/resize.cljs
Normal file
|
@ -0,0 +1,100 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.hooks.resize
|
||||
(:require
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.logging :as log]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(log/set-level! :warn)
|
||||
|
||||
(def last-resize-type nil)
|
||||
|
||||
(defn set-resize-type! [type]
|
||||
(set! last-resize-type type))
|
||||
|
||||
(defn use-resize-hook
|
||||
[initial min-val max-val axis negate? resize-type]
|
||||
(let [size-state (mf/use-state initial)
|
||||
parent-ref (mf/use-ref nil)
|
||||
|
||||
dragging-ref (mf/use-ref false)
|
||||
start-size-ref (mf/use-ref nil)
|
||||
start-ref (mf/use-ref nil)
|
||||
|
||||
on-pointer-down
|
||||
(fn [event]
|
||||
(dom/capture-pointer event)
|
||||
(mf/set-ref-val! start-size-ref @size-state)
|
||||
(mf/set-ref-val! dragging-ref true)
|
||||
(mf/set-ref-val! start-ref (dom/get-client-position event))
|
||||
(set! last-resize-type resize-type))
|
||||
|
||||
on-lost-pointer-capture
|
||||
(fn [event]
|
||||
(dom/release-pointer event)
|
||||
(mf/set-ref-val! start-size-ref nil)
|
||||
(mf/set-ref-val! dragging-ref false)
|
||||
(mf/set-ref-val! start-ref nil)
|
||||
(set! last-resize-type nil))
|
||||
|
||||
on-mouse-move
|
||||
(fn [event]
|
||||
(when (mf/ref-val dragging-ref)
|
||||
(let [start (mf/ref-val start-ref)
|
||||
pos (dom/get-client-position event)
|
||||
delta (-> (gpt/to-vec start pos)
|
||||
(cond-> negate? gpt/negate)
|
||||
(get axis))
|
||||
start-size (mf/ref-val start-size-ref)
|
||||
new-size (-> (+ start-size delta) (max min-val) (min max-val))]
|
||||
|
||||
(reset! size-state new-size))))]
|
||||
{:on-pointer-down on-pointer-down
|
||||
:on-lost-pointer-capture on-lost-pointer-capture
|
||||
:on-mouse-move on-mouse-move
|
||||
:parent-ref parent-ref
|
||||
:size @size-state}))
|
||||
|
||||
(defn use-resize-observer
|
||||
[callback]
|
||||
|
||||
(let [prev-val-ref (mf/use-ref nil)
|
||||
current-observer-ref (mf/use-ref nil)
|
||||
|
||||
node-ref
|
||||
(mf/use-callback
|
||||
(mf/deps callback)
|
||||
(fn [node]
|
||||
(let [current-observer (mf/ref-val current-observer-ref)
|
||||
prev-val (mf/ref-val prev-val-ref)]
|
||||
|
||||
(when (and (not= prev-val node) (some? current-observer))
|
||||
(log/debug :action "disconnect" :js/prev-val prev-val :js/node node)
|
||||
(.disconnect current-observer)
|
||||
(mf/set-ref-val! current-observer-ref nil))
|
||||
|
||||
(when (and (not= prev-val node) (some? node))
|
||||
(let [observer
|
||||
(js/ResizeObserver.
|
||||
(fn []
|
||||
(let [size (dom/get-client-size node)]
|
||||
(when callback (callback last-resize-type size)))))]
|
||||
(mf/set-ref-val! current-observer-ref observer)
|
||||
(log/debug :action "observe" :js/node node)
|
||||
(.observe observer node))))
|
||||
(mf/set-ref-val! prev-val-ref node)))]
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
(fn []
|
||||
(let [current-observer (mf/ref-val current-observer-ref)]
|
||||
(when (some? current-observer)
|
||||
(log/debug :action "disconnect")
|
||||
(.disconnect current-observer))))))
|
||||
node-ref))
|
|
@ -12,6 +12,7 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks.resize :refer [use-resize-observer]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.colorpalette :refer [colorpalette]]
|
||||
[app.main.ui.workspace.colorpicker]
|
||||
|
@ -39,11 +40,19 @@
|
|||
{:keys [options-mode]} local
|
||||
file (obj/get props "file")
|
||||
layout (obj/get props "layout")
|
||||
colorpalette? (:colorpalette layout)]
|
||||
colorpalette? (:colorpalette layout)
|
||||
|
||||
on-resize
|
||||
(mf/use-callback
|
||||
(fn [resize-type size]
|
||||
(when (:vport local)
|
||||
(st/emit! (dw/update-viewport-size resize-type size)))))
|
||||
|
||||
node-ref (use-resize-observer on-resize)]
|
||||
[:*
|
||||
(when colorpalette? [:& colorpalette])
|
||||
|
||||
[:section.workspace-content
|
||||
[:section.workspace-content {:ref node-ref}
|
||||
[:section.workspace-viewport
|
||||
[:& coordinates/coordinates {:colorpalette? colorpalette?}]
|
||||
|
||||
|
@ -131,3 +140,5 @@
|
|||
:layout layout}]
|
||||
[:& workspace-loader])]]]]]))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.main.store :as st]
|
||||
[app.main.ui.components.color-bullet :as cb]
|
||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.hooks.resize :refer [use-resize-hook]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.color :as uc]
|
||||
[app.util.i18n :refer [tr]]
|
||||
|
@ -52,7 +53,7 @@
|
|||
[:& cb/color-name {:color color :size size}]]))
|
||||
|
||||
(mf/defc palette
|
||||
[{:keys [current-colors recent-colors file-colors shared-libs selected size]}]
|
||||
[{:keys [current-colors recent-colors file-colors shared-libs selected]}]
|
||||
(let [state (mf/use-state {:show-menu false })
|
||||
|
||||
width (:width @state 0)
|
||||
|
@ -64,6 +65,9 @@
|
|||
|
||||
container (mf/use-ref nil)
|
||||
|
||||
{:keys [on-pointer-down on-lost-pointer-capture on-mouse-move parent-ref size]}
|
||||
(use-resize-hook 72 54 80 :y true :bottom)
|
||||
|
||||
on-left-arrow-click
|
||||
(mf/use-callback
|
||||
(mf/deps max-offset visible)
|
||||
|
@ -111,7 +115,11 @@
|
|||
(fn []
|
||||
(events/unlistenByKey key1))))
|
||||
|
||||
[:div.color-palette.left-sidebar-open
|
||||
[:div.color-palette {:ref parent-ref
|
||||
:style #js {"--height" (str size "px")}}
|
||||
[:div.resize-area {:on-pointer-down on-pointer-down
|
||||
:on-lost-pointer-capture on-lost-pointer-capture
|
||||
:on-mouse-move on-mouse-move}]
|
||||
[:& dropdown {:show (:show-menu @state)
|
||||
:on-close #(swap! state assoc :show-menu false)}
|
||||
[:ul.workspace-context-menu.palette-menu
|
||||
|
@ -170,8 +178,7 @@
|
|||
[:div.color-palette-inside {:style {:position "relative"
|
||||
:right (str (* 66 offset) "px")}}
|
||||
(for [[idx item] (map-indexed vector current-colors)]
|
||||
[:& palette-item {:size size
|
||||
:color item
|
||||
[:& palette-item {:color item
|
||||
:key idx}])]]
|
||||
|
||||
[:span.right-arrow {:on-click on-right-arrow-click} i/arrow-slide]]))
|
||||
|
@ -188,8 +195,6 @@
|
|||
file-colors (mf/deref refs/workspace-file-colors)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
selected (or (mf/deref selected-palette-ref) :recent)
|
||||
size (or (mf/deref selected-palette-size-ref) :big)
|
||||
|
||||
current-library-colors (mf/use-state [])]
|
||||
|
||||
(mf/use-effect
|
||||
|
@ -219,5 +224,4 @@
|
|||
:recent-colors recent-colors
|
||||
:file-colors file-colors
|
||||
:shared-libs shared-libs
|
||||
:selected selected
|
||||
:size size}]))
|
||||
:selected selected}]))
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.file-uploader :refer [file-uploader]]
|
||||
[app.main.ui.hooks.resize :as r]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
|
@ -136,5 +137,7 @@
|
|||
[:li.tooltip.tooltip-right
|
||||
{:alt (tr "workspace.toolbar.color-palette" (sc/get-tooltip :toggle-palette))
|
||||
:class (when (contains? layout :colorpalette) "selected")
|
||||
:on-click (st/emitf (dw/toggle-layout-flags :colorpalette))}
|
||||
:on-click (do
|
||||
(r/set-resize-type! :bottom)
|
||||
(st/emitf (dw/toggle-layout-flags :colorpalette)))}
|
||||
i/palette]]]]))
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.ui.workspace.sidebar
|
||||
(:require
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.hooks.resize :refer [use-resize-hook]]
|
||||
[app.main.ui.workspace.comments :refer [comments-sidebar]]
|
||||
[app.main.ui.workspace.sidebar.assets :refer [assets-toolbox]]
|
||||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox]]
|
||||
|
@ -21,19 +22,26 @@
|
|||
(mf/defc left-sidebar
|
||||
{:wrap [mf/memo]}
|
||||
[{:keys [layout ] :as props}]
|
||||
[:aside.settings-bar.settings-bar-left
|
||||
[:div.settings-bar-inside
|
||||
{:data-layout (str/join "," layout)}
|
||||
(when (contains? layout :layers)
|
||||
[:*
|
||||
[:& sitemap {:layout layout}]
|
||||
[:& layers-toolbox]])
|
||||
(let [{:keys [on-pointer-down on-lost-pointer-capture on-mouse-move parent-ref size]}
|
||||
(use-resize-hook 255 255 500 :x false :left)]
|
||||
|
||||
(when (contains? layout :document-history)
|
||||
[:& history-toolbox])
|
||||
[:aside.settings-bar.settings-bar-left {:ref parent-ref
|
||||
:style #js {"--width" (str size "px")}}
|
||||
[:div.resize-area {:on-pointer-down on-pointer-down
|
||||
:on-lost-pointer-capture on-lost-pointer-capture
|
||||
:on-mouse-move on-mouse-move}]
|
||||
[:div.settings-bar-inside
|
||||
{:data-layout (str/join "," layout)}
|
||||
(when (contains? layout :layers)
|
||||
[:*
|
||||
[:& sitemap {:layout layout}]
|
||||
[:& layers-toolbox]])
|
||||
|
||||
(when (contains? layout :assets)
|
||||
[:& assets-toolbox])]])
|
||||
(when (contains? layout :document-history)
|
||||
[:& history-toolbox])
|
||||
|
||||
(when (contains? layout :assets)
|
||||
[:& assets-toolbox])]]))
|
||||
|
||||
;; --- Right Sidebar (Component)
|
||||
|
||||
|
@ -41,8 +49,15 @@
|
|||
{::mf/wrap-props false
|
||||
::mf/wrap [mf/memo]}
|
||||
[props]
|
||||
(let [drawing-tool (:tool (mf/deref refs/workspace-drawing))]
|
||||
[:aside.settings-bar
|
||||
(let [{:keys [on-pointer-down on-lost-pointer-capture on-mouse-move parent-ref size]}
|
||||
(use-resize-hook 255 255 500 :x true :right)
|
||||
|
||||
drawing-tool (:tool (mf/deref refs/workspace-drawing))]
|
||||
[:aside.settings-bar.settings-bar-right {:ref parent-ref
|
||||
:style #js {"--width" (str size "px")}}
|
||||
[:div.resize-area {:on-pointer-down on-pointer-down
|
||||
:on-lost-pointer-capture on-lost-pointer-capture
|
||||
:on-mouse-move on-mouse-move}]
|
||||
[:div.settings-bar-inside
|
||||
(if (= drawing-tool :comments)
|
||||
[:& comments-sidebar]
|
||||
|
|
|
@ -163,7 +163,6 @@
|
|||
(hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport?)
|
||||
(hooks/setup-viewport-size viewport-ref)
|
||||
(hooks/setup-cursor cursor alt? panning drawing-tool drawing-path? node-editing?)
|
||||
(hooks/setup-resize layout viewport-ref)
|
||||
(hooks/setup-keyboard alt? ctrl? space?)
|
||||
(hooks/setup-hover-shapes page-id move-stream base-objects transform selected ctrl? hover hover-ids @hover-disabled? zoom)
|
||||
(hooks/setup-viewport-modifiers modifiers base-objects)
|
||||
|
@ -222,8 +221,6 @@
|
|||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:preserveAspectRatio "xMidYMid meet"
|
||||
:key (str "viewport" page-id)
|
||||
:width (:width vport 0)
|
||||
:height (:height vport 0)
|
||||
:view-box (utils/format-viewbox vbox)
|
||||
:ref viewport-ref
|
||||
:class (when drawing-tool "drawing")
|
||||
|
|
|
@ -492,11 +492,3 @@
|
|||
(when (and (not (#{"INPUT" "TEXTAREA"} tag-name)) (not @disable-paste))
|
||||
(st/emit! (dw/paste-from-event event @in-viewport?)))))))
|
||||
|
||||
(defn on-resize [viewport-ref]
|
||||
(mf/use-callback
|
||||
(fn [_]
|
||||
(let [node (mf/ref-val viewport-ref)
|
||||
prnt (dom/get-parent node)
|
||||
size (dom/get-client-size prnt)]
|
||||
;; We schedule the event so it fires after `initialize-page` event
|
||||
(timers/schedule #(st/emit! (dw/update-viewport-size size)))))))
|
||||
|
|
|
@ -220,12 +220,12 @@
|
|||
(defn guide-creation-area
|
||||
[vbox zoom axis]
|
||||
(if (= axis :x)
|
||||
{:x (:x vbox)
|
||||
{:x (+ (:x vbox) (/ 8 zoom))
|
||||
:y (:y vbox)
|
||||
:width (/ 24 zoom)
|
||||
:width (/ 16 zoom)
|
||||
:height (:height vbox)}
|
||||
|
||||
{:x (:x vbox)
|
||||
{:x (+ (:x vbox) (+ 28 zoom))
|
||||
:y (:y vbox)
|
||||
:width (:width vbox)
|
||||
:height (/ 24 zoom)}))
|
||||
|
|
|
@ -31,10 +31,9 @@
|
|||
on-key-up (actions/on-key-up)
|
||||
on-mouse-move (actions/on-mouse-move viewport-ref zoom)
|
||||
on-mouse-wheel (actions/on-mouse-wheel viewport-ref zoom)
|
||||
on-resize (actions/on-resize viewport-ref)
|
||||
on-paste (actions/on-paste disable-paste in-viewport?)]
|
||||
(mf/use-layout-effect
|
||||
(mf/deps on-key-down on-key-up on-mouse-move on-mouse-wheel on-resize on-paste)
|
||||
(mf/deps on-key-down on-key-up on-mouse-move on-mouse-wheel on-paste)
|
||||
(fn []
|
||||
(let [node (mf/ref-val viewport-ref)
|
||||
keys [(events/listen js/document EventType.KEYDOWN on-key-down)
|
||||
|
@ -43,7 +42,6 @@
|
|||
;; bind with passive=false to allow the event to be cancelled
|
||||
;; https://stackoverflow.com/a/57582286/3219895
|
||||
(events/listen js/window EventType.WHEEL on-mouse-wheel #js {:passive false})
|
||||
(events/listen js/window EventType.RESIZE on-resize)
|
||||
(events/listen js/window EventType.PASTE on-paste)]]
|
||||
|
||||
(fn []
|
||||
|
@ -52,12 +50,12 @@
|
|||
|
||||
(defn setup-viewport-size [viewport-ref]
|
||||
(mf/use-layout-effect
|
||||
(fn []
|
||||
(let [node (mf/ref-val viewport-ref)
|
||||
prnt (dom/get-parent node)
|
||||
size (dom/get-client-size prnt)]
|
||||
;; We schedule the event so it fires after `initialize-page` event
|
||||
(timers/schedule #(st/emit! (dw/initialize-viewport size)))))))
|
||||
(fn []
|
||||
(let [node (mf/ref-val viewport-ref)
|
||||
prnt (dom/get-parent node)
|
||||
size (dom/get-client-size prnt)]
|
||||
;; We schedule the event so it fires after `initialize-page` event
|
||||
(timers/schedule #(st/emit! (dw/initialize-viewport size)))))))
|
||||
|
||||
(defn setup-cursor [cursor alt? panning drawing-tool drawing-path? path-editing?]
|
||||
(mf/use-effect
|
||||
|
@ -80,10 +78,6 @@
|
|||
(when (not= @cursor new-cursor)
|
||||
(reset! cursor new-cursor))))))
|
||||
|
||||
(defn setup-resize [layout viewport-ref]
|
||||
(let [on-resize (actions/on-resize viewport-ref)]
|
||||
(mf/use-layout-effect (mf/deps layout) on-resize)))
|
||||
|
||||
(defn setup-keyboard [alt? ctrl? space?]
|
||||
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
||||
(hooks/use-stream ms/keyboard-ctrl #(reset! ctrl? %))
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
(:import goog.events.EventType))
|
||||
|
||||
(defn format-viewbox [vbox]
|
||||
(str/join " " [(+ (:x vbox 0) (:left-offset vbox 0))
|
||||
(str/join " " [(:x vbox 0)
|
||||
(:y vbox 0)
|
||||
(:width vbox 0)
|
||||
(:height vbox 0)]))
|
||||
|
|
|
@ -148,7 +148,7 @@
|
|||
(dom/remove-attribute node "transform")))))))
|
||||
|
||||
(defn format-viewbox [vbox]
|
||||
(str/join " " [(+ (:x vbox 0) (:left-offset vbox 0))
|
||||
(str/join " " [(:x vbox 0)
|
||||
(:y vbox 0)
|
||||
(:width vbox 0)
|
||||
(:height vbox 0)]))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue