|
|
@@ -112,116 +112,116 @@
|
|
|
[& prop-and-children]
|
|
|
(let [[prop children] (get-prop-and-children prop-and-children)]
|
|
|
[:div (merge {:class "ls-table w-full caption-bottom text-sm table-fixed"}
|
|
|
- prop)
|
|
|
+ prop)
|
|
|
children]))
|
|
|
|
|
|
;; FIXME: ux
|
|
|
(defn- use-sticky-element!
|
|
|
[^js/HTMLElement container target-ref]
|
|
|
(rum/use-effect!
|
|
|
- (fn []
|
|
|
- (let [^js el (rum/deref target-ref)
|
|
|
- ^js cls (.-classList el)
|
|
|
- *ticking? (volatile! false)
|
|
|
- el-top (-> el (.getBoundingClientRect) (.-top))
|
|
|
- head-top (-> (get-head-container) (js/getComputedStyle) (.-height) (js/parseInt))
|
|
|
- translate (fn [offset]
|
|
|
- (set! (. (.-style el) -transform) (str "translate3d(0, " offset "px , 0)"))
|
|
|
- (if (zero? offset)
|
|
|
- (.remove cls "translated")
|
|
|
- (.add cls "translated")))
|
|
|
- *last-offset (volatile! 0)
|
|
|
- handle (fn []
|
|
|
- (let [scroll-top (js/parseInt (.-scrollTop container))
|
|
|
- offset (if (> (+ scroll-top head-top) el-top)
|
|
|
- (+ (- scroll-top el-top) head-top 1) 0)
|
|
|
- offset (js/parseInt offset)
|
|
|
- last-offset @*last-offset]
|
|
|
- (if (and (not (zero? last-offset))
|
|
|
- (not= offset last-offset))
|
|
|
- (let [dir (if (neg? (- offset last-offset)) -1 1)]
|
|
|
- (loop [offset' (+ last-offset dir)]
|
|
|
- (translate offset')
|
|
|
- (if (and (not= offset offset')
|
|
|
- (< (abs (- offset offset')) 100))
|
|
|
- (recur (+ offset' dir))
|
|
|
- (translate offset))))
|
|
|
- (translate offset))
|
|
|
- (vreset! *last-offset offset)))
|
|
|
- handler (fn [^js e]
|
|
|
- (when (not @*ticking?)
|
|
|
- (js/window.requestAnimationFrame
|
|
|
- #(do (handle) (vreset! *ticking? false)))
|
|
|
- (vreset! *ticking? true)))]
|
|
|
- (.addEventListener container "scroll" handler)
|
|
|
- #(.removeEventListener container "scroll" handler)))
|
|
|
- []))
|
|
|
+ (fn []
|
|
|
+ (let [^js el (rum/deref target-ref)
|
|
|
+ ^js cls (.-classList el)
|
|
|
+ *ticking? (volatile! false)
|
|
|
+ el-top (-> el (.getBoundingClientRect) (.-top))
|
|
|
+ head-top (-> (get-head-container) (js/getComputedStyle) (.-height) (js/parseInt))
|
|
|
+ translate (fn [offset]
|
|
|
+ (set! (. (.-style el) -transform) (str "translate3d(0, " offset "px , 0)"))
|
|
|
+ (if (zero? offset)
|
|
|
+ (.remove cls "translated")
|
|
|
+ (.add cls "translated")))
|
|
|
+ *last-offset (volatile! 0)
|
|
|
+ handle (fn []
|
|
|
+ (let [scroll-top (js/parseInt (.-scrollTop container))
|
|
|
+ offset (if (> (+ scroll-top head-top) el-top)
|
|
|
+ (+ (- scroll-top el-top) head-top 1) 0)
|
|
|
+ offset (js/parseInt offset)
|
|
|
+ last-offset @*last-offset]
|
|
|
+ (if (and (not (zero? last-offset))
|
|
|
+ (not= offset last-offset))
|
|
|
+ (let [dir (if (neg? (- offset last-offset)) -1 1)]
|
|
|
+ (loop [offset' (+ last-offset dir)]
|
|
|
+ (translate offset')
|
|
|
+ (if (and (not= offset offset')
|
|
|
+ (< (abs (- offset offset')) 100))
|
|
|
+ (recur (+ offset' dir))
|
|
|
+ (translate offset))))
|
|
|
+ (translate offset))
|
|
|
+ (vreset! *last-offset offset)))
|
|
|
+ handler (fn [^js e]
|
|
|
+ (when (not @*ticking?)
|
|
|
+ (js/window.requestAnimationFrame
|
|
|
+ #(do (handle) (vreset! *ticking? false)))
|
|
|
+ (vreset! *ticking? true)))]
|
|
|
+ (.addEventListener container "scroll" handler)
|
|
|
+ #(.removeEventListener container "scroll" handler)))
|
|
|
+ []))
|
|
|
|
|
|
;; FIXME: another solution for the sticky header
|
|
|
(defn- use-sticky-element2!
|
|
|
[^js/HTMLDivElement target-ref]
|
|
|
(rum/use-effect!
|
|
|
- (fn []
|
|
|
- (let [^js target (rum/deref target-ref)
|
|
|
- ^js container (or (.closest target ".sidebar-item-list") (get-main-scroll-container))
|
|
|
- ^js target-cls (.-classList target)
|
|
|
- ^js table (.closest target ".ls-table-rows")
|
|
|
- ^js table-footer (some-> table (.querySelector ".ls-table-footer"))
|
|
|
- ^js page-el (.closest target ".page-inner")
|
|
|
- *ticking? (volatile! false)
|
|
|
- *el-top (volatile! (-> target (.getBoundingClientRect) (.-top)))
|
|
|
- head-top (-> (get-head-container) (js/getComputedStyle) (.-height) (js/parseInt))
|
|
|
- update-target-top! (fn []
|
|
|
- (when (not (.contains target-cls "ls-fixed"))
|
|
|
- (vreset! *el-top (+ (-> target (.getBoundingClientRect) (.-top))
|
|
|
+ (fn []
|
|
|
+ (let [^js target (rum/deref target-ref)
|
|
|
+ ^js container (or (.closest target ".sidebar-item-list") (get-main-scroll-container))
|
|
|
+ ^js target-cls (.-classList target)
|
|
|
+ ^js table (.closest target ".ls-table-rows")
|
|
|
+ ^js table-footer (some-> table (.querySelector ".ls-table-footer"))
|
|
|
+ ^js page-el (.closest target ".page-inner")
|
|
|
+ *ticking? (volatile! false)
|
|
|
+ *el-top (volatile! (-> target (.getBoundingClientRect) (.-top)))
|
|
|
+ head-top (-> (get-head-container) (js/getComputedStyle) (.-height) (js/parseInt))
|
|
|
+ update-target-top! (fn []
|
|
|
+ (when (not (.contains target-cls "ls-fixed"))
|
|
|
+ (vreset! *el-top (+ (-> target (.getBoundingClientRect) (.-top))
|
|
|
(.-scrollTop container)))))
|
|
|
- update-footer! (fn []
|
|
|
- (when table-footer
|
|
|
- (set! (. (.-style table-footer) -width) (str (.-scrollWidth table) "px"))))
|
|
|
- update-target! (fn []
|
|
|
- (if (.contains target-cls "ls-fixed")
|
|
|
- (let [^js rect (-> table (.getBoundingClientRect))
|
|
|
- width (.-clientWidth table)
|
|
|
- left (.-left rect)]
|
|
|
- (set! (. (.-style target) -width) (str width "px"))
|
|
|
- (set! (. (.-style target) -left) (str left "px")))
|
|
|
- (do
|
|
|
- (set! (. (.-style target) -width) "auto")
|
|
|
- (set! (. (.-style target) -left) "0px")))
|
|
|
+ update-footer! (fn []
|
|
|
+ (when table-footer
|
|
|
+ (set! (. (.-style table-footer) -width) (str (.-scrollWidth table) "px"))))
|
|
|
+ update-target! (fn []
|
|
|
+ (if (.contains target-cls "ls-fixed")
|
|
|
+ (let [^js rect (-> table (.getBoundingClientRect))
|
|
|
+ width (.-clientWidth table)
|
|
|
+ left (.-left rect)]
|
|
|
+ (set! (. (.-style target) -width) (str width "px"))
|
|
|
+ (set! (. (.-style target) -left) (str left "px")))
|
|
|
+ (do
|
|
|
+ (set! (. (.-style target) -width) "auto")
|
|
|
+ (set! (. (.-style target) -left) "0px")))
|
|
|
;; update scroll
|
|
|
- (set! (. target -scrollLeft) (.-scrollLeft table)))
|
|
|
+ (set! (. target -scrollLeft) (.-scrollLeft table)))
|
|
|
;; target observer
|
|
|
- target-observe! (fn []
|
|
|
- (let [scroll-top (js/parseInt (.-scrollTop container))
|
|
|
- table-in-top (+ scroll-top head-top)
|
|
|
- table-bottom (.-bottom (.getBoundingClientRect table))
|
|
|
- fixed? (and (> table-bottom (+ head-top 90))
|
|
|
- (> table-in-top @*el-top))]
|
|
|
- (if fixed?
|
|
|
- (.add target-cls "ls-fixed")
|
|
|
- (.remove target-cls "ls-fixed"))
|
|
|
- (update-target!)))
|
|
|
- target-observe-handle! (fn [^js _e]
|
|
|
- (when (not @*ticking?)
|
|
|
- (js/window.requestAnimationFrame
|
|
|
- #(do (target-observe!) (vreset! *ticking? false)))
|
|
|
- (vreset! *ticking? true)))
|
|
|
- resize-observer (js/ResizeObserver. update-target!)
|
|
|
- page-resize-observer (js/ResizeObserver. (fn [] (update-target-top!)))]
|
|
|
+ target-observe! (fn []
|
|
|
+ (let [scroll-top (js/parseInt (.-scrollTop container))
|
|
|
+ table-in-top (+ scroll-top head-top)
|
|
|
+ table-bottom (.-bottom (.getBoundingClientRect table))
|
|
|
+ fixed? (and (> table-bottom (+ head-top 90))
|
|
|
+ (> table-in-top @*el-top))]
|
|
|
+ (if fixed?
|
|
|
+ (.add target-cls "ls-fixed")
|
|
|
+ (.remove target-cls "ls-fixed"))
|
|
|
+ (update-target!)))
|
|
|
+ target-observe-handle! (fn [^js _e]
|
|
|
+ (when (not @*ticking?)
|
|
|
+ (js/window.requestAnimationFrame
|
|
|
+ #(do (target-observe!) (vreset! *ticking? false)))
|
|
|
+ (vreset! *ticking? true)))
|
|
|
+ resize-observer (js/ResizeObserver. update-target!)
|
|
|
+ page-resize-observer (js/ResizeObserver. (fn [] (update-target-top!)))]
|
|
|
;; events
|
|
|
- (.observe resize-observer container)
|
|
|
- (.observe resize-observer table)
|
|
|
- (some->> page-el (.observe page-resize-observer))
|
|
|
- (.addEventListener container "scroll" target-observe-handle!)
|
|
|
- (.addEventListener table "scroll" update-target!)
|
|
|
- (.addEventListener table "resize" update-target!)
|
|
|
- (update-footer!)
|
|
|
+ (.observe resize-observer container)
|
|
|
+ (.observe resize-observer table)
|
|
|
+ (some->> page-el (.observe page-resize-observer))
|
|
|
+ (.addEventListener container "scroll" target-observe-handle!)
|
|
|
+ (.addEventListener table "scroll" update-target!)
|
|
|
+ (.addEventListener table "resize" update-target!)
|
|
|
+ (update-footer!)
|
|
|
|
|
|
;; teardown
|
|
|
- #(do (.removeEventListener container "scroll" target-observe!)
|
|
|
- (.disconnect resize-observer)
|
|
|
- (.disconnect page-resize-observer))))
|
|
|
- []))
|
|
|
+ #(do (.removeEventListener container "scroll" target-observe!)
|
|
|
+ (.disconnect resize-observer)
|
|
|
+ (.disconnect page-resize-observer))))
|
|
|
+ []))
|
|
|
|
|
|
(rum/defc table-header < rum/static
|
|
|
[& prop-and-children]
|
|
|
@@ -244,7 +244,7 @@
|
|
|
[& prop-and-children]
|
|
|
(let [[prop children] (get-prop-and-children prop-and-children)]
|
|
|
[:div.ls-table-row.flex.flex-row.items-center (merge {:class "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted bg-gray-01 items-stretch"}
|
|
|
- prop)
|
|
|
+ prop)
|
|
|
children]))
|
|
|
|
|
|
(rum/defc table-cell < rum/static
|
|
|
@@ -272,3 +272,5 @@
|
|
|
:style {:z-index 101}}
|
|
|
prop)
|
|
|
children]))
|
|
|
+
|
|
|
+(def table-sort-rows impl/sort-rows)
|