@ceriousdevtech/react-cerious-scroll 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,11 +5,20 @@ All notable changes to react-cerious-scroll will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.7] - 2026-06-24
9
+
10
+ ### Changed
11
+ - **A change in the item count now grows/shrinks the dataset in place instead of recreating the engine.** The hook calls `updateTotalElements()` (propagating the new count to navigation bounds, the scrollbar track, the renderer, and the height cache) rather than tearing down and rebuilding the scroller. A live append/prepend therefore keeps the scroll position and any in-progress scrollbar drag alive, and an appended dataset keeps a stable bottom index instead of a bouncing tail. A shrink that leaves the position past the new end is clamped, and the scrollbar thumb is re-synced after the lengthened track re-renders. No public API change.
12
+ - Updated the core engine dependency to `@ceriousdevtech/cerious-scroll@^1.0.8` (native-scrollbar drag rendering is now coalesced to one render per frame, with no per-row layout thrash on fast drags).
13
+
8
14
  ## [1.0.6] - 2026-06-11
9
15
 
10
16
  ### Fixed
11
17
  - **`recalculate()` now refreshes row content, not just heights.** It re-runs `renderItem` for every currently-rendered row (busting the per-index portal cache), so rows whose content depends on state outside `(item, index)` — e.g. a sliding/windowed data source where index → content shifts — update on an in-place refresh. Previously `recalculate()` only cleared the engine's height caches and re-measured, leaving such rows showing stale content; this now matches the Vue/Angular wrappers, whose `recalculate()` re-runs the row template/slot. A plain scroll still reuses cached portals for unchanged rows, so heavy rows stay cheap to scroll.
12
18
 
19
+ ### Changed
20
+ - Updated the core engine dependency to `@ceriousdevtech/cerious-scroll@^1.0.7` (scrollbar drag-to-top fix).
21
+
13
22
  ## [1.0.5] - 2026-06-08
14
23
 
15
24
  ### Added
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ee=require("react/jsx-runtime"),r=require("react"),z=require("react-dom"),te=require("react-dom/server"),G=require("@ceriousdevtech/cerious-scroll"),$="data-cerious-scroll-content",re="data-cerious-scroll-row";function ne(e){const u=e.querySelector(`[${$}]`);if(u)return u;const n=document.createElement("div");return n.setAttribute($,""),n.style.position="relative",n.style.width="100%",n.style.height="100%",n.style.overflowY="clip",n.style.overflowX="auto",e.appendChild(n),n}function ce(e,u){const n=h=>{const l=h.detail;l&&u({percentage:l.percentage,currentElement:l.currentElement,scrollOffset:l.scrollOffset,result:{element:l.result.element,offset:l.result.offset}})},f=h=>{const l=h.detail;l&&u({percentage:l.percentage,currentElement:l.element,scrollOffset:l.scrollOffset,result:{element:l.element,offset:l.scrollOffset}})};return e.addEventListener("cerious-viewport-change",n),e.addEventListener("viewport-change",f),()=>{e.removeEventListener("cerious-viewport-change",n),e.removeEventListener("viewport-change",f)}}function le(e,u){const n=typeof e=="number"?e:typeof u=="number"?u:void 0;if(n===void 0||Number.isNaN(n))throw new Error("useCeriousScroll: provide `totalElements` or `items`.");return Math.max(1,Math.floor(n))}function J(e){var Y;const u=r.useRef(null),n=r.useRef(null),f=r.useRef(new Map),h=r.useRef(new Map),l=r.useRef(null),R=r.useRef(null),S=r.useRef(null),T=r.useRef(e.tableHeader),[,M]=r.useReducer(t=>t+1,0),[A,p]=r.useState(null),b=r.useRef(e.renderItem),g=r.useRef(e.items??null),v=r.useRef(e.getItem),L=r.useRef(e.options),q=r.useRef(e.autoRender??!0),D=r.useRef(e.totalElements??null),H=r.useRef(e.onViewportChange),P=r.useRef(e.onMeasuredViewport),j=r.useRef(e.onReady);b.current=e.renderItem,g.current=e.items??null,v.current=e.getItem,T.current=e.tableHeader,L.current=e.options,q.current=e.autoRender??!0,D.current=e.totalElements??null,H.current=e.onViewportChange,P.current=e.onMeasuredViewport,j.current=e.onReady;const B=r.useCallback(t=>{const c=v.current;if(c)return c(t);const o=g.current;return o?o[t]:void 0},[]),s=r.useCallback(()=>{var I,O;const t=n.current;if(!t)return null;const{scroller:c,contentEl:o,container:a}=t,k=a.clientHeight||a.offsetHeight||0,w=[],m=((I=L.current)==null?void 0:I.layout)==="table",_=(i,d)=>{const C=document.createElement("div");m&&(C.style.display="contents"),C.setAttribute(re,String(i)),C.innerHTML=te.renderToStaticMarkup(r.createElement(r.Fragment,null,b.current(B(i),i))),d.appendChild(C),f.current.set(i,{el:d,mount:C}),w.push(C)},y=c.renderViewport(k,o,_),F=new Set(c.getRenderedIndices());return f.current.forEach((i,d)=>{F.has(d)||f.current.delete(d)}),w.forEach(i=>{i.textContent=""}),z.flushSync(M),(O=P.current)==null||O.call(P,y),y},[]),K=e.totalElements??((Y=e.items)==null?void 0:Y.length)??null;r.useEffect(()=>{var F,I,O;const t=u.current;if(!t)return;const c=ne(t),o=L.current??{},a=o.onScroll,k={...o,onScroll:()=>{a==null||a(),q.current&&s()}};if(o.layout==="table"&&T.current!=null){const i=(F=o.table)==null?void 0:F.header;k.table={...o.table,header:d=>{S.current=d,i==null||i(d)}}}const w=le(D.current,((I=g.current)==null?void 0:I.length)??null),m=new G.CeriousScroll(t,w,k);R.current&&(m.currentElement=Math.min(R.current.currentElement,w-1),m.scrollOffset=R.current.scrollOffset,R.current=null),n.current={scroller:m,contentEl:c,container:t},p(m);const _=ce(t,i=>{var d;(d=H.current)==null||d.call(H,i)});(O=j.current)==null||O.call(j,m);let y=0;return q.current&&(y=requestAnimationFrame(()=>s())),()=>{cancelAnimationFrame(y),_(),R.current={currentElement:m.currentElement,scrollOffset:m.scrollOffset},f.current.clear(),h.current.clear(),l.current=null,c.textContent="",m.detachScrollbar(t),m.dispose(),n.current=null,p(null)}},[K,s]),r.useEffect(()=>{if(!n.current||!q.current)return;const t=requestAnimationFrame(()=>s());return()=>cancelAnimationFrame(t)},[e.items,e.getItem]);const Q=r.useCallback(t=>{const c=n.current;return c?(c.scroller.jumpToElement(t),s()):null},[s]),U=r.useCallback(t=>{const c=n.current;return c?(c.scroller.handleScrollPercentage(t),s()):null},[s]),Z=r.useCallback(()=>{const t=n.current;return t?(t.scroller.reset(),s()):null},[s]),x=r.useCallback(()=>{const t=n.current;return t?(t.scroller.clearAllCaches(),h.current.clear(),s()):null},[s]),W=g.current,X=!v.current&&W!=null?W.length:null,N=b.current,E=h.current;l.current!==N&&(E.clear(),l.current=N);const V=[];return f.current.forEach((t,c)=>{if(X!==null&&c>=X){E.delete(c);return}const o=B(c);let a=E.get(c);(!a||a.item!==o||a.mount!==t.mount)&&(a={item:o,mount:t.mount,node:z.createPortal(N(o,c),t.mount,String(c))},E.set(c,a)),V.push(a.node)}),E.size>f.current.size&&E.forEach((t,c)=>{f.current.has(c)||E.delete(c)}),e.tableHeader!=null&&S.current&&V.push(z.createPortal(e.tableHeader,S.current,"cerious-thead")),{containerRef:u,portals:V,scroller:A,render:s,jumpToElement:Q,scrollToPercentage:U,reset:Z,recalculate:x}}function oe(e,u){const{className:n,style:f,"data-testid":h,children:l,...R}=e,{containerRef:S,portals:T,scroller:M,render:A,jumpToElement:p,scrollToPercentage:b,reset:g,recalculate:v}=J(R);return r.useImperativeHandle(u,()=>({scroller:M,render:A,jumpToElement:p,scrollToPercentage:b,reset:g,recalculate:v}),[M,A,p,b,g,v]),ee.jsxs("div",{ref:S,className:n,"data-testid":h,style:{position:"relative",overflow:"hidden",...f},children:[l,T]})}const ue=r.forwardRef(oe);Object.defineProperty(exports,"CeriousScrollEngine",{enumerable:!0,get:()=>G.CeriousScroll});exports.CeriousScroll=ue;exports.useCeriousScroll=J;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=require("react/jsx-runtime"),r=require("react"),D=require("react-dom"),re=require("react-dom/server"),K=require("@ceriousdevtech/cerious-scroll"),G="data-cerious-scroll-content",ne="data-cerious-scroll-row";function ce(e){const a=e.querySelector(`[${G}]`);if(a)return a;const c=document.createElement("div");return c.setAttribute(G,""),c.style.position="relative",c.style.width="100%",c.style.height="100%",c.style.overflowY="clip",c.style.overflowX="auto",e.appendChild(c),c}function le(e,a){const c=h=>{const l=h.detail;l&&a({percentage:l.percentage,currentElement:l.currentElement,scrollOffset:l.scrollOffset,result:{element:l.result.element,offset:l.result.offset}})},f=h=>{const l=h.detail;l&&a({percentage:l.percentage,currentElement:l.element,scrollOffset:l.scrollOffset,result:{element:l.element,offset:l.scrollOffset}})};return e.addEventListener("cerious-viewport-change",c),e.addEventListener("viewport-change",f),()=>{e.removeEventListener("cerious-viewport-change",c),e.removeEventListener("viewport-change",f)}}function J(e,a){const c=typeof e=="number"?e:typeof a=="number"?a:void 0;if(c===void 0||Number.isNaN(c))throw new Error("useCeriousScroll: provide `totalElements` or `items`.");return Math.max(1,Math.floor(c))}function Q(e){var $;const a=r.useRef(null),c=r.useRef(null),f=r.useRef(new Map),h=r.useRef(new Map),l=r.useRef(null),g=r.useRef(null),S=r.useRef(null),M=r.useRef(e.tableHeader),[,A]=r.useReducer(t=>t+1,0),[q,p]=r.useState(null),b=r.useRef(e.renderItem),R=r.useRef(e.items??null),v=r.useRef(e.getItem),L=r.useRef(e.options),w=r.useRef(e.autoRender??!0),N=r.useRef(e.totalElements??null),j=r.useRef(e.onViewportChange),H=r.useRef(e.onMeasuredViewport),P=r.useRef(e.onReady);b.current=e.renderItem,R.current=e.items??null,v.current=e.getItem,M.current=e.tableHeader,L.current=e.options,w.current=e.autoRender??!0,N.current=e.totalElements??null,j.current=e.onViewportChange,H.current=e.onMeasuredViewport,P.current=e.onReady;const B=r.useCallback(t=>{const n=v.current;if(n)return n(t);const o=R.current;return o?o[t]:void 0},[]),s=r.useCallback(()=>{var I,O;const t=c.current;if(!t)return null;const{scroller:n,contentEl:o,container:u}=t,k=u.clientHeight||u.offsetHeight||0,y=[],m=((I=L.current)==null?void 0:I.layout)==="table",z=(i,d)=>{const C=document.createElement("div");m&&(C.style.display="contents"),C.setAttribute(ne,String(i)),C.innerHTML=re.renderToStaticMarkup(r.createElement(r.Fragment,null,b.current(B(i),i))),d.appendChild(C),f.current.set(i,{el:d,mount:C}),y.push(C)},T=n.renderViewport(k,o,z),F=new Set(n.getRenderedIndices());return f.current.forEach((i,d)=>{F.has(d)||f.current.delete(d)}),y.forEach(i=>{i.textContent=""}),D.flushSync(A),(O=H.current)==null||O.call(H,T),T},[]),W=e.totalElements??(($=e.items)==null?void 0:$.length)??null;r.useEffect(()=>{var F,I,O;const t=a.current;if(!t)return;const n=ce(t),o=L.current??{},u=o.onScroll,k={...o,onScroll:()=>{u==null||u(),w.current&&s()}};if(o.layout==="table"&&M.current!=null){const i=(F=o.table)==null?void 0:F.header;k.table={...o.table,header:d=>{S.current=d,i==null||i(d)}}}const y=J(N.current,((I=R.current)==null?void 0:I.length)??null),m=new K.CeriousScroll(t,y,k);g.current&&(m.currentElement=Math.min(g.current.currentElement,y-1),m.scrollOffset=g.current.scrollOffset,g.current=null),c.current={scroller:m,contentEl:n,container:t},p(m);const z=le(t,i=>{var d;(d=j.current)==null||d.call(j,i)});(O=P.current)==null||O.call(P,m);let T=0;return w.current&&(T=requestAnimationFrame(()=>s())),()=>{cancelAnimationFrame(T),z(),g.current={currentElement:m.currentElement,scrollOffset:m.scrollOffset},f.current.clear(),h.current.clear(),l.current=null,n.textContent="",m.detachScrollbar(t),m.dispose(),c.current=null,p(null)}},[s]),r.useEffect(()=>{var o;const t=c.current;if(!t||W==null)return;const n=J(N.current,((o=R.current)==null?void 0:o.length)??null);if(n!==t.scroller.totalElements)if(t.scroller.updateTotalElements(n),t.scroller.currentElement>n-1&&t.scroller.jumpToElement(n-1),w.current){const u=t.scroller;requestAnimationFrame(()=>{s(),u.syncScrollbar()})}else t.scroller.syncScrollbar()},[W,s]),r.useEffect(()=>{if(!c.current||!w.current)return;const t=requestAnimationFrame(()=>s());return()=>cancelAnimationFrame(t)},[e.items,e.getItem]);const U=r.useCallback(t=>{const n=c.current;return n?(n.scroller.jumpToElement(t),s()):null},[s]),Z=r.useCallback(t=>{const n=c.current;return n?(n.scroller.handleScrollPercentage(t),s()):null},[s]),x=r.useCallback(()=>{const t=c.current;return t?(t.scroller.reset(),s()):null},[s]),ee=r.useCallback(()=>{const t=c.current;return t?(t.scroller.clearAllCaches(),h.current.clear(),s()):null},[s]),X=R.current,Y=!v.current&&X!=null?X.length:null,V=b.current,E=h.current;l.current!==V&&(E.clear(),l.current=V);const _=[];return f.current.forEach((t,n)=>{if(Y!==null&&n>=Y){E.delete(n);return}const o=B(n);let u=E.get(n);(!u||u.item!==o||u.mount!==t.mount)&&(u={item:o,mount:t.mount,node:D.createPortal(V(o,n),t.mount,String(n))},E.set(n,u)),_.push(u.node)}),E.size>f.current.size&&E.forEach((t,n)=>{f.current.has(n)||E.delete(n)}),e.tableHeader!=null&&S.current&&_.push(D.createPortal(e.tableHeader,S.current,"cerious-thead")),{containerRef:a,portals:_,scroller:q,render:s,jumpToElement:U,scrollToPercentage:Z,reset:x,recalculate:ee}}function oe(e,a){const{className:c,style:f,"data-testid":h,children:l,...g}=e,{containerRef:S,portals:M,scroller:A,render:q,jumpToElement:p,scrollToPercentage:b,reset:R,recalculate:v}=Q(g);return r.useImperativeHandle(a,()=>({scroller:A,render:q,jumpToElement:p,scrollToPercentage:b,reset:R,recalculate:v}),[A,q,p,b,R,v]),te.jsxs("div",{ref:S,className:c,"data-testid":h,style:{position:"relative",overflow:"hidden",...f},children:[l,M]})}const se=r.forwardRef(oe);Object.defineProperty(exports,"CeriousScrollEngine",{enumerable:!0,get:()=>K.CeriousScroll});exports.CeriousScroll=se;exports.useCeriousScroll=Q;
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
- import { jsxs as ee } from "react/jsx-runtime";
2
- import { useRef as o, useReducer as te, useState as re, useCallback as w, useEffect as Y, createElement as ne, Fragment as ce, forwardRef as oe, useImperativeHandle as le } from "react";
3
- import { flushSync as se, createPortal as G } from "react-dom";
4
- import { renderToStaticMarkup as ue } from "react-dom/server";
5
- import { CeriousScroll as ae } from "@ceriousdevtech/cerious-scroll";
1
+ import { jsxs as te } from "react/jsx-runtime";
2
+ import { useRef as o, useReducer as re, useState as ne, useCallback as S, useEffect as B, createElement as ce, Fragment as le, forwardRef as oe, useImperativeHandle as se } from "react";
3
+ import { flushSync as ue, createPortal as J } from "react-dom";
4
+ import { renderToStaticMarkup as ae } from "react-dom/server";
5
+ import { CeriousScroll as ie } from "@ceriousdevtech/cerious-scroll";
6
6
  import { CeriousScroll as ye } from "@ceriousdevtech/cerious-scroll";
7
- const J = "data-cerious-scroll-content", ie = "data-cerious-scroll-row";
8
- function fe(e) {
9
- const s = e.querySelector(`[${J}]`);
10
- if (s) return s;
11
- const r = document.createElement("div");
12
- return r.setAttribute(J, ""), r.style.position = "relative", r.style.width = "100%", r.style.height = "100%", r.style.overflowY = "clip", r.style.overflowX = "auto", e.appendChild(r), r;
7
+ const K = "data-cerious-scroll-content", fe = "data-cerious-scroll-row";
8
+ function me(e) {
9
+ const a = e.querySelector(`[${K}]`);
10
+ if (a) return a;
11
+ const n = document.createElement("div");
12
+ return n.setAttribute(K, ""), n.style.position = "relative", n.style.width = "100%", n.style.height = "100%", n.style.overflowY = "clip", n.style.overflowX = "auto", e.appendChild(n), n;
13
13
  }
14
- function me(e, s) {
15
- const r = (h) => {
14
+ function de(e, a) {
15
+ const n = (h) => {
16
16
  const c = h.detail;
17
- c && s({
17
+ c && a({
18
18
  percentage: c.percentage,
19
19
  currentElement: c.currentElement,
20
20
  scrollOffset: c.scrollOffset,
@@ -22,152 +22,165 @@ function me(e, s) {
22
22
  });
23
23
  }, f = (h) => {
24
24
  const c = h.detail;
25
- c && s({
25
+ c && a({
26
26
  percentage: c.percentage,
27
27
  currentElement: c.element,
28
28
  scrollOffset: c.scrollOffset,
29
29
  result: { element: c.element, offset: c.scrollOffset }
30
30
  });
31
31
  };
32
- return e.addEventListener("cerious-viewport-change", r), e.addEventListener("viewport-change", f), () => {
33
- e.removeEventListener("cerious-viewport-change", r), e.removeEventListener("viewport-change", f);
32
+ return e.addEventListener("cerious-viewport-change", n), e.addEventListener("viewport-change", f), () => {
33
+ e.removeEventListener("cerious-viewport-change", n), e.removeEventListener("viewport-change", f);
34
34
  };
35
35
  }
36
- function de(e, s) {
37
- const r = typeof e == "number" ? e : typeof s == "number" ? s : void 0;
38
- if (r === void 0 || Number.isNaN(r))
36
+ function Q(e, a) {
37
+ const n = typeof e == "number" ? e : typeof a == "number" ? a : void 0;
38
+ if (n === void 0 || Number.isNaN(n))
39
39
  throw new Error("useCeriousScroll: provide `totalElements` or `items`.");
40
- return Math.max(1, Math.floor(r));
40
+ return Math.max(1, Math.floor(n));
41
41
  }
42
42
  function he(e) {
43
- var X;
44
- const s = o(null), r = o(null), f = o(/* @__PURE__ */ new Map()), h = o(/* @__PURE__ */ new Map()), c = o(null), g = o(null), C = o(null), M = o(e.tableHeader), [, A] = te((t) => t + 1, 0), [H, S] = re(null), v = o(e.renderItem), E = o(e.items ?? null), R = o(e.getItem), _ = o(e.options), F = o(e.autoRender ?? !0), $ = o(e.totalElements ?? null), L = o(e.onViewportChange), N = o(e.onMeasuredViewport), P = o(e.onReady);
45
- v.current = e.renderItem, E.current = e.items ?? null, R.current = e.getItem, M.current = e.tableHeader, _.current = e.options, F.current = e.autoRender ?? !0, $.current = e.totalElements ?? null, L.current = e.onViewportChange, N.current = e.onMeasuredViewport, P.current = e.onReady;
46
- const B = w((t) => {
47
- const n = R.current;
48
- if (n) return n(t);
49
- const l = E.current;
43
+ var G;
44
+ const a = o(null), n = o(null), f = o(/* @__PURE__ */ new Map()), h = o(/* @__PURE__ */ new Map()), c = o(null), E = o(null), w = o(null), M = o(e.tableHeader), [, H] = re((t) => t + 1, 0), [F, C] = ne(null), b = o(e.renderItem), g = o(e.items ?? null), v = o(e.getItem), V = o(e.options), y = o(e.autoRender ?? !0), _ = o(e.totalElements ?? null), L = o(e.onViewportChange), N = o(e.onMeasuredViewport), j = o(e.onReady);
45
+ b.current = e.renderItem, g.current = e.items ?? null, v.current = e.getItem, M.current = e.tableHeader, V.current = e.options, y.current = e.autoRender ?? !0, _.current = e.totalElements ?? null, L.current = e.onViewportChange, N.current = e.onMeasuredViewport, j.current = e.onReady;
46
+ const D = S((t) => {
47
+ const r = v.current;
48
+ if (r) return r(t);
49
+ const l = g.current;
50
50
  return l ? l[t] : void 0;
51
- }, []), u = w(() => {
52
- var T, O;
53
- const t = r.current;
51
+ }, []), s = S(() => {
52
+ var O, A;
53
+ const t = n.current;
54
54
  if (!t) return null;
55
- const { scroller: n, contentEl: l, container: a } = t, j = a.clientHeight || a.offsetHeight || 0, y = [], m = ((T = _.current) == null ? void 0 : T.layout) === "table", z = (i, d) => {
56
- const b = document.createElement("div");
57
- m && (b.style.display = "contents"), b.setAttribute(ie, String(i)), b.innerHTML = ue(
58
- ne(ce, null, v.current(B(i), i))
59
- ), d.appendChild(b), f.current.set(i, { el: d, mount: b }), y.push(b);
60
- }, I = n.renderViewport(j, l, z), V = new Set(n.getRenderedIndices());
55
+ const { scroller: r, contentEl: l, container: u } = t, P = u.clientHeight || u.offsetHeight || 0, T = [], m = ((O = V.current) == null ? void 0 : O.layout) === "table", $ = (i, d) => {
56
+ const R = document.createElement("div");
57
+ m && (R.style.display = "contents"), R.setAttribute(fe, String(i)), R.innerHTML = ae(
58
+ ce(le, null, b.current(D(i), i))
59
+ ), d.appendChild(R), f.current.set(i, { el: d, mount: R }), T.push(R);
60
+ }, I = r.renderViewport(P, l, $), q = new Set(r.getRenderedIndices());
61
61
  return f.current.forEach((i, d) => {
62
- V.has(d) || f.current.delete(d);
63
- }), y.forEach((i) => {
62
+ q.has(d) || f.current.delete(d);
63
+ }), T.forEach((i) => {
64
64
  i.textContent = "";
65
- }), se(A), (O = N.current) == null || O.call(N, I), I;
66
- }, []), K = e.totalElements ?? ((X = e.items) == null ? void 0 : X.length) ?? null;
67
- Y(() => {
68
- var V, T, O;
69
- const t = s.current;
65
+ }), ue(H), (A = N.current) == null || A.call(N, I), I;
66
+ }, []), W = e.totalElements ?? ((G = e.items) == null ? void 0 : G.length) ?? null;
67
+ B(() => {
68
+ var q, O, A;
69
+ const t = a.current;
70
70
  if (!t) return;
71
- const n = fe(t), l = _.current ?? {}, a = l.onScroll, j = {
71
+ const r = me(t), l = V.current ?? {}, u = l.onScroll, P = {
72
72
  ...l,
73
73
  onScroll: () => {
74
- a == null || a(), F.current && u();
74
+ u == null || u(), y.current && s();
75
75
  }
76
76
  };
77
77
  if (l.layout === "table" && M.current != null) {
78
- const i = (V = l.table) == null ? void 0 : V.header;
79
- j.table = {
78
+ const i = (q = l.table) == null ? void 0 : q.header;
79
+ P.table = {
80
80
  ...l.table,
81
81
  header: (d) => {
82
- C.current = d, i == null || i(d);
82
+ w.current = d, i == null || i(d);
83
83
  }
84
84
  };
85
85
  }
86
- const y = de($.current, ((T = E.current) == null ? void 0 : T.length) ?? null), m = new ae(t, y, j);
87
- g.current && (m.currentElement = Math.min(g.current.currentElement, y - 1), m.scrollOffset = g.current.scrollOffset, g.current = null), r.current = { scroller: m, contentEl: n, container: t }, S(m);
88
- const z = me(t, (i) => {
86
+ const T = Q(_.current, ((O = g.current) == null ? void 0 : O.length) ?? null), m = new ie(t, T, P);
87
+ E.current && (m.currentElement = Math.min(E.current.currentElement, T - 1), m.scrollOffset = E.current.scrollOffset, E.current = null), n.current = { scroller: m, contentEl: r, container: t }, C(m);
88
+ const $ = de(t, (i) => {
89
89
  var d;
90
90
  (d = L.current) == null || d.call(L, i);
91
91
  });
92
- (O = P.current) == null || O.call(P, m);
92
+ (A = j.current) == null || A.call(j, m);
93
93
  let I = 0;
94
- return F.current && (I = requestAnimationFrame(() => u())), () => {
95
- cancelAnimationFrame(I), z(), g.current = {
94
+ return y.current && (I = requestAnimationFrame(() => s())), () => {
95
+ cancelAnimationFrame(I), $(), E.current = {
96
96
  currentElement: m.currentElement,
97
97
  scrollOffset: m.scrollOffset
98
- }, f.current.clear(), h.current.clear(), c.current = null, n.textContent = "", m.detachScrollbar(t), m.dispose(), r.current = null, S(null);
98
+ }, f.current.clear(), h.current.clear(), c.current = null, r.textContent = "", m.detachScrollbar(t), m.dispose(), n.current = null, C(null);
99
99
  };
100
- }, [K, u]), Y(() => {
101
- if (!r.current || !F.current) return;
102
- const t = requestAnimationFrame(() => u());
100
+ }, [s]), B(() => {
101
+ var l;
102
+ const t = n.current;
103
+ if (!t || W == null) return;
104
+ const r = Q(_.current, ((l = g.current) == null ? void 0 : l.length) ?? null);
105
+ if (r !== t.scroller.totalElements)
106
+ if (t.scroller.updateTotalElements(r), t.scroller.currentElement > r - 1 && t.scroller.jumpToElement(r - 1), y.current) {
107
+ const u = t.scroller;
108
+ requestAnimationFrame(() => {
109
+ s(), u.syncScrollbar();
110
+ });
111
+ } else
112
+ t.scroller.syncScrollbar();
113
+ }, [W, s]), B(() => {
114
+ if (!n.current || !y.current) return;
115
+ const t = requestAnimationFrame(() => s());
103
116
  return () => cancelAnimationFrame(t);
104
117
  }, [e.items, e.getItem]);
105
- const Q = w(
118
+ const U = S(
106
119
  (t) => {
107
- const n = r.current;
108
- return n ? (n.scroller.jumpToElement(t), u()) : null;
120
+ const r = n.current;
121
+ return r ? (r.scroller.jumpToElement(t), s()) : null;
109
122
  },
110
- [u]
111
- ), U = w(
123
+ [s]
124
+ ), Z = S(
112
125
  (t) => {
113
- const n = r.current;
114
- return n ? (n.scroller.handleScrollPercentage(t), u()) : null;
126
+ const r = n.current;
127
+ return r ? (r.scroller.handleScrollPercentage(t), s()) : null;
115
128
  },
116
- [u]
117
- ), Z = w(() => {
118
- const t = r.current;
119
- return t ? (t.scroller.reset(), u()) : null;
120
- }, [u]), x = w(() => {
121
- const t = r.current;
122
- return t ? (t.scroller.clearAllCaches(), h.current.clear(), u()) : null;
123
- }, [u]), D = E.current, W = !R.current && D != null ? D.length : null, q = v.current, p = h.current;
124
- c.current !== q && (p.clear(), c.current = q);
125
- const k = [];
126
- return f.current.forEach((t, n) => {
127
- if (W !== null && n >= W) {
128
- p.delete(n);
129
+ [s]
130
+ ), x = S(() => {
131
+ const t = n.current;
132
+ return t ? (t.scroller.reset(), s()) : null;
133
+ }, [s]), ee = S(() => {
134
+ const t = n.current;
135
+ return t ? (t.scroller.clearAllCaches(), h.current.clear(), s()) : null;
136
+ }, [s]), X = g.current, Y = !v.current && X != null ? X.length : null, k = b.current, p = h.current;
137
+ c.current !== k && (p.clear(), c.current = k);
138
+ const z = [];
139
+ return f.current.forEach((t, r) => {
140
+ if (Y !== null && r >= Y) {
141
+ p.delete(r);
129
142
  return;
130
143
  }
131
- const l = B(n);
132
- let a = p.get(n);
133
- (!a || a.item !== l || a.mount !== t.mount) && (a = {
144
+ const l = D(r);
145
+ let u = p.get(r);
146
+ (!u || u.item !== l || u.mount !== t.mount) && (u = {
134
147
  item: l,
135
148
  mount: t.mount,
136
- node: G(q(l, n), t.mount, String(n))
137
- }, p.set(n, a)), k.push(a.node);
138
- }), p.size > f.current.size && p.forEach((t, n) => {
139
- f.current.has(n) || p.delete(n);
140
- }), e.tableHeader != null && C.current && k.push(G(e.tableHeader, C.current, "cerious-thead")), {
141
- containerRef: s,
142
- portals: k,
143
- scroller: H,
144
- render: u,
145
- jumpToElement: Q,
146
- scrollToPercentage: U,
147
- reset: Z,
148
- recalculate: x
149
+ node: J(k(l, r), t.mount, String(r))
150
+ }, p.set(r, u)), z.push(u.node);
151
+ }), p.size > f.current.size && p.forEach((t, r) => {
152
+ f.current.has(r) || p.delete(r);
153
+ }), e.tableHeader != null && w.current && z.push(J(e.tableHeader, w.current, "cerious-thead")), {
154
+ containerRef: a,
155
+ portals: z,
156
+ scroller: F,
157
+ render: s,
158
+ jumpToElement: U,
159
+ scrollToPercentage: Z,
160
+ reset: x,
161
+ recalculate: ee
149
162
  };
150
163
  }
151
- function ge(e, s) {
152
- const { className: r, style: f, "data-testid": h, children: c, ...g } = e, {
153
- containerRef: C,
164
+ function ge(e, a) {
165
+ const { className: n, style: f, "data-testid": h, children: c, ...E } = e, {
166
+ containerRef: w,
154
167
  portals: M,
155
- scroller: A,
156
- render: H,
157
- jumpToElement: S,
158
- scrollToPercentage: v,
159
- reset: E,
160
- recalculate: R
161
- } = he(g);
162
- return le(
163
- s,
164
- () => ({ scroller: A, render: H, jumpToElement: S, scrollToPercentage: v, reset: E, recalculate: R }),
165
- [A, H, S, v, E, R]
166
- ), /* @__PURE__ */ ee(
168
+ scroller: H,
169
+ render: F,
170
+ jumpToElement: C,
171
+ scrollToPercentage: b,
172
+ reset: g,
173
+ recalculate: v
174
+ } = he(E);
175
+ return se(
176
+ a,
177
+ () => ({ scroller: H, render: F, jumpToElement: C, scrollToPercentage: b, reset: g, recalculate: v }),
178
+ [H, F, C, b, g, v]
179
+ ), /* @__PURE__ */ te(
167
180
  "div",
168
181
  {
169
- ref: C,
170
- className: r,
182
+ ref: w,
183
+ className: n,
171
184
  "data-testid": h,
172
185
  style: { position: "relative", overflow: "hidden", ...f },
173
186
  children: [
@@ -177,9 +190,9 @@ function ge(e, s) {
177
190
  }
178
191
  );
179
192
  }
180
- const we = oe(ge);
193
+ const Se = oe(ge);
181
194
  export {
182
- we as CeriousScroll,
195
+ Se as CeriousScroll,
183
196
  ye as CeriousScrollEngine,
184
197
  he as useCeriousScroll
185
198
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ceriousdevtech/react-cerious-scroll",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "React bindings for CeriousScroll — high-performance virtual scrolling with O(1) memory and no height estimation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -56,7 +56,7 @@
56
56
  "demo:build": "vite build --config demo/vite.config.ts"
57
57
  },
58
58
  "dependencies": {
59
- "@ceriousdevtech/cerious-scroll": "^1.0.7"
59
+ "@ceriousdevtech/cerious-scroll": "^1.0.8"
60
60
  },
61
61
  "peerDependencies": {
62
62
  "react": ">=18 <20",