penpot/frontend/src/app/main/ui/viewer/thumbnails.cljs

120 lines
4.0 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) UXBOX Labs SL
(ns app.main.ui.viewer.thumbnails
(:require
[app.common.data :as d]
[app.main.data.viewer :as dv]
[app.main.render :as render]
[app.main.store :as st]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.object :as obj]
[app.util.timers :as ts]
[rumext.alpha :as mf]))
(mf/defc thumbnails-content
[{:keys [children expanded? total] :as props}]
(let [container (mf/use-ref)
width (mf/use-var (.. js/document -documentElement -clientWidth))
element-width (mf/use-var 152)
offset (mf/use-state 0)
on-left-arrow-click
(fn [_]
(swap! offset (fn [v]
(if (pos? v)
(dec v)
v))))
on-right-arrow-click
(fn [_]
(let [visible (/ @width @element-width)
max-val (- total visible)]
(swap! offset (fn [v]
(if (< v max-val)
(inc v)
v)))))
on-scroll
(fn [event]
(if (pos? (.. event -nativeEvent -deltaY))
(on-right-arrow-click event)
(on-left-arrow-click event)))
on-mount
(fn []
(let [dom (mf/ref-val container)]
(reset! width (obj/get dom "clientWidth"))))]
(mf/use-effect on-mount)
(if expanded?
[:div.thumbnails-content
[:div.thumbnails-list-expanded children]]
[:div.thumbnails-content
[:div.left-scroll-handler {:on-click on-left-arrow-click} i/arrow-slide]
[:div.right-scroll-handler {:on-click on-right-arrow-click} i/arrow-slide]
[:div.thumbnails-list {:ref container :on-wheel on-scroll}
[:div.thumbnails-list-inside {:style {:right (str (* @offset 152) "px")}}
children]]])))
(mf/defc thumbnails-summary
[{:keys [on-toggle-expand on-close total] :as props}]
[:div.thumbnails-summary
[:span.counter (tr "labels.num-of-frames" (i18n/c total))]
[:span.buttons
[:span.btn-expand {:on-click on-toggle-expand} i/arrow-down]
[:span.btn-close {:on-click on-close} i/close]]])
(mf/defc thumbnail-item
{::mf/wrap [mf/memo #(mf/deferred % ts/idle-then-raf)]}
[{:keys [selected? frame on-click index objects]}]
[:div.thumbnail-item {:on-click #(on-click % index)}
[:div.thumbnail-preview
{:class (dom/classnames :selected selected?)}
[:& render/frame-svg {:frame frame :objects objects}]]
[:div.thumbnail-info
[:span.name {:title (:name frame)} (:name frame)]]])
(mf/defc thumbnails-panel
[{:keys [frames page index show?] :as props}]
(let [expanded? (mf/use-state false)
container (mf/use-ref)
objects (:objects page)
on-close #(st/emit! dv/toggle-thumbnails-panel)
selected (mf/use-var false)
on-item-click
(mf/use-callback
(mf/deps @expanded?)
(fn [_ index]
(compare-and-set! selected false true)
(st/emit! (dv/go-to-frame-by-index index))
(when @expanded?
(on-close))))]
[:section.viewer-thumbnails
{:class (dom/classnames :expanded @expanded?
:invisible (not show?))
:ref container}
[:& thumbnails-summary {:on-toggle-expand #(swap! expanded? not)
:on-close on-close
:total (count frames)}]
[:& thumbnails-content {:expanded? @expanded?
:total (count frames)}
(for [[i frame] (d/enumerate frames)]
[:& thumbnail-item {:index i
:frame frame
:objects objects
:on-click on-item-click
:selected? (= i index)}])]]))