scroll-to-future 1.0.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/dist/index.js ADDED
@@ -0,0 +1,1796 @@
1
+ "use client";
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ ScrollToFuture: () => ScrollToFuture
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/ScrollToFuture.tsx
29
+ var import_react7 = require("react");
30
+
31
+ // src/components/Axios/ScrollAxis.tsx
32
+ var import_react = require("react");
33
+
34
+ // src/utils/constants.ts
35
+ var MIN_THUMB_SIZE = 24;
36
+ var DEFAULT_TRACK_THICKNESS = 8;
37
+ var MAX_THUMB_RATIO = 0.8;
38
+ var EMPTY_AXIS_METRICS = {
39
+ scrollSize: 0,
40
+ clientSize: 0,
41
+ scrollPos: 0,
42
+ canScroll: false
43
+ };
44
+
45
+ // src/utils/helper.ts
46
+ var clamp = (value, min, max) => Math.min(Math.max(value, min), Math.max(min, max));
47
+ var parsePxValue = (value) => {
48
+ if (!value) return null;
49
+ const match = /^(-?\d+(?:\.\d+)?)px$/.exec(value.trim());
50
+ return match ? Number(match[1]) : null;
51
+ };
52
+ var parseBoundaryOffset = (value) => {
53
+ if (!value) {
54
+ return {
55
+ start: 0,
56
+ end: 0
57
+ };
58
+ }
59
+ const parts = value.trim().split(/\s+/);
60
+ const start = Math.max(0, parsePxValue(parts[0]) ?? 0);
61
+ const end = parts.length > 1 ? Math.max(0, parsePxValue(parts[1]) ?? 0) : start;
62
+ return {
63
+ start,
64
+ end
65
+ };
66
+ };
67
+ var fitInsetsWithinSize = (start, end, size, minInnerSize = 1) => {
68
+ const safeSize = Math.max(0, size);
69
+ if (safeSize <= 0) {
70
+ return {
71
+ start: 0,
72
+ end: 0,
73
+ innerSize: 0
74
+ };
75
+ }
76
+ const actualMinInnerSize = Math.min(Math.max(0, minInnerSize), safeSize);
77
+ const safeStart = Math.max(0, start);
78
+ const safeEnd = Math.max(0, end);
79
+ const requestedInsetsSize = safeStart + safeEnd;
80
+ const maximumInsetsSize = safeSize - actualMinInnerSize;
81
+ if (requestedInsetsSize <= maximumInsetsSize) {
82
+ return {
83
+ start: safeStart,
84
+ end: safeEnd,
85
+ innerSize: safeSize - safeStart - safeEnd
86
+ };
87
+ }
88
+ if (requestedInsetsSize <= 0) {
89
+ return {
90
+ start: 0,
91
+ end: 0,
92
+ innerSize: safeSize
93
+ };
94
+ }
95
+ const scale = maximumInsetsSize / requestedInsetsSize;
96
+ const fittedStart = safeStart * scale;
97
+ const fittedEnd = safeEnd * scale;
98
+ return {
99
+ start: fittedStart,
100
+ end: fittedEnd,
101
+ innerSize: Math.max(
102
+ actualMinInnerSize,
103
+ safeSize - fittedStart - fittedEnd
104
+ )
105
+ };
106
+ };
107
+ var resolveTrackLength = (value, containerSize) => {
108
+ if (!value) return containerSize;
109
+ const px = parsePxValue(value);
110
+ if (px !== null) return px;
111
+ const percentMatch = /^(-?\d+(?:\.\d+)?)%$/.exec(value);
112
+ if (percentMatch) return Number(percentMatch[1]) / 100 * containerSize;
113
+ const vhMatch = /^(-?\d+(?:\.\d+)?)vh$/.exec(value);
114
+ if (vhMatch) {
115
+ const vh = typeof window !== "undefined" ? window.innerHeight : containerSize;
116
+ return Number(vhMatch[1]) / 100 * vh;
117
+ }
118
+ const dvhMatch = /^(-?\d+(?:\.\d+)?)d(s)?vh$/.exec(value);
119
+ if (dvhMatch) {
120
+ const dvh = typeof window !== "undefined" ? window.visualViewport?.height ?? window.innerHeight : containerSize;
121
+ return Number(dvhMatch[1]) / 100 * dvh;
122
+ }
123
+ return containerSize;
124
+ };
125
+ var computeThumbSize = (trackLength, metrics, thumbHeightTrack) => {
126
+ if (trackLength <= 0) return 0;
127
+ const minSize = Math.min(MIN_THUMB_SIZE, trackLength);
128
+ const maxSize = Math.min(
129
+ trackLength,
130
+ Math.max(minSize, trackLength * MAX_THUMB_RATIO)
131
+ );
132
+ if (!thumbHeightTrack || thumbHeightTrack === "auto") {
133
+ const ratio = metrics.scrollSize > 0 ? metrics.clientSize / metrics.scrollSize : 1;
134
+ const autoSize = trackLength * clamp(ratio, 0, 1);
135
+ return clamp(autoSize, minSize, maxSize);
136
+ }
137
+ const px = parsePxValue(thumbHeightTrack);
138
+ if (px !== null) {
139
+ return clamp(px, minSize, maxSize);
140
+ }
141
+ const percentMatch = /^(-?\d+(?:\.\d+)?)%$/.exec(thumbHeightTrack.trim());
142
+ if (percentMatch) {
143
+ const size = Number(percentMatch[1]) / 100 * trackLength;
144
+ return clamp(size, minSize, maxSize);
145
+ }
146
+ return maxSize;
147
+ };
148
+ var computeThumbPosition = (trackLength, thumbSize, metrics) => {
149
+ const maxScroll = metrics.scrollSize - metrics.clientSize;
150
+ const maxThumbTravel = trackLength - thumbSize;
151
+ if (maxScroll <= 0 || maxThumbTravel <= 0) return 0;
152
+ const ratio = clamp(metrics.scrollPos / maxScroll, 0, 1);
153
+ return ratio * maxThumbTravel;
154
+ };
155
+ var trackPositionToScroll = (trackPos, trackLength, thumbSize, metrics) => {
156
+ const maxScroll = metrics.scrollSize - metrics.clientSize;
157
+ const maxThumbTravel = trackLength - thumbSize;
158
+ if (maxScroll <= 0 || maxThumbTravel <= 0) return 0;
159
+ const ratio = clamp(trackPos / maxThumbTravel, 0, 1);
160
+ return ratio * maxScroll;
161
+ };
162
+ var computeReservedSpace = (boundaryOffset, trackThicknessPx, superimposition) => {
163
+ if (superimposition !== "after") {
164
+ return 0;
165
+ }
166
+ const { start, end } = parseBoundaryOffset(boundaryOffset);
167
+ return start + trackThicknessPx + end;
168
+ };
169
+ var isPageScrollTarget = (el) => typeof document !== "undefined" && (el === document.body || el === document.documentElement);
170
+
171
+ // src/components/Axios/ScrollAxis.tsx
172
+ var import_jsx_runtime = require("react/jsx-runtime");
173
+ var ScrollAxis = ({
174
+ axis,
175
+ target,
176
+ metrics,
177
+ scrollBar,
178
+ thumb,
179
+ positionMode,
180
+ superimposition,
181
+ hasCrossAxis,
182
+ vars
183
+ }) => {
184
+ const trackRef = (0, import_react.useRef)(null);
185
+ const dragState = (0, import_react.useRef)(null);
186
+ const [isDragging, setIsDragging] = (0, import_react.useState)(false);
187
+ const requestedTrackThickness = parsePxValue(scrollBar.widthTrack) ?? DEFAULT_TRACK_THICKNESS;
188
+ const trackThickness = Math.max(1, requestedTrackThickness);
189
+ const trackBoundary = parseBoundaryOffset(scrollBar.boundaryOffset);
190
+ const thumbBoundary = parseBoundaryOffset(thumb.boundaryOffset);
191
+ const requestedCrossAxisOccupation = trackBoundary.start + trackThickness + trackBoundary.end;
192
+ const maximumCrossAxisOccupation = Math.max(0, metrics.clientSize - 1);
193
+ const crossAxisOccupation = hasCrossAxis ? clamp(requestedCrossAxisOccupation, 0, maximumCrossAxisOccupation) : 0;
194
+ const availableMainStart = hasCrossAxis && positionMode === "before" ? crossAxisOccupation : 0;
195
+ const availableMainSize = Math.max(
196
+ 0,
197
+ metrics.clientSize - crossAxisOccupation
198
+ );
199
+ const trackCenter = availableMainStart + availableMainSize / 2;
200
+ const requestedTrackLength = resolveTrackLength(
201
+ scrollBar.heightTrack,
202
+ metrics.clientSize
203
+ );
204
+ const trackLength = availableMainSize > 0 ? clamp(requestedTrackLength, 1, availableMainSize) : 0;
205
+ const fittedThumbMainInsets = fitInsetsWithinSize(
206
+ thumbBoundary.start,
207
+ thumbBoundary.end,
208
+ trackLength,
209
+ 1
210
+ );
211
+ const thumbMainStart = fittedThumbMainInsets.start;
212
+ const innerTrackLength = fittedThumbMainInsets.innerSize;
213
+ const requestedThumbCrossSize = trackThickness - thumbBoundary.start - thumbBoundary.end;
214
+ const thumbCrossSize = clamp(requestedThumbCrossSize, 1, trackThickness);
215
+ const thumbSize = computeThumbSize(
216
+ innerTrackLength,
217
+ metrics,
218
+ thumb.heightTrack
219
+ );
220
+ const thumbPositionInsideTrack = computeThumbPosition(
221
+ innerTrackLength,
222
+ thumbSize,
223
+ metrics
224
+ );
225
+ const thumbPosition = thumbMainStart + thumbPositionInsideTrack;
226
+ const maxScroll = Math.max(0, metrics.scrollSize - metrics.clientSize);
227
+ const maxThumbTravel = Math.max(0, innerTrackLength - thumbSize);
228
+ const setScrollPosition = (value) => {
229
+ const targetElement = target;
230
+ if (!targetElement) return;
231
+ const nextValue = clamp(value, 0, Math.max(0, maxScroll));
232
+ if (!isPageScrollTarget(targetElement)) {
233
+ if (axis === "x") {
234
+ targetElement.scrollLeft = nextValue;
235
+ } else {
236
+ targetElement.scrollTop = nextValue;
237
+ }
238
+ return;
239
+ }
240
+ const targetStyle = window.getComputedStyle(targetElement);
241
+ const overflowValue = axis === "x" ? targetStyle.overflowX : targetStyle.overflowY;
242
+ const targetCanScroll = axis === "x" ? targetElement.scrollWidth - targetElement.clientWidth > 1 : targetElement.scrollHeight - targetElement.clientHeight > 1;
243
+ const targetOwnsScroll = targetCanScroll && /^(auto|scroll|overlay)$/.test(overflowValue);
244
+ if (targetOwnsScroll) {
245
+ if (axis === "x") {
246
+ targetElement.scrollLeft = nextValue;
247
+ } else {
248
+ targetElement.scrollTop = nextValue;
249
+ }
250
+ return;
251
+ }
252
+ window.scrollTo({
253
+ left: axis === "x" ? nextValue : window.scrollX,
254
+ top: axis === "y" ? nextValue : window.scrollY,
255
+ behavior: "auto"
256
+ });
257
+ };
258
+ const handleThumbPointerDown = (event) => {
259
+ event.preventDefault();
260
+ event.stopPropagation();
261
+ dragState.current = {
262
+ startPointer: axis === "x" ? event.clientX : event.clientY,
263
+ startScroll: metrics.scrollPos
264
+ };
265
+ setIsDragging(true);
266
+ event.currentTarget.setPointerCapture(event.pointerId);
267
+ };
268
+ const handleThumbPointerMove = (event) => {
269
+ const currentDragState = dragState.current;
270
+ if (!currentDragState) return;
271
+ if (maxScroll <= 0 || maxThumbTravel <= 0) return;
272
+ const pointerPosition = axis === "x" ? event.clientX : event.clientY;
273
+ const pointerDelta = pointerPosition - currentDragState.startPointer;
274
+ const scrollDelta = pointerDelta / maxThumbTravel * maxScroll;
275
+ setScrollPosition(currentDragState.startScroll + scrollDelta);
276
+ };
277
+ const stopDrag = (event) => {
278
+ if (!dragState.current) return;
279
+ dragState.current = null;
280
+ setIsDragging(false);
281
+ try {
282
+ event.currentTarget.releasePointerCapture(event.pointerId);
283
+ } catch {
284
+ }
285
+ };
286
+ const handleTrackPointerDown = (event) => {
287
+ if (event.target !== event.currentTarget) {
288
+ return;
289
+ }
290
+ const trackElement = trackRef.current;
291
+ if (!trackElement) return;
292
+ if (maxThumbTravel <= 0) return;
293
+ const rect = trackElement.getBoundingClientRect();
294
+ const clickPosition = axis === "x" ? event.clientX - rect.left : event.clientY - rect.top;
295
+ const clickInsideInnerTrack = clickPosition - thumbMainStart;
296
+ const targetThumbStart = clamp(
297
+ clickInsideInnerTrack - thumbSize / 2,
298
+ 0,
299
+ maxThumbTravel
300
+ );
301
+ const nextScroll = trackPositionToScroll(
302
+ targetThumbStart,
303
+ innerTrackLength,
304
+ thumbSize,
305
+ metrics
306
+ );
307
+ setScrollPosition(nextScroll);
308
+ };
309
+ if (!metrics.canScroll || metrics.clientSize <= 0 || trackLength < 1 || innerTrackLength < 1 || thumbSize < 1) {
310
+ return null;
311
+ }
312
+ const trackStyle = axis === "y" ? {
313
+ position: "absolute",
314
+ top: trackCenter,
315
+ transform: "translateY(-50%)",
316
+ width: trackThickness,
317
+ height: trackLength,
318
+ ...positionMode === "before" ? {
319
+ left: trackBoundary.start
320
+ } : {
321
+ right: trackBoundary.end
322
+ },
323
+ pointerEvents: "auto"
324
+ } : {
325
+ position: "absolute",
326
+ left: trackCenter,
327
+ transform: "translateX(-50%)",
328
+ width: trackLength,
329
+ height: trackThickness,
330
+ ...positionMode === "before" ? {
331
+ top: trackBoundary.start
332
+ } : {
333
+ bottom: trackBoundary.end
334
+ },
335
+ pointerEvents: "auto"
336
+ };
337
+ const thumbStyle = axis === "y" ? {
338
+ top: thumbPosition,
339
+ height: thumbSize,
340
+ //* horizontal center
341
+ left: "50%",
342
+ width: thumbCrossSize,
343
+ transform: "translateX(-50%)"
344
+ } : {
345
+ left: thumbPosition,
346
+ width: thumbSize,
347
+ //* vertical center
348
+ top: "50%",
349
+ height: thumbCrossSize,
350
+ transform: "translateY(-50%)"
351
+ };
352
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
353
+ "div",
354
+ {
355
+ ref: trackRef,
356
+ className: "scroll-to-future__track",
357
+ style: { ...trackStyle, ...vars },
358
+ onPointerDown: handleTrackPointerDown,
359
+ "data-axis": axis,
360
+ "data-superimposition": superimposition,
361
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
362
+ "div",
363
+ {
364
+ className: `scroll-to-future__thumb ${isDragging ? "scroll-to-future__thumb--dragging" : ""}`.trim(),
365
+ style: thumbStyle,
366
+ onPointerDown: handleThumbPointerDown,
367
+ onPointerMove: handleThumbPointerMove,
368
+ onPointerUp: stopDrag,
369
+ onPointerCancel: stopDrag
370
+ }
371
+ )
372
+ }
373
+ );
374
+ };
375
+
376
+ // src/hooks/useElementScrollObserver.ts
377
+ var import_react3 = require("react");
378
+
379
+ // src/hooks/useRefReady.ts
380
+ var import_react2 = require("react");
381
+ var useRefReady = (target) => {
382
+ const [tick, setTick] = (0, import_react2.useState)(0);
383
+ (0, import_react2.useEffect)(() => {
384
+ if (target) return;
385
+ let rafId;
386
+ const check = () => {
387
+ if (target) {
388
+ setTick((t) => t + 1);
389
+ } else {
390
+ rafId = requestAnimationFrame(check);
391
+ }
392
+ };
393
+ rafId = requestAnimationFrame(check);
394
+ return () => cancelAnimationFrame(rafId);
395
+ }, [target]);
396
+ return tick;
397
+ };
398
+
399
+ // src/hooks/useElementScrollObserver.ts
400
+ var isSameAxisMetrics = (previous, next) => previous.scrollSize === next.scrollSize && previous.clientSize === next.clientSize && previous.scrollPos === next.scrollPos && previous.canScroll === next.canScroll;
401
+ var getActualScrollPosition = (...values) => values.reduce((current, value) => {
402
+ return Math.abs(value) > Math.abs(current) ? value : current;
403
+ }, 0);
404
+ var useElementScrollObserver = (target) => {
405
+ const [metrics, setMetrics] = (0, import_react3.useState)({
406
+ x: EMPTY_AXIS_METRICS,
407
+ y: EMPTY_AXIS_METRICS
408
+ });
409
+ const rafRef = (0, import_react3.useRef)(null);
410
+ const ready = useRefReady(target);
411
+ (0, import_react3.useEffect)(() => {
412
+ const targetElement = target;
413
+ if (!targetElement) {
414
+ setMetrics({
415
+ x: EMPTY_AXIS_METRICS,
416
+ y: EMPTY_AXIS_METRICS
417
+ });
418
+ return;
419
+ }
420
+ const pageScroll = isPageScrollTarget(targetElement);
421
+ const measure = () => {
422
+ let nextX;
423
+ let nextY;
424
+ if (pageScroll) {
425
+ const root = document.documentElement;
426
+ const body = document.body;
427
+ const scrollingElement = document.scrollingElement;
428
+ const scrollWidth = Math.max(
429
+ root.scrollWidth,
430
+ body.scrollWidth,
431
+ scrollingElement?.scrollWidth ?? 0,
432
+ targetElement.scrollWidth
433
+ );
434
+ const scrollHeight = Math.max(
435
+ root.scrollHeight,
436
+ body.scrollHeight,
437
+ scrollingElement?.scrollHeight ?? 0,
438
+ targetElement.scrollHeight
439
+ );
440
+ const clientWidth = window.visualViewport?.width ?? window.innerWidth;
441
+ const clientHeight = window.visualViewport?.height ?? window.innerHeight;
442
+ const scrollLeft = getActualScrollPosition(
443
+ window.scrollX,
444
+ root.scrollLeft,
445
+ body.scrollLeft,
446
+ scrollingElement?.scrollLeft ?? 0,
447
+ targetElement.scrollLeft
448
+ );
449
+ const scrollTop = getActualScrollPosition(
450
+ window.scrollY,
451
+ root.scrollTop,
452
+ body.scrollTop,
453
+ scrollingElement?.scrollTop ?? 0,
454
+ targetElement.scrollTop
455
+ );
456
+ nextX = {
457
+ scrollSize: scrollWidth,
458
+ clientSize: clientWidth,
459
+ scrollPos: scrollLeft,
460
+ canScroll: scrollWidth - clientWidth > 1
461
+ };
462
+ nextY = {
463
+ scrollSize: scrollHeight,
464
+ clientSize: clientHeight,
465
+ scrollPos: scrollTop,
466
+ canScroll: scrollHeight - clientHeight > 1
467
+ };
468
+ } else {
469
+ nextX = {
470
+ scrollSize: targetElement.scrollWidth,
471
+ clientSize: targetElement.clientWidth,
472
+ scrollPos: targetElement.scrollLeft,
473
+ canScroll: targetElement.scrollWidth - targetElement.clientWidth > 1
474
+ };
475
+ nextY = {
476
+ scrollSize: targetElement.scrollHeight,
477
+ clientSize: targetElement.clientHeight,
478
+ scrollPos: targetElement.scrollTop,
479
+ canScroll: targetElement.scrollHeight - targetElement.clientHeight > 1
480
+ };
481
+ }
482
+ setMetrics((previous) => {
483
+ const sameX = isSameAxisMetrics(previous.x, nextX);
484
+ const sameY = isSameAxisMetrics(previous.y, nextY);
485
+ if (sameX && sameY) {
486
+ return previous;
487
+ }
488
+ return {
489
+ x: nextX,
490
+ y: nextY
491
+ };
492
+ });
493
+ };
494
+ const scheduleMeasure = () => {
495
+ if (rafRef.current !== null) return;
496
+ rafRef.current = requestAnimationFrame(() => {
497
+ rafRef.current = null;
498
+ measure();
499
+ });
500
+ };
501
+ measure();
502
+ const resizeObserver = new ResizeObserver(scheduleMeasure);
503
+ if (pageScroll) {
504
+ resizeObserver.observe(document.documentElement);
505
+ resizeObserver.observe(document.body);
506
+ if (targetElement !== document.documentElement && targetElement !== document.body) {
507
+ resizeObserver.observe(targetElement);
508
+ }
509
+ } else {
510
+ resizeObserver.observe(targetElement);
511
+ Array.from(targetElement.children).forEach((child) => {
512
+ resizeObserver.observe(child);
513
+ });
514
+ }
515
+ const mutationRoot = pageScroll ? document.documentElement : targetElement;
516
+ const mutationObserver = new MutationObserver((mutations) => {
517
+ for (const mutation of mutations) {
518
+ if (mutation.type !== "childList") continue;
519
+ mutation.addedNodes.forEach((node) => {
520
+ if (!(node instanceof Element)) return;
521
+ try {
522
+ resizeObserver.observe(node);
523
+ } catch {
524
+ }
525
+ });
526
+ }
527
+ scheduleMeasure();
528
+ });
529
+ mutationObserver.observe(mutationRoot, {
530
+ childList: true,
531
+ subtree: true,
532
+ attributes: true,
533
+ attributeFilter: ["style", "class", "hidden"]
534
+ });
535
+ window.addEventListener("scroll", scheduleMeasure, {
536
+ capture: true,
537
+ passive: true
538
+ });
539
+ targetElement.addEventListener("scroll", scheduleMeasure, {
540
+ passive: true
541
+ });
542
+ window.addEventListener("resize", scheduleMeasure);
543
+ window.visualViewport?.addEventListener("resize", scheduleMeasure);
544
+ window.visualViewport?.addEventListener("scroll", scheduleMeasure);
545
+ return () => {
546
+ resizeObserver.disconnect();
547
+ mutationObserver.disconnect();
548
+ window.removeEventListener("scroll", scheduleMeasure, true);
549
+ targetElement.removeEventListener("scroll", scheduleMeasure);
550
+ window.removeEventListener("resize", scheduleMeasure);
551
+ window.visualViewport?.removeEventListener(
552
+ "resize",
553
+ scheduleMeasure
554
+ );
555
+ window.visualViewport?.removeEventListener(
556
+ "scroll",
557
+ scheduleMeasure
558
+ );
559
+ if (rafRef.current !== null) {
560
+ cancelAnimationFrame(rafRef.current);
561
+ rafRef.current = null;
562
+ }
563
+ };
564
+ }, [target, ready]);
565
+ return metrics;
566
+ };
567
+
568
+ // src/hooks/useFuture.ts
569
+ var import_react4 = require("react");
570
+
571
+ // src/utils/native-scrollbar.ts
572
+ var STYLE_ID = "scroll-to-future-native-scrollbar-styles";
573
+ var ALWAYS_CLASS = "scroll-to-future-hide-native-scrollbar";
574
+ var FINE_POINTER_CLASS = "scroll-to-future-hide-native-scrollbar-fine";
575
+ var classCounters = /* @__PURE__ */ new WeakMap();
576
+ var installStyles = () => {
577
+ if (typeof document === "undefined") return;
578
+ if (document.getElementById(STYLE_ID)) {
579
+ return;
580
+ }
581
+ const style = document.createElement("style");
582
+ style.id = STYLE_ID;
583
+ style.textContent = `
584
+ .${ALWAYS_CLASS} {
585
+ scrollbar-width: none !important;
586
+ -ms-overflow-style: none !important;
587
+ }
588
+
589
+ .${ALWAYS_CLASS}::-webkit-scrollbar {
590
+ display: none !important;
591
+ width: 0 !important;
592
+ height: 0 !important;
593
+ background: transparent !important;
594
+ }
595
+
596
+ @media (any-pointer: fine) {
597
+ .${FINE_POINTER_CLASS} {
598
+ scrollbar-width: none !important;
599
+ -ms-overflow-style: none !important;
600
+ }
601
+
602
+ .${FINE_POINTER_CLASS}::-webkit-scrollbar {
603
+ display: none !important;
604
+ width: 0 !important;
605
+ height: 0 !important;
606
+ background: transparent !important;
607
+ }
608
+ }
609
+ `;
610
+ document.head.appendChild(style);
611
+ };
612
+ var retainClass = (element, className) => {
613
+ let elementCounters = classCounters.get(element);
614
+ if (!elementCounters) {
615
+ elementCounters = /* @__PURE__ */ new Map();
616
+ classCounters.set(element, elementCounters);
617
+ }
618
+ const currentCount = elementCounters.get(className) ?? 0;
619
+ elementCounters.set(className, currentCount + 1);
620
+ if (currentCount === 0) {
621
+ element.classList.add(className);
622
+ }
623
+ return () => {
624
+ const counters = classCounters.get(element);
625
+ if (!counters) return;
626
+ const count = counters.get(className) ?? 0;
627
+ if (count <= 1) {
628
+ counters.delete(className);
629
+ element.classList.remove(className);
630
+ } else {
631
+ counters.set(className, count - 1);
632
+ }
633
+ if (counters.size === 0) {
634
+ classCounters.delete(element);
635
+ }
636
+ };
637
+ };
638
+ var isDocumentScrollTarget = (target) => {
639
+ if (typeof document === "undefined") {
640
+ return false;
641
+ }
642
+ return target === document.body || target === document.documentElement || target === document.scrollingElement;
643
+ };
644
+ var resolveStyleTargets = (target) => {
645
+ if (!isDocumentScrollTarget(target)) {
646
+ return [target];
647
+ }
648
+ const targets = /* @__PURE__ */ new Set();
649
+ targets.add(document.documentElement);
650
+ if (document.body) {
651
+ targets.add(document.body);
652
+ }
653
+ const scrollingElement = document.scrollingElement;
654
+ if (scrollingElement instanceof HTMLElement) {
655
+ targets.add(scrollingElement);
656
+ }
657
+ return Array.from(targets);
658
+ };
659
+ var isMobileInputDevice = () => {
660
+ if (typeof window === "undefined" || typeof navigator === "undefined") {
661
+ return false;
662
+ }
663
+ const coarsePointer = window.matchMedia("(pointer: coarse)").matches;
664
+ const cannotHover = window.matchMedia("(hover: none)").matches;
665
+ const hasTouch = navigator.maxTouchPoints > 0;
666
+ return hasTouch && coarsePointer && cannotHover;
667
+ };
668
+ var hideNativeScrollbar = (target, mode, nativeOnMobile) => {
669
+ if (typeof window === "undefined" || typeof document === "undefined" || mode === false) {
670
+ return () => {
671
+ };
672
+ }
673
+ if (nativeOnMobile && isMobileInputDevice()) {
674
+ return () => {
675
+ };
676
+ }
677
+ installStyles();
678
+ const className = mode === "always" ? ALWAYS_CLASS : FINE_POINTER_CLASS;
679
+ const targets = resolveStyleTargets(target);
680
+ const cleanups = targets.map((element) => retainClass(element, className));
681
+ return () => {
682
+ cleanups.forEach((cleanup) => {
683
+ cleanup();
684
+ });
685
+ };
686
+ };
687
+
688
+ // src/hooks/useFuture.ts
689
+ var useFuture = ({
690
+ target,
691
+ anchorRef,
692
+ targetRef,
693
+ setFindedTarget,
694
+ mounted,
695
+ config,
696
+ showY,
697
+ showX,
698
+ superimposition,
699
+ findedTarget,
700
+ positionMode,
701
+ coversAllScrollableAxes,
702
+ nativeOnMobile
703
+ }) => {
704
+ (0, import_react4.useEffect)(() => {
705
+ if (!mounted) return;
706
+ let rafId = null;
707
+ const resolveTarget = () => {
708
+ const nextTarget = target ? target.current : anchorRef.current?.parentElement ?? null;
709
+ if (nextTarget) {
710
+ targetRef.current = nextTarget;
711
+ setFindedTarget(
712
+ (previousTarget) => previousTarget === nextTarget ? previousTarget : nextTarget
713
+ );
714
+ return;
715
+ }
716
+ rafId = requestAnimationFrame(resolveTarget);
717
+ };
718
+ resolveTarget();
719
+ return () => {
720
+ if (rafId !== null) {
721
+ cancelAnimationFrame(rafId);
722
+ }
723
+ };
724
+ }, [mounted, target]);
725
+ (0, import_react4.useEffect)(() => {
726
+ const el = targetRef.current;
727
+ if (!el) return;
728
+ const trackThickness = parsePxValue(config.scrollBar?.widthTrack) ?? DEFAULT_TRACK_THICKNESS;
729
+ const reservedY = showY ? computeReservedSpace(
730
+ config.scrollBar?.boundaryOffset,
731
+ trackThickness,
732
+ superimposition
733
+ ) : 0;
734
+ const reservedX = showX ? computeReservedSpace(
735
+ config.scrollBar?.boundaryOffset,
736
+ trackThickness,
737
+ superimposition
738
+ ) : 0;
739
+ const previousInlinePadding = {
740
+ left: el.style.paddingLeft,
741
+ right: el.style.paddingRight,
742
+ top: el.style.paddingTop,
743
+ bottom: el.style.paddingBottom
744
+ };
745
+ const computedStyle = window.getComputedStyle(el);
746
+ const basePadding = {
747
+ left: Number.parseFloat(computedStyle.paddingLeft) || 0,
748
+ right: Number.parseFloat(computedStyle.paddingRight) || 0,
749
+ top: Number.parseFloat(computedStyle.paddingTop) || 0,
750
+ bottom: Number.parseFloat(computedStyle.paddingBottom) || 0
751
+ };
752
+ if (reservedY > 0) {
753
+ if (positionMode === "before") {
754
+ el.style.paddingLeft = `${basePadding.left + reservedY}px`;
755
+ } else {
756
+ el.style.paddingRight = `${basePadding.right + reservedY}px`;
757
+ }
758
+ }
759
+ if (reservedX > 0) {
760
+ if (positionMode === "before") {
761
+ el.style.paddingTop = `${basePadding.top + reservedX}px`;
762
+ } else {
763
+ el.style.paddingBottom = `${basePadding.bottom + reservedX}px`;
764
+ }
765
+ }
766
+ return () => {
767
+ el.style.paddingLeft = previousInlinePadding.left;
768
+ el.style.paddingRight = previousInlinePadding.right;
769
+ el.style.paddingTop = previousInlinePadding.top;
770
+ el.style.paddingBottom = previousInlinePadding.bottom;
771
+ };
772
+ }, [
773
+ findedTarget,
774
+ showX,
775
+ showY,
776
+ positionMode,
777
+ superimposition,
778
+ config.scrollBar?.boundaryOffset,
779
+ config.scrollBar?.widthTrack
780
+ ]);
781
+ (0, import_react4.useEffect)(() => {
782
+ if (!findedTarget) return;
783
+ const mode = config.scrollBar?.hideNativeScrollbar ?? false;
784
+ console.log("native scrollbar effect:", {
785
+ mode,
786
+ nativeOnMobile,
787
+ coversAllScrollableAxes,
788
+ target: findedTarget
789
+ });
790
+ if (mode === false || !coversAllScrollableAxes) {
791
+ return;
792
+ }
793
+ return hideNativeScrollbar(findedTarget, mode, nativeOnMobile);
794
+ }, [
795
+ findedTarget,
796
+ coversAllScrollableAxes,
797
+ nativeOnMobile,
798
+ config.scrollBar?.hideNativeScrollbar
799
+ ]);
800
+ };
801
+
802
+ // src/hooks/useMounted.tsx
803
+ var import_react5 = require("react");
804
+ function useMounted() {
805
+ const [mounted, setMounted] = (0, import_react5.useState)(false);
806
+ (0, import_react5.useEffect)(() => {
807
+ if (mounted) return;
808
+ setMounted(true);
809
+ }, []);
810
+ return mounted;
811
+ }
812
+
813
+ // src/hooks/useTargetRect.ts
814
+ var import_react6 = require("react");
815
+ var EMPTY_RECT = { top: 0, left: 0, width: 0, height: 0 };
816
+ var useTargetRect = (target) => {
817
+ const [rect, setRect] = (0, import_react6.useState)(EMPTY_RECT);
818
+ const ready = useRefReady(target);
819
+ (0, import_react6.useEffect)(() => {
820
+ const el = target;
821
+ if (!el) {
822
+ setRect(EMPTY_RECT);
823
+ return;
824
+ }
825
+ let rafId = null;
826
+ const pageScroll = isPageScrollTarget(el);
827
+ const measure = () => {
828
+ const r = pageScroll ? {
829
+ top: 0,
830
+ left: 0,
831
+ width: window.innerWidth,
832
+ height: window.innerHeight
833
+ } : el.getBoundingClientRect();
834
+ setRect((prev) => {
835
+ if (prev.top === r.top && prev.left === r.left && prev.width === r.width && prev.height === r.height) {
836
+ return prev;
837
+ }
838
+ return {
839
+ top: r.top,
840
+ left: r.left,
841
+ width: r.width,
842
+ height: r.height
843
+ };
844
+ });
845
+ };
846
+ const scheduleMeasure = () => {
847
+ if (rafId != null) return;
848
+ rafId = requestAnimationFrame(() => {
849
+ rafId = null;
850
+ measure();
851
+ });
852
+ };
853
+ measure();
854
+ const resizeObserver = new ResizeObserver(scheduleMeasure);
855
+ resizeObserver.observe(el);
856
+ window.addEventListener("scroll", scheduleMeasure, {
857
+ capture: true,
858
+ passive: true
859
+ });
860
+ window.addEventListener("resize", scheduleMeasure);
861
+ return () => {
862
+ resizeObserver.disconnect();
863
+ window.removeEventListener("scroll", scheduleMeasure, true);
864
+ window.removeEventListener("resize", scheduleMeasure);
865
+ if (rafId != null) cancelAnimationFrame(rafId);
866
+ };
867
+ }, [target, ready]);
868
+ return rect;
869
+ };
870
+
871
+ // src/themes/collection.theme.ts
872
+ var primary = {
873
+ scrollBar: {
874
+ inactive: {
875
+ backgroundColor: "rgba(0, 0, 0, 0.15)",
876
+ borderRadius: "8px",
877
+ transition: "background-color 0.3s ease"
878
+ },
879
+ hover: {
880
+ backgroundColor: "rgba(0, 0, 0, 0.25)"
881
+ },
882
+ active: {
883
+ backgroundColor: "rgba(0, 0, 0, 0.35)",
884
+ transition: "background-color 0.15s ease"
885
+ }
886
+ },
887
+ thumb: {
888
+ inactive: {
889
+ backgroundColor: "rgba(255, 255, 255, 0.35)",
890
+ borderRadius: "8px"
891
+ },
892
+ hover: {
893
+ backgroundColor: "rgba(255, 255, 255, 0.55)",
894
+ transform: "scale(1)",
895
+ transition: "background-color 0s ease, transform 0s ease"
896
+ },
897
+ active: {
898
+ backgroundColor: "rgba(255, 255, 255, 0.75)",
899
+ transform: "scale(1.1)",
900
+ transition: "background-color 0.15s ease, transform 0.15s ease"
901
+ }
902
+ }
903
+ };
904
+ var midnight = {
905
+ scrollBar: {
906
+ inactive: {
907
+ backgroundColor: "rgba(15, 23, 42, 0.55)",
908
+ borderRadius: "8px",
909
+ transition: "background-color 0.3s ease"
910
+ },
911
+ hover: {
912
+ backgroundColor: "rgba(30, 41, 59, 0.72)"
913
+ },
914
+ active: {
915
+ backgroundColor: "rgba(51, 65, 85, 0.88)",
916
+ transition: "background-color 0.15s ease"
917
+ }
918
+ },
919
+ thumb: {
920
+ inactive: {
921
+ backgroundColor: "rgba(148, 163, 184, 0.55)",
922
+ borderRadius: "8px"
923
+ },
924
+ hover: {
925
+ backgroundColor: "rgba(203, 213, 225, 0.78)",
926
+ transform: "scale(1)",
927
+ transition: "background-color 0s ease, transform 0s ease"
928
+ },
929
+ active: {
930
+ backgroundColor: "rgba(241, 245, 249, 0.96)",
931
+ transform: "scale(1.1)",
932
+ transition: "background-color 0.15s ease, transform 0.15s ease"
933
+ }
934
+ }
935
+ };
936
+ var neonCyan = {
937
+ scrollBar: {
938
+ inactive: {
939
+ backgroundColor: "rgba(6, 78, 89, 0.35)",
940
+ borderRadius: "4px",
941
+ transition: "background-color 0.25s ease"
942
+ },
943
+ hover: {
944
+ backgroundColor: "rgba(8, 145, 178, 0.48)"
945
+ },
946
+ active: {
947
+ backgroundColor: "rgba(14, 116, 144, 0.68)",
948
+ transition: "background-color 0.12s ease"
949
+ }
950
+ },
951
+ thumb: {
952
+ inactive: {
953
+ backgroundColor: "rgba(34, 211, 238, 0.58)",
954
+ borderRadius: "3px"
955
+ },
956
+ hover: {
957
+ backgroundColor: "rgba(103, 232, 249, 0.85)",
958
+ transform: "scale(1.02)",
959
+ transition: "background-color 0.15s ease, transform 0.15s ease"
960
+ },
961
+ active: {
962
+ backgroundColor: "rgba(207, 250, 254, 1)",
963
+ transform: "scale(1.12)",
964
+ transition: "background-color 0.12s ease, transform 0.12s ease"
965
+ }
966
+ }
967
+ };
968
+ var ocean = {
969
+ scrollBar: {
970
+ inactive: {
971
+ backgroundColor: "rgba(7, 89, 133, 0.22)",
972
+ borderRadius: "999px",
973
+ transition: "background-color 0.35s ease"
974
+ },
975
+ hover: {
976
+ backgroundColor: "rgba(3, 105, 161, 0.35)"
977
+ },
978
+ active: {
979
+ backgroundColor: "rgba(2, 132, 199, 0.5)",
980
+ transition: "background-color 0.18s ease"
981
+ }
982
+ },
983
+ thumb: {
984
+ inactive: {
985
+ backgroundColor: "rgba(14, 165, 233, 0.58)",
986
+ borderRadius: "999px"
987
+ },
988
+ hover: {
989
+ backgroundColor: "rgba(56, 189, 248, 0.82)",
990
+ transform: "scale(1)",
991
+ transition: "background-color 0.2s ease"
992
+ },
993
+ active: {
994
+ backgroundColor: "rgba(186, 230, 253, 0.98)",
995
+ transform: "scale(1.08)",
996
+ transition: "background-color 0.14s ease, transform 0.14s ease"
997
+ }
998
+ }
999
+ };
1000
+ var deepSea = {
1001
+ scrollBar: {
1002
+ inactive: {
1003
+ backgroundColor: "rgba(2, 44, 55, 0.62)",
1004
+ borderRadius: "999px",
1005
+ transition: "background-color 0.3s ease"
1006
+ },
1007
+ hover: {
1008
+ backgroundColor: "rgba(6, 78, 89, 0.78)"
1009
+ },
1010
+ active: {
1011
+ backgroundColor: "rgba(14, 116, 144, 0.9)",
1012
+ transition: "background-color 0.15s ease"
1013
+ }
1014
+ },
1015
+ thumb: {
1016
+ inactive: {
1017
+ backgroundColor: "rgba(8, 145, 178, 0.62)",
1018
+ borderRadius: "999px"
1019
+ },
1020
+ hover: {
1021
+ backgroundColor: "rgba(34, 211, 238, 0.82)",
1022
+ transform: "scale(1.03)",
1023
+ transition: "background-color 0.18s ease, transform 0.18s ease"
1024
+ },
1025
+ active: {
1026
+ backgroundColor: "rgba(165, 243, 252, 0.98)",
1027
+ transform: "scale(1.12)",
1028
+ transition: "background-color 0.12s ease, transform 0.12s ease"
1029
+ }
1030
+ }
1031
+ };
1032
+ var forest = {
1033
+ scrollBar: {
1034
+ inactive: {
1035
+ backgroundColor: "rgba(20, 83, 45, 0.25)",
1036
+ borderRadius: "999px",
1037
+ transition: "background-color 0.3s ease"
1038
+ },
1039
+ hover: {
1040
+ backgroundColor: "rgba(21, 128, 61, 0.38)"
1041
+ },
1042
+ active: {
1043
+ backgroundColor: "rgba(22, 163, 74, 0.52)",
1044
+ transition: "background-color 0.15s ease"
1045
+ }
1046
+ },
1047
+ thumb: {
1048
+ inactive: {
1049
+ backgroundColor: "rgba(34, 197, 94, 0.55)",
1050
+ borderRadius: "999px"
1051
+ },
1052
+ hover: {
1053
+ backgroundColor: "rgba(74, 222, 128, 0.8)",
1054
+ transform: "scale(1)",
1055
+ transition: "background-color 0.2s ease"
1056
+ },
1057
+ active: {
1058
+ backgroundColor: "rgba(187, 247, 208, 0.98)",
1059
+ transform: "scale(1.1)",
1060
+ transition: "background-color 0.15s ease, transform 0.15s ease"
1061
+ }
1062
+ }
1063
+ };
1064
+ var moss = {
1065
+ scrollBar: {
1066
+ inactive: {
1067
+ backgroundColor: "rgba(54, 83, 20, 0.28)",
1068
+ borderRadius: "6px",
1069
+ transition: "background-color 0.3s ease"
1070
+ },
1071
+ hover: {
1072
+ backgroundColor: "rgba(63, 98, 18, 0.42)"
1073
+ },
1074
+ active: {
1075
+ backgroundColor: "rgba(77, 124, 15, 0.58)",
1076
+ transition: "background-color 0.14s ease"
1077
+ }
1078
+ },
1079
+ thumb: {
1080
+ inactive: {
1081
+ backgroundColor: "rgba(132, 204, 22, 0.55)",
1082
+ borderRadius: "5px"
1083
+ },
1084
+ hover: {
1085
+ backgroundColor: "rgba(163, 230, 53, 0.8)",
1086
+ transform: "scale(1.02)",
1087
+ transition: "background-color 0.18s ease, transform 0.18s ease"
1088
+ },
1089
+ active: {
1090
+ backgroundColor: "rgba(217, 249, 157, 0.98)",
1091
+ transform: "scale(1.1)",
1092
+ transition: "background-color 0.12s ease, transform 0.12s ease"
1093
+ }
1094
+ }
1095
+ };
1096
+ var lava = {
1097
+ scrollBar: {
1098
+ inactive: {
1099
+ backgroundColor: "rgba(69, 10, 10, 0.45)",
1100
+ borderRadius: "999px",
1101
+ transition: "background-color 0.22s ease"
1102
+ },
1103
+ hover: {
1104
+ backgroundColor: "rgba(127, 29, 29, 0.62)"
1105
+ },
1106
+ active: {
1107
+ backgroundColor: "rgba(153, 27, 27, 0.78)",
1108
+ transition: "background-color 0.1s ease"
1109
+ }
1110
+ },
1111
+ thumb: {
1112
+ inactive: {
1113
+ backgroundColor: "rgba(239, 68, 68, 0.62)",
1114
+ borderRadius: "999px"
1115
+ },
1116
+ hover: {
1117
+ backgroundColor: "rgba(249, 115, 22, 0.88)",
1118
+ transform: "scale(1.03)",
1119
+ transition: "background-color 0.16s ease, transform 0.16s ease"
1120
+ },
1121
+ active: {
1122
+ backgroundColor: "rgba(253, 186, 116, 1)",
1123
+ transform: "scale(1.14)",
1124
+ transition: "background-color 0.1s ease, transform 0.1s ease"
1125
+ }
1126
+ }
1127
+ };
1128
+ var ember = {
1129
+ scrollBar: {
1130
+ inactive: {
1131
+ backgroundColor: "rgba(67, 20, 7, 0.32)",
1132
+ borderRadius: "5px",
1133
+ transition: "background-color 0.25s ease"
1134
+ },
1135
+ hover: {
1136
+ backgroundColor: "rgba(124, 45, 18, 0.48)"
1137
+ },
1138
+ active: {
1139
+ backgroundColor: "rgba(154, 52, 18, 0.65)",
1140
+ transition: "background-color 0.12s ease"
1141
+ }
1142
+ },
1143
+ thumb: {
1144
+ inactive: {
1145
+ backgroundColor: "rgba(234, 88, 12, 0.6)",
1146
+ borderRadius: "4px"
1147
+ },
1148
+ hover: {
1149
+ backgroundColor: "rgba(251, 146, 60, 0.86)",
1150
+ transform: "scale(1)",
1151
+ transition: "background-color 0.18s ease"
1152
+ },
1153
+ active: {
1154
+ backgroundColor: "rgba(254, 215, 170, 0.98)",
1155
+ transform: "scale(1.1)",
1156
+ transition: "background-color 0.12s ease, transform 0.12s ease"
1157
+ }
1158
+ }
1159
+ };
1160
+ var gold = {
1161
+ scrollBar: {
1162
+ inactive: {
1163
+ backgroundColor: "rgba(113, 63, 18, 0.25)",
1164
+ borderRadius: "999px",
1165
+ transition: "background-color 0.3s ease"
1166
+ },
1167
+ hover: {
1168
+ backgroundColor: "rgba(161, 98, 7, 0.4)"
1169
+ },
1170
+ active: {
1171
+ backgroundColor: "rgba(202, 138, 4, 0.55)",
1172
+ transition: "background-color 0.15s ease"
1173
+ }
1174
+ },
1175
+ thumb: {
1176
+ inactive: {
1177
+ backgroundColor: "rgba(234, 179, 8, 0.62)",
1178
+ borderRadius: "999px"
1179
+ },
1180
+ hover: {
1181
+ backgroundColor: "rgba(250, 204, 21, 0.85)",
1182
+ transform: "scale(1.02)",
1183
+ transition: "background-color 0.2s ease, transform 0.2s ease"
1184
+ },
1185
+ active: {
1186
+ backgroundColor: "rgba(254, 240, 138, 1)",
1187
+ transform: "scale(1.1)",
1188
+ transition: "background-color 0.14s ease, transform 0.14s ease"
1189
+ }
1190
+ }
1191
+ };
1192
+ var roseQuartz = {
1193
+ scrollBar: {
1194
+ inactive: {
1195
+ backgroundColor: "rgba(136, 19, 55, 0.18)",
1196
+ borderRadius: "999px",
1197
+ transition: "background-color 0.32s ease"
1198
+ },
1199
+ hover: {
1200
+ backgroundColor: "rgba(190, 24, 93, 0.28)"
1201
+ },
1202
+ active: {
1203
+ backgroundColor: "rgba(219, 39, 119, 0.4)",
1204
+ transition: "background-color 0.16s ease"
1205
+ }
1206
+ },
1207
+ thumb: {
1208
+ inactive: {
1209
+ backgroundColor: "rgba(251, 113, 133, 0.58)",
1210
+ borderRadius: "999px"
1211
+ },
1212
+ hover: {
1213
+ backgroundColor: "rgba(244, 114, 182, 0.8)",
1214
+ transform: "scale(1)",
1215
+ transition: "background-color 0.2s ease"
1216
+ },
1217
+ active: {
1218
+ backgroundColor: "rgba(253, 164, 175, 0.98)",
1219
+ transform: "scale(1.1)",
1220
+ transition: "background-color 0.15s ease, transform 0.15s ease"
1221
+ }
1222
+ }
1223
+ };
1224
+ var violet = {
1225
+ scrollBar: {
1226
+ inactive: {
1227
+ backgroundColor: "rgba(76, 29, 149, 0.3)",
1228
+ borderRadius: "999px",
1229
+ transition: "background-color 0.28s ease"
1230
+ },
1231
+ hover: {
1232
+ backgroundColor: "rgba(91, 33, 182, 0.45)"
1233
+ },
1234
+ active: {
1235
+ backgroundColor: "rgba(109, 40, 217, 0.62)",
1236
+ transition: "background-color 0.14s ease"
1237
+ }
1238
+ },
1239
+ thumb: {
1240
+ inactive: {
1241
+ backgroundColor: "rgba(139, 92, 246, 0.62)",
1242
+ borderRadius: "999px"
1243
+ },
1244
+ hover: {
1245
+ backgroundColor: "rgba(167, 139, 250, 0.86)",
1246
+ transform: "scale(1.03)",
1247
+ transition: "background-color 0.18s ease, transform 0.18s ease"
1248
+ },
1249
+ active: {
1250
+ backgroundColor: "rgba(221, 214, 254, 1)",
1251
+ transform: "scale(1.12)",
1252
+ transition: "background-color 0.12s ease, transform 0.12s ease"
1253
+ }
1254
+ }
1255
+ };
1256
+ var royal = {
1257
+ scrollBar: {
1258
+ inactive: {
1259
+ backgroundColor: "rgba(30, 27, 75, 0.48)",
1260
+ borderRadius: "999px",
1261
+ transition: "background-color 0.3s ease"
1262
+ },
1263
+ hover: {
1264
+ backgroundColor: "rgba(49, 46, 129, 0.65)"
1265
+ },
1266
+ active: {
1267
+ backgroundColor: "rgba(67, 56, 202, 0.82)",
1268
+ transition: "background-color 0.15s ease"
1269
+ }
1270
+ },
1271
+ thumb: {
1272
+ inactive: {
1273
+ backgroundColor: "rgba(99, 102, 241, 0.65)",
1274
+ borderRadius: "999px"
1275
+ },
1276
+ hover: {
1277
+ backgroundColor: "rgba(165, 180, 252, 0.86)",
1278
+ transform: "scale(1.02)",
1279
+ transition: "background-color 0.2s ease, transform 0.2s ease"
1280
+ },
1281
+ active: {
1282
+ backgroundColor: "rgba(224, 231, 255, 1)",
1283
+ transform: "scale(1.12)",
1284
+ transition: "background-color 0.14s ease, transform 0.14s ease"
1285
+ }
1286
+ }
1287
+ };
1288
+ var arctic = {
1289
+ scrollBar: {
1290
+ inactive: {
1291
+ backgroundColor: "rgba(186, 230, 253, 0.22)",
1292
+ borderRadius: "999px",
1293
+ transition: "background-color 0.35s ease"
1294
+ },
1295
+ hover: {
1296
+ backgroundColor: "rgba(125, 211, 252, 0.36)"
1297
+ },
1298
+ active: {
1299
+ backgroundColor: "rgba(56, 189, 248, 0.5)",
1300
+ transition: "background-color 0.18s ease"
1301
+ }
1302
+ },
1303
+ thumb: {
1304
+ inactive: {
1305
+ backgroundColor: "rgba(224, 242, 254, 0.65)",
1306
+ borderRadius: "999px"
1307
+ },
1308
+ hover: {
1309
+ backgroundColor: "rgba(240, 249, 255, 0.88)",
1310
+ transform: "scale(1)",
1311
+ transition: "background-color 0.2s ease"
1312
+ },
1313
+ active: {
1314
+ backgroundColor: "rgba(255, 255, 255, 1)",
1315
+ transform: "scale(1.08)",
1316
+ transition: "background-color 0.15s ease, transform 0.15s ease"
1317
+ }
1318
+ }
1319
+ };
1320
+ var glass = {
1321
+ scrollBar: {
1322
+ inactive: {
1323
+ backgroundColor: "rgba(255, 255, 255, 0.08)",
1324
+ borderRadius: "999px",
1325
+ transition: "background-color 0.3s ease"
1326
+ },
1327
+ hover: {
1328
+ backgroundColor: "rgba(255, 255, 255, 0.14)"
1329
+ },
1330
+ active: {
1331
+ backgroundColor: "rgba(255, 255, 255, 0.22)",
1332
+ transition: "background-color 0.15s ease"
1333
+ }
1334
+ },
1335
+ thumb: {
1336
+ inactive: {
1337
+ backgroundColor: "rgba(255, 255, 255, 0.28)",
1338
+ borderRadius: "999px"
1339
+ },
1340
+ hover: {
1341
+ backgroundColor: "rgba(255, 255, 255, 0.46)",
1342
+ transform: "scale(1)",
1343
+ transition: "background-color 0.2s ease"
1344
+ },
1345
+ active: {
1346
+ backgroundColor: "rgba(255, 255, 255, 0.7)",
1347
+ transform: "scale(1.08)",
1348
+ transition: "background-color 0.15s ease, transform 0.15s ease"
1349
+ }
1350
+ }
1351
+ };
1352
+ var graphite = {
1353
+ scrollBar: {
1354
+ inactive: {
1355
+ backgroundColor: "rgba(17, 24, 39, 0.52)",
1356
+ borderRadius: "3px",
1357
+ transition: "background-color 0.22s ease"
1358
+ },
1359
+ hover: {
1360
+ backgroundColor: "rgba(31, 41, 55, 0.7)"
1361
+ },
1362
+ active: {
1363
+ backgroundColor: "rgba(55, 65, 81, 0.88)",
1364
+ transition: "background-color 0.1s ease"
1365
+ }
1366
+ },
1367
+ thumb: {
1368
+ inactive: {
1369
+ backgroundColor: "rgba(107, 114, 128, 0.65)",
1370
+ borderRadius: "2px"
1371
+ },
1372
+ hover: {
1373
+ backgroundColor: "rgba(156, 163, 175, 0.82)",
1374
+ transform: "scale(1)",
1375
+ transition: "background-color 0.15s ease"
1376
+ },
1377
+ active: {
1378
+ backgroundColor: "rgba(229, 231, 235, 0.98)",
1379
+ transform: "scale(1.06)",
1380
+ transition: "background-color 0.1s ease, transform 0.1s ease"
1381
+ }
1382
+ }
1383
+ };
1384
+ var terminal = {
1385
+ scrollBar: {
1386
+ inactive: {
1387
+ backgroundColor: "rgba(0, 20, 5, 0.72)",
1388
+ borderRadius: "0px",
1389
+ transition: "background-color 0.15s linear"
1390
+ },
1391
+ hover: {
1392
+ backgroundColor: "rgba(0, 40, 10, 0.82)"
1393
+ },
1394
+ active: {
1395
+ backgroundColor: "rgba(0, 65, 18, 0.92)",
1396
+ transition: "background-color 0.08s linear"
1397
+ }
1398
+ },
1399
+ thumb: {
1400
+ inactive: {
1401
+ backgroundColor: "rgba(34, 197, 94, 0.62)",
1402
+ borderRadius: "0px"
1403
+ },
1404
+ hover: {
1405
+ backgroundColor: "rgba(74, 222, 128, 0.85)",
1406
+ transform: "scale(1)",
1407
+ transition: "background-color 0.1s linear"
1408
+ },
1409
+ active: {
1410
+ backgroundColor: "rgba(187, 247, 208, 1)",
1411
+ transform: "scale(1.06)",
1412
+ transition: "background-color 0.08s linear, transform 0.08s linear"
1413
+ }
1414
+ }
1415
+ };
1416
+ var toxic = {
1417
+ scrollBar: {
1418
+ inactive: {
1419
+ backgroundColor: "rgba(54, 83, 20, 0.48)",
1420
+ borderRadius: "2px",
1421
+ transition: "background-color 0.2s ease"
1422
+ },
1423
+ hover: {
1424
+ backgroundColor: "rgba(77, 124, 15, 0.65)"
1425
+ },
1426
+ active: {
1427
+ backgroundColor: "rgba(101, 163, 13, 0.82)",
1428
+ transition: "background-color 0.1s ease"
1429
+ }
1430
+ },
1431
+ thumb: {
1432
+ inactive: {
1433
+ backgroundColor: "rgba(163, 230, 53, 0.68)",
1434
+ borderRadius: "1px"
1435
+ },
1436
+ hover: {
1437
+ backgroundColor: "rgba(190, 242, 100, 0.9)",
1438
+ transform: "scale(1.04)",
1439
+ transition: "background-color 0.14s ease, transform 0.14s ease"
1440
+ },
1441
+ active: {
1442
+ backgroundColor: "rgba(236, 252, 203, 1)",
1443
+ transform: "scale(1.15)",
1444
+ transition: "background-color 0.08s ease, transform 0.08s ease"
1445
+ }
1446
+ }
1447
+ };
1448
+ var candy = {
1449
+ scrollBar: {
1450
+ inactive: {
1451
+ backgroundColor: "rgba(244, 114, 182, 0.18)",
1452
+ borderRadius: "999px",
1453
+ transition: "background-color 0.3s ease"
1454
+ },
1455
+ hover: {
1456
+ backgroundColor: "rgba(192, 132, 252, 0.28)"
1457
+ },
1458
+ active: {
1459
+ backgroundColor: "rgba(129, 140, 248, 0.42)",
1460
+ transition: "background-color 0.15s ease"
1461
+ }
1462
+ },
1463
+ thumb: {
1464
+ inactive: {
1465
+ backgroundColor: "rgba(251, 113, 133, 0.62)",
1466
+ borderRadius: "999px"
1467
+ },
1468
+ hover: {
1469
+ backgroundColor: "rgba(244, 114, 182, 0.84)",
1470
+ transform: "scale(1.03)",
1471
+ transition: "background-color 0.18s ease, transform 0.18s ease"
1472
+ },
1473
+ active: {
1474
+ backgroundColor: "rgba(224, 231, 255, 1)",
1475
+ transform: "scale(1.12)",
1476
+ transition: "background-color 0.12s ease, transform 0.12s ease"
1477
+ }
1478
+ }
1479
+ };
1480
+ var sand = {
1481
+ scrollBar: {
1482
+ inactive: {
1483
+ backgroundColor: "rgba(120, 53, 15, 0.16)",
1484
+ borderRadius: "999px",
1485
+ transition: "background-color 0.32s ease"
1486
+ },
1487
+ hover: {
1488
+ backgroundColor: "rgba(180, 83, 9, 0.25)"
1489
+ },
1490
+ active: {
1491
+ backgroundColor: "rgba(217, 119, 6, 0.38)",
1492
+ transition: "background-color 0.16s ease"
1493
+ }
1494
+ },
1495
+ thumb: {
1496
+ inactive: {
1497
+ backgroundColor: "rgba(217, 119, 6, 0.52)",
1498
+ borderRadius: "999px"
1499
+ },
1500
+ hover: {
1501
+ backgroundColor: "rgba(245, 158, 11, 0.75)",
1502
+ transform: "scale(1)",
1503
+ transition: "background-color 0.2s ease"
1504
+ },
1505
+ active: {
1506
+ backgroundColor: "rgba(253, 230, 138, 0.98)",
1507
+ transform: "scale(1.08)",
1508
+ transition: "background-color 0.15s ease, transform 0.15s ease"
1509
+ }
1510
+ }
1511
+ };
1512
+ var monoLight = {
1513
+ scrollBar: {
1514
+ inactive: {
1515
+ backgroundColor: "rgba(0, 0, 0, 0.08)",
1516
+ borderRadius: "6px",
1517
+ transition: "background-color 0.3s ease"
1518
+ },
1519
+ hover: {
1520
+ backgroundColor: "rgba(0, 0, 0, 0.14)"
1521
+ },
1522
+ active: {
1523
+ backgroundColor: "rgba(0, 0, 0, 0.22)",
1524
+ transition: "background-color 0.15s ease"
1525
+ }
1526
+ },
1527
+ thumb: {
1528
+ inactive: {
1529
+ backgroundColor: "rgba(0, 0, 0, 0.32)",
1530
+ borderRadius: "6px"
1531
+ },
1532
+ hover: {
1533
+ backgroundColor: "rgba(0, 0, 0, 0.52)",
1534
+ transform: "scale(1)",
1535
+ transition: "background-color 0.18s ease"
1536
+ },
1537
+ active: {
1538
+ backgroundColor: "rgba(0, 0, 0, 0.75)",
1539
+ transform: "scale(1.08)",
1540
+ transition: "background-color 0.12s ease, transform 0.12s ease"
1541
+ }
1542
+ }
1543
+ };
1544
+ var monoDark = {
1545
+ scrollBar: {
1546
+ inactive: {
1547
+ backgroundColor: "rgba(255, 255, 255, 0.08)",
1548
+ borderRadius: "6px",
1549
+ transition: "background-color 0.3s ease"
1550
+ },
1551
+ hover: {
1552
+ backgroundColor: "rgba(255, 255, 255, 0.14)"
1553
+ },
1554
+ active: {
1555
+ backgroundColor: "rgba(255, 255, 255, 0.22)",
1556
+ transition: "background-color 0.15s ease"
1557
+ }
1558
+ },
1559
+ thumb: {
1560
+ inactive: {
1561
+ backgroundColor: "rgba(255, 255, 255, 0.32)",
1562
+ borderRadius: "6px"
1563
+ },
1564
+ hover: {
1565
+ backgroundColor: "rgba(255, 255, 255, 0.55)",
1566
+ transform: "scale(1)",
1567
+ transition: "background-color 0.18s ease"
1568
+ },
1569
+ active: {
1570
+ backgroundColor: "rgba(255, 255, 255, 0.82)",
1571
+ transform: "scale(1.08)",
1572
+ transition: "background-color 0.12s ease, transform 0.12s ease"
1573
+ }
1574
+ }
1575
+ };
1576
+
1577
+ // src/themes/preset.ts
1578
+ var presets = {
1579
+ primary,
1580
+ midnight,
1581
+ neonCyan,
1582
+ ocean,
1583
+ deepSea,
1584
+ forest,
1585
+ moss,
1586
+ lava,
1587
+ ember,
1588
+ gold,
1589
+ roseQuartz,
1590
+ violet,
1591
+ royal,
1592
+ arctic,
1593
+ glass,
1594
+ graphite,
1595
+ terminal,
1596
+ toxic,
1597
+ candy,
1598
+ sand,
1599
+ monoLight,
1600
+ monoDark
1601
+ };
1602
+
1603
+ // src/utils/config.ts
1604
+ var defaultConfig = {
1605
+ scrollBar: {
1606
+ mode: "both",
1607
+ positionMode: "after",
1608
+ superimposition: "after",
1609
+ boundaryOffset: "4px",
1610
+ heightTrack: "98%",
1611
+ hideNativeScrollbar: "always"
1612
+ },
1613
+ thumb: {
1614
+ boundaryOffset: "1px 1px",
1615
+ heightTrack: "auto"
1616
+ },
1617
+ nativeOnMobile: true,
1618
+ selectTheme: "primary",
1619
+ optionsTheme: {}
1620
+ };
1621
+
1622
+ // src/utils/merge.ts
1623
+ var merge = (config) => {
1624
+ const selectedTheme = presets[config.selectTheme ?? defaultConfig.selectTheme];
1625
+ return {
1626
+ scrollBar: {
1627
+ ...defaultConfig.scrollBar,
1628
+ ...config.scrollBar
1629
+ },
1630
+ thumb: {
1631
+ ...defaultConfig.thumb,
1632
+ ...config.thumb
1633
+ },
1634
+ optionsTheme: themeMerge(selectedTheme, config.optionsTheme)
1635
+ };
1636
+ };
1637
+ var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1638
+ var themeMerge = (base, override) => {
1639
+ if (!override) return base;
1640
+ const result = { ...base };
1641
+ for (const key of Object.keys(override)) {
1642
+ const overrideValue = override[key];
1643
+ const baseValue = base[key];
1644
+ if (overrideValue === void 0) continue;
1645
+ if (isPlainObject(overrideValue) && isPlainObject(baseValue)) {
1646
+ result[key] = themeMerge(
1647
+ baseValue,
1648
+ overrideValue
1649
+ );
1650
+ } else {
1651
+ result[key] = overrideValue;
1652
+ }
1653
+ }
1654
+ return result;
1655
+ };
1656
+
1657
+ // src/utils/mobile-detect.ts
1658
+ var shouldUseNativeScrollbar = () => {
1659
+ if (typeof window === "undefined") {
1660
+ return true;
1661
+ }
1662
+ const primaryPointerIsCoarse = window.matchMedia("(pointer: coarse)").matches;
1663
+ const hasAnyFinePointer = window.matchMedia("(any-pointer: fine)").matches;
1664
+ return primaryPointerIsCoarse && !hasAnyFinePointer;
1665
+ };
1666
+
1667
+ // src/utils/variables-css.ts
1668
+ var variables = (theme) => {
1669
+ const styles = {};
1670
+ for (const key in theme) {
1671
+ const k = key;
1672
+ const statusTheme = theme[k];
1673
+ if (!statusTheme) continue;
1674
+ const type = k === "scrollBar" ? "scrollbar" : "thumb";
1675
+ for (const status in statusTheme) {
1676
+ const properties = statusTheme[status];
1677
+ if (!properties) continue;
1678
+ const statusPrefix = status === "inactive" ? "" : `-${status}`;
1679
+ for (const prop in properties) {
1680
+ const value = properties[prop];
1681
+ if (value === void 0) continue;
1682
+ styles[`--${type}${statusPrefix}-${prop}`] = value;
1683
+ }
1684
+ }
1685
+ }
1686
+ return styles;
1687
+ };
1688
+
1689
+ // src/ScrollToFuture.tsx
1690
+ var import_jsx_runtime2 = require("react/jsx-runtime");
1691
+ var ScrollToFuture = ({
1692
+ target,
1693
+ scrollBar = {},
1694
+ thumb = {},
1695
+ selectTheme = "primary",
1696
+ optionsTheme = {},
1697
+ nativeOnMobile = true
1698
+ }) => {
1699
+ const anchorRef = (0, import_react7.useRef)(null);
1700
+ const targetRef = (0, import_react7.useRef)(null);
1701
+ const mounted = useMounted();
1702
+ const [findedTarget, setFindedTarget] = (0, import_react7.useState)(null);
1703
+ const config = merge({ scrollBar, thumb, selectTheme, optionsTheme });
1704
+ console.log("hideNativeScrollbar:", {
1705
+ original: scrollBar.hideNativeScrollbar,
1706
+ merged: config.scrollBar.hideNativeScrollbar
1707
+ });
1708
+ const vars = variables(config.optionsTheme);
1709
+ const mode = config.scrollBar?.mode ?? "both";
1710
+ const positionMode = config.scrollBar?.positionMode ?? "after";
1711
+ const superimposition = config.scrollBar?.superimposition ?? "over";
1712
+ const nativeScrollOnMobile = shouldUseNativeScrollbar() && nativeOnMobile;
1713
+ const metrics = useElementScrollObserver(findedTarget);
1714
+ const rect = useTargetRect(findedTarget);
1715
+ const wantsY = mode === "vertical" || mode === "both";
1716
+ const wantsX = mode === "horizontal" || mode === "both";
1717
+ const showY = wantsY && metrics.y.canScroll;
1718
+ const showX = wantsX && metrics.x.canScroll;
1719
+ const coversAllScrollableAxes = (!metrics.x.canScroll || showX) && (!metrics.y.canScroll || showY);
1720
+ useFuture({
1721
+ target,
1722
+ anchorRef,
1723
+ targetRef,
1724
+ setFindedTarget,
1725
+ mounted,
1726
+ config,
1727
+ showY,
1728
+ showX,
1729
+ superimposition,
1730
+ findedTarget,
1731
+ positionMode,
1732
+ coversAllScrollableAxes,
1733
+ nativeOnMobile
1734
+ });
1735
+ if (!mounted || nativeScrollOnMobile) {
1736
+ return null;
1737
+ }
1738
+ const canRenderOverlay = findedTarget !== null && rect.width > 0 && rect.height > 0;
1739
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1740
+ !target && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1741
+ "span",
1742
+ {
1743
+ ref: anchorRef,
1744
+ "aria-hidden": "true",
1745
+ style: { display: "none" }
1746
+ }
1747
+ ),
1748
+ canRenderOverlay && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1749
+ "div",
1750
+ {
1751
+ className: "scroll-to-future__overlay",
1752
+ style: {
1753
+ top: rect.top,
1754
+ left: rect.left,
1755
+ width: rect.width,
1756
+ height: rect.height
1757
+ },
1758
+ children: [
1759
+ showY && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1760
+ ScrollAxis,
1761
+ {
1762
+ vars,
1763
+ axis: "y",
1764
+ target: findedTarget,
1765
+ metrics: metrics.y,
1766
+ scrollBar: config.scrollBar,
1767
+ thumb,
1768
+ positionMode,
1769
+ superimposition,
1770
+ hasCrossAxis: showX
1771
+ }
1772
+ ),
1773
+ showX && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1774
+ ScrollAxis,
1775
+ {
1776
+ vars,
1777
+ axis: "x",
1778
+ target: findedTarget,
1779
+ metrics: metrics.x,
1780
+ scrollBar: config.scrollBar,
1781
+ thumb,
1782
+ positionMode,
1783
+ superimposition,
1784
+ hasCrossAxis: showY
1785
+ }
1786
+ )
1787
+ ]
1788
+ }
1789
+ )
1790
+ ] });
1791
+ };
1792
+ // Annotate the CommonJS export names for ESM import in node:
1793
+ 0 && (module.exports = {
1794
+ ScrollToFuture
1795
+ });
1796
+ //# sourceMappingURL=index.js.map