mirror of
https://github.com/penpot/penpot.git
synced 2025-06-11 10:41:37 +02:00
51 lines
1.8 KiB
Clojure
51 lines
1.8 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) 2019 Andrey Antukh <niwi@niwi.nz>
|
|
|
|
(ns uxbox.util.components
|
|
"A collection of general purpose utility components."
|
|
(:require
|
|
[beicon.core :as rx]
|
|
[rumext.alpha :as mf]
|
|
[uxbox.util.timers :refer [schedule-on-idle]]))
|
|
|
|
(mf/defc chunked-list
|
|
[{:keys [items children initial-size chunk-size]
|
|
:or {initial-size 30 chunk-size 5}
|
|
:as props}]
|
|
(letfn [(initial-state []
|
|
(let [total (count items)
|
|
size (if (> total initial-size) initial-size total)
|
|
current (take size items)
|
|
pending (drop size items)]
|
|
{:current (vec current)
|
|
:pending pending
|
|
:pending-num (- total size)}))
|
|
|
|
(update-state [{:keys [current pending pending-num] :as state}]
|
|
(let [chunk-size (if (> pending-num chunk-size) chunk-size pending-num)]
|
|
{:current (into current (take chunk-size pending))
|
|
:pending (drop chunk-size pending)
|
|
:pending-num (- pending-num chunk-size)}))
|
|
(after-render [state]
|
|
(when (pos? (:pending-num @state))
|
|
(let [sem (schedule-on-idle (fn [] (swap! state update-state)))]
|
|
#(rx/cancel! sem))))]
|
|
|
|
(let [initial (mf/use-memo initial-state)
|
|
state (mf/use-state initial)]
|
|
(mf/use-effect {:deps true :fn #(after-render state)})
|
|
(for [item (:current @state)]
|
|
(children item)))))
|
|
|
|
(defn use-rxsub
|
|
[ob]
|
|
(let [[state reset-state!] (mf/useState @ob)]
|
|
(mf/useEffect
|
|
(fn []
|
|
(let [sub (rx/subscribe ob #(reset-state! %))]
|
|
#(rx/cancel! sub)))
|
|
#js [ob])
|
|
state))
|