@aiquants/virtualscroll 1.0.0 → 1.2.0
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/README.md +56 -6
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +745 -669
- package/dist/index.js.map +1 -1
- package/dist/src/ScrollBar.d.ts +24 -1
- package/dist/src/ScrollBar.d.ts.map +1 -1
- package/dist/src/ScrollPane.d.ts +5 -1
- package/dist/src/ScrollPane.d.ts.map +1 -1
- package/dist/src/VirtualScroll.d.ts +2 -0
- package/dist/src/VirtualScroll.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/virtualscroll.css +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -95,6 +95,7 @@ function App() {
|
|
|
95
95
|
| `initialScrollIndex` | `number` | ❌ | Initial scroll index |
|
|
96
96
|
| `initialScrollOffset` | `number` | ❌ | Initial scroll offset |
|
|
97
97
|
| `tapScrollCircleOptions` | `ScrollBarTapCircleOptions` | ❌ | Customization for the auxiliary tap scroll circle |
|
|
98
|
+
| `renderThumbOverlay` | `(props: ScrollBarThumbOverlayRenderProps) => ReactNode` | ❌ | Render prop to anchor custom UI near the scrollbar thumb |
|
|
98
99
|
| `inertiaOptions` | `ScrollPaneInertiaOptions` | ❌ | Physics tuning for drag inertia |
|
|
99
100
|
|
|
100
101
|
### VirtualScrollHandle Methods
|
|
@@ -114,11 +115,21 @@ function App() {
|
|
|
114
115
|
### With Ref and Scroll Control
|
|
115
116
|
|
|
116
117
|
```tsx
|
|
117
|
-
import { VirtualScroll, VirtualScrollHandle } from '@aiquants/virtualscroll'
|
|
118
|
-
import { useRef } from 'react'
|
|
118
|
+
import { ScrollBarThumbOverlayRenderProps, VirtualScroll, VirtualScrollHandle } from '@aiquants/virtualscroll'
|
|
119
|
+
import { useCallback, useRef, useState } from 'react'
|
|
120
|
+
|
|
121
|
+
const items = Array.from({ length: 100000 }, (_, index) => ({
|
|
122
|
+
id: index,
|
|
123
|
+
text: `Item ${index}`,
|
|
124
|
+
height: (index % 20) * 2 + 30,
|
|
125
|
+
}))
|
|
126
|
+
|
|
127
|
+
const getItem = (index: number) => items[index]
|
|
128
|
+
const getItemHeight = (index: number) => items[index].height
|
|
119
129
|
|
|
120
130
|
function AdvancedExample() {
|
|
121
131
|
const virtualScrollRef = useRef<VirtualScrollHandle>(null)
|
|
132
|
+
const [visibleStartIndex, setVisibleStartIndex] = useState(0)
|
|
122
133
|
|
|
123
134
|
const scrollToTop = () => {
|
|
124
135
|
virtualScrollRef.current?.scrollTo(0)
|
|
@@ -128,6 +139,40 @@ function AdvancedExample() {
|
|
|
128
139
|
virtualScrollRef.current?.scrollToIndex(index)
|
|
129
140
|
}
|
|
130
141
|
|
|
142
|
+
const handleRangeChange = useCallback((
|
|
143
|
+
_renderingStartIndex: number,
|
|
144
|
+
_renderingEndIndex: number,
|
|
145
|
+
visibleStart: number,
|
|
146
|
+
_visibleEndIndex: number,
|
|
147
|
+
_scrollPosition: number,
|
|
148
|
+
_totalHeight: number,
|
|
149
|
+
) => {
|
|
150
|
+
setVisibleStartIndex(visibleStart)
|
|
151
|
+
}, [])
|
|
152
|
+
|
|
153
|
+
const renderThumbOverlay = useCallback((props: ScrollBarThumbOverlayRenderProps) => {
|
|
154
|
+
if (!(props.isDragging || props.isTapScrollActive)) {
|
|
155
|
+
return null
|
|
156
|
+
}
|
|
157
|
+
const activeItem = items[visibleStartIndex]
|
|
158
|
+
const label = activeItem ? activeItem.text : `Item ${visibleStartIndex}`
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<div
|
|
162
|
+
className="pointer-events-none absolute flex items-center"
|
|
163
|
+
style={
|
|
164
|
+
props.orientation === 'vertical'
|
|
165
|
+
? { top: props.thumbCenter, left: -14, transform: 'translate(-100%, -50%)' }
|
|
166
|
+
: { left: props.thumbCenter, top: -14, transform: 'translate(-50%, -100%)' }
|
|
167
|
+
}
|
|
168
|
+
>
|
|
169
|
+
<div className="rounded-full border border-slate-200 bg-white px-2 py-1 text-xs font-medium text-slate-700 shadow-md">
|
|
170
|
+
{label}
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
)
|
|
174
|
+
}, [visibleStartIndex])
|
|
175
|
+
|
|
131
176
|
return (
|
|
132
177
|
<div>
|
|
133
178
|
<div>
|
|
@@ -136,13 +181,12 @@ function AdvancedExample() {
|
|
|
136
181
|
</div>
|
|
137
182
|
<VirtualScroll
|
|
138
183
|
ref={virtualScrollRef}
|
|
139
|
-
itemCount={
|
|
184
|
+
itemCount={items.length}
|
|
140
185
|
getItem={getItem}
|
|
141
186
|
getItemHeight={getItemHeight}
|
|
142
187
|
viewportSize={400}
|
|
143
|
-
onRangeChange={
|
|
144
|
-
|
|
145
|
-
}}
|
|
188
|
+
onRangeChange={handleRangeChange}
|
|
189
|
+
renderThumbOverlay={renderThumbOverlay}
|
|
146
190
|
>
|
|
147
191
|
{(item, index) => <ItemComponent item={item} index={index} />}
|
|
148
192
|
</VirtualScroll>
|
|
@@ -182,6 +226,7 @@ The auxiliary tap scroll circle can replace the native scrollbar for large datas
|
|
|
182
226
|
|
|
183
227
|
- **Adaptive speed scaling** automatically ramps up to a `120×` multiplier as `itemCount` grows (trillions supported).
|
|
184
228
|
- **Manual overrides** let you clamp or extend speed via `maxSpeedMultiplier` when you need deterministic behavior.
|
|
229
|
+
- **Exponential capping** enables distance-sensitive ceilings with `maxSpeedCurve`, blending gentle near-threshold drag with high-speed travel at extended distances. Use `easedOffset` to slightly raise the entry-level speed without changing the ceiling.
|
|
185
230
|
- **Full layout control** (`size`, `offsetX`, `offsetY`) keeps the circle accessible on both desktop and touch devices.
|
|
186
231
|
- **Visibility tuning** exposes an `opacity` knob so you can match subdued or high-contrast UI themes.
|
|
187
232
|
|
|
@@ -203,6 +248,11 @@ export function UltraFastExample() {
|
|
|
203
248
|
viewportSize={480}
|
|
204
249
|
tapScrollCircleOptions={{
|
|
205
250
|
maxSpeedMultiplier: 80, // Optional: override adaptive speed when needed
|
|
251
|
+
maxSpeedCurve: {
|
|
252
|
+
exponentialSteepness: 6,
|
|
253
|
+
exponentialScale: 80,
|
|
254
|
+
easedOffset: 0.1,
|
|
255
|
+
},
|
|
206
256
|
offsetX: -96,
|
|
207
257
|
opacity: 0.85,
|
|
208
258
|
}}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("react/jsx-runtime"),n=require("react"),be=require("tailwind-merge"),Ne={active:!1,offsetX:0,offsetY:0,distance:0,direction:0},Oe=6,et=({dragState:a,normalizedDistance:e})=>{const t=1+e*.18,s=.16+e*.24,r=.38+e*.28,i=a.active?"80ms ease-out":"220ms ease";return E.jsxs(E.Fragment,{children:[E.jsx("div",{className:"absolute inset-0 rounded-full",style:{background:"linear-gradient(140deg, rgba(255,255,255,0.62), rgba(72,72,72,0.48))",boxShadow:`0 0 0 1px rgba(255,255,255,0.28), 0 10px 22px rgba(0,0,0,${s})`,transform:`scale(${t})`,transition:`${i}, ${a.active?"80ms":"260ms"} box-shadow ease`}}),E.jsx("div",{className:"absolute inset-[18%] rounded-full",style:{background:"linear-gradient(140deg, rgba(255,255,255,0.72), rgba(28,28,28,0.58))",boxShadow:"inset 0 4px 10px rgba(0,0,0,0.24), inset 0 0 2px rgba(255,255,255,0.55)",opacity:r,transition:a.active?"120ms opacity ease-out":"220ms opacity ease"}})]})},Xe=n.forwardRef(({onDragChange:a,className:e,maxVisualDistance:t=160,size:s=40,style:r,opacity:i=1,renderVisual:c},l)=>{const[m,d]=n.useState(Ne),f=n.useRef(null),g=n.useRef({x:0,y:0}),A=n.useRef(null),V=n.useCallback(p=>{d(p),a(p)},[a]),H=n.useCallback((p,D,h=!1)=>{const{x:k,y:x}=g.current,N=p-k,L=D-x,F=Math.abs(L),R=F<Oe?0:L<0?-1:1;V({active:h||F>=Oe,offsetX:N,offsetY:L,distance:F,direction:R})},[V]),Q=n.useCallback(p=>{if(p===null)return;const D=A.current;D?.hasPointerCapture(p)&&D.releasePointerCapture(p)},[]),T=n.useCallback((p=!1)=>{p&&Q(f.current),f.current=null,V(Ne)},[V,Q]),oe=n.useCallback(p=>{p.preventDefault(),p.stopPropagation();const D=A.current??p.currentTarget,{left:h,top:k,width:x,height:N}=D.getBoundingClientRect();g.current={x:h+x/2,y:k+N/2},f.current=p.pointerId,D.setPointerCapture(p.pointerId),H(p.clientX,p.clientY,!0)},[H]),ae=n.useCallback(p=>{f.current===p.pointerId&&(p.preventDefault(),H(p.clientX,p.clientY))},[H]),G=n.useCallback(p=>{f.current===p.pointerId&&(p.preventDefault(),p.stopPropagation(),T(!0))},[T]);n.useImperativeHandle(l,()=>({reset:()=>{T(!0)},getElement:()=>A.current}),[T]);const _=Math.min(Math.max(i,0),1),$=s/64,O=Math.min(m.distance,t)/t,b=m.direction*O*10*$,P=c??et,S={dragState:m,normalizedDistance:O,sizeScale:$,size:s,opacity:_},j={...r,width:s,height:s,transform:`translateY(${b}px)`};return j.opacity=_,E.jsx("div",{ref:A,className:be.twMerge("relative flex touch-none select-none items-center justify-center","transition-transform duration-100 ease-out",e),style:j,onPointerDown:oe,onPointerMove:ae,onPointerUp:G,onPointerCancel:G,role:"presentation",children:P(S)})});Xe.displayName="TapScrollCircle";const U=(a,e,t)=>Math.min(t,Math.max(e,a)),Ye=(a,e,t)=>{const s="touches"in a.nativeEvent,r=s?a.nativeEvent.touches[0]:a.nativeEvent,i=l=>{s&&l.cancelable&&l.preventDefault();const m="touches"in l?l.touches[0]:l;e({deltaX:m.clientX-r.clientX,deltaY:m.clientY-r.clientY})},c=()=>{s?(document.removeEventListener("touchmove",i),document.removeEventListener("touchend",c)):(document.removeEventListener("mousemove",i),document.removeEventListener("mouseup",c)),t?.()};s?(document.addEventListener("touchmove",i,{passive:!1}),document.addEventListener("touchend",c)):(document.addEventListener("mousemove",i),document.addEventListener("mouseup",c))},Ce="virtualscroll:tap-scroll-cancel",ze=20,tt=250,st=60,nt=20,rt=20,ot=220,je={active:!1,offsetX:0,offsetY:0,distance:0,direction:0},Re=2.2,at=8,it=120,fe={enabled:!0,size:40,offsetX:-80,offsetY:0,className:void 0,maxVisualDistance:ot,opacity:1,renderVisual:void 0},lt=a=>{if(!a||a<=0)return Re;const e=Math.max(1,a),t=Math.log10(e),s=Re+t*at;return U(s,Re,it)},Ue=({contentSize:a,viewportSize:e,scrollPosition:t,onScroll:s,enableThumbDrag:r=!0,enableTrackClick:i=!0,enableArrowButtons:c=!0,horizontal:l=!1,scrollBarWidth:m=12,className:d,ariaControls:f,tapScrollCircleOptions:g,itemCount:A})=>{const[V,H]=n.useState(!1),[Q,T]=n.useState(!1),[oe,ae]=n.useState(!1),G=n.useRef(null),_=n.useRef(t),$=n.useRef(null),O=n.useRef(null),b=n.useRef(je),P=n.useRef(null),S=n.useRef(null),j=n.useRef(null),p=n.useMemo(()=>{const o=g?.maxSpeedMultiplier,v=typeof o=="number"?o:lt(A);return{enabled:g?.enabled??fe.enabled,size:g?.size??fe.size,offsetX:g?.offsetX??fe.offsetX,offsetY:g?.offsetY??fe.offsetY,className:g?.className??fe.className,maxVisualDistance:g?.maxVisualDistance??fe.maxVisualDistance,maxSpeedMultiplier:v,opacity:U(g?.opacity??fe.opacity,0,1),renderVisual:g?.renderVisual??fe.renderVisual}},[A,g]),{enabled:D,size:h,offsetX:k,offsetY:x,className:N,maxVisualDistance:L,maxSpeedMultiplier:F,opacity:R,renderVisual:w}=p,M=l?"width":"height",y=l?"height":"width",I=l?"left":"top",C=l?"clientX":"clientY",q=(o,v)=>l?o:v,ne=o=>o[C],K=l?["Scroll left","Scroll right"]:["Scroll up","Scroll down"],W=l?["◀","▶"]:["▲","▼"],te=l?"flex flex-row items-stretch":"flex flex-col items-stretch",B=Math.max(L,1),ce=e/a,Y=m,u=Math.max(e-Y*2,0),Z=ce*u,J=Math.min(Math.max(ze,Z||0),u||ze),z=a-e,re=Math.max(u-J,0),he=z<=0||re<=0?0:t/z*re,ue=a>e,Ae=ue&&c;n.useEffect(()=>{_.current=t},[t]),n.useEffect(()=>{r||T(!1)},[r]),n.useEffect(()=>{const o=G.current;if(!o)return;const v=l?"scaleY(1.06)":"scaleX(1.06)",X=l?"scaleY(1.12)":"scaleX(1.12)";if(!r){o.style.removeProperty("transform"),o.style.backgroundColor="#7F7F7F",o.style.removeProperty("transition");return}if(V){o.style.transform=X,o.style.backgroundColor="#4F4F4F",o.style.transition="transform 60ms ease-out";return}o.style.transition="transform 80ms ease-out",Q?(o.style.transform=v,o.style.backgroundColor="#5F5F5F"):(o.style.removeProperty("transform"),o.style.backgroundColor="#7F7F7F")},[r,l,V,Q]);const ve=n.useCallback(()=>{$.current!==null&&(window.clearInterval($.current),$.current=null),O.current!==null&&(window.clearTimeout(O.current),O.current=null)},[]),ie=n.useCallback(()=>{S.current!==null&&(window.cancelAnimationFrame(S.current),S.current=null),j.current=null},[]),le=n.useCallback(()=>{b.current={...je},ae(!1),P.current?.reset(),ie()},[ie]),Te=n.useCallback(o=>{const v=b.current;if(!v.active||v.direction===0){ie();return}if(!ue||z<=0){ie();return}const X=j.current??o,ee=Math.max((o-X)/1e3,0);if(j.current=o,ee<=0){S.current=window.requestAnimationFrame(Te);return}const Me=(Math.min(v.distance,B)/B)**1.1,pe=Math.max(e*.2,40),Ee=Math.max(e*F,1200),Ve=pe+(Ee-pe)*Me,ge=_.current,Pe=U(ge+v.direction*Ve*ee,0,z);if(Pe===ge){ie();return}_.current=Pe,s?.(Pe,ge),S.current=window.requestAnimationFrame(Te)},[B,z,s,ue,ie,F,e]),_e=n.useCallback(()=>{S.current===null&&(j.current=null,S.current=window.requestAnimationFrame(Te))},[Te]);n.useEffect(()=>()=>{ve(),ie()},[ve,ie]);const Ge=n.useCallback(o=>{b.current=o,ae(o.active),o.active&&o.direction!==0?_e():ie()},[_e,ie]);n.useEffect(()=>{D||le()},[le,D]),n.useEffect(()=>{const o=v=>{const ee=v.detail?.paneId;ee&&f&&ee!==f||le()};return window.addEventListener(Ce,o),()=>{window.removeEventListener(Ce,o)}},[f,le]),n.useEffect(()=>{if(!D)return;const o=v=>{if(!b.current.active)return;const X=v.target;if(!(X instanceof Node)){le();return}P.current?.getElement()?.contains(X)||le()};return document.addEventListener("pointerdown",o,!0),()=>{document.removeEventListener("pointerdown",o,!0)}},[le,D]);const Se=o=>{if(!ue||re<=0||z<=0)return 0;const v=U(o,0,re);return U(v/re*z,0,z)},Ie=o=>{if(!ue||z<=0)return;const v=Math.max(Math.round(e/rt),nt),X=_.current,ee=U(X+o*v,0,z);ee!==X&&(_.current=ee,s?.(ee,X))},ye=()=>{ve()},ke=o=>v=>{Ae&&(v.preventDefault(),v.stopPropagation(),le(),ve(),Ie(o),O.current=window.setTimeout(()=>{$.current=window.setInterval(()=>{Ie(o)},st)},tt))},Ze=o=>v=>{c&&(v.key==="Enter"||v.key===" "||v.key==="Spacebar")&&(v.preventDefault(),Ie(o))},Le=o=>{if(!ue)return;if(!r){o.preventDefault(),o.stopPropagation();return}if("button"in o&&o.button!==0||o.ctrlKey)return;o.stopPropagation(),le();const v=he;H(!0),T(!0),Ye(o,({deltaX:X,deltaY:ee})=>{const me=q(X,ee);s?.(Se(v+me),he)},()=>{H(!1),G.current&&!G.current.matches(":hover")&&T(!1)})},Fe=o=>{if(!ue)return;if(!i){o.preventDefault(),o.stopPropagation();return}if("button"in o&&o.button!==0||o.ctrlKey)return;const X="touches"in o.nativeEvent?o.nativeEvent.touches[0]:o.nativeEvent,ee=ne(X),me=o.currentTarget.getBoundingClientRect(),Me=ee-(l?me.left:me.top);le();const pe=Me-J/2;s?.(Se(pe),he),Ye(o,({deltaX:Ee,deltaY:Ve})=>{const ge=q(Ee,Ve);s?.(Se(pe+ge),he)})},Je=n.useMemo(()=>U((oe?1:.8)*R,0,1),[oe,R]),Qe=n.useMemo(()=>{const v=`calc(50% - ${h/2}px + ${x}px)`;return{left:k,top:v}},[k,x,h]),De=(o,v,X)=>E.jsx("button",{type:"button",className:"flex items-center justify-center text-[#313131] text-xs transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[#60a5fa] focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50",style:{[M]:Y,[y]:m,backgroundColor:"#E0E0E0"},"aria-label":v,onMouseDown:ke(o),onTouchStart:ke(o),onMouseUp:ye,onMouseLeave:ye,onTouchEnd:ye,onTouchCancel:ye,onKeyDown:Ze(o),"aria-disabled":!c,disabled:!Ae,children:E.jsx("span",{"aria-hidden":"true",children:X})});return E.jsxs("div",{className:be.twMerge("group relative cursor-default select-none",te,d),style:{[M]:e,[y]:m,backgroundColor:"white",userSelect:"none",position:"relative"},role:"scrollbar",tabIndex:-1,"aria-controls":f,"aria-valuenow":t,"aria-valuemin":0,"aria-valuemax":z,"aria-orientation":l?"horizontal":"vertical",children:[!l&&ue&&D&&E.jsx(Xe,{ref:P,className:be.twMerge("pointer-events-auto absolute transition-opacity duration-150",N),size:h,maxVisualDistance:B,style:Qe,opacity:Je,renderVisual:w,onDragChange:Ge}),De(-1,K[0],W[0]),E.jsx("div",{className:"relative flex-1",style:{backgroundColor:"#F5F5F5",borderRadius:m/2},onMouseDown:Fe,onTouchStart:Fe,"aria-disabled":!i,children:ue&&E.jsx("div",{className:"group absolute",style:{[M]:J,[I]:he,...l?{top:0,bottom:0}:{left:0,right:0}},onMouseDown:Le,onTouchStart:Le,role:"slider","aria-orientation":l?"horizontal":"vertical","aria-valuenow":t,"aria-valuemin":0,"aria-valuemax":z,"aria-disabled":!r,tabIndex:r?0:-1,children:E.jsx("div",{ref:G,className:be.twMerge("absolute",l?`inset-x-0 inset-y-[1.5px] group-hover:inset-y-[-0.5px] ${V?"-inset-y-0.5":"group-active:-inset-y-0.5"}`:`inset-x-[1.5px] inset-y-0 group-hover:inset-x-[-0.5px] ${V?"-inset-x-0.5":"group-active:-inset-x-0.5"}`),style:{backgroundColor:"#7F7F7F",borderRadius:m-1,cursor:r?"pointer":"default",...l?{left:0,right:0,top:1.5,bottom:1.5}:{top:0,bottom:0,left:1.5,right:1.5}},onMouseEnter:()=>{r&&T(!0)},onMouseLeave:()=>{r&&T(!1)}})})}),De(1,K[1],W[1])]})},se={debug(a,...e){typeof window<"u"&&window.localStorage?.getItem("debug")==="true"&&console.debug(`[VirtualScroll] ${a}`,...e)},warn(a,...e){console.warn(`[VirtualScroll] ${a}`,...e)},error(a,...e){console.error(`[VirtualScroll] ${a}`,...e)}},xe={maxVelocity:6,minVelocity:.02,deceleration:.0025,velocitySampleWindow:90,startVelocityThreshold:.04},we=(a,e,t)=>{for(const[s,r,i]of e)t==="add"?a.addEventListener(s,r,i):a.removeEventListener(s,r,i)},qe=n.forwardRef(({children:a,contentSize:e,viewportSize:t,scrollBarWidth:s=12,enableThumbDrag:r=!0,enableTrackClick:i=!0,enableArrowButtons:c=!0,enablePointerDrag:l=!0,onScroll:m,className:d,style:f,background:g,tapScrollCircleOptions:A,inertiaOptions:V,itemCount:H},Q)=>{const T=n.useRef(0),[oe,ae]=n.useReducer(h=>h+1,0),G=n.useRef(null),_=n.useRef(null),$=n.useRef({frame:null,velocity:0,lastTimestamp:null}),O=n.useMemo(()=>({maxVelocity:V?.maxVelocity??xe.maxVelocity,minVelocity:V?.minVelocity??xe.minVelocity,deceleration:V?.deceleration??xe.deceleration,velocitySampleWindow:V?.velocitySampleWindow??xe.velocitySampleWindow,startVelocityThreshold:V?.startVelocityThreshold??xe.startVelocityThreshold}),[V]);se.debug("[ScrollPane] ScrollPane rendered",{contentSize:e,viewportSize:t,scrollBarWidth:s,className:d,style:f,tapScrollCircleOptions:A,inertiaOptions:V,enablePointerDrag:l});const b=n.useRef({contentSize:e,viewportSize:t}),P=n.useMemo(()=>e>t,[e,t]),S=n.useCallback(h=>{const{contentSize:k,viewportSize:x}=b.current,N=k>x,L=T.current;if(se.debug("[ScrollPane] scrollTo called",{newPosition:h,contentSize:k,viewportSize:x,currentIsScrollable:N,prevPosition:L}),!N){T.current!==0&&(T.current=0,m?.(0,L));return}const F=typeof h=="function"?h(T.current):h,R=U(F,0,k-x);T.current!==R&&(T.current=R,m?.(R,L))},[m]),j=n.useCallback(()=>{const h=$.current;h.frame!==null&&cancelAnimationFrame(h.frame),h.frame=null,h.velocity=0,h.lastTimestamp=null},[]),p=n.useCallback(h=>{if(!P)return;const{maxVelocity:k,minVelocity:x,deceleration:N,startVelocityThreshold:L}=O,F=U(h,-k,k);if(Math.abs(F)<L)return;j(),$.current.velocity=F,$.current.lastTimestamp=null;const R=w=>{const M=$.current;if(M.lastTimestamp===null){M.lastTimestamp=w,M.frame=requestAnimationFrame(R);return}const y=w-M.lastTimestamp;if(M.lastTimestamp=w,y<=0){M.frame=requestAnimationFrame(R);return}const I=M.velocity;let C=I;const q=N*y;I>0?C=Math.max(0,I-q):I<0&&(C=Math.min(0,I+q));const K=(I+C)/2*y,W=T.current;K!==0&&S(Z=>Z+K);const te=T.current,{contentSize:B,viewportSize:ce}=b.current,Y=Math.max(B-ce,0);M.velocity=C;const u=te===W||te<=0&&C<=0||te>=Y&&C>=0;if(Math.abs(C)<x||u){j();return}M.frame=requestAnimationFrame(R)};$.current.frame=requestAnimationFrame(R)},[P,O,S,j]);n.useLayoutEffect(()=>{b.current={contentSize:e,viewportSize:t}},[e,t]),n.useLayoutEffect(()=>{if(P){se.debug("[ScrollPane] Adjusting scroll position due to content or viewport size change",{contentSize:e,viewportSize:t,scrollPosition:T.current});const h=U(e-t,0,e);T.current>h&&S(h)}else S(0)},[P,S,e,t]),n.useEffect(()=>{const h=x=>{if(!P)return;x.preventDefault(),j();let N=x.deltaY;x.deltaMode===1?N*=16:x.deltaMode===2&&(N*=t),se.debug("[ScrollPane] wheel event",{deltaY:N,scrollPosition:T.current}),S(L=>L+N)},k=G.current;return k&&k.addEventListener("wheel",h,{passive:!1}),()=>{k&&k.removeEventListener("wheel",h)}},[P,S,j,t]),n.useImperativeHandle(Q,()=>({scrollTo:S,getScrollPosition:()=>T.current,getContentSize:()=>e,getViewportSize:()=>t}),[S,e,t]);const D=n.useId();return n.useEffect(()=>{const h=_.current;if(!h)return;if(!l){j();return}const k=6;let x=null,N=0,L=0,F=!1,R=!1,w=null,M=[];const y=()=>{x=null,N=0,L=0,F=!1,M=[]},I=u=>{const Z=performance.now();M.push({clientY:u,time:Z}),M=M.filter(J=>Z-J.time<=O.velocitySampleWindow)},C=u=>u instanceof HTMLElement&&u.closest("[data-scrollpane-ignore-drag='true']")!==null,q=u=>{R&&(u.preventDefault(),u.stopPropagation(),R=!1)},ne=u=>{F||(F=!0,R=!0,h.hasPointerCapture(u.pointerId)||h.setPointerCapture(u.pointerId),I(u.clientY))},K=u=>{if(x!==u.pointerId||!F&&(Math.abs(u.clientY-N)<k||(ne(u),!F)))return;I(u.clientY);const Z=u.clientY-N,J=L-Z;S(J),u.cancelable&&u.preventDefault()},W=u=>{if(x!==u.pointerId)return;F&&R&&u.cancelable&&(u.preventDefault(),u.stopPropagation()),h.hasPointerCapture(u.pointerId)&&h.releasePointerCapture(u.pointerId);let Z=0;if(F&&M.length>=2){const J=M[M.length-1],z=M.find(re=>J.time-re.time<=O.velocitySampleWindow)??M[0];if(J&&z&&J.time!==z.time){const re=J.clientY-z.clientY,he=J.time-z.time;Z=-(re/he)}}y(),w!==null&&window.clearTimeout(w),R&&(w=window.setTimeout(()=>{R=!1,w=null},0)),Math.abs(Z)>=O.startVelocityThreshold&&p(Z)},te=u=>{P&&(u.button!==0&&u.pointerType==="mouse"||u.ctrlKey||u.metaKey||u.altKey||C(u.target)||(window.dispatchEvent(new CustomEvent(Ce,{detail:{paneId:D}})),j(),x=u.pointerId,N=u.clientY,L=T.current,F=!1,R=!1,M=[]))},B=u=>{x===u.pointerId&&(R=!1,h.hasPointerCapture(u.pointerId)&&h.releasePointerCapture(u.pointerId),w!==null&&(window.clearTimeout(w),w=null),y())},ce=[["click",q,!0],["pointerdown",te,{passive:!1}],["pointermove",K,{passive:!1}],["pointerup",W,void 0],["pointercancel",B,void 0]],Y=[["pointermove",K,{passive:!1}],["pointerup",W,void 0],["pointercancel",B,void 0]];return we(h,ce,"add"),we(window,Y,"add"),()=>{we(h,ce,"remove"),we(window,Y,"remove"),x!==null&&h.hasPointerCapture(x)&&h.releasePointerCapture(x),w!==null&&window.clearTimeout(w),j()}},[l,D,P,O,S,p,j]),E.jsxs("div",{ref:G,className:be.twMerge("flex",d),style:f,children:[E.jsxs("div",{ref:_,className:"relative h-full flex-1 overflow-hidden",style:{height:t,...l?{touchAction:"none"}:{}},id:D,children:[g,a(T.current)]}),P&&E.jsx(Ue,{contentSize:e,viewportSize:t,scrollPosition:T.current,onScroll:S,enableThumbDrag:r,enableTrackClick:i,enableArrowButtons:c,scrollBarWidth:s,ariaControls:D,tapScrollCircleOptions:A,itemCount:H})]})}),He=(a,e,t)=>Math.min(Math.max(a,e),t),ct=({dragState:a,normalizedDistance:e,sizeScale:t,size:s})=>{const r=Math.max(s/2,1),i=1+e*.65,c=Math.max(.65,1-e*.25),l=a.direction*e*26*t,m=.8+e*.18,d=3*t,f=6*t,g=22*t,A=Math.abs(l)+f,V=l>0?d:-Math.abs(l)-d,H=Math.max(2.5,3*t),Q=He(a.offsetX,-r,r),T=He(a.offsetY,-r,r),oe=r*.35,ae=Q/r*oe,G=T/r*oe,_=ae*.45,$=G*.45,O=Math.max(g*.38,6),b=.65+e*.2,P=a.active;return E.jsxs(E.Fragment,{children:[E.jsx("div",{className:"absolute inset-0 rounded-full border border-white/40 bg-linear-to-br from-[#1d4ed8]/60 via-[#60a5fa]/55 to-[#bfdbfe]/40 shadow-md",style:{transform:`scale(${c}, ${i})`,transition:P?"40ms transform ease-out":"200ms ease transform"}}),E.jsx("div",{className:"absolute top-1/2 left-1/2 rounded-full border border-white/50 bg-white/85",style:{width:g,height:g,transform:`translate(calc(-50% + ${ae}px), calc(-50% + ${G}px)) scale(${c}, ${m*i})`,transition:P?"70ms transform ease-out":"200ms ease transform"}}),E.jsx("div",{className:"absolute top-1/2 left-1/2 rounded-full bg-white/80",style:{width:O,height:O,transform:`translate(calc(-50% + ${_}px), calc(-50% + ${$}px)) scale(${c}, ${i})`,opacity:b,boxShadow:"0 0 8px rgba(255,255,255,0.45)",transition:P?"120ms opacity 150ms, 120ms transform ease-out ease-out":"220ms ease transform, 240ms opacity ease"}}),E.jsx("div",{className:"absolute top-1/2 left-1/2 rounded-full bg-white/50",style:{width:H,height:A,transform:`translate(-50%, ${V}px)`,opacity:e,transition:P?"40ms height, 60ms opacity ease-out ease-out":"200ms ease height, 120ms ease opacity"}})]})};class Ke{tree;deltas;size;baseValue;valueFn;total;constructor(e,t,s){this.reset(e,t,s)}reset(e,t,s){if(this.size=e,this.tree=new Map,this.deltas=new Map,this.total=void 0,typeof t=="function"){if(this.valueFn=t,this.size>0){const i=s?.sampleRange??{from:0,to:Math.min(99,this.size-1)},{mode:c,materializedValues:l}=this._calculateMode(i.from,i.to);if(this.baseValue=c,s?.materialize)for(let m=0;m<l.length;m++){const d=l[m],f=i.from+m;if(f>=this.size)break;const g=d-this.baseValue;this.deltas.set(f,g),this._updateTree(f,g)}}else this.baseValue=0;this.total=this.getTotal()}else this.valueFn=void 0,this.baseValue=t,this.total=this.baseValue*this.size}setValueFn(e){typeof e=="function"?this.valueFn=e:(this.valueFn=void 0,this.baseValue=e)}_calculateMode(e,t){if(!this.valueFn)return{mode:0,materializedValues:[]};const s=[];for(let d=e;d<=t&&!(d>=this.size);d++)s.push(this.valueFn(d));const r=[...s];if(s.length===0)return{mode:0,materializedValues:[]};s.sort((d,f)=>d-f);const i=Math.floor(s.length/2);let c;s.length%2===0?c=Math.floor((s[i-1]+s[i])/2):c=s[i];const l=new Map;let m=0;for(const d of s){const f=(l.get(d)??0)+1;l.set(d,f),f>m&&(m=f)}if(m>1){const d=[];for(const[g,A]of l.entries())A===m&&d.push(g);const f=d.reduce((g,A)=>g+A,0);c=Math.floor(f/d.length)}return{mode:c,materializedValues:r}}update(e,t){return this.updates([{index:e,value:t}])}updates(e){const t=this._buildDeltaUpdates(e);return t.length>0?this.updateDeltas(t):this.total}updateDelta(e,t){return this.updateDeltas([{index:e,change:t}])}updateDeltas(e){for(const{index:t,change:s}of e){if(t<0||t>=this.size)throw new Error(`Index ${t} out of bounds`);const r=this.deltas.get(t)??0;this.deltas.set(t,r+s),this._updateTree(t,s)}return this.total}_updateTree(e,t){if(t===0)return;let s=e+1;for(;s<=this.size;)this.tree.set(s,(this.tree.get(s)??0)+t),s+=s&-s;this.total!==void 0&&(this.total+=t)}_buildDeltaUpdates(e){const t=[];for(const{index:s,value:r}of e){if(s<0||s>=this.size)throw new Error(`Index ${s} out of bounds`);if(r<0)throw new Error("Value cannot be negative.");const i=this.deltas.has(s)?(this.deltas.get(s)??0)+this.baseValue:this.baseValue,c=r-i;c!==0&&t.push({index:s,change:c})}return t}_materialize(e,t=!0){if(this.valueFn){const s=this.deltas.get(e)??0,i=this.valueFn(e)-this.baseValue;if(i!==s&&(this.deltas.set(e,i),t)){const c=i-s;this._updateTree(e,c)}}}_materializeRanges(e,t,s=!1){if(!(e?.materialize&&this.valueFn))return;const r=e.ranges;if(r&&r.length>0){for(const l of r){const m=l.from,d=Math.min(l.to,this.size-1);for(let f=m;f<=d;f++)this._materialize(f)}if(t===void 0)return;if(s){this._materialize(t);return}const i=r[0].from,c=r[r.length-1].to;t>=i&&t<=c&&this._materialize(t);return}t!==void 0&&this._materialize(t)}_findIndex(e,t={},s){if(this.size===0)return{index:-1,total:this.total??0,cumulative:void 0,currentValue:void 0,safeIndex:void 0};let r=0,i=this.size-1,c=-1,l,m=this.total;for(;r<=i;){const d=Math.floor((r+i)/2);l=this.prefixSum(d,t),m=l.total,(s?l.cumulative>=e:l.cumulative<=e)?(c=d,s?i=d-1:r=d+1):s?r=d+1:i=d-1}return{index:c,total:m,cumulative:l?.cumulative,currentValue:l?.currentValue,safeIndex:l?.safeIndex}}prefixSum(e,t){if(e<0)return{cumulative:0,total:this.total,currentValue:0,safeIndex:0};const s=U(e,0,this.size-1),r=t?.materializeOption;this._materializeRanges(r,s,!0);let i=0,c=s+1;for(;c>0;){const m=this.tree.get(c)??0;i+=m,c-=c&-c}const l=r?.materialize?this.get(s):(this.deltas.get(s)||0)+this.baseValue;return{cumulative:i+this.baseValue*(s+1),total:this.total,currentValue:l,safeIndex:s}}get(e,t){if(e<0||e>=this.size)throw new Error("Index out of bounds");const s=t?.materializeOption;return this._materializeRanges(s,e),(this.deltas.get(e)??0)+this.baseValue}getTotal(e){const t=e?.materializeOption;if(this._materializeRanges(t),this.total===void 0)if(this.size===0)this.total=0;else{let s=this.baseValue*this.size;for(const i of this.deltas.values())s+=i;this.total=s;const r=this.prefixSum(this.getSize()-1);console.assert(r.cumulative===r.total,"Inconsistent Fenwick Tree state")}return this.total}rebuildTree(e){if(e?.materialize&&this.valueFn){const r=this.valueFn;this.reset(this.size,i=>r(i),{materialize:!0});return}const t=new Map;let s=this.baseValue*this.size;for(const[r,i]of this.deltas.entries()){if(s+=i,i===0)continue;let c=r+1;for(;c<=this.size;)t.set(c,(t.get(c)??0)+i),c+=c&-c}this.tree=t,this.total=s}calculateAccumulatedError(){if(this.total===void 0)return 0;let e=this.baseValue*this.size;for(const t of this.deltas.values())e+=t;return this.total-e}changeSize(e){const t=this.size;if(e===t)return;if(e<t)for(const r of this.deltas.keys())r>=e&&this.deltas.delete(r);this.size=e,this.rebuildTree();const s=this.prefixSum(this.getSize()-1);console.assert(s.cumulative===s.total,"Inconsistent Fenwick Tree state")}getSize(){return this.size}findIndexAtOrAfter(e,t){return this._findIndex(e,t??{},!0)}findIndexAtOrBefore(e,t){return this._findIndex(e,t??{},!1)}}const We=(a,e,t)=>{const s=Math.max(0,a),r=n.useRef(null),i=n.useMemo(()=>new Ke(s,e,t),[s,e,t]);return Object.is(r.current,i)||console.warn("[useFenwickMapTree] instance changed"),r.current=i,i};class ut{key;value;prev=null;next=null;constructor(e,t){this.key=e,this.value=t}}class $e{head=null;tail=null;addToTail(e){this.tail?(this.tail.next=e,e.prev=this.tail,this.tail=e):this.head=this.tail=e}remove(e){e.prev?e.prev.next=e.next:this.head=e.next,e.next?e.next.prev=e.prev:this.tail=e.prev,e.prev=null,e.next=null}removeHead(){const e=this.head;return e&&this.remove(e),e}moveToTail(e){this.remove(e),this.addToTail(e)}}function Be(a){const e=n.useRef(new Map),t=n.useRef(new $e);n.useEffect(()=>{for(;e.current.size>a;){const d=t.current.removeHead();if(d)e.current.delete(d.key);else break}},[a]);const s=n.useCallback(d=>{const f=e.current.get(d);if(f)return t.current.moveToTail(f),f.value},[]),r=n.useCallback((d,f)=>{if(a<=0)return;let g=e.current.get(d);if(g)g.value=f,t.current.moveToTail(g);else{if(e.current.size>=a){const A=t.current.removeHead();A&&e.current.delete(A.key)}g=new ut(d,f),e.current.set(d,g),t.current.addToTail(g)}},[a]),i=n.useCallback(d=>e.current.has(d),[]),c=n.useCallback(()=>{e.current.clear(),t.current=new $e},[]),[l,m]=n.useState(()=>({get:s,set:r,has:i,clear:c}));return n.useEffect(()=>m({get:s,set:r,has:i,clear:c}),[s,r,i,c]),l}const dt=1e4,ft=()=>{const{get:a,set:e,has:t,clear:s}=Be(dt);return{get:a,set:e,has:t,clear:s}},de=(a,e)=>e<=0?0:U(a,0,e-1),ht=(a,e,t,s,r,i)=>{if(s===0)return{renderingStartIndex:0,renderingEndIndex:0,visibleStartIndex:0,visibleEndIndex:0};const{index:c,cumulative:l,currentValue:m}=i.findIndexAtOrAfter(a,{materializeOption:{materialize:!1}}),d=c===-1?0:c,f=c!==-1&&(l??0)<a+(m??0)?d+1:d,g=de(f,s),A=de(g-t,s);let V=0,H=g;for(;H<s&&V<e;)V+=r(H),H++;const Q=de(H-1,s),T=de(Q+t,s);return{renderingStartIndex:A,renderingEndIndex:T,visibleStartIndex:g,visibleEndIndex:Q}};function mt({itemCount:a,getItem:e,getItemHeight:t,viewportSize:s,overscanCount:r=5,className:i,onScroll:c,onRangeChange:l,children:m,background:d,initialScrollIndex:f,initialScrollOffset:g,tapScrollCircleOptions:A,scrollBarWidth:V,enableThumbDrag:H,enableTrackClick:Q,enableArrowButtons:T,enablePointerDrag:oe,inertiaOptions:ae},G){const _=n.useRef(null),$=n.useRef(!1);n.useEffect(()=>($.current=!0,()=>{$.current=!1}),[]);const O=n.useRef({size:a,valueOrFn:t,options:{sampleRange:{from:0,to:100}}}),b=We(O.current.size,O.current.valueOrFn,O.current.options),[P]=n.useState(()=>{let y=0,I=0;if(typeof f=="number"){const C=U(f,0,a-1),q=U(C-r*2,0,a-1),ne=U(C+r*2,0,a-1),K=f>0?{materializeOption:{materialize:!0,ranges:[{from:q,to:ne}]}}:void 0,{cumulative:W,total:te,currentValue:B}=b.prefixSum(f,K);y=W-B,I=te??b.getTotal()}else typeof g=="number"&&(y=g),I=b.getTotal();return{position:y,total:I}}),[S,j]=n.useState(P.position),[p,D]=n.useState(P.total),[h,k]=n.useState(P.position),[x,N]=n.useState(a);n.useLayoutEffect(()=>{b.setValueFn(t),x!==a&&(b.changeSize(a),N(a));const y=b.getTotal();p!==y&&D(y)},[b,x,a,p,t]),n.useLayoutEffect(()=>{h!==null&&_.current&&(se.debug("[VirtualScroll] Scrolling to position:",h),_.current.scrollTo(h),k(null))},[h]);const L=n.useCallback(y=>{if(!_.current)return;const I=de(y,x),C=de(I-r*2,x),q=de(I+r*2,x),{cumulative:ne,total:K,currentValue:W}=b.prefixSum(I,{materializeOption:{materialize:!0,ranges:[{from:C,to:q}]}});se.debug("[VirtualScroll] Scrolling to index:",I,"Offset:",ne,"Total height:",K,"Current value:",W,"safeIndexFrom:",C,"safeIndexTo:",q),K&&(D(K),k(ne-W),se.debug("[VirtualScroll] Setting scroll position to:",ne-W))},[b,r,x]),F=n.useCallback(y=>{if(!_.current)return;const I=b.getTotal(),C=U(Math.floor(y),0,I),q=b.findIndexAtOrAfter(C,{materializeOption:{materialize:!1}}).index;L(q)},[b,L]),R=n.useCallback((y,I)=>{se.debug("[VirtualScroll] Scroll position changed:",y),j(y);const C=b.getTotal();c?.(y,C)},[b,c]),w=n.useMemo(()=>{const y=ht(S,s,r,x,t,b);return se.debug("[VirtualScroll] Calculated rendering range:",{...y,scrollPosition:S,renderingContentSize:b.getTotal(),overscanCount:r,viewportSize:s}),y},[S,s,r,x,t,b]);n.useEffect(()=>{const y=_.current?.getScrollPosition()??0;se.debug("[VirtualScroll] Range change effect triggered",{renderingStartIndex:w.renderingStartIndex,renderingEndIndex:w.renderingEndIndex,visibleStartIndex:w.visibleStartIndex,visibleEndIndex:w.visibleEndIndex,scrollPosition:S,contentSize:p,scrollPaneScrollPosition:y}),l?.(w.renderingStartIndex,w.renderingEndIndex,w.visibleStartIndex,w.visibleEndIndex,S,p)},[w.renderingStartIndex,w.renderingEndIndex,w.visibleStartIndex,w.visibleEndIndex,l,S,p]);const M=n.useCallback(y=>{const{renderingStartIndex:I,renderingEndIndex:C}=w;if(se.debug("[VirtualScroll] Rendering visible items",{currentScrollPosition:y,renderingStartIndex:I,renderingEndIndex:C,fenwickSize:x,viewportSize:s}),x===0)return E.jsx("div",{className:"absolute w-full",style:{top:0},children:E.jsx("div",{className:"text-center text-gray-500",children:"No items"})});const q=de(I,x),{cumulative:ne,currentValue:K}=b.prefixSum(q,{materializeOption:{materialize:!1}}),W=ne-K,te=[],B=[];for(let Y=I;Y<=C;Y++){const u=t(Y);te.push({item:e(Y),height:u,index:Y}),b.get(Y)!==u&&B.push({index:Y,value:u})}B.length>0&&Promise.resolve().then(()=>{const Y=b.updates(B);Y&&(D(Y),se.debug("[VirtualScroll] Updated heights for items",B,"New total height:",Y))});const ce=p<s?0:W-y;return se.debug("[VirtualScroll] Rendering items",{visibleItems:te,containerTop:ce}),E.jsx("div",{className:"absolute w-full",style:{top:ce},children:te.map(({item:Y,index:u})=>{const Z=de(u,x),{cumulative:J,currentValue:z}=b.prefixSum(Z,{materializeOption:{materialize:!1}}),re=J-z;return E.jsx("div",{"data-index":u,style:{position:"absolute",top:re-W,width:"100%"},children:m(Y,u)},u)})})},[e,m,p,s,w,b,x,t]);return n.useImperativeHandle(G,()=>({getScrollPosition:()=>_.current?.getScrollPosition()??-1,getContentSize:()=>_.current?.getContentSize()??-1,getViewportSize:()=>_.current?.getViewportSize()??-1,scrollTo:F,scrollToIndex:L,getFenwickTreeTotalHeight:()=>b.getTotal(),getFenwickSize:()=>b.getSize()}),[F,L,b]),E.jsx(qe,{ref:_,contentSize:p,viewportSize:s,className:i,onScroll:R,background:d,tapScrollCircleOptions:A,inertiaOptions:ae,itemCount:a,scrollBarWidth:V,enableThumbDrag:H,enableTrackClick:Q,enableArrowButtons:T,enablePointerDrag:oe,children:M})}const pt=n.forwardRef(mt);exports.FenwickMapTree=Ke;exports.ScrollBar=Ue;exports.ScrollPane=qe;exports.VirtualScroll=pt;exports.minmax=U;exports.tapScrollCircleSampleVisual=ct;exports.useFenwickMapTree=We;exports.useHeightCache=ft;exports.useLruCache=Be;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("react/jsx-runtime"),s=require("react"),ve=require("tailwind-merge"),He={active:!1,offsetX:0,offsetY:0,distance:0,direction:0},$e=6,pt=({dragState:a,normalizedDistance:e})=>{const t=1+e*.18,n=.16+e*.24,r=.38+e*.28,o=a.active?"80ms ease-out":"220ms ease";return y.jsxs(y.Fragment,{children:[y.jsx("div",{className:"absolute inset-0 rounded-full",style:{background:"linear-gradient(140deg, rgba(255,255,255,0.62), rgba(72,72,72,0.48))",boxShadow:`0 0 0 1px rgba(255,255,255,0.28), 0 10px 22px rgba(0,0,0,${n})`,transform:`scale(${t})`,transition:`${o}, ${a.active?"80ms":"260ms"} box-shadow ease`}}),y.jsx("div",{className:"absolute inset-[18%] rounded-full",style:{background:"linear-gradient(140deg, rgba(255,255,255,0.72), rgba(28,28,28,0.58))",boxShadow:"inset 0 4px 10px rgba(0,0,0,0.24), inset 0 0 2px rgba(255,255,255,0.55)",opacity:r,transition:a.active?"120ms opacity ease-out":"220ms opacity ease"}})]})},Ge=s.forwardRef(({onDragChange:a,className:e,maxVisualDistance:t=160,size:n=40,style:r,opacity:o=1,renderVisual:i},l)=>{const[h,u]=s.useState(He),d=s.useRef(null),g=s.useRef({x:0,y:0}),V=s.useRef(null),A=s.useCallback(f=>{u(f),a(f)},[a]),O=s.useCallback((f,C,N=!1)=>{const{x:G,y:m}=g.current,_=f-G,x=C-m,E=Math.abs(x),k=E<$e?0:x<0?-1:1;A({active:N||E>=$e,offsetX:_,offsetY:x,distance:E,direction:k})},[A]),ee=s.useCallback(f=>{if(f===null)return;const C=V.current;C?.hasPointerCapture(f)&&C.releasePointerCapture(f)},[]),H=s.useCallback((f=!1)=>{f&&ee(d.current),d.current=null,A(He)},[A,ee]),te=s.useCallback(f=>{f.preventDefault(),f.stopPropagation();const C=V.current??f.currentTarget,{left:N,top:G,width:m,height:_}=C.getBoundingClientRect();g.current={x:N+m/2,y:G+_/2},d.current=f.pointerId,C.setPointerCapture(f.pointerId),O(f.clientX,f.clientY,!0)},[O]),w=s.useCallback(f=>{d.current===f.pointerId&&(f.preventDefault(),O(f.clientX,f.clientY))},[O]),ie=s.useCallback(f=>{d.current===f.pointerId&&(f.preventDefault(),f.stopPropagation(),H(!0))},[H]);s.useImperativeHandle(l,()=>({reset:()=>{H(!0)},getElement:()=>V.current}),[H]);const oe=Math.min(Math.max(o,0),1),W=n/64,R=Math.min(h.distance,t)/t,U=h.direction*R*10*W,I=i??pt,b={dragState:h,normalizedDistance:R,sizeScale:W,size:n,opacity:oe},j={...r,width:n,height:n,transform:`translateY(${U}px)`};return j.opacity=oe,y.jsx("div",{ref:V,className:ve.twMerge("relative flex touch-none select-none items-center justify-center","transition-transform duration-100 ease-out",e),style:j,onPointerDown:te,onPointerMove:w,onPointerUp:ie,onPointerCancel:ie,role:"presentation",children:I(b)})});Ge.displayName="TapScrollCircle";const X=(a,e,t)=>Math.min(t,Math.max(e,a)),Xe=(a,e,t)=>{const n="touches"in a.nativeEvent,r=n?a.nativeEvent.touches[0]:a.nativeEvent,o=l=>{n&&l.cancelable&&l.preventDefault();const h="touches"in l?l.touches[0]:l;e({deltaX:h.clientX-r.clientX,deltaY:h.clientY-r.clientY})},i=()=>{n?(document.removeEventListener("touchmove",o),document.removeEventListener("touchend",i)):(document.removeEventListener("mousemove",o),document.removeEventListener("mouseup",i)),t?.()};n?(document.addEventListener("touchmove",o,{passive:!1}),document.addEventListener("touchend",i)):(document.addEventListener("mousemove",o),document.addEventListener("mouseup",i))},_e="virtualscroll:tap-scroll-cancel",Ue=20,gt=250,xt=60,bt=20,vt=20,St=220,Ke={active:!1,offsetX:0,offsetY:0,distance:0,direction:0},Ae=2.2,Tt=8,yt=120,fe={enabled:!0,size:40,offsetX:-80,offsetY:0,className:void 0,maxVisualDistance:St,minSpeedMultiplier:.2,opacity:1,renderVisual:void 0,maxSpeedCurve:void 0},wt=a=>a?{mainSizeKey:"width",crossSizeKey:"height",positionKey:"left",selectDelta:(e,t)=>e,getPointerCoordinate:({clientX:e})=>e,arrowLabels:["Scroll left","Scroll right"],arrowIcons:["◀","▶"],directionClass:"flex flex-row items-stretch",orientation:"horizontal"}:{mainSizeKey:"height",crossSizeKey:"width",positionKey:"top",selectDelta:(e,t)=>t,getPointerCoordinate:({clientY:e})=>e,arrowLabels:["Scroll up","Scroll down"],arrowIcons:["▲","▼"],directionClass:"flex flex-col items-stretch",orientation:"vertical"},Mt=(a,e)=>{const t=a?.maxSpeedMultiplier,n=typeof t=="number"?t:Et(e);return{enabled:a?.enabled??fe.enabled,size:a?.size??fe.size,offsetX:a?.offsetX??fe.offsetX,offsetY:a?.offsetY??fe.offsetY,className:a?.className??fe.className,maxVisualDistance:a?.maxVisualDistance??fe.maxVisualDistance,maxSpeedMultiplier:n,minSpeedMultiplier:Math.max(a?.minSpeedMultiplier??fe.minSpeedMultiplier,0),opacity:X(a?.opacity??fe.opacity,0,1),renderVisual:a?.renderVisual??fe.renderVisual,maxSpeedCurve:a?.maxSpeedCurve??fe.maxSpeedCurve}},It=({thumbRef:a,isDragging:e,isThumbHovered:t,enableThumbDrag:n,horizontal:r})=>{s.useEffect(()=>{const o=a.current;if(!o)return;const i=r?"scaleY(1.06)":"scaleX(1.06)",l=r?"scaleY(1.12)":"scaleX(1.12)";if(!n){o.style.removeProperty("transform"),o.style.backgroundColor="#7F7F7F",o.style.removeProperty("transition");return}if(e){o.style.transform=l,o.style.backgroundColor="#4F4F4F",o.style.transition="transform 60ms ease-out";return}o.style.transition="transform 80ms ease-out",t?(o.style.transform=i,o.style.backgroundColor="#5F5F5F"):(o.style.removeProperty("transform"),o.style.backgroundColor="#7F7F7F")},[n,r,e,t,a])},Ct=({canUseArrowButtons:a,enableArrowButtons:e,resetTapScroll:t,scrollByStep:n})=>{const r=s.useRef(null),o=s.useRef(null),i=s.useCallback(()=>{r.current!==null&&(window.clearInterval(r.current),r.current=null),o.current!==null&&(window.clearTimeout(o.current),o.current=null)},[]),l=s.useCallback(()=>{i()},[i]),h=s.useCallback(d=>g=>{a&&(g.preventDefault(),g.stopPropagation(),t(),i(),n(d),o.current=window.setTimeout(()=>{r.current=window.setInterval(()=>{n(d)},xt)},gt))},[a,i,t,n]),u=s.useCallback(d=>g=>{e&&(g.key==="Enter"||g.key===" "||g.key==="Spacebar")&&(g.preventDefault(),n(d))},[e,n]);return s.useEffect(()=>()=>{i()},[i]),{handleArrowPointerDown:h,handleArrowPointerUp:l,handleArrowKeyDown:u}},Et=a=>{if(!a||a<=0)return Ae;const e=Math.max(1,a),t=Math.log10(e),n=Ae+t*Tt;return X(n,Ae,yt)},Ze=({contentSize:a,viewportSize:e,scrollPosition:t,onScroll:n,enableThumbDrag:r=!0,enableTrackClick:o=!0,enableArrowButtons:i=!0,horizontal:l=!1,scrollBarWidth:h=12,className:u,ariaControls:d,tapScrollCircleOptions:g,itemCount:V,renderThumbOverlay:A})=>{const[O,ee]=s.useState(!1),[H,te]=s.useState(!1),[w,ie]=s.useState(!1),oe=s.useRef(null),W=s.useRef(t),R=s.useRef(Ke),U=s.useRef(null),I=s.useRef(null),b=s.useRef(null),j=s.useMemo(()=>Mt(g,V),[V,g]),f=s.useMemo(()=>wt(l),[l]),{enabled:C,size:N,offsetX:G,offsetY:m,className:_,maxVisualDistance:x,maxSpeedMultiplier:E,minSpeedMultiplier:k,opacity:z,renderVisual:L,maxSpeedCurve:v}=j,{mainSizeKey:M,crossSizeKey:S,positionKey:T,selectDelta:P,getPointerCoordinate:Z,arrowLabels:se,arrowIcons:K,directionClass:J,orientation:re}=f,q=Math.max(x,1),he=e/a,F=h,c=Math.max(e-F*2,0),Q=he*c,$=Math.min(Math.max(Ue,Q||0),c||Ue),D=a-e,le=Math.max(c-$,0),me=D<=0||le<=0?0:t/D*le,tt=me+$/2,ce=a>e,ke=ce&&i;s.useEffect(()=>{W.current=t},[t]),s.useEffect(()=>{r||te(!1)},[r]),It({thumbRef:oe,isDragging:O,isThumbHovered:H,enableThumbDrag:r,horizontal:l});const ue=s.useCallback(()=>{I.current!==null&&(window.cancelAnimationFrame(I.current),I.current=null),b.current=null},[]),de=s.useCallback(()=>{R.current={...Ke},ie(!1),U.current?.reset(),ue()},[ue]),Se=s.useCallback(p=>{const Y=R.current;if(!Y.active||Y.direction===0){ue();return}if(!ce||D<=0){ue();return}const B=b.current??p,ne=Math.max((p-B)/1e3,0);if(b.current=p,ne<=0){I.current=window.requestAnimationFrame(Se);return}const pe=Math.min(Y.distance,q)/q,Ce=pe**1.1,ye=typeof g?.maxSpeedMultiplier=="number",xe=Math.max(e*k,40),Ee=ye?xe:1200;let Pe=Math.max(e*E,Ee);if(v){const we=Math.max(v.exponentialSteepness,0),dt=Math.max(v.exponentialScale??E,0),ft=we===0?pe:Math.expm1(we*pe),je=we===0?1:Math.expm1(we)||1,ht=je===0?pe:Math.min(Math.max(ft/je,0),1),mt=e*dt*ht;Pe=Math.min(Pe,Math.max(mt,xe))}const it=Math.max(Pe,xe),lt=Math.max(v?.easedOffset??0,0),ct=Math.min(1,Ce+lt),ut=xe+(it-xe)*ct,Ve=W.current,Re=X(Ve+Y.direction*ut*ne,0,D);if(Re===Ve){ue();return}W.current=Re,n?.(Re,Ve),I.current=window.requestAnimationFrame(Se)},[q,D,n,ce,ue,v,E,k,g,e]),Le=s.useCallback(()=>{I.current===null&&(b.current=null,I.current=window.requestAnimationFrame(Se))},[Se]);s.useEffect(()=>()=>{ue()},[ue]);const nt=s.useCallback(p=>{R.current=p,ie(p.active),p.active&&p.direction!==0?Le():ue()},[Le,ue]);s.useEffect(()=>{C||de()},[de,C]),s.useEffect(()=>{const p=Y=>{const ne=Y.detail?.paneId;ne&&d&&ne!==d||de()};return window.addEventListener(_e,p),()=>{window.removeEventListener(_e,p)}},[d,de]),s.useEffect(()=>{if(!C)return;const p=Y=>{if(!R.current.active)return;const B=Y.target;if(!(B instanceof Node)){de();return}U.current?.getElement()?.contains(B)||de()};return document.addEventListener("pointerdown",p,!0),()=>{document.removeEventListener("pointerdown",p,!0)}},[de,C]);const Ie=p=>{if(!ce||le<=0||D<=0)return 0;const Y=X(p,0,le);return X(Y/le*D,0,D)},st=p=>{if(!ce||D<=0)return;const Y=Math.max(Math.round(e/vt),bt),B=W.current,ne=X(B+p*Y,0,D);ne!==B&&(W.current=ne,n?.(ne,B))},{handleArrowPointerDown:Fe,handleArrowPointerUp:Te,handleArrowKeyDown:rt}=Ct({canUseArrowButtons:ke,enableArrowButtons:i,resetTapScroll:de,scrollByStep:st}),De=p=>{if(!ce)return;if(!r){p.preventDefault(),p.stopPropagation();return}if("button"in p&&p.button!==0||p.ctrlKey)return;p.stopPropagation(),de();const Y=me;ee(!0),te(!0),Xe(p,({deltaX:B,deltaY:ne})=>{const pe=P(B,ne);n?.(Ie(Y+pe),me)},()=>{ee(!1),oe.current&&!oe.current.matches(":hover")&&te(!1)})},Oe=p=>{if(!ce)return;if(!o){p.preventDefault(),p.stopPropagation();return}if("button"in p&&p.button!==0||p.ctrlKey)return;const B="touches"in p.nativeEvent?p.nativeEvent.touches[0]:p.nativeEvent,ne=Z(B),pe=p.currentTarget.getBoundingClientRect(),Ce=ne-(l?pe.left:pe.top);de();const ye=Ce-$/2;n?.(Ie(ye),me),Xe(p,({deltaX:xe,deltaY:Ee})=>{const Ye=P(xe,Ee);n?.(Ie(ye+Ye),me)})},at=s.useMemo(()=>X((w?1:.8)*z,0,1),[w,z]),ot=s.useMemo(()=>{const Y=`calc(50% - ${N/2}px + ${m}px)`;return{left:G,top:Y}},[G,m,N]),Ne=(p,Y,B)=>y.jsx("button",{type:"button",className:"flex items-center justify-center text-[#313131] text-xs transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[#60a5fa] focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50",style:{[M]:F,[S]:h,backgroundColor:"#E0E0E0"},"aria-label":Y,onMouseDown:Fe(p),onTouchStart:Fe(p),onMouseUp:Te,onMouseLeave:Te,onTouchEnd:Te,onTouchCancel:Te,onKeyDown:rt(p),"aria-disabled":!i,disabled:!ke,children:y.jsx("span",{"aria-hidden":"true",children:B})}),ze=A&&ce?{orientation:re,scrollPosition:t,maxScrollPosition:D,contentSize:a,viewportSize:e,thumbSize:$,thumbPosition:me,thumbCenter:tt,trackSize:c,isDragging:O,isTapScrollActive:w}:null;return y.jsxs("div",{className:ve.twMerge("group relative cursor-default select-none",J,u),style:{[M]:e,[S]:h,backgroundColor:"white",userSelect:"none",position:"relative"},role:"scrollbar",tabIndex:-1,"aria-controls":d,"aria-valuenow":t,"aria-valuemin":0,"aria-valuemax":D,"aria-orientation":l?"horizontal":"vertical",children:[!l&&ce&&C&&y.jsx(Ge,{ref:U,className:ve.twMerge("pointer-events-auto absolute transition-opacity duration-150",_),size:N,maxVisualDistance:q,style:ot,opacity:at,renderVisual:L,onDragChange:nt}),Ne(-1,se[0],K[0]),y.jsxs("div",{className:"relative flex-1",style:{backgroundColor:"#F5F5F5",borderRadius:h/2},onMouseDown:Oe,onTouchStart:Oe,"aria-disabled":!o,children:[ze&&y.jsx("div",{className:"pointer-events-none absolute inset-0","aria-hidden":!0,children:A?.(ze)}),ce&&y.jsx("div",{className:"group absolute",style:{[M]:$,[T]:me,...l?{top:0,bottom:0}:{left:0,right:0}},onMouseDown:De,onTouchStart:De,role:"slider","aria-orientation":l?"horizontal":"vertical","aria-valuenow":t,"aria-valuemin":0,"aria-valuemax":D,"aria-disabled":!r,tabIndex:r?0:-1,children:y.jsx("div",{ref:oe,className:ve.twMerge("absolute",l?`inset-x-0 inset-y-[1.5px] group-hover:inset-y-[-0.5px] ${O?"-inset-y-0.5":"group-active:-inset-y-0.5"}`:`inset-x-[1.5px] inset-y-0 group-hover:inset-x-[-0.5px] ${O?"-inset-x-0.5":"group-active:-inset-x-0.5"}`),style:{backgroundColor:"#7F7F7F",borderRadius:h-1,cursor:r?"pointer":"default",...l?{left:0,right:0,top:1.5,bottom:1.5}:{top:0,bottom:0,left:1.5,right:1.5}},onMouseEnter:()=>{r&&te(!0)},onMouseLeave:()=>{r&&te(!1)}})})]}),Ne(1,se[1],K[1])]})},ae={debug(a,...e){typeof window<"u"&&window.localStorage?.getItem("debug")==="true"&&console.debug(`[VirtualScroll] ${a}`,...e)},warn(a,...e){console.warn(`[VirtualScroll] ${a}`,...e)},error(a,...e){console.error(`[VirtualScroll] ${a}`,...e)}},be={maxVelocity:6,minVelocity:.02,deceleration:.0025,velocitySampleWindow:90,startVelocityThreshold:.04},Me=(a,e,t)=>{for(const[n,r,o]of e)t==="add"?a.addEventListener(n,r,o):a.removeEventListener(n,r,o)},Je=s.forwardRef(({children:a,contentSize:e,viewportSize:t,scrollBarWidth:n=12,enableThumbDrag:r=!0,enableTrackClick:o=!0,enableArrowButtons:i=!0,enablePointerDrag:l=!0,onScroll:h,className:u,style:d,background:g,tapScrollCircleOptions:V,inertiaOptions:A,itemCount:O,renderThumbOverlay:ee,wheelSpeedMultiplier:H=1},te)=>{const w=s.useRef(0),[ie,oe]=s.useReducer(m=>m+1,0),W=s.useRef(null),R=s.useRef(null),U=s.useRef({frame:null,velocity:0,lastTimestamp:null}),I=s.useMemo(()=>({maxVelocity:A?.maxVelocity??be.maxVelocity,minVelocity:A?.minVelocity??be.minVelocity,deceleration:A?.deceleration??be.deceleration,velocitySampleWindow:A?.velocitySampleWindow??be.velocitySampleWindow,startVelocityThreshold:A?.startVelocityThreshold??be.startVelocityThreshold}),[A]);ae.debug("[ScrollPane] ScrollPane rendered",{contentSize:e,viewportSize:t,scrollBarWidth:n,className:u,style:d,tapScrollCircleOptions:V,inertiaOptions:A,enablePointerDrag:l});const b=s.useRef({contentSize:e,viewportSize:t}),j=s.useMemo(()=>e>t,[e,t]),f=s.useCallback(m=>{const{contentSize:_,viewportSize:x}=b.current,E=_>x,k=w.current;if(ae.debug("[ScrollPane] scrollTo called",{newPosition:m,contentSize:_,viewportSize:x,currentIsScrollable:E,prevPosition:k}),!E){w.current!==0&&(w.current=0,h?.(0,k));return}const z=typeof m=="function"?m(w.current):m,L=X(z,0,_-x);w.current!==L&&(w.current=L,h?.(L,k))},[h]),C=s.useCallback(()=>{const m=U.current;m.frame!==null&&cancelAnimationFrame(m.frame),m.frame=null,m.velocity=0,m.lastTimestamp=null},[]),N=s.useCallback(m=>{if(!j)return;const{maxVelocity:_,minVelocity:x,deceleration:E,startVelocityThreshold:k}=I,z=X(m,-_,_);if(Math.abs(z)<k)return;C(),U.current.velocity=z,U.current.lastTimestamp=null;const L=v=>{const M=U.current;if(M.lastTimestamp===null){M.lastTimestamp=v,M.frame=requestAnimationFrame(L);return}const S=v-M.lastTimestamp;if(M.lastTimestamp=v,S<=0){M.frame=requestAnimationFrame(L);return}const T=M.velocity;let P=T;const Z=E*S;T>0?P=Math.max(0,T-Z):T<0&&(P=Math.min(0,T+Z));const K=(T+P)/2*S,J=w.current;K!==0&&f(Q=>Q+K);const re=w.current,{contentSize:q,viewportSize:he}=b.current,F=Math.max(q-he,0);M.velocity=P;const c=re===J||re<=0&&P<=0||re>=F&&P>=0;if(Math.abs(P)<x||c){C();return}M.frame=requestAnimationFrame(L)};U.current.frame=requestAnimationFrame(L)},[j,I,f,C]);s.useLayoutEffect(()=>{b.current={contentSize:e,viewportSize:t}},[e,t]),s.useLayoutEffect(()=>{if(j){ae.debug("[ScrollPane] Adjusting scroll position due to content or viewport size change",{contentSize:e,viewportSize:t,scrollPosition:w.current});const m=X(e-t,0,e);w.current>m&&f(m)}else f(0)},[j,f,e,t]),s.useEffect(()=>{const m=x=>{if(!j)return;x.preventDefault(),C();let E=x.deltaY;x.deltaMode===1?E*=16:x.deltaMode===2&&(E*=t),H!==1&&(E*=H),ae.debug("[ScrollPane] wheel event",{deltaY:E,scrollPosition:w.current,wheelSpeedMultiplier:H}),f(k=>k+E)},_=W.current;return _&&_.addEventListener("wheel",m,{passive:!1}),()=>{_&&_.removeEventListener("wheel",m)}},[j,f,C,t,H]),s.useImperativeHandle(te,()=>({scrollTo:f,getScrollPosition:()=>w.current,getContentSize:()=>e,getViewportSize:()=>t}),[f,e,t]);const G=s.useId();return s.useEffect(()=>{const m=R.current;if(!m)return;if(!l){C();return}const _=6;let x=null,E=0,k=0,z=!1,L=!1,v=null,M=[];const S=()=>{x=null,E=0,k=0,z=!1,M=[]},T=c=>{const Q=performance.now();M.push({clientY:c,time:Q}),M=M.filter($=>Q-$.time<=I.velocitySampleWindow)},P=c=>c instanceof HTMLElement&&c.closest("[data-scrollpane-ignore-drag='true']")!==null,Z=c=>{L&&(c.preventDefault(),c.stopPropagation(),L=!1)},se=c=>{z||(z=!0,L=!0,m.hasPointerCapture(c.pointerId)||m.setPointerCapture(c.pointerId),T(c.clientY))},K=c=>{if(x!==c.pointerId||!z&&(Math.abs(c.clientY-E)<_||(se(c),!z)))return;T(c.clientY);const Q=c.clientY-E,$=k-Q;f($),c.cancelable&&c.preventDefault()},J=c=>{if(x!==c.pointerId)return;z&&L&&c.cancelable&&(c.preventDefault(),c.stopPropagation()),m.hasPointerCapture(c.pointerId)&&m.releasePointerCapture(c.pointerId);let Q=0;if(z&&M.length>=2){const $=M[M.length-1],D=M.find(le=>$.time-le.time<=I.velocitySampleWindow)??M[0];if($&&D&&$.time!==D.time){const le=$.clientY-D.clientY,me=$.time-D.time;Q=-(le/me)}}S(),v!==null&&window.clearTimeout(v),L&&(v=window.setTimeout(()=>{L=!1,v=null},0)),Math.abs(Q)>=I.startVelocityThreshold&&N(Q)},re=c=>{j&&(c.button!==0&&c.pointerType==="mouse"||c.ctrlKey||c.metaKey||c.altKey||P(c.target)||(window.dispatchEvent(new CustomEvent(_e,{detail:{paneId:G}})),C(),x=c.pointerId,E=c.clientY,k=w.current,z=!1,L=!1,M=[]))},q=c=>{x===c.pointerId&&(L=!1,m.hasPointerCapture(c.pointerId)&&m.releasePointerCapture(c.pointerId),v!==null&&(window.clearTimeout(v),v=null),S())},he=[["click",Z,!0],["pointerdown",re,{passive:!1}],["pointermove",K,{passive:!1}],["pointerup",J,void 0],["pointercancel",q,void 0]],F=[["pointermove",K,{passive:!1}],["pointerup",J,void 0],["pointercancel",q,void 0]];return Me(m,he,"add"),Me(window,F,"add"),()=>{Me(m,he,"remove"),Me(window,F,"remove"),x!==null&&m.hasPointerCapture(x)&&m.releasePointerCapture(x),v!==null&&window.clearTimeout(v),C()}},[l,G,j,I,f,N,C]),y.jsxs("div",{ref:W,className:ve.twMerge("flex",u),style:d,children:[y.jsxs("div",{ref:R,className:"relative h-full flex-1 overflow-hidden",style:{height:t,...l?{touchAction:"none"}:{}},id:G,children:[g,a(w.current)]}),j&&y.jsx(Ze,{contentSize:e,viewportSize:t,scrollPosition:w.current,onScroll:f,enableThumbDrag:r,enableTrackClick:o,enableArrowButtons:i,scrollBarWidth:n,ariaControls:G,tapScrollCircleOptions:V,itemCount:O,renderThumbOverlay:ee})]})}),qe=(a,e,t)=>Math.min(Math.max(a,e),t),Pt=({dragState:a,normalizedDistance:e,sizeScale:t,size:n})=>{const r=Math.max(n/2,1),o=1+e*.65,i=Math.max(.65,1-e*.25),l=a.direction*e*26*t,h=.8+e*.18,u=3*t,d=6*t,g=22*t,V=Math.abs(l)+d,A=l>0?u:-Math.abs(l)-u,O=Math.max(2.5,3*t),ee=qe(a.offsetX,-r,r),H=qe(a.offsetY,-r,r),te=r*.35,w=ee/r*te,ie=H/r*te,oe=w*.45,W=ie*.45,R=Math.max(g*.38,6),U=.65+e*.2,I=a.active;return y.jsxs(y.Fragment,{children:[y.jsx("div",{className:"absolute inset-0 rounded-full border border-white/40 bg-linear-to-br from-[#1d4ed8]/60 via-[#60a5fa]/55 to-[#bfdbfe]/40 shadow-md",style:{transform:`scale(${i}, ${o})`,transition:I?"40ms transform ease-out":"200ms ease transform"}}),y.jsx("div",{className:"absolute top-1/2 left-1/2 rounded-full border border-white/50 bg-white/85",style:{width:g,height:g,transform:`translate(calc(-50% + ${w}px), calc(-50% + ${ie}px)) scale(${i}, ${h*o})`,transition:I?"70ms transform ease-out":"200ms ease transform"}}),y.jsx("div",{className:"absolute top-1/2 left-1/2 rounded-full bg-white/80",style:{width:R,height:R,transform:`translate(calc(-50% + ${oe}px), calc(-50% + ${W}px)) scale(${i}, ${o})`,opacity:U,boxShadow:"0 0 8px rgba(255,255,255,0.45)",transition:I?"120ms opacity 150ms, 120ms transform ease-out ease-out":"220ms ease transform, 240ms opacity ease"}}),y.jsx("div",{className:"absolute top-1/2 left-1/2 rounded-full bg-white/50",style:{width:O,height:V,transform:`translate(-50%, ${A}px)`,opacity:e,transition:I?"40ms height, 60ms opacity ease-out ease-out":"200ms ease height, 120ms ease opacity"}})]})};class Qe{tree;deltas;size;baseValue;valueFn;total;constructor(e,t,n){this.reset(e,t,n)}reset(e,t,n){if(this.size=e,this.tree=new Map,this.deltas=new Map,this.total=void 0,typeof t=="function"){if(this.valueFn=t,this.size>0){const o=n?.sampleRange??{from:0,to:Math.min(99,this.size-1)},{mode:i,materializedValues:l}=this._calculateMode(o.from,o.to);if(this.baseValue=i,n?.materialize)for(let h=0;h<l.length;h++){const u=l[h],d=o.from+h;if(d>=this.size)break;const g=u-this.baseValue;this.deltas.set(d,g),this._updateTree(d,g)}}else this.baseValue=0;this.total=this.getTotal()}else this.valueFn=void 0,this.baseValue=t,this.total=this.baseValue*this.size}setValueFn(e){typeof e=="function"?this.valueFn=e:(this.valueFn=void 0,this.baseValue=e)}_calculateMode(e,t){if(!this.valueFn)return{mode:0,materializedValues:[]};const n=[];for(let u=e;u<=t&&!(u>=this.size);u++)n.push(this.valueFn(u));const r=[...n];if(n.length===0)return{mode:0,materializedValues:[]};n.sort((u,d)=>u-d);const o=Math.floor(n.length/2);let i;n.length%2===0?i=Math.floor((n[o-1]+n[o])/2):i=n[o];const l=new Map;let h=0;for(const u of n){const d=(l.get(u)??0)+1;l.set(u,d),d>h&&(h=d)}if(h>1){const u=[];for(const[g,V]of l.entries())V===h&&u.push(g);const d=u.reduce((g,V)=>g+V,0);i=Math.floor(d/u.length)}return{mode:i,materializedValues:r}}update(e,t){return this.updates([{index:e,value:t}])}updates(e){const t=this._buildDeltaUpdates(e);return t.length>0?this.updateDeltas(t):this.total}updateDelta(e,t){return this.updateDeltas([{index:e,change:t}])}updateDeltas(e){for(const{index:t,change:n}of e){if(t<0||t>=this.size)throw new Error(`Index ${t} out of bounds`);const r=this.deltas.get(t)??0;this.deltas.set(t,r+n),this._updateTree(t,n)}return this.total}_updateTree(e,t){if(t===0)return;let n=e+1;for(;n<=this.size;)this.tree.set(n,(this.tree.get(n)??0)+t),n+=n&-n;this.total!==void 0&&(this.total+=t)}_buildDeltaUpdates(e){const t=[];for(const{index:n,value:r}of e){if(n<0||n>=this.size)throw new Error(`Index ${n} out of bounds`);if(r<0)throw new Error("Value cannot be negative.");const o=this.deltas.has(n)?(this.deltas.get(n)??0)+this.baseValue:this.baseValue,i=r-o;i!==0&&t.push({index:n,change:i})}return t}_materialize(e,t=!0){if(this.valueFn){const n=this.deltas.get(e)??0,o=this.valueFn(e)-this.baseValue;if(o!==n&&(this.deltas.set(e,o),t)){const i=o-n;this._updateTree(e,i)}}}_materializeRanges(e,t,n=!1){if(!(e?.materialize&&this.valueFn))return;const r=e.ranges;if(r&&r.length>0){for(const l of r){const h=l.from,u=Math.min(l.to,this.size-1);for(let d=h;d<=u;d++)this._materialize(d)}if(t===void 0)return;if(n){this._materialize(t);return}const o=r[0].from,i=r[r.length-1].to;t>=o&&t<=i&&this._materialize(t);return}t!==void 0&&this._materialize(t)}_findIndex(e,t={},n){if(this.size===0)return{index:-1,total:this.total??0,cumulative:void 0,currentValue:void 0,safeIndex:void 0};let r=0,o=this.size-1,i=-1,l,h=this.total;for(;r<=o;){const u=Math.floor((r+o)/2);l=this.prefixSum(u,t),h=l.total,(n?l.cumulative>=e:l.cumulative<=e)?(i=u,n?o=u-1:r=u+1):n?r=u+1:o=u-1}return{index:i,total:h,cumulative:l?.cumulative,currentValue:l?.currentValue,safeIndex:l?.safeIndex}}prefixSum(e,t){if(e<0)return{cumulative:0,total:this.total,currentValue:0,safeIndex:0};const n=X(e,0,this.size-1),r=t?.materializeOption;this._materializeRanges(r,n,!0);let o=0,i=n+1;for(;i>0;){const h=this.tree.get(i)??0;o+=h,i-=i&-i}const l=r?.materialize?this.get(n):(this.deltas.get(n)||0)+this.baseValue;return{cumulative:o+this.baseValue*(n+1),total:this.total,currentValue:l,safeIndex:n}}get(e,t){if(e<0||e>=this.size)throw new Error("Index out of bounds");const n=t?.materializeOption;return this._materializeRanges(n,e),(this.deltas.get(e)??0)+this.baseValue}getTotal(e){const t=e?.materializeOption;if(this._materializeRanges(t),this.total===void 0)if(this.size===0)this.total=0;else{let n=this.baseValue*this.size;for(const o of this.deltas.values())n+=o;this.total=n;const r=this.prefixSum(this.getSize()-1);console.assert(r.cumulative===r.total,"Inconsistent Fenwick Tree state")}return this.total}rebuildTree(e){if(e?.materialize&&this.valueFn){const r=this.valueFn;this.reset(this.size,o=>r(o),{materialize:!0});return}const t=new Map;let n=this.baseValue*this.size;for(const[r,o]of this.deltas.entries()){if(n+=o,o===0)continue;let i=r+1;for(;i<=this.size;)t.set(i,(t.get(i)??0)+o),i+=i&-i}this.tree=t,this.total=n}calculateAccumulatedError(){if(this.total===void 0)return 0;let e=this.baseValue*this.size;for(const t of this.deltas.values())e+=t;return this.total-e}changeSize(e){const t=this.size;if(e===t)return;if(e<t)for(const r of this.deltas.keys())r>=e&&this.deltas.delete(r);this.size=e,this.rebuildTree();const n=this.prefixSum(this.getSize()-1);console.assert(n.cumulative===n.total,"Inconsistent Fenwick Tree state")}getSize(){return this.size}findIndexAtOrAfter(e,t){return this._findIndex(e,t??{},!0)}findIndexAtOrBefore(e,t){return this._findIndex(e,t??{},!1)}}const Be=(a,e,t)=>{const n=Math.max(0,a),r=s.useRef(null),o=s.useMemo(()=>new Qe(n,e,t),[n,e,t]);return Object.is(r.current,o)||console.warn("[useFenwickMapTree] instance changed"),r.current=o,o};class Vt{key;value;prev=null;next=null;constructor(e,t){this.key=e,this.value=t}}class We{head=null;tail=null;addToTail(e){this.tail?(this.tail.next=e,e.prev=this.tail,this.tail=e):this.head=this.tail=e}remove(e){e.prev?e.prev.next=e.next:this.head=e.next,e.next?e.next.prev=e.prev:this.tail=e.prev,e.prev=null,e.next=null}removeHead(){const e=this.head;return e&&this.remove(e),e}moveToTail(e){this.remove(e),this.addToTail(e)}}function et(a){const e=s.useRef(new Map),t=s.useRef(new We);s.useEffect(()=>{for(;e.current.size>a;){const u=t.current.removeHead();if(u)e.current.delete(u.key);else break}},[a]);const n=s.useCallback(u=>{const d=e.current.get(u);if(d)return t.current.moveToTail(d),d.value},[]),r=s.useCallback((u,d)=>{if(a<=0)return;let g=e.current.get(u);if(g)g.value=d,t.current.moveToTail(g);else{if(e.current.size>=a){const V=t.current.removeHead();V&&e.current.delete(V.key)}g=new Vt(u,d),e.current.set(u,g),t.current.addToTail(g)}},[a]),o=s.useCallback(u=>e.current.has(u),[]),i=s.useCallback(()=>{e.current.clear(),t.current=new We},[]),[l,h]=s.useState(()=>({get:n,set:r,has:o,clear:i}));return s.useEffect(()=>h({get:n,set:r,has:o,clear:i}),[n,r,o,i]),l}const Rt=1e4,At=()=>{const{get:a,set:e,has:t,clear:n}=et(Rt);return{get:a,set:e,has:t,clear:n}},ge=(a,e)=>e<=0?0:X(a,0,e-1),_t=(a,e,t,n,r,o)=>{if(n===0)return{renderingStartIndex:0,renderingEndIndex:0,visibleStartIndex:0,visibleEndIndex:0};const{index:i,cumulative:l,currentValue:h}=o.findIndexAtOrAfter(a,{materializeOption:{materialize:!1}}),u=i===-1?0:i,d=i!==-1&&(l??0)<a+(h??0)?u+1:u,g=ge(d,n),V=ge(g-t,n);let A=0,O=g;for(;O<n&&A<e;)A+=r(O),O++;const ee=ge(O-1,n),H=ge(ee+t,n);return{renderingStartIndex:V,renderingEndIndex:H,visibleStartIndex:g,visibleEndIndex:ee}};function kt({itemCount:a,getItem:e,getItemHeight:t,viewportSize:n,overscanCount:r=5,className:o,onScroll:i,onRangeChange:l,children:h,background:u,initialScrollIndex:d,initialScrollOffset:g,tapScrollCircleOptions:V,scrollBarWidth:A,enableThumbDrag:O,enableTrackClick:ee,enableArrowButtons:H,enablePointerDrag:te,inertiaOptions:w,renderThumbOverlay:ie,wheelSpeedMultiplier:oe},W){const R=s.useRef(null),U=s.useRef(!1);s.useEffect(()=>(U.current=!0,()=>{U.current=!1}),[]);const I=s.useRef({size:a,valueOrFn:t,options:{sampleRange:{from:0,to:100}}}),b=Be(I.current.size,I.current.valueOrFn,I.current.options),[j]=s.useState(()=>{let S=0,T=0;if(typeof d=="number"){const P=X(d,0,a-1),Z=X(P-r*2,0,a-1),se=X(P+r*2,0,a-1),K=d>0?{materializeOption:{materialize:!0,ranges:[{from:Z,to:se}]}}:void 0,{cumulative:J,total:re,currentValue:q}=b.prefixSum(d,K);S=J-q,T=re??b.getTotal()}else typeof g=="number"&&(S=g),T=b.getTotal();return{position:S,total:T}}),[f,C]=s.useState(j.position),[N,G]=s.useState(j.total),[m,_]=s.useState(j.position),[x,E]=s.useState(a);s.useLayoutEffect(()=>{b.setValueFn(t),x!==a&&(b.changeSize(a),E(a));const S=b.getTotal();N!==S&&G(S)},[b,x,a,N,t]),s.useLayoutEffect(()=>{m!==null&&R.current&&(ae.debug("[VirtualScroll] Scrolling to position:",m),R.current.scrollTo(m),_(null))},[m]);const k=s.useCallback(S=>{if(!R.current)return;const T=ge(S,x),P=ge(T-r*2,x),Z=ge(T+r*2,x),{cumulative:se,total:K,currentValue:J}=b.prefixSum(T,{materializeOption:{materialize:!0,ranges:[{from:P,to:Z}]}});ae.debug("[VirtualScroll] Scrolling to index:",T,"Offset:",se,"Total height:",K,"Current value:",J,"safeIndexFrom:",P,"safeIndexTo:",Z),K&&(G(K),_(se-J),ae.debug("[VirtualScroll] Setting scroll position to:",se-J))},[b,r,x]),z=s.useCallback(S=>{if(!R.current)return;const T=b.getTotal(),P=X(Math.floor(S),0,T),Z=b.findIndexAtOrAfter(P,{materializeOption:{materialize:!1}}).index;k(Z)},[b,k]),L=s.useCallback((S,T)=>{ae.debug("[VirtualScroll] Scroll position changed:",S),C(S);const P=b.getTotal();i?.(S,P)},[b,i]),v=s.useMemo(()=>{const S=_t(f,n,r,x,t,b);return ae.debug("[VirtualScroll] Calculated rendering range:",{...S,scrollPosition:f,renderingContentSize:b.getTotal(),overscanCount:r,viewportSize:n}),S},[f,n,r,x,t,b]);s.useEffect(()=>{const S=R.current?.getScrollPosition()??0;ae.debug("[VirtualScroll] Range change effect triggered",{renderingStartIndex:v.renderingStartIndex,renderingEndIndex:v.renderingEndIndex,visibleStartIndex:v.visibleStartIndex,visibleEndIndex:v.visibleEndIndex,scrollPosition:f,contentSize:N,scrollPaneScrollPosition:S}),l?.(v.renderingStartIndex,v.renderingEndIndex,v.visibleStartIndex,v.visibleEndIndex,f,N)},[v.renderingStartIndex,v.renderingEndIndex,v.visibleStartIndex,v.visibleEndIndex,l,f,N]);const M=s.useCallback(S=>{const{renderingStartIndex:T,renderingEndIndex:P}=v;if(ae.debug("[VirtualScroll] Rendering visible items",{currentScrollPosition:S,renderingStartIndex:T,renderingEndIndex:P,fenwickSize:x,viewportSize:n}),x===0)return y.jsx("div",{className:"absolute w-full",style:{top:0},children:y.jsx("div",{className:"text-center text-gray-500",children:"No items"})});const Z=ge(T,x),{cumulative:se,currentValue:K}=b.prefixSum(Z,{materializeOption:{materialize:!1}}),J=se-K,re=[],q=[];for(let F=T;F<=P;F++){const c=t(F);re.push({item:e(F),height:c,index:F}),b.get(F)!==c&&q.push({index:F,value:c})}q.length>0&&Promise.resolve().then(()=>{const F=b.updates(q);F&&(G(F),ae.debug("[VirtualScroll] Updated heights for items",q,"New total height:",F))});const he=N<n?0:J-S;return ae.debug("[VirtualScroll] Rendering items",{visibleItems:re,containerTop:he}),y.jsx("div",{className:"absolute w-full",style:{top:he},children:re.map(({item:F,index:c})=>{const Q=ge(c,x),{cumulative:$,currentValue:D}=b.prefixSum(Q,{materializeOption:{materialize:!1}}),le=$-D;return y.jsx("div",{"data-index":c,style:{position:"absolute",top:le-J,width:"100%"},children:h(F,c)},c)})})},[e,h,N,n,v,b,x,t]);return s.useImperativeHandle(W,()=>({getScrollPosition:()=>R.current?.getScrollPosition()??-1,getContentSize:()=>R.current?.getContentSize()??-1,getViewportSize:()=>R.current?.getViewportSize()??-1,scrollTo:z,scrollToIndex:k,getFenwickTreeTotalHeight:()=>b.getTotal(),getFenwickSize:()=>b.getSize()}),[z,k,b]),y.jsx(Je,{ref:R,contentSize:N,viewportSize:n,className:o,onScroll:L,background:u,tapScrollCircleOptions:V,inertiaOptions:w,itemCount:a,scrollBarWidth:A,enableThumbDrag:O,enableTrackClick:ee,enableArrowButtons:H,enablePointerDrag:te,renderThumbOverlay:ie,wheelSpeedMultiplier:oe,children:M})}const Lt=s.forwardRef(kt);exports.FenwickMapTree=Qe;exports.ScrollBar=Ze;exports.ScrollPane=Je;exports.VirtualScroll=Lt;exports.minmax=X;exports.tapScrollCircleSampleVisual=Pt;exports.useFenwickMapTree=Be;exports.useHeightCache=At;exports.useLruCache=et;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|