@mantine-vue/hooks 1.1.2

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.
Files changed (101) hide show
  1. package/cjs/index.cjs +4696 -0
  2. package/cjs/index.cjs.map +1 -0
  3. package/esm/index.mjs +4579 -0
  4. package/esm/index.mjs.map +1 -0
  5. package/lib/index.d.mts +141 -0
  6. package/lib/index.d.ts +141 -0
  7. package/lib/use-click-outside/use-click-outside.d.ts +4 -0
  8. package/lib/use-clipboard/use-clipboard.d.ts +11 -0
  9. package/lib/use-collapse/use-collapse.d.ts +38 -0
  10. package/lib/use-collapse/use-horizontal-collapse.d.ts +4 -0
  11. package/lib/use-color-scheme/use-color-scheme.d.ts +4 -0
  12. package/lib/use-counter/use-counter.d.ts +14 -0
  13. package/lib/use-debounced-callback/use-debounced-callback.d.ts +12 -0
  14. package/lib/use-debounced-state/use-debounced-state.d.ts +6 -0
  15. package/lib/use-debounced-value/use-debounced-value.d.ts +14 -0
  16. package/lib/use-did-update/use-did-update.d.ts +2 -0
  17. package/lib/use-disclosure/use-disclosure.d.ts +13 -0
  18. package/lib/use-document-title/use-document-title.d.ts +2 -0
  19. package/lib/use-document-visibility/use-document-visibility.d.ts +2 -0
  20. package/lib/use-drag/use-drag.d.ts +56 -0
  21. package/lib/use-event-listener/use-event-listener.d.ts +2 -0
  22. package/lib/use-eye-dropper/use-eye-dropper.d.ts +12 -0
  23. package/lib/use-favicon/use-favicon.d.ts +2 -0
  24. package/lib/use-fetch/use-fetch.d.ts +12 -0
  25. package/lib/use-file-dialog/use-file-dialog.d.ts +25 -0
  26. package/lib/use-floating-window/use-floating-window.d.ts +30 -0
  27. package/lib/use-focus-return/use-focus-return.d.ts +6 -0
  28. package/lib/use-focus-trap/scope-tab.d.ts +1 -0
  29. package/lib/use-focus-trap/tabbable.d.ts +4 -0
  30. package/lib/use-focus-trap/use-focus-trap.d.ts +5 -0
  31. package/lib/use-focus-within/use-focus-within.d.ts +10 -0
  32. package/lib/use-force-update/use-force-update.d.ts +2 -0
  33. package/lib/use-fullscreen/use-fullscreen.d.ts +12 -0
  34. package/lib/use-hash/use-hash.d.ts +6 -0
  35. package/lib/use-headroom/use-headroom.d.ts +27 -0
  36. package/lib/use-hotkeys/parse-hotkey.d.ts +20 -0
  37. package/lib/use-hotkeys/use-hotkeys.d.ts +15 -0
  38. package/lib/use-hover/use-hover.d.ts +6 -0
  39. package/lib/use-id/use-id.d.ts +2 -0
  40. package/lib/use-idle/use-idle.d.ts +6 -0
  41. package/lib/use-in-viewport/use-in-viewport.d.ts +6 -0
  42. package/lib/use-input-state/use-input-state.d.ts +6 -0
  43. package/lib/use-intersection/use-intersection.d.ts +6 -0
  44. package/lib/use-interval/use-interval.d.ts +16 -0
  45. package/lib/use-is-first-render/use-is-first-render.d.ts +2 -0
  46. package/lib/use-isomorphic-effect/use-isomorphic-effect.d.ts +1 -0
  47. package/lib/use-list-state/use-list-state.d.ts +25 -0
  48. package/lib/use-local-storage/create-storage.d.ts +23 -0
  49. package/lib/use-local-storage/use-local-storage.d.ts +3 -0
  50. package/lib/use-logger/use-logger.d.ts +2 -0
  51. package/lib/use-long-press/use-long-press.d.ts +20 -0
  52. package/lib/use-map/use-map.d.ts +1 -0
  53. package/lib/use-mask/use-mask.d.ts +57 -0
  54. package/lib/use-media-query/use-media-query.d.ts +5 -0
  55. package/lib/use-merged-ref/use-merged-ref.d.ts +6 -0
  56. package/lib/use-mounted/use-mounted.d.ts +2 -0
  57. package/lib/use-mouse/use-mouse.d.ts +15 -0
  58. package/lib/use-move/use-move.d.ts +17 -0
  59. package/lib/use-mutation-observer/use-mutation-observer.d.ts +3 -0
  60. package/lib/use-network/use-network.d.ts +11 -0
  61. package/lib/use-orientation/use-orientation.d.ts +23 -0
  62. package/lib/use-os/use-os.d.ts +6 -0
  63. package/lib/use-page-leave/use-page-leave.d.ts +2 -0
  64. package/lib/use-pagination/use-pagination.d.ts +20 -0
  65. package/lib/use-previous/use-previous.d.ts +2 -0
  66. package/lib/use-queue/use-queue.d.ts +20 -0
  67. package/lib/use-radial-move/use-radial-move.d.ts +13 -0
  68. package/lib/use-reduced-motion/use-reduced-motion.d.ts +3 -0
  69. package/lib/use-resize-observer/use-resize-observer.d.ts +13 -0
  70. package/lib/use-roving-index/use-roving-index.d.ts +45 -0
  71. package/lib/use-scroll-direction/use-scroll-direction.d.ts +3 -0
  72. package/lib/use-scroll-into-view/use-scroll-into-view.d.ts +32 -0
  73. package/lib/use-scroll-spy/use-scroll-spy.d.ts +30 -0
  74. package/lib/use-scroller/use-scroller.d.ts +25 -0
  75. package/lib/use-selection/use-selection.d.ts +27 -0
  76. package/lib/use-session-storage/use-session-storage.d.ts +3 -0
  77. package/lib/use-set/use-set.d.ts +9 -0
  78. package/lib/use-set-state/use-set-state.d.ts +4 -0
  79. package/lib/use-shallow-effect/use-shallow-effect.d.ts +2 -0
  80. package/lib/use-splitter/use-splitter.d.ts +94 -0
  81. package/lib/use-state-history/use-state-history.d.ts +17 -0
  82. package/lib/use-text-selection/use-text-selection.d.ts +2 -0
  83. package/lib/use-throttled-callback/use-throttled-callback.d.ts +2 -0
  84. package/lib/use-throttled-state/use-throttled-state.d.ts +3 -0
  85. package/lib/use-throttled-value/use-throttled-value.d.ts +2 -0
  86. package/lib/use-timeout/use-timeout.d.ts +8 -0
  87. package/lib/use-toggle/use-toggle.d.ts +4 -0
  88. package/lib/use-uncontrolled/use-uncontrolled.d.ts +13 -0
  89. package/lib/use-validated-state/use-validated-state.d.ts +16 -0
  90. package/lib/use-viewport-size/use-viewport-size.d.ts +6 -0
  91. package/lib/use-window-event/use-window-event.d.ts +2 -0
  92. package/lib/use-window-scroll/use-window-scroll.d.ts +8 -0
  93. package/lib/utils/clamp/clamp.d.ts +1 -0
  94. package/lib/utils/index.d.ts +7 -0
  95. package/lib/utils/lower-first/lower-first.d.ts +1 -0
  96. package/lib/utils/random-id/random-id.d.ts +1 -0
  97. package/lib/utils/range/range.d.ts +1 -0
  98. package/lib/utils/shallow-equal/shallow-equal.d.ts +1 -0
  99. package/lib/utils/upper-first/upper-first.d.ts +1 -0
  100. package/lib/utils/use-callback-ref/use-callback-ref.d.ts +2 -0
  101. package/package.json +37 -0
package/esm/index.mjs ADDED
@@ -0,0 +1,4579 @@
1
+ import { computed, getCurrentInstance, isRef, nextTick, onBeforeUnmount, onMounted, onUpdated, reactive, readonly, ref, shallowRef, toValue, triggerRef, watch, watchEffect } from "vue";
2
+ //#region src/utils/clamp/clamp.ts
3
+ function clamp(value, min, max) {
4
+ if (min === void 0 && max === void 0) return value;
5
+ if (min !== void 0 && max === void 0) return Math.max(value, min);
6
+ if (min === void 0 && max !== void 0) return Math.min(value, max);
7
+ return Math.min(Math.max(value, min), max);
8
+ }
9
+ //#endregion
10
+ //#region src/utils/lower-first/lower-first.ts
11
+ function lowerFirst(value) {
12
+ return typeof value !== "string" ? "" : value.charAt(0).toLowerCase() + value.slice(1);
13
+ }
14
+ //#endregion
15
+ //#region src/utils/random-id/random-id.ts
16
+ function randomId(prefix = "mantine-") {
17
+ return `${prefix}${Math.random().toString(36).slice(2, 11)}`;
18
+ }
19
+ //#endregion
20
+ //#region src/utils/range/range.ts
21
+ function range(start, end) {
22
+ const length = Math.abs(end - start) + 1;
23
+ if (!(start > end)) return Array.from({ length }, (_, index) => index + start);
24
+ return Array.from({ length }, (_, index) => start - index);
25
+ }
26
+ //#endregion
27
+ //#region src/utils/shallow-equal/shallow-equal.ts
28
+ function shallowEqual(a, b) {
29
+ if (a === b) return true;
30
+ if (Number.isNaN(a) && Number.isNaN(b)) return true;
31
+ if (!(a instanceof Object) || !(b instanceof Object)) return false;
32
+ const keys = Object.keys(a);
33
+ const { length } = keys;
34
+ if (length !== Object.keys(b).length) return false;
35
+ for (let i = 0; i < length; i += 1) {
36
+ const key = keys[i];
37
+ if (!(key in b)) return false;
38
+ if (a[key] !== b[key] && !(Number.isNaN(a[key]) && Number.isNaN(b[key]))) return false;
39
+ }
40
+ return true;
41
+ }
42
+ //#endregion
43
+ //#region src/utils/upper-first/upper-first.ts
44
+ function upperFirst(value) {
45
+ return typeof value !== "string" ? "" : value.charAt(0).toUpperCase() + value.slice(1);
46
+ }
47
+ //#endregion
48
+ //#region src/utils/use-callback-ref/use-callback-ref.ts
49
+ function useCallbackRef(callback) {
50
+ const callbackRef = ref(toValue(callback));
51
+ watchEffect(() => {
52
+ callbackRef.value = toValue(callback);
53
+ });
54
+ return ((...args) => callbackRef.value?.(...args));
55
+ }
56
+ //#endregion
57
+ //#region src/use-debounced-callback/use-debounced-callback.ts
58
+ function useDebouncedCallback(callback, waitOrOptions) {
59
+ const { delay, flushOnUnmount = false, leading = false, maxWait } = typeof waitOrOptions === "number" ? { delay: waitOrOptions } : waitOrOptions;
60
+ let timeout;
61
+ let maxTimeout;
62
+ let lastArgs;
63
+ let leadingCalled = false;
64
+ const clear = () => {
65
+ if (timeout) {
66
+ clearTimeout(timeout);
67
+ timeout = void 0;
68
+ }
69
+ if (maxTimeout) {
70
+ clearTimeout(maxTimeout);
71
+ maxTimeout = void 0;
72
+ }
73
+ };
74
+ const invoke = () => {
75
+ if (!lastArgs) return;
76
+ callback(...lastArgs);
77
+ lastArgs = void 0;
78
+ leadingCalled = false;
79
+ clear();
80
+ };
81
+ const cancel = () => {
82
+ lastArgs = void 0;
83
+ leadingCalled = false;
84
+ clear();
85
+ };
86
+ onBeforeUnmount(() => {
87
+ if (flushOnUnmount) invoke();
88
+ else cancel();
89
+ });
90
+ const debounced = (...args) => {
91
+ lastArgs = args;
92
+ if (leading && !leadingCalled) {
93
+ callback(...args);
94
+ lastArgs = void 0;
95
+ leadingCalled = true;
96
+ timeout = setTimeout(() => {
97
+ leadingCalled = false;
98
+ timeout = void 0;
99
+ }, delay);
100
+ return;
101
+ }
102
+ if (timeout) clearTimeout(timeout);
103
+ timeout = setTimeout(() => {
104
+ if (!leading || maxWait !== void 0) invoke();
105
+ else {
106
+ lastArgs = void 0;
107
+ leadingCalled = false;
108
+ clear();
109
+ }
110
+ }, delay);
111
+ if (maxWait !== void 0 && !maxTimeout) maxTimeout = setTimeout(invoke, maxWait);
112
+ };
113
+ debounced.cancel = cancel;
114
+ debounced.flush = invoke;
115
+ debounced.isPending = () => lastArgs !== void 0;
116
+ return debounced;
117
+ }
118
+ //#endregion
119
+ //#region src/use-click-outside/use-click-outside.ts
120
+ function useClickOutside(callback, events = ["mousedown", "touchstart"], nodes, enabled = true) {
121
+ const element = ref(null);
122
+ let activeEvents = [];
123
+ const listener = (event) => {
124
+ const target = event.target;
125
+ if (!target || !document.body.contains(target) && target.tagName !== "HTML") return;
126
+ const path = event.composedPath();
127
+ const resolvedNodes = nodes ? toValue(nodes) : void 0;
128
+ if (resolvedNodes) {
129
+ if (resolvedNodes.every((node) => !!node && !path.includes(node))) callback(event);
130
+ } else if (element.value && !path.includes(element.value)) callback(event);
131
+ };
132
+ const cleanup = () => {
133
+ activeEvents.forEach((event) => document.removeEventListener(event, listener));
134
+ activeEvents = [];
135
+ };
136
+ const bind = () => {
137
+ cleanup();
138
+ if (!toValue(enabled)) return;
139
+ activeEvents = toValue(events) || ["mousedown", "touchstart"];
140
+ activeEvents.forEach((event) => document.addEventListener(event, listener));
141
+ };
142
+ onMounted(bind);
143
+ watch([() => toValue(events)?.join(","), () => toValue(enabled)], bind);
144
+ onBeforeUnmount(cleanup);
145
+ return element;
146
+ }
147
+ //#endregion
148
+ //#region src/use-clipboard/use-clipboard.ts
149
+ function useClipboard({ timeout = 2e3 } = {}) {
150
+ const copied = ref(false);
151
+ const error = ref(null);
152
+ let timer;
153
+ const reset = () => {
154
+ copied.value = false;
155
+ error.value = null;
156
+ clearTimeout(timer);
157
+ };
158
+ const copy = async (value) => {
159
+ let succeeded = true;
160
+ if (typeof navigator !== "undefined" && navigator.clipboard) try {
161
+ await navigator.clipboard.writeText(value);
162
+ error.value = null;
163
+ } catch (err) {
164
+ error.value = err;
165
+ succeeded = false;
166
+ }
167
+ if (succeeded) {
168
+ copied.value = true;
169
+ clearTimeout(timer);
170
+ timer = setTimeout(() => {
171
+ copied.value = false;
172
+ }, timeout);
173
+ }
174
+ };
175
+ onBeforeUnmount(() => clearTimeout(timer));
176
+ return {
177
+ copy,
178
+ copied,
179
+ reset,
180
+ error
181
+ };
182
+ }
183
+ //#endregion
184
+ //#region src/use-media-query/use-media-query.ts
185
+ function getInitialMediaQueryValue(query, initialValue) {
186
+ if (typeof initialValue === "boolean") return initialValue;
187
+ if (typeof window !== "undefined" && typeof window.matchMedia === "function") return window.matchMedia(query).matches;
188
+ return false;
189
+ }
190
+ function useMediaQuery(query, initialValue = false, options = { getInitialValueInEffect: true }) {
191
+ const matches = ref(initialValue);
192
+ const instance = getCurrentInstance();
193
+ let mediaQueryList;
194
+ const cleanup = () => mediaQueryList?.removeEventListener("change", update);
195
+ const update = (event) => {
196
+ matches.value = event ? event.matches : Boolean(mediaQueryList?.matches);
197
+ };
198
+ if (!options.getInitialValueInEffect) matches.value = getInitialMediaQueryValue(toValue(query), initialValue);
199
+ if (instance) {
200
+ onMounted(() => {
201
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
202
+ mediaQueryList = window.matchMedia(toValue(query));
203
+ update();
204
+ mediaQueryList.addEventListener("change", update);
205
+ });
206
+ onBeforeUnmount(cleanup);
207
+ }
208
+ watch(() => toValue(query), () => {
209
+ cleanup();
210
+ if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
211
+ mediaQueryList = window.matchMedia(toValue(query));
212
+ update();
213
+ mediaQueryList.addEventListener("change", update);
214
+ }
215
+ });
216
+ return readonly(matches);
217
+ }
218
+ //#endregion
219
+ //#region src/use-color-scheme/use-color-scheme.ts
220
+ function useColorScheme(initialValue, options) {
221
+ const prefersDark = useMediaQuery("(prefers-color-scheme: dark)", initialValue === "dark", options);
222
+ return computed(() => prefersDark.value ? "dark" : "light");
223
+ }
224
+ //#endregion
225
+ //#region src/use-counter/use-counter.ts
226
+ function useCounter(initialValue = 0, options = {}) {
227
+ const step = Math.abs(options.step ?? 1);
228
+ const clamp = (value) => Math.min(options.max ?? value, Math.max(options.min ?? value, value));
229
+ const count = ref(clamp(initialValue));
230
+ const set = (value) => {
231
+ count.value = clamp(typeof value === "function" ? value(count.value) : value);
232
+ };
233
+ return [count, {
234
+ increment: () => set((value) => value + step),
235
+ decrement: () => set((value) => value - step),
236
+ set,
237
+ reset: () => set(initialValue)
238
+ }];
239
+ }
240
+ //#endregion
241
+ //#region src/use-debounced-state/use-debounced-state.ts
242
+ function useDebouncedState(initialValue, wait, options = {}) {
243
+ const value = ref(initialValue);
244
+ let timeout;
245
+ let leadingCalled = false;
246
+ const clear = () => {
247
+ if (timeout) {
248
+ clearTimeout(timeout);
249
+ timeout = void 0;
250
+ }
251
+ };
252
+ const setValue = (nextValue) => {
253
+ const next = nextValue instanceof Function ? nextValue(value.value) : nextValue;
254
+ if (options.leading && !leadingCalled) {
255
+ value.value = next;
256
+ leadingCalled = true;
257
+ } else {
258
+ clear();
259
+ timeout = setTimeout(() => {
260
+ value.value = next;
261
+ leadingCalled = false;
262
+ }, wait);
263
+ }
264
+ };
265
+ onBeforeUnmount(clear);
266
+ return [value, setValue];
267
+ }
268
+ //#endregion
269
+ //#region src/use-debounced-value/use-debounced-value.ts
270
+ function useDebouncedValue(value, wait, options = {}) {
271
+ const debounced = ref(toValue(value));
272
+ let timeout;
273
+ let cooldown = false;
274
+ let latestValue = toValue(value);
275
+ const cancel = () => {
276
+ if (timeout) {
277
+ clearTimeout(timeout);
278
+ timeout = void 0;
279
+ }
280
+ cooldown = false;
281
+ };
282
+ const flush = () => {
283
+ if (timeout) {
284
+ cancel();
285
+ debounced.value = latestValue;
286
+ }
287
+ };
288
+ watch(() => toValue(value), (nextValue) => {
289
+ latestValue = nextValue;
290
+ if (!cooldown && options.leading) {
291
+ cooldown = true;
292
+ debounced.value = nextValue;
293
+ timeout = setTimeout(() => {
294
+ cooldown = false;
295
+ timeout = void 0;
296
+ }, wait);
297
+ } else {
298
+ cancel();
299
+ timeout = setTimeout(() => {
300
+ cooldown = false;
301
+ timeout = void 0;
302
+ debounced.value = nextValue;
303
+ }, wait);
304
+ }
305
+ });
306
+ onBeforeUnmount(cancel);
307
+ return [
308
+ readonly(debounced),
309
+ cancel,
310
+ {
311
+ cancel,
312
+ flush
313
+ }
314
+ ];
315
+ }
316
+ //#endregion
317
+ //#region src/use-isomorphic-effect/use-isomorphic-effect.ts
318
+ function useIsomorphicEffect(effect) {
319
+ if (typeof window === "undefined") return;
320
+ onMounted(effect);
321
+ }
322
+ //#endregion
323
+ //#region src/use-document-title/use-document-title.ts
324
+ function useDocumentTitle(title) {
325
+ useIsomorphicEffect(() => {
326
+ watch(() => toValue(title), (value) => {
327
+ const nextTitle = value.trim();
328
+ if (nextTitle) document.title = nextTitle;
329
+ }, { immediate: true });
330
+ });
331
+ }
332
+ //#endregion
333
+ //#region src/use-document-visibility/use-document-visibility.ts
334
+ function useDocumentVisibility() {
335
+ const documentVisibility = ref("visible");
336
+ const listener = () => {
337
+ documentVisibility.value = document.visibilityState;
338
+ };
339
+ onMounted(() => {
340
+ documentVisibility.value = document.visibilityState;
341
+ document.addEventListener("visibilitychange", listener);
342
+ });
343
+ onBeforeUnmount(() => document.removeEventListener("visibilitychange", listener));
344
+ return readonly(documentVisibility);
345
+ }
346
+ //#endregion
347
+ //#region src/use-focus-return/use-focus-return.ts
348
+ function useFocusReturn({ opened, shouldReturnFocus = true }) {
349
+ let lastActiveElement = null;
350
+ let timeout;
351
+ const value = (input) => typeof input === "function" ? input() : typeof input === "object" && input && "value" in input ? input.value : input;
352
+ const returnFocus = () => lastActiveElement?.focus?.({ preventScroll: true });
353
+ const clearOnTab = (event) => event.key === "Tab" && clearTimeout(timeout);
354
+ watch(() => value(opened), (isOpened, wasOpened) => {
355
+ if (typeof document === "undefined" || isOpened === wasOpened) return;
356
+ clearTimeout(timeout);
357
+ if (isOpened) {
358
+ lastActiveElement = document.activeElement;
359
+ document.addEventListener("keydown", clearOnTab);
360
+ } else {
361
+ document.removeEventListener("keydown", clearOnTab);
362
+ if (value(shouldReturnFocus)) {
363
+ const activeAtClose = document.activeElement;
364
+ timeout = setTimeout(() => {
365
+ if (!document.activeElement || document.activeElement === document.body || document.activeElement === activeAtClose) returnFocus();
366
+ }, 10);
367
+ }
368
+ }
369
+ });
370
+ onBeforeUnmount(() => {
371
+ clearTimeout(timeout);
372
+ document?.removeEventListener("keydown", clearOnTab);
373
+ });
374
+ return returnFocus;
375
+ }
376
+ //#endregion
377
+ //#region src/use-did-update/use-did-update.ts
378
+ function useDidUpdate(effect, deps) {
379
+ let cleanup;
380
+ const runEffect = () => {
381
+ cleanup?.();
382
+ cleanup = effect();
383
+ };
384
+ if (!deps) {
385
+ onUpdated(runEffect);
386
+ return;
387
+ }
388
+ watch(deps.map((dep) => () => toValue(dep)), runEffect);
389
+ }
390
+ //#endregion
391
+ //#region src/use-focus-trap/tabbable.ts
392
+ var TABBABLE_NODES = /input|select|textarea|button|object/;
393
+ var FOCUS_SELECTOR = "a, input, select, textarea, button, object, [tabindex]";
394
+ function hidden(element) {
395
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "test") return false;
396
+ return element.style.display === "none";
397
+ }
398
+ function visible(element) {
399
+ if (element.getAttribute("aria-hidden") || element.getAttribute("hidden") || element.getAttribute("type") === "hidden") return false;
400
+ let parentElement = element;
401
+ while (parentElement) {
402
+ if (parentElement === document.body || parentElement.nodeType === 11) break;
403
+ if (hidden(parentElement)) return false;
404
+ parentElement = parentElement.parentNode;
405
+ }
406
+ return true;
407
+ }
408
+ function getElementTabIndex(element) {
409
+ const tabIndex = element.getAttribute("tabindex");
410
+ return Number.parseInt(tabIndex ?? "", 10);
411
+ }
412
+ function focusable(element) {
413
+ const nodeName = element.nodeName.toLowerCase();
414
+ const isTabIndexNotNaN = !Number.isNaN(getElementTabIndex(element));
415
+ const disabled = "disabled" in element ? Boolean(element.disabled) : false;
416
+ return (TABBABLE_NODES.test(nodeName) && !disabled || (element instanceof HTMLAnchorElement ? Boolean(element.href) || isTabIndexNotNaN : isTabIndexNotNaN)) && visible(element);
417
+ }
418
+ function tabbable(element) {
419
+ const tabIndex = getElementTabIndex(element);
420
+ return (Number.isNaN(tabIndex) || tabIndex >= 0) && focusable(element);
421
+ }
422
+ function findTabbableDescendants(element) {
423
+ return Array.from(element.querySelectorAll(FOCUS_SELECTOR)).filter(tabbable);
424
+ }
425
+ //#endregion
426
+ //#region src/use-focus-trap/scope-tab.ts
427
+ function scopeTab(node, event) {
428
+ const tabbable = findTabbableDescendants(node);
429
+ if (!tabbable.length) {
430
+ event.preventDefault();
431
+ return;
432
+ }
433
+ const finalTabbable = tabbable[event.shiftKey ? 0 : tabbable.length - 1];
434
+ const root = node.getRootNode();
435
+ let leavingFinalTabbable = finalTabbable === root.activeElement || node === root.activeElement;
436
+ const activeElement = root.activeElement;
437
+ if (activeElement?.tagName === "INPUT" && activeElement.getAttribute("type") === "radio") leavingFinalTabbable = tabbable.filter((element) => element.getAttribute("type") === "radio" && element.getAttribute("name") === activeElement.getAttribute("name")).includes(finalTabbable);
438
+ if (!leavingFinalTabbable) return;
439
+ event.preventDefault();
440
+ tabbable[event.shiftKey ? tabbable.length - 1 : 0]?.focus();
441
+ }
442
+ //#endregion
443
+ //#region src/use-focus-trap/use-focus-trap.ts
444
+ function getElement(node) {
445
+ return (node?.$el ?? node) || null;
446
+ }
447
+ function focusNode(node) {
448
+ let focusElement = node.querySelector("[data-autofocus]");
449
+ if (!focusElement) {
450
+ const children = Array.from(node.querySelectorAll(FOCUS_SELECTOR));
451
+ focusElement = children.find(tabbable) || children.find(focusable) || null;
452
+ if (!focusElement && focusable(node)) focusElement = node;
453
+ }
454
+ focusElement?.focus({ preventScroll: true });
455
+ }
456
+ function useFocusTrap(active = true) {
457
+ const refTarget = ref(null);
458
+ const isActive = () => toValue(active);
459
+ const setRef = (node) => {
460
+ const element = getElement(node);
461
+ if (!isActive()) {
462
+ refTarget.value = element;
463
+ return;
464
+ }
465
+ if (element === null) {
466
+ refTarget.value = null;
467
+ return;
468
+ }
469
+ if (refTarget.value === element) return;
470
+ setTimeout(() => {
471
+ if (element.isConnected || element.getRootNode()) focusNode(element);
472
+ });
473
+ refTarget.value = element;
474
+ };
475
+ const handleKeyDown = (event) => {
476
+ if (event.key === "Tab" && refTarget.value && isActive()) scopeTab(refTarget.value, event);
477
+ };
478
+ onMounted(() => {
479
+ if (typeof document === "undefined") return;
480
+ document.addEventListener("keydown", handleKeyDown);
481
+ if (isActive() && refTarget.value) setTimeout(() => {
482
+ if (refTarget.value) focusNode(refTarget.value);
483
+ });
484
+ });
485
+ onBeforeUnmount(() => {
486
+ if (typeof document !== "undefined") document.removeEventListener("keydown", handleKeyDown);
487
+ });
488
+ watch(() => isActive(), (value) => {
489
+ if (value && refTarget.value) setTimeout(() => {
490
+ if (refTarget.value) focusNode(refTarget.value);
491
+ });
492
+ });
493
+ return setRef;
494
+ }
495
+ //#endregion
496
+ //#region src/use-force-update/use-force-update.ts
497
+ function useForceUpdate() {
498
+ const key = ref(0);
499
+ return [key, () => key.value++];
500
+ }
501
+ //#endregion
502
+ //#region src/use-id/use-id.ts
503
+ var idCounter = 0;
504
+ function useId(staticId) {
505
+ const id = ref(staticId || "");
506
+ onMounted(() => {
507
+ if (!id.value) id.value = `mantine-vue-${++idCounter}`;
508
+ });
509
+ if (staticId) id.value = staticId;
510
+ return id;
511
+ }
512
+ //#endregion
513
+ //#region src/use-idle/use-idle.ts
514
+ var DEFAULT_OPTIONS = {
515
+ events: [
516
+ "keydown",
517
+ "mousemove",
518
+ "touchmove",
519
+ "click",
520
+ "scroll",
521
+ "wheel"
522
+ ],
523
+ initialState: true
524
+ };
525
+ function useIdle(timeout, options) {
526
+ const { events, initialState } = {
527
+ ...DEFAULT_OPTIONS,
528
+ ...options
529
+ };
530
+ const idle = ref(initialState);
531
+ let timer = -1;
532
+ const handleEvents = () => {
533
+ idle.value = false;
534
+ if (timer) window.clearTimeout(timer);
535
+ timer = window.setTimeout(() => {
536
+ idle.value = true;
537
+ }, toValue(timeout));
538
+ };
539
+ const bind = () => {
540
+ events.forEach((event) => document.addEventListener(event, handleEvents));
541
+ timer = window.setTimeout(() => {
542
+ idle.value = true;
543
+ }, toValue(timeout));
544
+ };
545
+ const cleanup = () => {
546
+ events.forEach((event) => document.removeEventListener(event, handleEvents));
547
+ window.clearTimeout(timer);
548
+ timer = -1;
549
+ };
550
+ onMounted(bind);
551
+ onBeforeUnmount(cleanup);
552
+ watch(() => toValue(timeout), () => {
553
+ cleanup();
554
+ bind();
555
+ });
556
+ return idle;
557
+ }
558
+ //#endregion
559
+ //#region src/use-interval/use-interval.ts
560
+ function useInterval(fn, interval, options = {}) {
561
+ const { autoInvoke = false } = options;
562
+ const active = ref(false);
563
+ let intervalId = null;
564
+ const start = () => {
565
+ if (!active.value && !intervalId) intervalId = window.setInterval(fn, toValue(interval));
566
+ active.value = true;
567
+ };
568
+ const stop = () => {
569
+ active.value = false;
570
+ if (intervalId) window.clearInterval(intervalId);
571
+ intervalId = null;
572
+ };
573
+ const toggle = () => {
574
+ if (active.value) stop();
575
+ else start();
576
+ };
577
+ watch(() => toValue(interval), () => {
578
+ if (active.value) {
579
+ stop();
580
+ start();
581
+ }
582
+ });
583
+ onMounted(() => {
584
+ if (autoInvoke) start();
585
+ });
586
+ onBeforeUnmount(stop);
587
+ return {
588
+ start,
589
+ stop,
590
+ toggle,
591
+ active
592
+ };
593
+ }
594
+ //#endregion
595
+ //#region src/use-list-state/use-list-state.ts
596
+ function useListState(initialValue = []) {
597
+ const state = ref(typeof initialValue === "function" ? initialValue() : initialValue);
598
+ const setState = (value) => {
599
+ state.value = typeof value === "function" ? value(state.value) : value;
600
+ };
601
+ const append = (...items) => setState((current) => [...current, ...items]);
602
+ const prepend = (...items) => setState((current) => [...items, ...current]);
603
+ const insert = (index, ...items) => setState((current) => [
604
+ ...current.slice(0, index),
605
+ ...items,
606
+ ...current.slice(index)
607
+ ]);
608
+ const apply = (fn) => setState((current) => current.map((item, index) => fn(item, index)));
609
+ const remove = (...indices) => setState((current) => current.filter((_, index) => !indices.includes(index)));
610
+ const pop = () => setState((current) => {
611
+ const cloned = [...current];
612
+ cloned.pop();
613
+ return cloned;
614
+ });
615
+ const shift = () => setState((current) => {
616
+ const cloned = [...current];
617
+ cloned.shift();
618
+ return cloned;
619
+ });
620
+ const reorder = ({ from, to }) => setState((current) => {
621
+ const cloned = [...current];
622
+ const item = current[from];
623
+ cloned.splice(from, 1);
624
+ cloned.splice(to, 0, item);
625
+ return cloned;
626
+ });
627
+ const swap = ({ from, to }) => setState((current) => {
628
+ const cloned = [...current];
629
+ const fromItem = cloned[from];
630
+ const toItem = cloned[to];
631
+ cloned.splice(to, 1, fromItem);
632
+ cloned.splice(from, 1, toItem);
633
+ return cloned;
634
+ });
635
+ const setItem = (index, item) => setState((current) => {
636
+ const cloned = [...current];
637
+ cloned[index] = item;
638
+ return cloned;
639
+ });
640
+ const setItemProp = (index, prop, value) => setState((current) => {
641
+ const cloned = [...current];
642
+ cloned[index] = {
643
+ ...cloned[index],
644
+ [prop]: value
645
+ };
646
+ return cloned;
647
+ });
648
+ const applyWhere = (condition, fn) => setState((current) => current.map((item, index) => condition(item, index) ? fn(item, index) : item));
649
+ const filter = (fn) => {
650
+ setState((current) => current.filter(fn));
651
+ };
652
+ return [state, {
653
+ setState,
654
+ append,
655
+ prepend,
656
+ insert,
657
+ pop,
658
+ shift,
659
+ apply,
660
+ applyWhere,
661
+ remove,
662
+ reorder,
663
+ swap,
664
+ setItem,
665
+ setItemProp,
666
+ filter
667
+ }];
668
+ }
669
+ //#endregion
670
+ //#region src/use-window-event/use-window-event.ts
671
+ function useWindowEvent(type, listener, options) {
672
+ const getListener = () => isRef(listener) ? listener.value : listener;
673
+ const handler = (event) => getListener()(event);
674
+ let currentType;
675
+ let mounted = false;
676
+ const add = (eventType) => {
677
+ currentType = eventType;
678
+ window.addEventListener(eventType, handler, options);
679
+ };
680
+ const remove = () => {
681
+ if (currentType) {
682
+ window.removeEventListener(currentType, handler, options);
683
+ currentType = void 0;
684
+ }
685
+ };
686
+ onMounted(() => {
687
+ mounted = true;
688
+ add(toValue(type));
689
+ });
690
+ watch(() => toValue(type), (nextType) => {
691
+ if (mounted && nextType !== currentType) {
692
+ remove();
693
+ add(nextType);
694
+ }
695
+ });
696
+ onBeforeUnmount(remove);
697
+ }
698
+ //#endregion
699
+ //#region src/use-local-storage/create-storage.ts
700
+ function serializeJSON(value, hookName = "use-local-storage") {
701
+ try {
702
+ return JSON.stringify(value);
703
+ } catch {
704
+ throw new Error(`@mantine-vue/hooks ${hookName}: Failed to serialize the value`);
705
+ }
706
+ }
707
+ function deserializeJSON(value) {
708
+ try {
709
+ return value && JSON.parse(value);
710
+ } catch {
711
+ return value;
712
+ }
713
+ }
714
+ function createStorageHandler(type) {
715
+ const getItem = (key) => {
716
+ try {
717
+ return window[type].getItem(key);
718
+ } catch {
719
+ console.warn(`use-local-storage: Failed to get value from storage, ${type} is blocked`);
720
+ return null;
721
+ }
722
+ };
723
+ const setItem = (key, value) => {
724
+ try {
725
+ window[type].setItem(key, value);
726
+ } catch {
727
+ console.warn(`use-local-storage: Failed to set value to storage, ${type} is blocked`);
728
+ }
729
+ };
730
+ const removeItem = (key) => {
731
+ try {
732
+ window[type].removeItem(key);
733
+ } catch {
734
+ console.warn(`use-local-storage: Failed to remove value from storage, ${type} is blocked`);
735
+ }
736
+ };
737
+ return {
738
+ getItem,
739
+ setItem,
740
+ removeItem
741
+ };
742
+ }
743
+ function createStorage(type, hookName) {
744
+ const eventName = type === "localStorage" ? "mantine-vue-local-storage" : "mantine-vue-session-storage";
745
+ const { getItem, setItem, removeItem } = createStorageHandler(type);
746
+ return function useStorage({ key, defaultValue, getInitialValueInEffect = true, sync = true, deserialize = deserializeJSON, serialize = (value) => serializeJSON(value, hookName) }) {
747
+ const readStorageValue = (skipStorage) => {
748
+ let storageBlockedOrSkipped;
749
+ try {
750
+ storageBlockedOrSkipped = typeof window === "undefined" || !(type in window) || window[type] === null || !!skipStorage;
751
+ } catch {
752
+ storageBlockedOrSkipped = true;
753
+ }
754
+ if (storageBlockedOrSkipped) return defaultValue;
755
+ const storageValue = getItem(key);
756
+ return storageValue !== null ? deserialize(storageValue) : defaultValue;
757
+ };
758
+ const value = ref(readStorageValue(getInitialValueInEffect));
759
+ const dispatchSyncEvent = (result) => {
760
+ if (typeof window === "undefined") return;
761
+ queueMicrotask(() => {
762
+ window.dispatchEvent(new CustomEvent(eventName, { detail: {
763
+ key,
764
+ value: result
765
+ } }));
766
+ });
767
+ };
768
+ const setStorageValue = (val) => {
769
+ const result = val instanceof Function ? val(value.value) : val;
770
+ setItem(key, serialize(result));
771
+ value.value = result;
772
+ dispatchSyncEvent(result);
773
+ };
774
+ const removeStorageValue = () => {
775
+ removeItem(key);
776
+ value.value = defaultValue;
777
+ dispatchSyncEvent(defaultValue);
778
+ };
779
+ useWindowEvent("storage", (event) => {
780
+ if (sync && event.storageArea === window[type] && event.key === key) value.value = deserialize(event.newValue ?? void 0);
781
+ });
782
+ const handleSyncEvent = (event) => {
783
+ const detail = event.detail;
784
+ if (sync && detail.key === key) value.value = detail.value;
785
+ };
786
+ onMounted(() => {
787
+ window.addEventListener(eventName, handleSyncEvent);
788
+ if (defaultValue !== void 0 && value.value === void 0) setStorageValue(defaultValue);
789
+ const val = readStorageValue();
790
+ if (val !== void 0) value.value = val;
791
+ });
792
+ onBeforeUnmount(() => {
793
+ window.removeEventListener(eventName, handleSyncEvent);
794
+ });
795
+ return [
796
+ value,
797
+ setStorageValue,
798
+ removeStorageValue
799
+ ];
800
+ };
801
+ }
802
+ function readValue(type) {
803
+ const { getItem } = createStorageHandler(type);
804
+ return function read({ key, defaultValue, deserialize = deserializeJSON }) {
805
+ let storageBlockedOrSkipped;
806
+ try {
807
+ storageBlockedOrSkipped = typeof window === "undefined" || !(type in window) || window[type] === null;
808
+ } catch {
809
+ storageBlockedOrSkipped = true;
810
+ }
811
+ if (storageBlockedOrSkipped) return defaultValue;
812
+ const storageValue = getItem(key);
813
+ return storageValue !== null ? deserialize(storageValue) : defaultValue;
814
+ };
815
+ }
816
+ //#endregion
817
+ //#region src/use-local-storage/use-local-storage.ts
818
+ function readLocalStorageValue(options) {
819
+ return readValue("localStorage")(options);
820
+ }
821
+ function useLocalStorage(options) {
822
+ return createStorage("localStorage", "use-local-storage")(options);
823
+ }
824
+ //#endregion
825
+ //#region src/use-session-storage/use-session-storage.ts
826
+ function readSessionStorageValue(options) {
827
+ return readValue("sessionStorage")(options);
828
+ }
829
+ function useSessionStorage(options) {
830
+ return createStorage("sessionStorage", "use-session-storage")(options);
831
+ }
832
+ //#endregion
833
+ //#region src/use-merged-ref/use-merged-ref.ts
834
+ function assignRef(refTarget, value) {
835
+ if (typeof refTarget === "function") refTarget(value);
836
+ else if (refTarget) refTarget.value = value;
837
+ }
838
+ function mergeRefs(...refs) {
839
+ return (value) => refs.forEach((refTarget) => assignRef(refTarget, value));
840
+ }
841
+ function useMergedRef(...refs) {
842
+ return mergeRefs(...refs);
843
+ }
844
+ //#endregion
845
+ //#region src/use-mouse/use-mouse.ts
846
+ function useMouse(options = { resetOnExit: false }) {
847
+ const elementRef = ref(null);
848
+ const x = ref(0);
849
+ const y = ref(0);
850
+ let cleanup;
851
+ watch(elementRef, (node) => {
852
+ cleanup?.();
853
+ cleanup = void 0;
854
+ const target = node instanceof EventTarget ? node : null;
855
+ const setMousePosition = (event) => {
856
+ const mouseEvent = event;
857
+ if (target) {
858
+ const rect = target.getBoundingClientRect();
859
+ x.value = Math.max(0, Math.round(mouseEvent.clientX - rect.left));
860
+ y.value = Math.max(0, Math.round(mouseEvent.clientY - rect.top));
861
+ } else {
862
+ x.value = mouseEvent.clientX;
863
+ y.value = mouseEvent.clientY;
864
+ }
865
+ };
866
+ const resetMousePosition = () => {
867
+ x.value = 0;
868
+ y.value = 0;
869
+ };
870
+ target?.addEventListener("mousemove", setMousePosition);
871
+ if (options.resetOnExit) target?.addEventListener("mouseleave", resetMousePosition);
872
+ cleanup = () => {
873
+ target?.removeEventListener("mousemove", setMousePosition);
874
+ if (options.resetOnExit) target?.removeEventListener("mouseleave", resetMousePosition);
875
+ };
876
+ }, { immediate: true });
877
+ onBeforeUnmount(() => cleanup?.());
878
+ return {
879
+ ref: elementRef,
880
+ x,
881
+ y
882
+ };
883
+ }
884
+ function useMousePosition() {
885
+ const x = ref(0);
886
+ const y = ref(0);
887
+ const setMousePosition = (event) => {
888
+ x.value = event.clientX;
889
+ y.value = event.clientY;
890
+ };
891
+ onMounted(() => document.addEventListener("mousemove", setMousePosition));
892
+ onBeforeUnmount(() => document.removeEventListener("mousemove", setMousePosition));
893
+ return {
894
+ x,
895
+ y
896
+ };
897
+ }
898
+ //#endregion
899
+ //#region src/use-move/use-move.ts
900
+ var clamp$3 = (value, min, max) => Math.min(max, Math.max(min, value));
901
+ function clampUseMovePosition(position) {
902
+ return {
903
+ x: clamp$3(position.x, 0, 1),
904
+ y: clamp$3(position.y, 0, 1)
905
+ };
906
+ }
907
+ function useMove(onChange, handlers = {}, dir = "ltr") {
908
+ const active = ref(false);
909
+ let element = null;
910
+ let mounted = false;
911
+ let frame = 0;
912
+ const scrub = (x, y) => {
913
+ cancelAnimationFrame(frame);
914
+ frame = requestAnimationFrame(() => {
915
+ if (!mounted || !element) return;
916
+ const rect = element.getBoundingClientRect();
917
+ if (!rect.width || !rect.height) return;
918
+ const positionX = clamp$3((x - rect.left) / rect.width, 0, 1);
919
+ onChange({
920
+ x: dir === "ltr" ? positionX : 1 - positionX,
921
+ y: clamp$3((y - rect.top) / rect.height, 0, 1)
922
+ });
923
+ });
924
+ };
925
+ const mouseMove = (event) => scrub(event.clientX, event.clientY);
926
+ const touchMove = (event) => {
927
+ if (event.cancelable) event.preventDefault();
928
+ const touch = event.changedTouches[0];
929
+ if (touch) scrub(touch.clientX, touch.clientY);
930
+ };
931
+ const unbind = () => {
932
+ document.removeEventListener("mousemove", mouseMove);
933
+ document.removeEventListener("mouseup", stop);
934
+ document.removeEventListener("touchmove", touchMove);
935
+ document.removeEventListener("touchend", stop);
936
+ };
937
+ const stop = () => {
938
+ if (!active.value) return;
939
+ active.value = false;
940
+ unbind();
941
+ setTimeout(() => handlers.onScrubEnd?.(), 0);
942
+ };
943
+ const start = (event) => {
944
+ if (!mounted) return;
945
+ if ("button" in event && event.button !== 0) return;
946
+ if (event.cancelable) event.preventDefault();
947
+ active.value = true;
948
+ handlers.onScrubStart?.();
949
+ document.addEventListener("mousemove", mouseMove);
950
+ document.addEventListener("mouseup", stop);
951
+ document.addEventListener("touchmove", touchMove, { passive: false });
952
+ document.addEventListener("touchend", stop);
953
+ if ("changedTouches" in event) touchMove(event);
954
+ else mouseMove(event);
955
+ };
956
+ const setRef = (node) => {
957
+ const safeNode = node instanceof HTMLElement ? node : null;
958
+ element?.removeEventListener("mousedown", start);
959
+ element?.removeEventListener("touchstart", start);
960
+ element = safeNode;
961
+ element?.addEventListener("mousedown", start);
962
+ element?.addEventListener("touchstart", start, { passive: false });
963
+ };
964
+ onMounted(() => {
965
+ mounted = true;
966
+ });
967
+ onBeforeUnmount(() => {
968
+ mounted = false;
969
+ unbind();
970
+ cancelAnimationFrame(frame);
971
+ element?.removeEventListener("mousedown", start);
972
+ element?.removeEventListener("touchstart", start);
973
+ });
974
+ return {
975
+ ref: setRef,
976
+ active: readonly(active)
977
+ };
978
+ }
979
+ //#endregion
980
+ //#region src/use-uncontrolled/use-uncontrolled.ts
981
+ function useUncontrolled({ value, defaultValue, finalValue, onChange = () => {} }) {
982
+ const uncontrolledValue = ref(defaultValue !== void 0 ? defaultValue : finalValue);
983
+ const isControlled = computed(() => toValue(value) !== void 0);
984
+ return [
985
+ computed({
986
+ get: () => isControlled.value ? toValue(value) : uncontrolledValue.value,
987
+ set: (nextValue) => {
988
+ if (!isControlled.value) uncontrolledValue.value = nextValue;
989
+ onChange(nextValue);
990
+ }
991
+ }),
992
+ (nextValue, ...payload) => {
993
+ if (!isControlled.value) uncontrolledValue.value = nextValue;
994
+ onChange(nextValue, ...payload);
995
+ },
996
+ isControlled
997
+ ];
998
+ }
999
+ //#endregion
1000
+ //#region src/use-pagination/use-pagination.ts
1001
+ var DOTS = "dots";
1002
+ function range$1(start, end) {
1003
+ const length = Math.max(end - start + 1, 0);
1004
+ return Array.from({ length }, (_, index) => index + start);
1005
+ }
1006
+ function usePagination({ total, siblings = 1, boundaries = 1, page, initialPage, onChange, startValue = 1 }) {
1007
+ const start = computed(() => Math.max(Math.trunc(startValue), 1));
1008
+ const end = computed(() => Math.max(Math.trunc(total), start.value));
1009
+ const totalPages = computed(() => end.value - start.value + 1);
1010
+ const firstPage = computed(() => initialPage ?? start.value);
1011
+ const [active, setActive] = useUncontrolled({
1012
+ value: page,
1013
+ defaultValue: firstPage.value,
1014
+ finalValue: firstPage.value,
1015
+ onChange
1016
+ });
1017
+ const setPage = (pageNumber) => {
1018
+ const nextPage = Math.min(end.value, Math.max(start.value, pageNumber));
1019
+ if (nextPage !== active.value) setActive(nextPage);
1020
+ };
1021
+ return {
1022
+ range: computed(() => {
1023
+ if (siblings * 2 + 3 + boundaries * 2 >= totalPages.value) return range$1(start.value, end.value);
1024
+ const leftSiblingIndex = Math.max(active.value - siblings, start.value + boundaries - 1);
1025
+ const rightSiblingIndex = Math.min(active.value + siblings, end.value - boundaries);
1026
+ const shouldShowLeftDots = leftSiblingIndex > start.value + boundaries + 1;
1027
+ const shouldShowRightDots = rightSiblingIndex < end.value - boundaries;
1028
+ if (!shouldShowLeftDots && shouldShowRightDots) {
1029
+ const leftItemCount = siblings * 2 + boundaries + 2;
1030
+ return [
1031
+ ...range$1(start.value, start.value + leftItemCount - 1),
1032
+ DOTS,
1033
+ ...range$1(end.value - (boundaries - 1), end.value)
1034
+ ];
1035
+ }
1036
+ if (shouldShowLeftDots && !shouldShowRightDots) {
1037
+ const rightItemCount = boundaries + 1 + siblings * 2;
1038
+ return [
1039
+ ...range$1(start.value, start.value + boundaries - 1),
1040
+ DOTS,
1041
+ ...range$1(end.value - rightItemCount, end.value)
1042
+ ];
1043
+ }
1044
+ return [
1045
+ ...range$1(start.value, start.value + boundaries - 1),
1046
+ DOTS,
1047
+ ...range$1(leftSiblingIndex, rightSiblingIndex),
1048
+ DOTS,
1049
+ ...range$1(end.value - boundaries + 1, end.value)
1050
+ ];
1051
+ }),
1052
+ active,
1053
+ setPage,
1054
+ next: () => setPage(active.value + 1),
1055
+ previous: () => setPage(active.value - 1),
1056
+ first: () => setPage(start.value),
1057
+ last: () => setPage(end.value)
1058
+ };
1059
+ }
1060
+ //#endregion
1061
+ //#region src/use-queue/use-queue.ts
1062
+ function useQueue({ initialValues = [], limit }) {
1063
+ const stateRef = ref(initialValues.slice(0, limit));
1064
+ const queueRef = ref(initialValues.slice(limit));
1065
+ const add = (...items) => {
1066
+ const results = [
1067
+ ...stateRef.value,
1068
+ ...queueRef.value,
1069
+ ...items
1070
+ ];
1071
+ stateRef.value = results.slice(0, limit);
1072
+ queueRef.value = results.slice(limit);
1073
+ };
1074
+ const update = (fn) => {
1075
+ const results = fn([...stateRef.value, ...queueRef.value]);
1076
+ stateRef.value = results.slice(0, limit);
1077
+ queueRef.value = results.slice(limit);
1078
+ };
1079
+ const cleanQueue = () => {
1080
+ queueRef.value = [];
1081
+ };
1082
+ return {
1083
+ state: readonly(stateRef),
1084
+ queue: readonly(queueRef),
1085
+ add,
1086
+ update,
1087
+ cleanQueue
1088
+ };
1089
+ }
1090
+ //#endregion
1091
+ //#region src/use-page-leave/use-page-leave.ts
1092
+ function usePageLeave(onPageLeave) {
1093
+ const getHandler = () => isRef(onPageLeave) ? onPageLeave.value : onPageLeave;
1094
+ const handleMouseLeave = () => getHandler()();
1095
+ onMounted(() => {
1096
+ document.documentElement.addEventListener("mouseleave", handleMouseLeave);
1097
+ });
1098
+ onBeforeUnmount(() => {
1099
+ document.documentElement.removeEventListener("mouseleave", handleMouseLeave);
1100
+ });
1101
+ }
1102
+ //#endregion
1103
+ //#region src/use-reduced-motion/use-reduced-motion.ts
1104
+ function useReducedMotion(initialValue, options) {
1105
+ return useMediaQuery("(prefers-reduced-motion: reduce)", initialValue, options);
1106
+ }
1107
+ //#endregion
1108
+ //#region src/use-scroll-into-view/use-scroll-into-view.ts
1109
+ function useScrollIntoView(options = {}) {
1110
+ const { duration = 1250, axis = "y", onScrollFinish, onScrollCancel, easing = easeInOutQuad, offset = 0, cancelable = true, isList = false } = options;
1111
+ const frameID = ref(0);
1112
+ const startTime = ref(0);
1113
+ const shouldStop = ref(false);
1114
+ const scrolling = ref(false);
1115
+ const scrollableRef = ref(null);
1116
+ const targetRef = ref(null);
1117
+ const reducedMotion = useReducedMotion();
1118
+ const cancel = () => {
1119
+ if (frameID.value) {
1120
+ cancelAnimationFrame(frameID.value);
1121
+ frameID.value = 0;
1122
+ scrolling.value = false;
1123
+ }
1124
+ };
1125
+ const scrollIntoView = ({ alignment = "start" } = {}) => {
1126
+ shouldStop.value = false;
1127
+ if (frameID.value) cancel();
1128
+ const start = getScrollStart({
1129
+ parent: scrollableRef.value,
1130
+ axis
1131
+ }) ?? 0;
1132
+ const change = getRelativePosition({
1133
+ parent: scrollableRef.value,
1134
+ target: targetRef.value,
1135
+ axis,
1136
+ alignment,
1137
+ offset,
1138
+ isList
1139
+ }) - (scrollableRef.value ? 0 : start);
1140
+ scrolling.value = true;
1141
+ function animateScroll() {
1142
+ if (startTime.value === 0) startTime.value = performance.now();
1143
+ const elapsed = performance.now() - startTime.value;
1144
+ const t = reducedMotion.value || duration === 0 ? 1 : elapsed / duration;
1145
+ const distance = start + change * easing(t);
1146
+ setScrollParam({
1147
+ parent: scrollableRef.value,
1148
+ axis,
1149
+ distance
1150
+ });
1151
+ if (!shouldStop.value && t < 1) frameID.value = requestAnimationFrame(animateScroll);
1152
+ else {
1153
+ if (shouldStop.value) onScrollCancel?.();
1154
+ else onScrollFinish?.();
1155
+ startTime.value = 0;
1156
+ frameID.value = 0;
1157
+ scrolling.value = false;
1158
+ cancel();
1159
+ }
1160
+ }
1161
+ animateScroll();
1162
+ };
1163
+ const handleStop = () => {
1164
+ if (cancelable) shouldStop.value = true;
1165
+ };
1166
+ /**
1167
+ * Detection of one of these events stops scroll animation
1168
+ * wheel - mouse wheel / touch pad
1169
+ * touchmove - any touchable device
1170
+ */
1171
+ useWindowEvent("wheel", handleStop, { passive: true });
1172
+ useWindowEvent("touchmove", handleStop, { passive: true });
1173
+ onBeforeUnmount(cancel);
1174
+ return {
1175
+ scrollableRef,
1176
+ targetRef,
1177
+ scrollIntoView,
1178
+ cancel,
1179
+ scrolling
1180
+ };
1181
+ }
1182
+ function easeInOutQuad(t) {
1183
+ return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
1184
+ }
1185
+ function getRelativePosition({ axis, target, parent, alignment, offset, isList }) {
1186
+ const safeTarget = target instanceof Element ? target : null;
1187
+ const safeParent = parent instanceof Element ? parent : null;
1188
+ if (!safeTarget || !safeParent && typeof document === "undefined") return 0;
1189
+ const isCustomParent = !!safeParent;
1190
+ const parentPosition = (safeParent || document.body).getBoundingClientRect();
1191
+ const targetPosition = safeTarget.getBoundingClientRect();
1192
+ const getDiff = (property) => targetPosition[property] - parentPosition[property];
1193
+ if (axis === "y") {
1194
+ const diff = getDiff("top");
1195
+ if (diff === 0) return 0;
1196
+ if (alignment === "start") {
1197
+ const distance = diff - offset;
1198
+ return distance <= targetPosition.height * (isList ? 0 : 1) || !isList ? distance : 0;
1199
+ }
1200
+ const parentHeight = isCustomParent ? parentPosition.height : window.innerHeight;
1201
+ if (alignment === "end") {
1202
+ const distance = diff + offset - parentHeight + targetPosition.height;
1203
+ return distance >= -targetPosition.height * (isList ? 0 : 1) || !isList ? distance : 0;
1204
+ }
1205
+ if (alignment === "center") return diff - parentHeight / 2 + targetPosition.height / 2;
1206
+ return 0;
1207
+ }
1208
+ if (axis === "x") {
1209
+ const diff = getDiff("left");
1210
+ if (diff === 0) return 0;
1211
+ if (alignment === "start") {
1212
+ const distance = diff - offset;
1213
+ return distance <= targetPosition.width || !isList ? distance : 0;
1214
+ }
1215
+ const parentWidth = isCustomParent ? parentPosition.width : window.innerWidth;
1216
+ if (alignment === "end") {
1217
+ const distance = diff + offset - parentWidth + targetPosition.width;
1218
+ return distance >= -targetPosition.width || !isList ? distance : 0;
1219
+ }
1220
+ if (alignment === "center") return diff - parentWidth / 2 + targetPosition.width / 2;
1221
+ return 0;
1222
+ }
1223
+ return 0;
1224
+ }
1225
+ function getScrollStart({ axis, parent }) {
1226
+ const safeParent = parent instanceof Element ? parent : null;
1227
+ if (!safeParent && typeof document === "undefined") return 0;
1228
+ const method = axis === "y" ? "scrollTop" : "scrollLeft";
1229
+ if (safeParent) return safeParent[method];
1230
+ const { body, documentElement } = document;
1231
+ return body[method] + documentElement[method];
1232
+ }
1233
+ function setScrollParam({ axis, parent, distance }) {
1234
+ const safeParent = parent instanceof Element ? parent : null;
1235
+ if (!safeParent && typeof document === "undefined") return;
1236
+ const method = axis === "y" ? "scrollTop" : "scrollLeft";
1237
+ if (safeParent) safeParent[method] = distance;
1238
+ else {
1239
+ const { body, documentElement } = document;
1240
+ body[method] = distance;
1241
+ documentElement[method] = distance;
1242
+ }
1243
+ }
1244
+ //#endregion
1245
+ //#region src/use-resize-observer/use-resize-observer.ts
1246
+ var defaultState = {
1247
+ x: 0,
1248
+ y: 0,
1249
+ width: 0,
1250
+ height: 0,
1251
+ top: 0,
1252
+ left: 0,
1253
+ bottom: 0,
1254
+ right: 0
1255
+ };
1256
+ function useResizeObserver(options) {
1257
+ const elementRef = ref(null);
1258
+ const rect = ref(defaultState);
1259
+ let observer;
1260
+ const disconnect = () => {
1261
+ observer?.disconnect();
1262
+ observer = void 0;
1263
+ };
1264
+ watch(elementRef, (node) => {
1265
+ disconnect();
1266
+ if (!node || typeof ResizeObserver === "undefined") return;
1267
+ observer = new ResizeObserver((entries) => {
1268
+ const entry = entries[0];
1269
+ if (entry) {
1270
+ const boxSize = entry.borderBoxSize?.[0] || entry.contentBoxSize?.[0];
1271
+ if (boxSize) rect.value = {
1272
+ width: boxSize.inlineSize,
1273
+ height: boxSize.blockSize,
1274
+ x: entry.contentRect.x,
1275
+ y: entry.contentRect.y,
1276
+ top: entry.contentRect.top,
1277
+ left: entry.contentRect.left,
1278
+ bottom: entry.contentRect.bottom,
1279
+ right: entry.contentRect.right
1280
+ };
1281
+ else rect.value = entry.contentRect;
1282
+ }
1283
+ });
1284
+ observer.observe(node, options);
1285
+ }, {
1286
+ immediate: true,
1287
+ flush: "sync"
1288
+ });
1289
+ onBeforeUnmount(disconnect);
1290
+ return {
1291
+ ref: elementRef,
1292
+ rect
1293
+ };
1294
+ }
1295
+ function useElementSize(options) {
1296
+ const { ref: elementRef, rect } = useResizeObserver(options);
1297
+ const width = ref(0);
1298
+ const height = ref(0);
1299
+ watch(rect, (value) => {
1300
+ width.value = value.width;
1301
+ height.value = value.height;
1302
+ }, { immediate: true });
1303
+ return {
1304
+ ref: elementRef,
1305
+ width,
1306
+ height
1307
+ };
1308
+ }
1309
+ //#endregion
1310
+ //#region src/use-shallow-effect/use-shallow-effect.ts
1311
+ function shallowEqual$1(a, b) {
1312
+ if (a === b) return true;
1313
+ if (typeof a === "number" && typeof b === "number" && Number.isNaN(a) && Number.isNaN(b)) return true;
1314
+ if (!(a instanceof Object) || !(b instanceof Object)) return false;
1315
+ const keys = Object.keys(a);
1316
+ const { length } = keys;
1317
+ if (length !== Object.keys(b).length) return false;
1318
+ for (let i = 0; i < length; i += 1) {
1319
+ const key = keys[i];
1320
+ if (!(key in b)) return false;
1321
+ const aValue = a[key];
1322
+ const bValue = b[key];
1323
+ if (aValue !== bValue && !(Number.isNaN(aValue) && Number.isNaN(bValue))) return false;
1324
+ }
1325
+ return true;
1326
+ }
1327
+ function shallowCompareDeps(prev, curr) {
1328
+ if (!prev || !curr) return false;
1329
+ if (prev === curr) return true;
1330
+ if (prev.length !== curr.length) return false;
1331
+ for (let i = 0; i < prev.length; i += 1) if (!shallowEqual$1(prev[i], curr[i])) return false;
1332
+ return true;
1333
+ }
1334
+ function useShallowEffect(effect, dependencies) {
1335
+ if (!dependencies) {
1336
+ effect();
1337
+ onUpdated(effect);
1338
+ return;
1339
+ }
1340
+ let previous;
1341
+ const getDeps = () => dependencies.map((dep) => toValue(dep));
1342
+ watch(getDeps, (curr) => {
1343
+ if (!shallowCompareDeps(previous, curr)) {
1344
+ previous = curr;
1345
+ effect();
1346
+ }
1347
+ }, { immediate: true });
1348
+ }
1349
+ //#endregion
1350
+ //#region src/use-toggle/use-toggle.ts
1351
+ function useToggle(options = [false, true]) {
1352
+ const state = ref(options[0]);
1353
+ const toggle = (value) => {
1354
+ if (value !== void 0) {
1355
+ const nextValue = value instanceof Function ? value(state.value) : value;
1356
+ state.value = options[Math.abs(options.indexOf(nextValue))];
1357
+ return;
1358
+ }
1359
+ state.value = options[(options.indexOf(state.value) + 1) % options.length];
1360
+ };
1361
+ return [state, toggle];
1362
+ }
1363
+ //#endregion
1364
+ //#region src/use-viewport-size/use-viewport-size.ts
1365
+ var eventListenerOptions = { passive: true };
1366
+ function useViewportSize() {
1367
+ const width = ref(0);
1368
+ const height = ref(0);
1369
+ const setSize = () => {
1370
+ width.value = window.innerWidth || 0;
1371
+ height.value = window.innerHeight || 0;
1372
+ };
1373
+ useWindowEvent("resize", setSize, eventListenerOptions);
1374
+ useWindowEvent("orientationchange", setSize, eventListenerOptions);
1375
+ onMounted(setSize);
1376
+ return {
1377
+ width,
1378
+ height
1379
+ };
1380
+ }
1381
+ //#endregion
1382
+ //#region src/use-window-scroll/use-window-scroll.ts
1383
+ function getScrollPosition() {
1384
+ return typeof window !== "undefined" ? {
1385
+ x: window.scrollX,
1386
+ y: window.scrollY
1387
+ } : {
1388
+ x: 0,
1389
+ y: 0
1390
+ };
1391
+ }
1392
+ function scrollTo({ x, y }) {
1393
+ if (typeof window !== "undefined") {
1394
+ const scrollOptions = { behavior: "smooth" };
1395
+ if (typeof x === "number") scrollOptions.left = x;
1396
+ if (typeof y === "number") scrollOptions.top = y;
1397
+ window.scrollTo(scrollOptions);
1398
+ }
1399
+ }
1400
+ function useWindowScroll() {
1401
+ const position = ref({
1402
+ x: 0,
1403
+ y: 0
1404
+ });
1405
+ useWindowEvent("scroll", () => position.value = getScrollPosition(), { passive: true });
1406
+ useWindowEvent("resize", () => position.value = getScrollPosition(), { passive: true });
1407
+ onMounted(() => {
1408
+ position.value = getScrollPosition();
1409
+ });
1410
+ return [position, scrollTo];
1411
+ }
1412
+ //#endregion
1413
+ //#region src/use-intersection/use-intersection.ts
1414
+ function useIntersection(options) {
1415
+ const elementRef = ref(null);
1416
+ const entry = ref(null);
1417
+ let observer;
1418
+ watch(elementRef, (node) => {
1419
+ observer?.disconnect();
1420
+ observer = void 0;
1421
+ if (!node) {
1422
+ entry.value = null;
1423
+ return;
1424
+ }
1425
+ observer = new IntersectionObserver(([_entry]) => {
1426
+ entry.value = _entry;
1427
+ }, options);
1428
+ observer.observe(node);
1429
+ }, { immediate: true });
1430
+ onBeforeUnmount(() => observer?.disconnect());
1431
+ return {
1432
+ ref: elementRef,
1433
+ entry
1434
+ };
1435
+ }
1436
+ //#endregion
1437
+ //#region src/use-hash/use-hash.ts
1438
+ function getInitialHash(getInitialValueInEffect) {
1439
+ if (getInitialValueInEffect) return "";
1440
+ return typeof window !== "undefined" ? window.location.hash || "" : "";
1441
+ }
1442
+ function useHash(options = {}) {
1443
+ const { getInitialValueInEffect = true } = options;
1444
+ const hash = ref(getInitialHash(getInitialValueInEffect));
1445
+ const setHashHandler = (value) => {
1446
+ const valueWithHash = value.startsWith("#") ? value : `#${value}`;
1447
+ if (typeof window !== "undefined") window.location.hash = valueWithHash;
1448
+ hash.value = valueWithHash;
1449
+ };
1450
+ useWindowEvent("hashchange", () => {
1451
+ const newHash = window.location.hash;
1452
+ if (hash.value !== newHash) hash.value = newHash;
1453
+ });
1454
+ onMounted(() => {
1455
+ if (getInitialValueInEffect) hash.value = window.location.hash;
1456
+ });
1457
+ return [hash, setHashHandler];
1458
+ }
1459
+ //#endregion
1460
+ //#region src/use-hotkeys/parse-hotkey.ts
1461
+ var keyNameMap = {
1462
+ " ": "space",
1463
+ ArrowLeft: "arrowleft",
1464
+ ArrowRight: "arrowright",
1465
+ ArrowUp: "arrowup",
1466
+ ArrowDown: "arrowdown",
1467
+ Escape: "escape",
1468
+ Esc: "escape",
1469
+ esc: "escape",
1470
+ Enter: "enter",
1471
+ Tab: "tab",
1472
+ Backspace: "backspace",
1473
+ Delete: "delete",
1474
+ Insert: "insert",
1475
+ Home: "home",
1476
+ End: "end",
1477
+ PageUp: "pageup",
1478
+ PageDown: "pagedown",
1479
+ "+": "plus",
1480
+ "-": "minus",
1481
+ "*": "asterisk",
1482
+ "/": "slash"
1483
+ };
1484
+ function normalizeKey(key) {
1485
+ const lowerKey = key.replace("Key", "").toLowerCase();
1486
+ return keyNameMap[key] || lowerKey;
1487
+ }
1488
+ function parseHotkey(hotkey) {
1489
+ const keys = hotkey.toLowerCase().split("+").map((part) => part.trim());
1490
+ const modifiers = {
1491
+ alt: keys.includes("alt"),
1492
+ ctrl: keys.includes("ctrl"),
1493
+ meta: keys.includes("meta"),
1494
+ mod: keys.includes("mod"),
1495
+ shift: keys.includes("shift")
1496
+ };
1497
+ const reservedKeys = [
1498
+ "alt",
1499
+ "ctrl",
1500
+ "meta",
1501
+ "shift",
1502
+ "mod"
1503
+ ];
1504
+ const freeKey = keys.find((key) => !reservedKeys.includes(key));
1505
+ return {
1506
+ ...modifiers,
1507
+ key: freeKey === "[plus]" ? "+" : freeKey
1508
+ };
1509
+ }
1510
+ function isExactHotkey(hotkey, event, usePhysicalKeys) {
1511
+ const { alt, ctrl, meta, mod, shift, key } = hotkey;
1512
+ const { altKey, ctrlKey, metaKey, shiftKey, key: pressedKey, code: pressedCode } = event;
1513
+ if (alt !== altKey) return false;
1514
+ if (mod) {
1515
+ if (!ctrlKey && !metaKey) return false;
1516
+ } else {
1517
+ if (ctrl !== ctrlKey) return false;
1518
+ if (meta !== metaKey) return false;
1519
+ }
1520
+ if (shift !== shiftKey) return false;
1521
+ if (key && (usePhysicalKeys ? normalizeKey(pressedCode) === normalizeKey(key) : normalizeKey(pressedKey ?? pressedCode) === normalizeKey(key))) return true;
1522
+ return false;
1523
+ }
1524
+ function getHotkeyMatcher(hotkey, usePhysicalKeys) {
1525
+ return (event) => isExactHotkey(parseHotkey(hotkey), event, usePhysicalKeys);
1526
+ }
1527
+ function getHotkeyHandler(hotkeys) {
1528
+ return (event) => {
1529
+ hotkeys.forEach(([hotkey, handler, options = {
1530
+ preventDefault: true,
1531
+ usePhysicalKeys: false
1532
+ }]) => {
1533
+ if (getHotkeyMatcher(hotkey, options.usePhysicalKeys)(event)) {
1534
+ if (options.preventDefault) event.preventDefault();
1535
+ handler(event);
1536
+ }
1537
+ });
1538
+ };
1539
+ }
1540
+ //#endregion
1541
+ //#region src/use-hotkeys/use-hotkeys.ts
1542
+ function shouldFireEvent(event, tagsToIgnore, triggerOnContentEditable = false) {
1543
+ if (event.target instanceof HTMLElement) {
1544
+ const tagName = event.target.tagName.toLowerCase();
1545
+ if (triggerOnContentEditable) return !tagsToIgnore.includes(tagName);
1546
+ return !event.target.isContentEditable && !tagsToIgnore.includes(tagName);
1547
+ }
1548
+ return true;
1549
+ }
1550
+ /**
1551
+ * Listens for global keydown events and invokes matching handlers.
1552
+ *
1553
+ * NOTE: the listener is attached to `window` rather than
1554
+ * `document.documentElement` (which is what React Mantine uses). Real
1555
+ * keyboard events always bubble to `window`, so this is behaviorally
1556
+ * equivalent for actual usage while remaining consistent with how the rest
1557
+ * of this package (and its test suite) dispatches synthetic events.
1558
+ */
1559
+ function useHotkeys(hotkeys, tagsToIgnore = [
1560
+ "input",
1561
+ "textarea",
1562
+ "select"
1563
+ ], triggerOnContentEditable = false) {
1564
+ const handleKeydown = (event) => {
1565
+ toValue(hotkeys).forEach(([hotkey, handler, options = {
1566
+ preventDefault: true,
1567
+ usePhysicalKeys: false
1568
+ }]) => {
1569
+ if (getHotkeyMatcher(hotkey, options.usePhysicalKeys)(event) && shouldFireEvent(event, toValue(tagsToIgnore) ?? [
1570
+ "input",
1571
+ "textarea",
1572
+ "select"
1573
+ ], toValue(triggerOnContentEditable))) {
1574
+ if (options.preventDefault) event.preventDefault();
1575
+ handler(event);
1576
+ }
1577
+ });
1578
+ };
1579
+ onMounted(() => window.addEventListener("keydown", handleKeydown));
1580
+ onBeforeUnmount(() => window.removeEventListener("keydown", handleKeydown));
1581
+ }
1582
+ //#endregion
1583
+ //#region src/use-fullscreen/use-fullscreen.ts
1584
+ function getFullscreenElement() {
1585
+ const _document = window.document;
1586
+ return _document.fullscreenElement || _document.webkitFullscreenElement || _document.mozFullScreenElement || _document.msFullscreenElement || null;
1587
+ }
1588
+ function exitFullscreen() {
1589
+ const _document = window.document;
1590
+ if (typeof _document.exitFullscreen === "function") return _document.exitFullscreen();
1591
+ if (typeof _document.msExitFullscreen === "function") return _document.msExitFullscreen();
1592
+ if (typeof _document.webkitExitFullscreen === "function") return _document.webkitExitFullscreen();
1593
+ if (typeof _document.mozCancelFullScreen === "function") return _document.mozCancelFullScreen();
1594
+ return null;
1595
+ }
1596
+ function enterFullScreen(element) {
1597
+ const _element = element;
1598
+ return _element.requestFullscreen?.() || _element.msRequestFullscreen?.() || _element.webkitEnterFullscreen?.() || _element.webkitRequestFullscreen?.() || _element.mozRequestFullscreen?.();
1599
+ }
1600
+ var prefixes = [
1601
+ "",
1602
+ "webkit",
1603
+ "moz",
1604
+ "ms"
1605
+ ];
1606
+ function addEvents(element, events) {
1607
+ const { onFullScreen, onError } = events;
1608
+ prefixes.forEach((prefix) => {
1609
+ element.addEventListener(`${prefix}fullscreenchange`, onFullScreen);
1610
+ element.addEventListener(`${prefix}fullscreenerror`, onError);
1611
+ });
1612
+ return () => removeEvents(element, events);
1613
+ }
1614
+ function removeEvents(element, { onFullScreen, onError }) {
1615
+ prefixes.forEach((prefix) => {
1616
+ element.removeEventListener(`${prefix}fullscreenchange`, onFullScreen);
1617
+ element.removeEventListener(`${prefix}fullscreenerror`, onError);
1618
+ });
1619
+ }
1620
+ function useFullscreenElement() {
1621
+ const fullscreen = ref(false);
1622
+ const elementRef = ref(null);
1623
+ let removeEventsFn;
1624
+ const handleFullscreenChange = () => {
1625
+ fullscreen.value = elementRef.value === getFullscreenElement();
1626
+ };
1627
+ const handleFullscreenError = () => {
1628
+ fullscreen.value = false;
1629
+ };
1630
+ const toggle = async () => {
1631
+ if (!getFullscreenElement() && elementRef.value) await enterFullScreen(elementRef.value);
1632
+ else await exitFullscreen();
1633
+ };
1634
+ watch(elementRef, (node) => {
1635
+ removeEventsFn?.();
1636
+ removeEventsFn = void 0;
1637
+ if (node) removeEventsFn = addEvents(node, {
1638
+ onFullScreen: handleFullscreenChange,
1639
+ onError: handleFullscreenError
1640
+ });
1641
+ }, { immediate: true });
1642
+ onBeforeUnmount(() => removeEventsFn?.());
1643
+ return {
1644
+ ref: elementRef,
1645
+ toggle,
1646
+ fullscreen
1647
+ };
1648
+ }
1649
+ function useFullscreenDocument() {
1650
+ const fullscreen = ref(false);
1651
+ let removeEventsFn;
1652
+ const handleFullscreenChange = () => {
1653
+ fullscreen.value = getFullscreenElement() === window.document.documentElement;
1654
+ };
1655
+ const handleFullscreenError = () => {
1656
+ fullscreen.value = false;
1657
+ };
1658
+ const toggle = async () => {
1659
+ if (!getFullscreenElement()) await enterFullScreen(window.document.documentElement);
1660
+ else await exitFullscreen();
1661
+ };
1662
+ onMounted(() => {
1663
+ removeEventsFn = addEvents(window.document.documentElement, {
1664
+ onFullScreen: handleFullscreenChange,
1665
+ onError: handleFullscreenError
1666
+ });
1667
+ });
1668
+ onBeforeUnmount(() => removeEventsFn?.());
1669
+ return {
1670
+ toggle,
1671
+ fullscreen
1672
+ };
1673
+ }
1674
+ //#endregion
1675
+ //#region src/use-logger/use-logger.ts
1676
+ function useLogger(componentName, props) {
1677
+ onMounted(() => {
1678
+ console.log(`${componentName} mounted`, ...props.map((prop) => toValue(prop)));
1679
+ });
1680
+ onBeforeUnmount(() => {
1681
+ console.log(`${componentName} unmounted`);
1682
+ });
1683
+ useDidUpdate(() => {
1684
+ console.log(`${componentName} updated`, ...props.map((prop) => toValue(prop)));
1685
+ }, props);
1686
+ return null;
1687
+ }
1688
+ //#endregion
1689
+ //#region src/use-hover/use-hover.ts
1690
+ function useHover() {
1691
+ const refTarget = ref(null);
1692
+ const hovered = ref(false);
1693
+ let cleanup;
1694
+ onMounted(() => {
1695
+ const node = refTarget.value;
1696
+ if (!node) return;
1697
+ const onEnter = () => hovered.value = true;
1698
+ const onLeave = () => hovered.value = false;
1699
+ node.addEventListener("mouseenter", onEnter);
1700
+ node.addEventListener("mouseleave", onLeave);
1701
+ cleanup = () => {
1702
+ node.removeEventListener("mouseenter", onEnter);
1703
+ node.removeEventListener("mouseleave", onLeave);
1704
+ };
1705
+ });
1706
+ onBeforeUnmount(() => cleanup?.());
1707
+ return {
1708
+ ref: refTarget,
1709
+ hovered
1710
+ };
1711
+ }
1712
+ //#endregion
1713
+ //#region src/use-validated-state/use-validated-state.ts
1714
+ function useValidatedState(initialValue, validate, initialValidationState) {
1715
+ const state = ref({
1716
+ value: initialValue,
1717
+ lastValidValue: validate(initialValue) ? initialValue : void 0,
1718
+ valid: typeof initialValidationState === "boolean" ? initialValidationState : validate(initialValue)
1719
+ });
1720
+ const onChange = (val) => {
1721
+ const isValid = validate(val);
1722
+ state.value = {
1723
+ value: val,
1724
+ lastValidValue: isValid ? val : state.value.lastValidValue,
1725
+ valid: isValid
1726
+ };
1727
+ };
1728
+ return [readonly(state), onChange];
1729
+ }
1730
+ //#endregion
1731
+ //#region src/use-os/use-os.ts
1732
+ function isMacOS(userAgent) {
1733
+ return /(Macintosh)|(MacIntel)|(MacPPC)|(Mac68K)/i.test(userAgent);
1734
+ }
1735
+ function isIOS(userAgent) {
1736
+ return /(iPhone)|(iPad)|(iPod)/i.test(userAgent);
1737
+ }
1738
+ function isWindows(userAgent) {
1739
+ return /(Win32)|(Win64)|(Windows)|(WinCE)/i.test(userAgent);
1740
+ }
1741
+ function isAndroid(userAgent) {
1742
+ return /Android/i.test(userAgent);
1743
+ }
1744
+ function isLinux(userAgent) {
1745
+ return /Linux/i.test(userAgent);
1746
+ }
1747
+ function isChromeOS(userAgent) {
1748
+ return /CrOS/i.test(userAgent);
1749
+ }
1750
+ function getOS() {
1751
+ if (typeof window === "undefined") return "undetermined";
1752
+ const { userAgent } = window.navigator;
1753
+ if (isIOS(userAgent) || isMacOS(userAgent) && "ontouchend" in document) return "ios";
1754
+ if (isMacOS(userAgent)) return "macos";
1755
+ if (isWindows(userAgent)) return "windows";
1756
+ if (isAndroid(userAgent)) return "android";
1757
+ if (isChromeOS(userAgent)) return "chromeos";
1758
+ if (isLinux(userAgent)) return "linux";
1759
+ return "undetermined";
1760
+ }
1761
+ function useOs(options = { getValueInEffect: true }) {
1762
+ const value = ref(options.getValueInEffect ? "undetermined" : getOS());
1763
+ useIsomorphicEffect(() => {
1764
+ if (options.getValueInEffect) value.value = getOS();
1765
+ });
1766
+ return readonly(value);
1767
+ }
1768
+ //#endregion
1769
+ //#region src/use-set-state/use-set-state.ts
1770
+ function useSetState(initialState) {
1771
+ const state = ref(initialState);
1772
+ const setState = (statePartial) => {
1773
+ state.value = {
1774
+ ...state.value,
1775
+ ...typeof statePartial === "function" ? statePartial(state.value) : statePartial
1776
+ };
1777
+ };
1778
+ return [state, setState];
1779
+ }
1780
+ //#endregion
1781
+ //#region src/use-input-state/use-input-state.ts
1782
+ function useInputState(initialValue) {
1783
+ const value = ref(initialValue);
1784
+ const setValue = (eventOrValue) => {
1785
+ if (eventOrValue instanceof Function) {
1786
+ value.value = eventOrValue(value.value);
1787
+ return;
1788
+ }
1789
+ if (eventOrValue instanceof Event || eventOrValue && typeof eventOrValue === "object" && "currentTarget" in eventOrValue && "nativeEvent" in eventOrValue) {
1790
+ const target = eventOrValue.target ?? eventOrValue.currentTarget;
1791
+ value.value = target.type === "checkbox" ? target.checked : target.value;
1792
+ } else value.value = eventOrValue;
1793
+ };
1794
+ return [value, setValue];
1795
+ }
1796
+ //#endregion
1797
+ //#region src/use-event-listener/use-event-listener.ts
1798
+ function useEventListener(type, listener, options) {
1799
+ const elementRef = ref(null);
1800
+ let cleanup;
1801
+ watch(elementRef, (node) => {
1802
+ cleanup?.();
1803
+ cleanup = void 0;
1804
+ if (!node) return;
1805
+ node.addEventListener(type, listener, options);
1806
+ cleanup = () => node.removeEventListener(type, listener, options);
1807
+ }, { immediate: true });
1808
+ onBeforeUnmount(() => cleanup?.());
1809
+ return elementRef;
1810
+ }
1811
+ //#endregion
1812
+ //#region src/use-disclosure/use-disclosure.ts
1813
+ function useDisclosure(initialState = false, options = {}) {
1814
+ const opened = ref(initialState);
1815
+ const set = (value) => {
1816
+ if (value && !opened.value) options.onOpen?.();
1817
+ if (!value && opened.value) options.onClose?.();
1818
+ opened.value = value;
1819
+ };
1820
+ return [opened, {
1821
+ set,
1822
+ open: () => set(true),
1823
+ close: () => set(false),
1824
+ toggle: () => set(!opened.value)
1825
+ }];
1826
+ }
1827
+ //#endregion
1828
+ //#region src/use-focus-within/use-focus-within.ts
1829
+ function useFocusWithin(options = {}) {
1830
+ const refTarget = ref(null);
1831
+ const focused = ref(false);
1832
+ let cleanup;
1833
+ onMounted(() => {
1834
+ const node = refTarget.value;
1835
+ if (!node) return;
1836
+ const onFocusIn = (event) => {
1837
+ focused.value = true;
1838
+ options.onFocus?.(event);
1839
+ };
1840
+ const onFocusOut = (event) => nextTick(() => {
1841
+ const isFocused = node.matches(":focus-within");
1842
+ if (!isFocused && focused.value) options.onBlur?.(event);
1843
+ focused.value = isFocused;
1844
+ });
1845
+ node.addEventListener("focusin", onFocusIn);
1846
+ node.addEventListener("focusout", onFocusOut);
1847
+ cleanup = () => {
1848
+ node.removeEventListener("focusin", onFocusIn);
1849
+ node.removeEventListener("focusout", onFocusOut);
1850
+ };
1851
+ });
1852
+ onBeforeUnmount(() => cleanup?.());
1853
+ return {
1854
+ ref: refTarget,
1855
+ focused
1856
+ };
1857
+ }
1858
+ //#endregion
1859
+ //#region src/use-network/use-network.ts
1860
+ function getConnection() {
1861
+ if (typeof navigator === "undefined") return {};
1862
+ const nav = navigator;
1863
+ const connection = nav.connection || nav.mozConnection || nav.webkitConnection;
1864
+ if (!connection) return {};
1865
+ return {
1866
+ downlink: connection.downlink,
1867
+ downlinkMax: connection.downlinkMax,
1868
+ effectiveType: connection.effectiveType,
1869
+ rtt: connection.rtt,
1870
+ saveData: connection.saveData,
1871
+ type: connection.type
1872
+ };
1873
+ }
1874
+ function useNetwork() {
1875
+ const status = ref({ online: true });
1876
+ const handleConnectionChange = () => {
1877
+ status.value = {
1878
+ ...status.value,
1879
+ ...getConnection()
1880
+ };
1881
+ };
1882
+ useWindowEvent("online", () => {
1883
+ status.value = {
1884
+ online: true,
1885
+ ...getConnection()
1886
+ };
1887
+ });
1888
+ useWindowEvent("offline", () => {
1889
+ status.value = {
1890
+ online: false,
1891
+ ...getConnection()
1892
+ };
1893
+ });
1894
+ onMounted(() => {
1895
+ const nav = navigator;
1896
+ if (nav.connection) {
1897
+ status.value = {
1898
+ online: nav.onLine,
1899
+ ...getConnection()
1900
+ };
1901
+ nav.connection.addEventListener("change", handleConnectionChange);
1902
+ return;
1903
+ }
1904
+ if (typeof nav.onLine === "boolean") status.value = {
1905
+ ...status.value,
1906
+ online: nav.onLine
1907
+ };
1908
+ });
1909
+ onBeforeUnmount(() => {
1910
+ navigator.connection?.removeEventListener("change", handleConnectionChange);
1911
+ });
1912
+ return status;
1913
+ }
1914
+ //#endregion
1915
+ //#region src/use-timeout/use-timeout.ts
1916
+ function useTimeout(callback, delay, options = { autoInvoke: false }) {
1917
+ let timeout;
1918
+ const start = (...callbackParams) => {
1919
+ clear();
1920
+ timeout = setTimeout(() => callback(...callbackParams), delay);
1921
+ };
1922
+ const clear = () => {
1923
+ if (timeout) {
1924
+ clearTimeout(timeout);
1925
+ timeout = void 0;
1926
+ }
1927
+ };
1928
+ if (options.autoInvoke) start();
1929
+ onBeforeUnmount(clear);
1930
+ return {
1931
+ start,
1932
+ clear
1933
+ };
1934
+ }
1935
+ //#endregion
1936
+ //#region src/use-text-selection/use-text-selection.ts
1937
+ function useTextSelection() {
1938
+ const selection = shallowRef(null);
1939
+ const handleSelectionChange = () => {
1940
+ selection.value = document.getSelection();
1941
+ triggerRef(selection);
1942
+ };
1943
+ onMounted(() => {
1944
+ selection.value = document.getSelection();
1945
+ triggerRef(selection);
1946
+ document.addEventListener("selectionchange", handleSelectionChange);
1947
+ });
1948
+ onBeforeUnmount(() => {
1949
+ document.removeEventListener("selectionchange", handleSelectionChange);
1950
+ });
1951
+ return selection;
1952
+ }
1953
+ //#endregion
1954
+ //#region src/use-previous/use-previous.ts
1955
+ function usePrevious(value) {
1956
+ const previous = shallowRef();
1957
+ watch(() => toValue(value), (_, oldValue) => {
1958
+ previous.value = oldValue;
1959
+ });
1960
+ return previous;
1961
+ }
1962
+ //#endregion
1963
+ //#region src/use-favicon/use-favicon.ts
1964
+ var MIME_TYPES = {
1965
+ ico: "image/x-icon",
1966
+ png: "image/png",
1967
+ svg: "image/svg+xml",
1968
+ gif: "image/gif"
1969
+ };
1970
+ function useFavicon(url) {
1971
+ let link = null;
1972
+ useIsomorphicEffect(() => {
1973
+ watch(() => toValue(url), (value) => {
1974
+ if (!value) return;
1975
+ if (!link) {
1976
+ document.querySelectorAll("link[rel*=\"icon\"]").forEach((element) => document.head.removeChild(element));
1977
+ const element = document.createElement("link");
1978
+ element.rel = "shortcut icon";
1979
+ link = element;
1980
+ document.querySelector("head").appendChild(element);
1981
+ }
1982
+ const splittedUrl = value.split(".");
1983
+ const mimeType = MIME_TYPES[splittedUrl[splittedUrl.length - 1].toLowerCase()];
1984
+ if (mimeType) link.setAttribute("type", mimeType);
1985
+ else link.removeAttribute("type");
1986
+ link.setAttribute("href", value);
1987
+ }, { immediate: true });
1988
+ });
1989
+ }
1990
+ //#endregion
1991
+ //#region src/use-scroll-direction/use-scroll-direction.ts
1992
+ function useScrollDirection() {
1993
+ const scrollDirection = ref("unknown");
1994
+ let lastScrollTop = 0;
1995
+ let isResizing = false;
1996
+ let resizeTimer;
1997
+ const handleScroll = () => {
1998
+ if (isResizing) return;
1999
+ const currentScrollTop = window.scrollY || document.documentElement.scrollTop;
2000
+ scrollDirection.value = currentScrollTop < lastScrollTop ? "up" : "down";
2001
+ lastScrollTop = currentScrollTop;
2002
+ };
2003
+ const handleResize = () => {
2004
+ isResizing = true;
2005
+ window.clearTimeout(resizeTimer);
2006
+ resizeTimer = window.setTimeout(() => {
2007
+ isResizing = false;
2008
+ }, 300);
2009
+ };
2010
+ useWindowEvent("scroll", handleScroll);
2011
+ useWindowEvent("resize", handleResize);
2012
+ onBeforeUnmount(() => window.clearTimeout(resizeTimer));
2013
+ return readonly(scrollDirection);
2014
+ }
2015
+ //#endregion
2016
+ //#region src/use-headroom/use-headroom.ts
2017
+ var isFixed = (current, fixedAt) => current <= fixedAt;
2018
+ var isPinned = (current, previous) => current <= previous;
2019
+ var isReleased = (current, previous, fixedAt) => !isPinned(current, previous) && !isFixed(current, fixedAt);
2020
+ var isPinnedOrReleased = (current, fixedAt, isCurrentlyPinnedRef, isScrollingUp, onPin, onRelease) => {
2021
+ const isInFixedPosition = isFixed(current, fixedAt);
2022
+ if (isInFixedPosition && !isCurrentlyPinnedRef.value) {
2023
+ isCurrentlyPinnedRef.value = true;
2024
+ onPin?.();
2025
+ } else if (!isInFixedPosition && isScrollingUp && !isCurrentlyPinnedRef.value) {
2026
+ isCurrentlyPinnedRef.value = true;
2027
+ onPin?.();
2028
+ } else if (!isInFixedPosition && !isScrollingUp && isCurrentlyPinnedRef.value) {
2029
+ isCurrentlyPinnedRef.value = false;
2030
+ onRelease?.();
2031
+ }
2032
+ };
2033
+ function useHeadroom({ fixedAt = 0, scrollDistance = 100, onPin, onFix, onRelease } = {}) {
2034
+ const scrollDirection = useScrollDirection();
2035
+ const scrollY = ref(typeof window === "undefined" ? 0 : window.scrollY || document.documentElement.scrollTop);
2036
+ useWindowEvent("scroll", () => {
2037
+ scrollY.value = window.scrollY || document.documentElement.scrollTop;
2038
+ });
2039
+ const pinned = ref(false);
2040
+ const scrollProgress = ref(0);
2041
+ const isCurrentlyPinned = { value: false };
2042
+ let wasFixed = isFixed(scrollY.value, fixedAt);
2043
+ let prevIsFixed = wasFixed;
2044
+ let directionChangeScrollY = scrollY.value;
2045
+ let progressAtDirectionChange = wasFixed ? 1 : 0;
2046
+ let prevIsScrollingUp = scrollDirection.value === "up";
2047
+ const recalc = () => {
2048
+ const current = scrollY.value;
2049
+ const isScrollingUp = scrollDirection.value === "up";
2050
+ isPinnedOrReleased(current, fixedAt, isCurrentlyPinned, isScrollingUp, onPin, onRelease);
2051
+ const currentlyFixed = isFixed(current, fixedAt);
2052
+ if (currentlyFixed && !wasFixed) onFix?.();
2053
+ wasFixed = currentlyFixed;
2054
+ if (prevIsFixed !== currentlyFixed) {
2055
+ prevIsFixed = currentlyFixed;
2056
+ directionChangeScrollY = currentlyFixed ? current : fixedAt;
2057
+ progressAtDirectionChange = 1;
2058
+ prevIsScrollingUp = isScrollingUp;
2059
+ }
2060
+ if (!currentlyFixed && prevIsScrollingUp !== isScrollingUp) {
2061
+ const transitionDelta = Math.abs(current - directionChangeScrollY);
2062
+ const transitionProgress = prevIsScrollingUp ? Math.min(progressAtDirectionChange + transitionDelta / scrollDistance, 1) : Math.max(progressAtDirectionChange - transitionDelta / scrollDistance, 0);
2063
+ prevIsScrollingUp = isScrollingUp;
2064
+ directionChangeScrollY = current;
2065
+ progressAtDirectionChange = transitionProgress;
2066
+ }
2067
+ let nextScrollProgress;
2068
+ if (currentlyFixed) nextScrollProgress = 1;
2069
+ else {
2070
+ const scrollDelta = Math.abs(current - directionChangeScrollY);
2071
+ nextScrollProgress = isScrollingUp ? Math.min(progressAtDirectionChange + scrollDelta / scrollDistance, 1) : Math.max(progressAtDirectionChange - scrollDelta / scrollDistance, 0);
2072
+ }
2073
+ scrollProgress.value = nextScrollProgress;
2074
+ pinned.value = nextScrollProgress > 0;
2075
+ };
2076
+ watch([scrollY, scrollDirection], recalc, { immediate: true });
2077
+ return {
2078
+ pinned,
2079
+ scrollProgress
2080
+ };
2081
+ }
2082
+ //#endregion
2083
+ //#region src/use-eye-dropper/use-eye-dropper.ts
2084
+ function isOpera() {
2085
+ return navigator.userAgent.includes("OPR");
2086
+ }
2087
+ function useEyeDropper() {
2088
+ const supported = ref(false);
2089
+ useIsomorphicEffect(() => {
2090
+ supported.value = typeof window !== "undefined" && !isOpera() && "EyeDropper" in window;
2091
+ });
2092
+ const open = (options = {}) => {
2093
+ if (supported.value) return new window.EyeDropper().open(options);
2094
+ return Promise.resolve(void 0);
2095
+ };
2096
+ return {
2097
+ supported,
2098
+ open
2099
+ };
2100
+ }
2101
+ //#endregion
2102
+ //#region src/use-in-viewport/use-in-viewport.ts
2103
+ function useInViewport() {
2104
+ const elementRef = ref(null);
2105
+ const inViewport = ref(false);
2106
+ let observer;
2107
+ watch(elementRef, (node) => {
2108
+ if (typeof IntersectionObserver === "undefined") return;
2109
+ observer?.disconnect();
2110
+ const target = node instanceof Element ? node : null;
2111
+ if (target) {
2112
+ observer = new IntersectionObserver((entries) => {
2113
+ inViewport.value = entries[entries.length - 1].isIntersecting;
2114
+ });
2115
+ observer.observe(target);
2116
+ } else {
2117
+ observer = void 0;
2118
+ inViewport.value = false;
2119
+ }
2120
+ }, { immediate: true });
2121
+ onBeforeUnmount(() => observer?.disconnect());
2122
+ return {
2123
+ ref: elementRef,
2124
+ inViewport
2125
+ };
2126
+ }
2127
+ //#endregion
2128
+ //#region src/use-mutation-observer/use-mutation-observer.ts
2129
+ function useMutationObserver(callback, options) {
2130
+ const elementRef = ref(null);
2131
+ let observer;
2132
+ watch(elementRef, (node) => {
2133
+ observer?.disconnect();
2134
+ observer = void 0;
2135
+ if (node instanceof Element) {
2136
+ observer = new MutationObserver(callback);
2137
+ observer.observe(node, options);
2138
+ }
2139
+ }, { immediate: true });
2140
+ onBeforeUnmount(() => observer?.disconnect());
2141
+ return elementRef;
2142
+ }
2143
+ function useMutationObserverTarget(callback, options, target) {
2144
+ let observer;
2145
+ const connect = () => {
2146
+ observer?.disconnect();
2147
+ observer = void 0;
2148
+ const targetElement = toValue(target);
2149
+ if (targetElement instanceof Element) {
2150
+ observer = new MutationObserver(callback);
2151
+ observer.observe(targetElement, options);
2152
+ }
2153
+ };
2154
+ onMounted(connect);
2155
+ watch(() => toValue(target), connect);
2156
+ onBeforeUnmount(() => observer?.disconnect());
2157
+ }
2158
+ //#endregion
2159
+ //#region src/use-mounted/use-mounted.ts
2160
+ function useMounted() {
2161
+ const mounted = ref(false);
2162
+ onMounted(() => {
2163
+ mounted.value = true;
2164
+ });
2165
+ return readonly(mounted);
2166
+ }
2167
+ //#endregion
2168
+ //#region src/use-state-history/use-state-history.ts
2169
+ function useStateHistory(initialValue) {
2170
+ const historyState = ref({
2171
+ history: [initialValue],
2172
+ current: 0
2173
+ });
2174
+ const set = (val) => {
2175
+ const nextHistory = [...historyState.value.history.slice(0, historyState.value.current + 1), val];
2176
+ historyState.value = {
2177
+ history: nextHistory,
2178
+ current: nextHistory.length - 1
2179
+ };
2180
+ };
2181
+ const back = (steps = 1) => {
2182
+ historyState.value = {
2183
+ history: historyState.value.history,
2184
+ current: Math.max(0, historyState.value.current - steps)
2185
+ };
2186
+ };
2187
+ const forward = (steps = 1) => {
2188
+ historyState.value = {
2189
+ history: historyState.value.history,
2190
+ current: Math.min(historyState.value.history.length - 1, historyState.value.current + steps)
2191
+ };
2192
+ };
2193
+ const reset = () => {
2194
+ historyState.value = {
2195
+ history: [initialValue],
2196
+ current: 0
2197
+ };
2198
+ };
2199
+ const handlers = {
2200
+ back,
2201
+ forward,
2202
+ reset,
2203
+ set
2204
+ };
2205
+ return [
2206
+ computed(() => historyState.value.history[historyState.value.current]),
2207
+ handlers,
2208
+ readonly(historyState)
2209
+ ];
2210
+ }
2211
+ //#endregion
2212
+ //#region src/use-map/use-map.ts
2213
+ function useMap(initialState) {
2214
+ return reactive(new Map(initialState));
2215
+ }
2216
+ //#endregion
2217
+ //#region src/use-set/use-set.ts
2218
+ function readonlySetLikeToSet(input) {
2219
+ if (input instanceof Set) return input;
2220
+ const result = /* @__PURE__ */ new Set();
2221
+ const iterator = input.keys();
2222
+ let next = iterator.next();
2223
+ while (!next.done) {
2224
+ result.add(next.value);
2225
+ next = iterator.next();
2226
+ }
2227
+ return result;
2228
+ }
2229
+ function useSet(values) {
2230
+ const rawSet = new Set(values);
2231
+ rawSet.union = (other) => {
2232
+ const result = new Set(rawSet);
2233
+ readonlySetLikeToSet(other).forEach((item) => result.add(item));
2234
+ return result;
2235
+ };
2236
+ rawSet.intersection = (other) => {
2237
+ const result = /* @__PURE__ */ new Set();
2238
+ const otherSet = readonlySetLikeToSet(other);
2239
+ rawSet.forEach((item) => {
2240
+ if (otherSet.has(item)) result.add(item);
2241
+ });
2242
+ return result;
2243
+ };
2244
+ rawSet.difference = (other) => {
2245
+ const result = /* @__PURE__ */ new Set();
2246
+ const otherSet = readonlySetLikeToSet(other);
2247
+ rawSet.forEach((item) => {
2248
+ if (!otherSet.has(item)) result.add(item);
2249
+ });
2250
+ return result;
2251
+ };
2252
+ rawSet.symmetricDifference = (other) => {
2253
+ const result = /* @__PURE__ */ new Set();
2254
+ const otherSet = readonlySetLikeToSet(other);
2255
+ rawSet.forEach((item) => {
2256
+ if (!otherSet.has(item)) result.add(item);
2257
+ });
2258
+ otherSet.forEach((item) => {
2259
+ if (!rawSet.has(item)) result.add(item);
2260
+ });
2261
+ return result;
2262
+ };
2263
+ return reactive(rawSet);
2264
+ }
2265
+ //#endregion
2266
+ //#region src/use-throttled-callback/use-throttled-callback.ts
2267
+ function useThrottledCallbackWithClearTimeout(callback, wait) {
2268
+ let latestInArgs = null;
2269
+ let latestOutArgs = null;
2270
+ let active = true;
2271
+ let timeoutId = -1;
2272
+ const clear = () => window.clearTimeout(timeoutId);
2273
+ const callThrottledCallback = (...args) => {
2274
+ callback(...args);
2275
+ latestInArgs = args;
2276
+ latestOutArgs = args;
2277
+ active = false;
2278
+ };
2279
+ const timerCallback = () => {
2280
+ if (latestInArgs && latestInArgs !== latestOutArgs) {
2281
+ callThrottledCallback(...latestInArgs);
2282
+ timeoutId = window.setTimeout(timerCallback, wait);
2283
+ } else active = true;
2284
+ };
2285
+ const throttled = (...args) => {
2286
+ if (active) {
2287
+ callThrottledCallback(...args);
2288
+ timeoutId = window.setTimeout(timerCallback, wait);
2289
+ } else latestInArgs = args;
2290
+ };
2291
+ return [throttled, clear];
2292
+ }
2293
+ function useThrottledCallback(callback, wait) {
2294
+ const [throttled, clear] = useThrottledCallbackWithClearTimeout(callback, wait);
2295
+ onBeforeUnmount(clear);
2296
+ return throttled;
2297
+ }
2298
+ //#endregion
2299
+ //#region src/use-throttled-state/use-throttled-state.ts
2300
+ function useThrottledState(defaultValue, wait) {
2301
+ const value = ref(defaultValue);
2302
+ const [setThrottledValue, clear] = useThrottledCallbackWithClearTimeout((nextValue) => {
2303
+ value.value = nextValue;
2304
+ }, wait);
2305
+ onBeforeUnmount(clear);
2306
+ return [value, setThrottledValue];
2307
+ }
2308
+ //#endregion
2309
+ //#region src/use-throttled-value/use-throttled-value.ts
2310
+ function useThrottledValue(value, wait) {
2311
+ const throttledValue = ref(toValue(value));
2312
+ const [throttledSetValue, clear] = useThrottledCallbackWithClearTimeout((nextValue) => {
2313
+ throttledValue.value = nextValue;
2314
+ }, wait);
2315
+ watch(() => toValue(value), (nextValue) => throttledSetValue(nextValue));
2316
+ onBeforeUnmount(clear);
2317
+ return readonly(throttledValue);
2318
+ }
2319
+ //#endregion
2320
+ //#region src/use-is-first-render/use-is-first-render.ts
2321
+ function useIsFirstRender() {
2322
+ const isFirst = ref(true);
2323
+ onUpdated(() => {
2324
+ isFirst.value = false;
2325
+ });
2326
+ return readonly(isFirst);
2327
+ }
2328
+ //#endregion
2329
+ //#region src/use-orientation/use-orientation.ts
2330
+ function getInitialValue(initialValue, getInitialValueInEffect) {
2331
+ if (getInitialValueInEffect) return initialValue;
2332
+ if (typeof window !== "undefined" && "screen" in window) return {
2333
+ angle: window.screen.orientation?.angle ?? initialValue.angle,
2334
+ type: window.screen.orientation?.type ?? initialValue.type
2335
+ };
2336
+ return initialValue;
2337
+ }
2338
+ function useOrientation(options = {}) {
2339
+ const { defaultAngle = 0, defaultType = "landscape-primary", getInitialValueInEffect = true } = options;
2340
+ const orientation = ref(getInitialValue({
2341
+ angle: defaultAngle,
2342
+ type: defaultType
2343
+ }, getInitialValueInEffect));
2344
+ const handleOrientationChange = (event) => {
2345
+ const target = event.currentTarget;
2346
+ orientation.value = {
2347
+ angle: target?.angle || 0,
2348
+ type: target?.type || "landscape-primary"
2349
+ };
2350
+ };
2351
+ useIsomorphicEffect(() => {
2352
+ if (window.screen.orientation) {
2353
+ orientation.value = {
2354
+ angle: window.screen.orientation.angle,
2355
+ type: window.screen.orientation.type
2356
+ };
2357
+ window.screen.orientation.addEventListener("change", handleOrientationChange);
2358
+ }
2359
+ });
2360
+ onBeforeUnmount(() => {
2361
+ if (typeof window !== "undefined") window.screen.orientation?.removeEventListener("change", handleOrientationChange);
2362
+ });
2363
+ return orientation;
2364
+ }
2365
+ //#endregion
2366
+ //#region src/use-fetch/use-fetch.ts
2367
+ function useFetch(url, { autoInvoke = true, ...options } = {}) {
2368
+ const data = ref(null);
2369
+ const loading = ref(false);
2370
+ const error = ref(null);
2371
+ let controller = null;
2372
+ const refetch = () => {
2373
+ if (controller) controller.abort();
2374
+ controller = new AbortController();
2375
+ loading.value = true;
2376
+ return fetch(toValue(url), {
2377
+ ...options,
2378
+ signal: controller.signal
2379
+ }).then((res) => {
2380
+ if (!res.ok) throw new Error(`Request failed with status ${res.status}`);
2381
+ return res.json();
2382
+ }).then((res) => {
2383
+ data.value = res;
2384
+ loading.value = false;
2385
+ return res;
2386
+ }).catch((err) => {
2387
+ loading.value = false;
2388
+ if (err.name !== "AbortError") error.value = err;
2389
+ return err;
2390
+ });
2391
+ };
2392
+ const abort = () => {
2393
+ if (controller) controller.abort("");
2394
+ };
2395
+ watch(() => toValue(url), () => {
2396
+ if (autoInvoke) refetch();
2397
+ }, { immediate: true });
2398
+ onBeforeUnmount(() => {
2399
+ if (controller) controller.abort("");
2400
+ });
2401
+ return {
2402
+ data,
2403
+ loading,
2404
+ error,
2405
+ refetch,
2406
+ abort
2407
+ };
2408
+ }
2409
+ //#endregion
2410
+ //#region src/use-radial-move/use-radial-move.ts
2411
+ function clamp$2(value, min, max) {
2412
+ return Math.min(max, Math.max(min, value));
2413
+ }
2414
+ function radiansToDegrees(radians) {
2415
+ return radians * (180 / Math.PI);
2416
+ }
2417
+ function getElementCenter(element) {
2418
+ const rect = element.getBoundingClientRect();
2419
+ return [rect.left + rect.width / 2, rect.top + rect.height / 2];
2420
+ }
2421
+ function getAngle(coordinates, element) {
2422
+ const center = getElementCenter(element);
2423
+ const x = coordinates[0] - center[0];
2424
+ const y = coordinates[1] - center[1];
2425
+ return 360 - (radiansToDegrees(Math.atan2(x, y)) + 180);
2426
+ }
2427
+ function toFixed(value, digits) {
2428
+ return Number.parseFloat(value.toFixed(digits));
2429
+ }
2430
+ function getDigitsAfterDot(value) {
2431
+ return value.toString().split(".")[1]?.length || 0;
2432
+ }
2433
+ function normalizeRadialValue(degree, step) {
2434
+ const clamped = clamp$2(degree, 0, 360);
2435
+ const high = Math.ceil(clamped / step);
2436
+ const low = Math.round(clamped / step);
2437
+ return toFixed(high >= clamped / step ? high * step === 360 ? 0 : high * step : low * step, getDigitsAfterDot(step));
2438
+ }
2439
+ function useRadialMove(onChange, { step = .01, onChangeEnd, onScrubStart, onScrubEnd } = {}) {
2440
+ const active = ref(false);
2441
+ let nodeRef = null;
2442
+ let cleanupNode;
2443
+ const update = (event, done = false) => {
2444
+ if (!nodeRef) return;
2445
+ nodeRef.style.userSelect = "none";
2446
+ const nextValue = normalizeRadialValue(getAngle([event.clientX, event.clientY], nodeRef), step || 1);
2447
+ onChange(nextValue);
2448
+ if (done) onChangeEnd?.(nextValue);
2449
+ };
2450
+ const handleMouseMove = (event) => update(event);
2451
+ const handleMouseUp = (event) => {
2452
+ update(event, true);
2453
+ endTracking();
2454
+ };
2455
+ const handleTouchMove = (event) => {
2456
+ event.preventDefault();
2457
+ update(event.touches[0]);
2458
+ };
2459
+ const handleTouchEnd = (event) => {
2460
+ update(event.changedTouches[0], true);
2461
+ endTracking();
2462
+ };
2463
+ function beginTracking() {
2464
+ onScrubStart?.();
2465
+ active.value = true;
2466
+ document.addEventListener("mousemove", handleMouseMove, false);
2467
+ document.addEventListener("mouseup", handleMouseUp, false);
2468
+ document.addEventListener("touchmove", handleTouchMove, { passive: false });
2469
+ document.addEventListener("touchend", handleTouchEnd, false);
2470
+ }
2471
+ function endTracking() {
2472
+ onScrubEnd?.();
2473
+ active.value = false;
2474
+ document.removeEventListener("mousemove", handleMouseMove, false);
2475
+ document.removeEventListener("mouseup", handleMouseUp, false);
2476
+ document.removeEventListener("touchmove", handleTouchMove, false);
2477
+ document.removeEventListener("touchend", handleTouchEnd, false);
2478
+ }
2479
+ const handleMouseDown = (event) => {
2480
+ beginTracking();
2481
+ update(event);
2482
+ };
2483
+ const handleTouchStart = (event) => {
2484
+ event.preventDefault();
2485
+ beginTracking();
2486
+ update(event.touches[0]);
2487
+ };
2488
+ const setRef = (node) => {
2489
+ cleanupNode?.();
2490
+ nodeRef = node;
2491
+ if (!node) {
2492
+ cleanupNode = void 0;
2493
+ return;
2494
+ }
2495
+ node.addEventListener("mousedown", handleMouseDown);
2496
+ node.addEventListener("touchstart", handleTouchStart, { passive: false });
2497
+ cleanupNode = () => {
2498
+ node.removeEventListener("mousedown", handleMouseDown);
2499
+ node.removeEventListener("touchstart", handleTouchStart);
2500
+ };
2501
+ };
2502
+ onBeforeUnmount(() => {
2503
+ cleanupNode?.();
2504
+ endTracking();
2505
+ });
2506
+ return {
2507
+ ref: setRef,
2508
+ active
2509
+ };
2510
+ }
2511
+ //#endregion
2512
+ //#region src/use-scroll-spy/use-scroll-spy.ts
2513
+ var scrollSpyId = 0;
2514
+ function getActiveElement(rects, offset = 0) {
2515
+ if (rects.length === 0) return -1;
2516
+ return rects.reduce((closest, rect, index) => Math.abs(closest.position - offset) < Math.abs(rect.y - offset) ? closest : {
2517
+ index,
2518
+ position: rect.y
2519
+ }, {
2520
+ index: 0,
2521
+ position: rects[0].y
2522
+ }).index;
2523
+ }
2524
+ function useScrollSpy(options = {}) {
2525
+ const active = ref(-1);
2526
+ const initialized = ref(false);
2527
+ const data = ref([]);
2528
+ let host;
2529
+ const updateActive = () => {
2530
+ active.value = getActiveElement(data.value.map((item) => item.getNode()?.getBoundingClientRect()).filter(Boolean), toValue(options.offset) ?? 0);
2531
+ };
2532
+ const reinitialize = () => {
2533
+ if (typeof document === "undefined") return;
2534
+ const getDepth = options.getDepth ?? ((element) => Number(element.tagName[1]));
2535
+ const getValue = options.getValue ?? ((element) => element.textContent || "");
2536
+ data.value = Array.from(document.querySelectorAll(toValue(options.selector) ?? "h1, h2, h3, h4, h5, h6")).map((heading) => ({
2537
+ depth: getDepth(heading),
2538
+ value: getValue(heading),
2539
+ id: heading.id || `mantine-scroll-spy-${++scrollSpyId}`,
2540
+ getNode: () => heading.id ? document.getElementById(heading.id) ?? heading : heading
2541
+ }));
2542
+ initialized.value = true;
2543
+ updateActive();
2544
+ };
2545
+ const bind = () => {
2546
+ host?.removeEventListener("scroll", updateActive);
2547
+ host = toValue(options.scrollHost) ?? (typeof window !== "undefined" ? window : void 0);
2548
+ host?.addEventListener("scroll", updateActive, { passive: true });
2549
+ };
2550
+ onMounted(() => {
2551
+ reinitialize();
2552
+ bind();
2553
+ });
2554
+ onBeforeUnmount(() => host?.removeEventListener("scroll", updateActive));
2555
+ watch(() => [
2556
+ toValue(options.selector),
2557
+ toValue(options.offset),
2558
+ toValue(options.scrollHost)
2559
+ ], () => {
2560
+ reinitialize();
2561
+ bind();
2562
+ });
2563
+ return {
2564
+ active: readonly(active),
2565
+ initialized: readonly(initialized),
2566
+ data: readonly(data),
2567
+ reinitialize
2568
+ };
2569
+ }
2570
+ //#endregion
2571
+ //#region src/use-scroller/use-scroller.ts
2572
+ function useScroller({ scrollAmount = 200, draggable = true, onScrollStateChange } = {}) {
2573
+ let containerRef = null;
2574
+ let resizeObserver;
2575
+ let isDraggingRef = false;
2576
+ let hasDraggedRef = false;
2577
+ let startX = 0;
2578
+ let scrollLeftStart = 0;
2579
+ const canScrollStart = ref(false);
2580
+ const canScrollEnd = ref(false);
2581
+ const isDragging = ref(false);
2582
+ const updateScrollState = () => {
2583
+ const container = containerRef;
2584
+ if (!container) return;
2585
+ const { scrollLeft, scrollWidth, clientWidth } = container;
2586
+ const isRtl = getComputedStyle(container).direction === "rtl";
2587
+ const nextCanScrollStart = isRtl ? scrollLeft < -1 : scrollLeft > 1;
2588
+ const nextCanScrollEnd = isRtl ? scrollLeft > -(scrollWidth - clientWidth) + 1 : scrollLeft < scrollWidth - clientWidth - 1;
2589
+ canScrollStart.value = nextCanScrollStart;
2590
+ canScrollEnd.value = nextCanScrollEnd;
2591
+ onScrollStateChange?.({
2592
+ canScrollStart: nextCanScrollStart,
2593
+ canScrollEnd: nextCanScrollEnd
2594
+ });
2595
+ };
2596
+ const setRef = (node) => {
2597
+ const safeNode = node instanceof HTMLElement ? node : null;
2598
+ if (containerRef) {
2599
+ containerRef.removeEventListener("scroll", updateScrollState);
2600
+ resizeObserver?.disconnect();
2601
+ }
2602
+ containerRef = safeNode;
2603
+ if (safeNode) {
2604
+ safeNode.addEventListener("scroll", updateScrollState);
2605
+ if (typeof ResizeObserver !== "undefined") {
2606
+ resizeObserver = new ResizeObserver(updateScrollState);
2607
+ resizeObserver.observe(safeNode);
2608
+ }
2609
+ updateScrollState();
2610
+ }
2611
+ };
2612
+ const scroll = (direction) => {
2613
+ if (!containerRef) return;
2614
+ const isRtl = getComputedStyle(containerRef).direction === "rtl";
2615
+ const scrollBy = direction === "end" ? scrollAmount : -scrollAmount;
2616
+ const adjustedScrollBy = isRtl ? -scrollBy : scrollBy;
2617
+ containerRef.scrollBy({
2618
+ left: adjustedScrollBy,
2619
+ behavior: "smooth"
2620
+ });
2621
+ };
2622
+ const handleMouseDown = (event) => {
2623
+ if (!draggable || !containerRef) return;
2624
+ isDraggingRef = true;
2625
+ hasDraggedRef = false;
2626
+ isDragging.value = true;
2627
+ startX = event.pageX - containerRef.offsetLeft;
2628
+ scrollLeftStart = containerRef.scrollLeft;
2629
+ containerRef.style.cursor = "grabbing";
2630
+ containerRef.style.userSelect = "none";
2631
+ };
2632
+ const handleMouseMove = (event) => {
2633
+ if (!isDraggingRef || !containerRef) return;
2634
+ event.preventDefault();
2635
+ const walk = event.pageX - containerRef.offsetLeft - startX;
2636
+ if (Math.abs(walk) > 5) hasDraggedRef = true;
2637
+ containerRef.scrollLeft = scrollLeftStart - walk;
2638
+ };
2639
+ const handleMouseUp = () => {
2640
+ const wasDragged = hasDraggedRef;
2641
+ isDraggingRef = false;
2642
+ hasDraggedRef = false;
2643
+ isDragging.value = false;
2644
+ if (!containerRef) return;
2645
+ containerRef.style.cursor = "";
2646
+ containerRef.style.userSelect = "";
2647
+ if (wasDragged) {
2648
+ const suppressClick = (event) => {
2649
+ event.stopPropagation();
2650
+ event.preventDefault();
2651
+ containerRef?.removeEventListener("click", suppressClick, true);
2652
+ };
2653
+ containerRef.addEventListener("click", suppressClick, true);
2654
+ }
2655
+ };
2656
+ onBeforeUnmount(() => {
2657
+ if (containerRef) containerRef.removeEventListener("scroll", updateScrollState);
2658
+ resizeObserver?.disconnect();
2659
+ });
2660
+ return {
2661
+ ref: setRef,
2662
+ canScrollStart,
2663
+ canScrollEnd,
2664
+ scrollStart: () => scroll("start"),
2665
+ scrollEnd: () => scroll("end"),
2666
+ isDragging,
2667
+ dragHandlers: {
2668
+ onMousedown: handleMouseDown,
2669
+ onMousemove: handleMouseMove,
2670
+ onMouseup: handleMouseUp,
2671
+ onMouseleave: () => {
2672
+ if (isDraggingRef) handleMouseUp();
2673
+ }
2674
+ }
2675
+ };
2676
+ }
2677
+ //#endregion
2678
+ //#region src/use-file-dialog/use-file-dialog.ts
2679
+ var defaultOptions = {
2680
+ multiple: true,
2681
+ accept: "*"
2682
+ };
2683
+ function getInitialFilesList(files) {
2684
+ if (!files) return null;
2685
+ if (files instanceof FileList) return files;
2686
+ const result = new DataTransfer();
2687
+ for (const file of files) result.items.add(file);
2688
+ return result.files;
2689
+ }
2690
+ function createInput(options) {
2691
+ if (typeof document === "undefined") return null;
2692
+ const input = document.createElement("input");
2693
+ input.type = "file";
2694
+ if (options.accept) input.accept = options.accept;
2695
+ if (options.multiple) input.multiple = options.multiple;
2696
+ if (options.capture) input.capture = options.capture;
2697
+ if (options.directory) input.webkitdirectory = options.directory;
2698
+ input.style.display = "none";
2699
+ return input;
2700
+ }
2701
+ function useFileDialog(input = {}) {
2702
+ const options = {
2703
+ ...defaultOptions,
2704
+ ...input
2705
+ };
2706
+ const files = ref(getInitialFilesList(options.initialFiles));
2707
+ let inputElement = null;
2708
+ const handleChange = (event) => {
2709
+ const target = event.target;
2710
+ if (target?.files) {
2711
+ files.value = target.files;
2712
+ options.onChange?.(target.files);
2713
+ }
2714
+ };
2715
+ const createAndSetupInput = () => {
2716
+ inputElement?.remove();
2717
+ inputElement = createInput(options);
2718
+ if (inputElement) {
2719
+ inputElement.addEventListener("change", handleChange, { once: true });
2720
+ if (options.onCancel) inputElement.addEventListener("cancel", options.onCancel, { once: true });
2721
+ document.body.appendChild(inputElement);
2722
+ }
2723
+ };
2724
+ useIsomorphicEffect(() => {
2725
+ createAndSetupInput();
2726
+ });
2727
+ onBeforeUnmount(() => inputElement?.remove());
2728
+ const reset = () => {
2729
+ files.value = null;
2730
+ options.onChange?.(null);
2731
+ };
2732
+ const open = () => {
2733
+ if (options.resetOnOpen) reset();
2734
+ createAndSetupInput();
2735
+ inputElement?.click();
2736
+ };
2737
+ return {
2738
+ files,
2739
+ open,
2740
+ reset
2741
+ };
2742
+ }
2743
+ //#endregion
2744
+ //#region src/use-long-press/use-long-press.ts
2745
+ var getPosition = (event) => {
2746
+ if ("touches" in event) {
2747
+ const touch = event.touches[0] ?? event.changedTouches[0];
2748
+ return touch ? {
2749
+ x: touch.clientX,
2750
+ y: touch.clientY
2751
+ } : null;
2752
+ }
2753
+ return {
2754
+ x: event.clientX,
2755
+ y: event.clientY
2756
+ };
2757
+ };
2758
+ function useLongPress(onLongPress, options = {}) {
2759
+ const events = options.events ?? ["mouse", "touch"];
2760
+ const threshold = options.threshold ?? 400;
2761
+ const moveThreshold = options.cancelOnMove === true ? 10 : typeof options.cancelOnMove === "number" ? options.cancelOnMove : 0;
2762
+ let timeout;
2763
+ let active = false;
2764
+ let pressed = false;
2765
+ let startPosition = null;
2766
+ const clear = () => {
2767
+ clearTimeout(timeout);
2768
+ timeout = void 0;
2769
+ };
2770
+ const start = (event) => {
2771
+ options.onStart?.(event);
2772
+ startPosition = getPosition(event);
2773
+ pressed = true;
2774
+ clear();
2775
+ timeout = setTimeout(() => {
2776
+ onLongPress(event);
2777
+ active = true;
2778
+ }, threshold);
2779
+ };
2780
+ const cancel = (event) => {
2781
+ if (active) options.onFinish?.(event);
2782
+ else if (pressed) options.onCancel?.(event);
2783
+ active = false;
2784
+ pressed = false;
2785
+ startPosition = null;
2786
+ clear();
2787
+ };
2788
+ const move = (event) => {
2789
+ if (!options.cancelOnMove || !pressed || active || !startPosition) return;
2790
+ const current = getPosition(event);
2791
+ if (!current) return;
2792
+ if (Math.hypot(current.x - startPosition.x, current.y - startPosition.y) > moveThreshold) cancel(event);
2793
+ };
2794
+ onBeforeUnmount(clear);
2795
+ return {
2796
+ ...events.includes("mouse") ? {
2797
+ onMousedown: start,
2798
+ onMouseup: cancel,
2799
+ onMouseleave: cancel,
2800
+ ...options.cancelOnMove ? { onMousemove: move } : {}
2801
+ } : {},
2802
+ ...events.includes("touch") ? {
2803
+ onTouchstart: start,
2804
+ onTouchend: cancel,
2805
+ onTouchcancel: cancel,
2806
+ ...options.cancelOnMove ? { onTouchmove: move } : {}
2807
+ } : {}
2808
+ };
2809
+ }
2810
+ //#endregion
2811
+ //#region src/use-selection/use-selection.ts
2812
+ function useSelection(input) {
2813
+ const selectionSet = ref(new Set(input.defaultSelection || []));
2814
+ useDidUpdate(() => {
2815
+ if (toValue(input.resetSelectionOnDataChange)) selectionSet.value = /* @__PURE__ */ new Set();
2816
+ }, [input.data, input.resetSelectionOnDataChange]);
2817
+ const select = (selected) => {
2818
+ if (!selectionSet.value.has(selected)) {
2819
+ const newSet = new Set(selectionSet.value);
2820
+ newSet.add(selected);
2821
+ selectionSet.value = newSet;
2822
+ }
2823
+ };
2824
+ const deselect = (deselected) => {
2825
+ if (selectionSet.value.has(deselected)) {
2826
+ const newSet = new Set(selectionSet.value);
2827
+ newSet.delete(deselected);
2828
+ selectionSet.value = newSet;
2829
+ }
2830
+ };
2831
+ const toggle = (toggled) => {
2832
+ const newSet = new Set(selectionSet.value);
2833
+ if (newSet.has(toggled)) newSet.delete(toggled);
2834
+ else newSet.add(toggled);
2835
+ selectionSet.value = newSet;
2836
+ };
2837
+ const resetSelection = () => {
2838
+ selectionSet.value = /* @__PURE__ */ new Set();
2839
+ };
2840
+ const setSelection = (selection) => {
2841
+ selectionSet.value = new Set(selection);
2842
+ };
2843
+ const isAllSelected = () => {
2844
+ const data = toValue(input.data);
2845
+ if (data.length === 0) return false;
2846
+ return data.every((item) => selectionSet.value.has(item));
2847
+ };
2848
+ const isSomeSelected = () => {
2849
+ return toValue(input.data).some((item) => selectionSet.value.has(item));
2850
+ };
2851
+ return [computed(() => Array.from(selectionSet.value)), {
2852
+ select,
2853
+ deselect,
2854
+ toggle,
2855
+ isAllSelected,
2856
+ isSomeSelected,
2857
+ setSelection,
2858
+ resetSelection
2859
+ }];
2860
+ }
2861
+ //#endregion
2862
+ //#region src/use-floating-window/use-floating-window.ts
2863
+ function px(value) {
2864
+ return value.endsWith("px") ? parseFloat(value) : 0;
2865
+ }
2866
+ function clampToViewport(x, y, element, offset = 0) {
2867
+ const rect = element.getBoundingClientRect();
2868
+ return {
2869
+ x: Math.min(Math.max(offset, x), Math.max(offset, window.innerWidth - rect.width - offset)),
2870
+ y: Math.min(Math.max(offset, y), Math.max(offset, window.innerHeight - rect.height - offset))
2871
+ };
2872
+ }
2873
+ function constrain(element, position, options) {
2874
+ return options.constrainToViewport ? clampToViewport(position.x, position.y, element, options.constrainOffset) : position;
2875
+ }
2876
+ function calculateInitialPosition(element, options) {
2877
+ const rect = element.getBoundingClientRect();
2878
+ const style = getComputedStyle(element);
2879
+ const offset = options.constrainOffset ?? 0;
2880
+ const initial = options.initialPosition ?? {};
2881
+ return constrain(element, {
2882
+ x: initial.left ?? (initial.right !== void 0 ? window.innerWidth - rect.width - initial.right : px(style.left) || window.innerWidth - rect.width - px(style.right) || offset),
2883
+ y: initial.top ?? (initial.bottom !== void 0 ? window.innerHeight - rect.height - initial.bottom : px(style.top) || window.innerHeight - rect.height - px(style.bottom) || offset)
2884
+ }, options);
2885
+ }
2886
+ function excluded(target, selector) {
2887
+ return Boolean(selector && target instanceof Element && target.closest(selector));
2888
+ }
2889
+ function isHandle(element, target, options) {
2890
+ if (!(target instanceof Node) || excluded(target, options.excludeDragHandleSelector)) return false;
2891
+ if (!options.dragHandleSelector) return true;
2892
+ return Array.from(element.querySelectorAll(options.dragHandleSelector)).some((item) => item.contains(target));
2893
+ }
2894
+ function useFloatingWindow(options = {}) {
2895
+ const element = ref(null);
2896
+ const isDragging = ref(false);
2897
+ let position = {
2898
+ x: 0,
2899
+ y: 0
2900
+ };
2901
+ let pointerOffset = {
2902
+ x: 0,
2903
+ y: 0
2904
+ };
2905
+ let observer;
2906
+ const applyPosition = (next, notify = true) => {
2907
+ if (!element.value) return;
2908
+ position = constrain(element.value, next, options);
2909
+ element.value.style.left = `${position.x}px`;
2910
+ element.value.style.top = `${position.y}px`;
2911
+ element.value.style.right = "unset";
2912
+ element.value.style.bottom = "unset";
2913
+ if (notify) options.onPositionChange?.(position);
2914
+ };
2915
+ const setPosition = (next) => {
2916
+ const node = element.value;
2917
+ if (!node) return;
2918
+ const rect = node.getBoundingClientRect();
2919
+ applyPosition({
2920
+ x: next.left ?? (next.right !== void 0 ? window.innerWidth - rect.width - next.right : position.x),
2921
+ y: next.top ?? (next.bottom !== void 0 ? window.innerHeight - rect.height - next.bottom : position.y)
2922
+ });
2923
+ };
2924
+ const end = () => {
2925
+ if (!isDragging.value) return;
2926
+ isDragging.value = false;
2927
+ document.body.style.userSelect = "";
2928
+ document.body.style.webkitUserSelect = "";
2929
+ options.onDragEnd?.();
2930
+ document.removeEventListener("mousemove", move);
2931
+ document.removeEventListener("mouseup", end);
2932
+ document.removeEventListener("touchmove", move);
2933
+ document.removeEventListener("touchend", end);
2934
+ };
2935
+ const move = (event) => {
2936
+ if (!isDragging.value || !element.value) return;
2937
+ const point = "touches" in event ? event.touches[0] : event;
2938
+ event.preventDefault();
2939
+ const next = constrain(element.value, {
2940
+ x: point.clientX - pointerOffset.x,
2941
+ y: point.clientY - pointerOffset.y
2942
+ }, options);
2943
+ applyPosition({
2944
+ x: options.axis === "y" ? position.x : next.x,
2945
+ y: options.axis === "x" ? position.y : next.y
2946
+ });
2947
+ };
2948
+ const start = (event) => {
2949
+ const node = element.value;
2950
+ if (!node || options.enabled === false || !isHandle(node, event.target, options)) return;
2951
+ if ("button" in event && event.button !== 0) return;
2952
+ const point = "touches" in event ? event.touches[0] : event;
2953
+ const rect = node.getBoundingClientRect();
2954
+ pointerOffset = {
2955
+ x: point.clientX - rect.left,
2956
+ y: point.clientY - rect.top
2957
+ };
2958
+ isDragging.value = true;
2959
+ document.body.style.userSelect = "none";
2960
+ document.body.style.webkitUserSelect = "none";
2961
+ options.onDragStart?.();
2962
+ document.addEventListener("mousemove", move);
2963
+ document.addEventListener("mouseup", end);
2964
+ document.addEventListener("touchmove", move, { passive: false });
2965
+ document.addEventListener("touchend", end);
2966
+ };
2967
+ const setRef = (node) => {
2968
+ const safeNode = node instanceof Element ? node : null;
2969
+ if (safeNode === element.value) return;
2970
+ if (element.value) {
2971
+ element.value.removeEventListener("mousedown", start);
2972
+ element.value.removeEventListener("touchstart", start);
2973
+ }
2974
+ observer?.disconnect();
2975
+ observer = void 0;
2976
+ element.value = safeNode;
2977
+ if (safeNode) {
2978
+ safeNode.addEventListener("mousedown", start);
2979
+ safeNode.addEventListener("touchstart", start, { passive: false });
2980
+ position = calculateInitialPosition(safeNode, options);
2981
+ applyPosition(position, false);
2982
+ if (typeof ResizeObserver !== "undefined") {
2983
+ observer = new ResizeObserver(() => applyPosition(position, false));
2984
+ observer.observe(safeNode);
2985
+ }
2986
+ }
2987
+ };
2988
+ onMounted(() => element.value && applyPosition(calculateInitialPosition(element.value, options), false));
2989
+ onBeforeUnmount(() => {
2990
+ end();
2991
+ observer?.disconnect();
2992
+ element.value?.removeEventListener("mousedown", start);
2993
+ element.value?.removeEventListener("touchstart", start);
2994
+ });
2995
+ return {
2996
+ ref: setRef,
2997
+ element: readonly(element),
2998
+ isDragging: readonly(isDragging),
2999
+ setPosition
3000
+ };
3001
+ }
3002
+ //#endregion
3003
+ //#region src/use-collapse/use-collapse.ts
3004
+ function getAutoSizeDuration(size) {
3005
+ if (!size || typeof size === "string") return 0;
3006
+ const constant = size / 36;
3007
+ return Math.round((4 + 15 * constant ** .25 + constant / 5) * 10);
3008
+ }
3009
+ function getElementContentSize(element, dimension) {
3010
+ if (!element) return "auto";
3011
+ const size = dimension === "height" ? element.scrollHeight : element.scrollWidth;
3012
+ if (size !== 0) return size;
3013
+ const children = Array.from(element.children).filter((child) => child instanceof HTMLElement);
3014
+ if (children.length === 0) return size;
3015
+ const childrenScrollSize = children.reduce((acc, child) => acc + (dimension === "height" ? child.scrollHeight : child.scrollWidth), 0);
3016
+ if (childrenScrollSize !== 0) return childrenScrollSize;
3017
+ const rect = element.getBoundingClientRect();
3018
+ const start = dimension === "height" ? rect.top : rect.left;
3019
+ const endProperty = dimension === "height" ? "bottom" : "right";
3020
+ const marginProperty = dimension === "height" ? "marginBottom" : "marginRight";
3021
+ const view = element.ownerDocument.defaultView;
3022
+ return Math.max(...children.map((child) => {
3023
+ const childRect = child.getBoundingClientRect();
3024
+ const childStyles = view?.getComputedStyle(child);
3025
+ const margin = childStyles ? Number.parseFloat(childStyles[marginProperty]) || 0 : 0;
3026
+ return childRect[endProperty] - start + margin;
3027
+ }), 0);
3028
+ }
3029
+ function getCssSize(size) {
3030
+ return typeof size === "number" ? `${size}px` : size;
3031
+ }
3032
+ function createCollapse({ dimension, getElementSize, expanded, transitionDuration, transitionTimingFunction = "ease", onTransitionEnd, onTransitionStart, keepMounted }) {
3033
+ const isExpanded = () => toValue(expanded);
3034
+ const collapsedStyles = {
3035
+ [dimension]: 0,
3036
+ overflow: "hidden",
3037
+ ...keepMounted ? {} : { display: "none" }
3038
+ };
3039
+ const elementRef = ref(null);
3040
+ const styles = ref(isExpanded() ? {} : collapsedStyles);
3041
+ const state = ref(isExpanded() ? "entered" : "exited");
3042
+ const raf = typeof window === "undefined" ? (callback) => callback(0) : window.requestAnimationFrame;
3043
+ const mergeStyles = (nextStyles) => {
3044
+ styles.value = {
3045
+ ...styles.value,
3046
+ ...nextStyles
3047
+ };
3048
+ };
3049
+ const measureExpandedSize = (attempt = 0) => {
3050
+ if (!isExpanded()) return;
3051
+ const size = getElementSize(elementRef.value);
3052
+ if (size === 0 && elementRef.value?.children.length && attempt < 5) {
3053
+ raf(() => measureExpandedSize(attempt + 1));
3054
+ return;
3055
+ }
3056
+ mergeStyles({
3057
+ ...getTransitionStyles(size),
3058
+ [dimension]: getCssSize(size)
3059
+ });
3060
+ };
3061
+ const getTransitionStyles = (size) => {
3062
+ const duration = transitionDuration ?? getAutoSizeDuration(size);
3063
+ return { transition: `${dimension} ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}` };
3064
+ };
3065
+ watch(() => isExpanded(), (value, oldValue) => {
3066
+ if (value === oldValue) return;
3067
+ if (transitionDuration !== 0) onTransitionStart?.();
3068
+ if (value) raf(() => {
3069
+ state.value = "entering";
3070
+ mergeStyles({
3071
+ willChange: dimension,
3072
+ display: "block",
3073
+ overflow: "hidden"
3074
+ });
3075
+ nextTick(() => {
3076
+ raf(() => {
3077
+ raf(() => measureExpandedSize());
3078
+ });
3079
+ });
3080
+ });
3081
+ else raf(() => {
3082
+ state.value = "exiting";
3083
+ const size = getElementSize(elementRef.value);
3084
+ mergeStyles({
3085
+ ...getTransitionStyles(size),
3086
+ willChange: dimension,
3087
+ [dimension]: getCssSize(size)
3088
+ });
3089
+ raf(() => mergeStyles({
3090
+ [dimension]: 0,
3091
+ overflow: "hidden"
3092
+ }));
3093
+ });
3094
+ }, { flush: "post" });
3095
+ const handleTransitionEnd = (event) => {
3096
+ if (event.target !== elementRef.value || event.propertyName !== dimension) return;
3097
+ if (isExpanded()) {
3098
+ const size = getElementSize(elementRef.value);
3099
+ if (getCssSize(size) === styles.value[dimension]) styles.value = {};
3100
+ else mergeStyles({ [dimension]: getCssSize(size) });
3101
+ state.value = "entered";
3102
+ onTransitionEnd?.();
3103
+ } else if (styles.value[dimension] === 0) {
3104
+ styles.value = collapsedStyles;
3105
+ state.value = "exited";
3106
+ onTransitionEnd?.();
3107
+ }
3108
+ };
3109
+ return {
3110
+ state,
3111
+ getCollapseProps: (input = {}) => {
3112
+ const setRef = (value) => {
3113
+ const element = value?.$el ?? value;
3114
+ elementRef.value = element;
3115
+ assignRef(input.ref, element);
3116
+ };
3117
+ return {
3118
+ "aria-hidden": !isExpanded(),
3119
+ inert: !isExpanded(),
3120
+ ref: setRef,
3121
+ onTransitionend: handleTransitionEnd,
3122
+ style: {
3123
+ boxSizing: "border-box",
3124
+ ...input.style,
3125
+ ...styles.value
3126
+ }
3127
+ };
3128
+ }
3129
+ };
3130
+ }
3131
+ function useCollapse(input) {
3132
+ return createCollapse({
3133
+ ...input,
3134
+ dimension: "height",
3135
+ getElementSize: (element) => getElementContentSize(element, "height")
3136
+ });
3137
+ }
3138
+ //#endregion
3139
+ //#region src/use-collapse/use-horizontal-collapse.ts
3140
+ function useHorizontalCollapse(input) {
3141
+ return createCollapse({
3142
+ ...input,
3143
+ dimension: "width",
3144
+ getElementSize: (element) => getElementContentSize(element, "width")
3145
+ });
3146
+ }
3147
+ //#endregion
3148
+ //#region src/use-mask/use-mask.ts
3149
+ var DEFAULT_TOKENS = {
3150
+ "9": /[0-9]/,
3151
+ a: /[A-Za-z]/,
3152
+ A: /[A-Z]/,
3153
+ "*": /[A-Za-z0-9]/,
3154
+ "#": /[-+0-9]/
3155
+ };
3156
+ var MAX_UNDO_HISTORY = 100;
3157
+ function parseMask(mask, tokens) {
3158
+ if (Array.isArray(mask)) return mask.map((item) => {
3159
+ if (item instanceof RegExp) return {
3160
+ type: "token",
3161
+ char: "_",
3162
+ pattern: item
3163
+ };
3164
+ return {
3165
+ type: "literal",
3166
+ char: item
3167
+ };
3168
+ });
3169
+ const slots = [];
3170
+ let optional = false;
3171
+ for (let i = 0; i < mask.length; i++) {
3172
+ const char = mask[i];
3173
+ if (char === "\\" && i + 1 < mask.length) {
3174
+ i++;
3175
+ slots.push({
3176
+ type: "literal",
3177
+ char: mask[i]
3178
+ });
3179
+ continue;
3180
+ }
3181
+ if (char === "?") {
3182
+ optional = true;
3183
+ continue;
3184
+ }
3185
+ if (tokens[char]) slots.push({
3186
+ type: "token",
3187
+ char,
3188
+ pattern: tokens[char],
3189
+ optional
3190
+ });
3191
+ else slots.push({
3192
+ type: "literal",
3193
+ char,
3194
+ optional
3195
+ });
3196
+ }
3197
+ return slots;
3198
+ }
3199
+ function getSlotChar(slotCharOption, index) {
3200
+ if (slotCharOption === null || slotCharOption === "" || slotCharOption === void 0) return "";
3201
+ if (slotCharOption.length > 1) return slotCharOption[index] || "_";
3202
+ return slotCharOption;
3203
+ }
3204
+ function applyMaskToRaw(raw, slots, _slotCharOption, transform) {
3205
+ let result = "";
3206
+ let rawIndex = 0;
3207
+ let slotIndex = 0;
3208
+ for (slotIndex = 0; slotIndex < slots.length; slotIndex++) {
3209
+ const slot = slots[slotIndex];
3210
+ if (slot.type === "literal") result += slot.char;
3211
+ else if (rawIndex < raw.length) {
3212
+ const ch = transform ? transform(raw[rawIndex]) : raw[rawIndex];
3213
+ if (slot.pattern && slot.pattern.test(ch)) {
3214
+ result += ch;
3215
+ rawIndex++;
3216
+ } else {
3217
+ rawIndex++;
3218
+ slotIndex--;
3219
+ }
3220
+ } else break;
3221
+ }
3222
+ return result;
3223
+ }
3224
+ function buildDisplayValue(value, slots, slotCharOption, showSlots) {
3225
+ if (!showSlots) return value;
3226
+ let display = value;
3227
+ for (let i = value.length; i < slots.length; i++) {
3228
+ const slot = slots[i];
3229
+ if (slot.type === "literal") display += slot.char;
3230
+ else {
3231
+ const sc = getSlotChar(slotCharOption, i);
3232
+ if (!sc) break;
3233
+ display += sc;
3234
+ }
3235
+ }
3236
+ return display;
3237
+ }
3238
+ function extractRaw(masked, slots) {
3239
+ let raw = "";
3240
+ for (let i = 0; i < masked.length && i < slots.length; i++) if (slots[i].type === "token") raw += masked[i];
3241
+ return raw;
3242
+ }
3243
+ function checkComplete(masked, slots) {
3244
+ for (let i = 0; i < slots.length; i++) if (slots[i].type === "token" && !slots[i].optional) {
3245
+ if (i >= masked.length) return false;
3246
+ if (!slots[i].pattern.test(masked[i])) return false;
3247
+ }
3248
+ return true;
3249
+ }
3250
+ function findNextTokenIndex(slots, from) {
3251
+ for (let i = from; i < slots.length; i++) if (slots[i].type === "token") return i;
3252
+ return slots.length;
3253
+ }
3254
+ function findPrevTokenIndex(slots, from) {
3255
+ for (let i = from; i >= 0; i--) if (slots[i].type === "token") return i;
3256
+ return -1;
3257
+ }
3258
+ function processInput(inputValue, slots, _slotCharOption) {
3259
+ let result = "";
3260
+ let inputIndex = 0;
3261
+ for (let slotIndex = 0; slotIndex < slots.length && inputIndex <= inputValue.length; slotIndex++) {
3262
+ const slot = slots[slotIndex];
3263
+ if (slot.type === "literal") {
3264
+ result += slot.char;
3265
+ if (inputIndex < inputValue.length && inputValue[inputIndex] === slot.char) inputIndex++;
3266
+ continue;
3267
+ }
3268
+ if (inputIndex >= inputValue.length) break;
3269
+ while (inputIndex < inputValue.length) {
3270
+ const ch = inputValue[inputIndex];
3271
+ inputIndex++;
3272
+ if (slot.pattern.test(ch)) {
3273
+ result += ch;
3274
+ break;
3275
+ }
3276
+ }
3277
+ if (result.length <= slotIndex) break;
3278
+ }
3279
+ return result;
3280
+ }
3281
+ function getResolvedOptions(options, rawValue) {
3282
+ const tokens = {
3283
+ ...DEFAULT_TOKENS,
3284
+ ...options.tokens
3285
+ };
3286
+ let mask = options.mask;
3287
+ let slotChar = options.slotChar === void 0 ? "_" : options.slotChar;
3288
+ let separate = options.separate ?? false;
3289
+ if (options.modify) {
3290
+ const overrides = options.modify(rawValue);
3291
+ if (overrides) {
3292
+ if (overrides.mask !== void 0) mask = overrides.mask;
3293
+ if (overrides.tokens !== void 0) Object.assign(tokens, overrides.tokens);
3294
+ if (overrides.slotChar !== void 0) slotChar = overrides.slotChar;
3295
+ if (overrides.separate !== void 0) separate = overrides.separate;
3296
+ }
3297
+ }
3298
+ return {
3299
+ slots: parseMask(mask, tokens),
3300
+ slotChar,
3301
+ separate,
3302
+ tokens,
3303
+ transform: options.transform
3304
+ };
3305
+ }
3306
+ function formatMask(raw, options) {
3307
+ const { slots, slotChar, transform } = getResolvedOptions(options, raw);
3308
+ return applyMaskToRaw(raw, slots, slotChar, transform);
3309
+ }
3310
+ function unformatMask(masked, options) {
3311
+ const { slots } = getResolvedOptions(options, "");
3312
+ return extractRaw(masked, slots);
3313
+ }
3314
+ function isMaskComplete(masked, options) {
3315
+ const { slots } = getResolvedOptions(options, "");
3316
+ return checkComplete(masked, slots);
3317
+ }
3318
+ function generatePattern(mode, options) {
3319
+ const { slots } = getResolvedOptions(options, "");
3320
+ let pattern = "";
3321
+ for (const slot of slots) if (slot.type === "literal") pattern += slot.char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3322
+ else {
3323
+ const src = slot.pattern.source;
3324
+ if (mode === "full-inexact") pattern += slot.optional ? `${src}?` : src;
3325
+ else pattern += slot.optional ? `(${src})?` : `(${src})`;
3326
+ }
3327
+ return pattern;
3328
+ }
3329
+ function findNextEditablePosition(from, slots, value) {
3330
+ let pos = from;
3331
+ while (pos < slots.length && pos < value.length && slots[pos] && slots[pos].type === "literal") pos++;
3332
+ return pos;
3333
+ }
3334
+ function useMask(options) {
3335
+ let node = null;
3336
+ const maskedValue = ref("");
3337
+ const rawValue = ref("");
3338
+ const isComplete = ref(false);
3339
+ let processed = "";
3340
+ let display = "";
3341
+ let rawInternal = "";
3342
+ let wasComplete = false;
3343
+ let isFocused = false;
3344
+ let undoStack = [];
3345
+ let redoStack = [];
3346
+ const applyValue = (input) => {
3347
+ const { reprocessed, newRaw, displayValue, resolvedSlots, cursorPos, notifyChange } = input;
3348
+ processed = reprocessed;
3349
+ display = displayValue;
3350
+ rawInternal = newRaw;
3351
+ maskedValue.value = displayValue;
3352
+ rawValue.value = newRaw;
3353
+ if (node) {
3354
+ node.value = displayValue;
3355
+ if (cursorPos !== void 0 && document.activeElement === node) {
3356
+ const pos = Math.min(cursorPos, reprocessed.length);
3357
+ node.setSelectionRange(pos, pos);
3358
+ }
3359
+ }
3360
+ if (notifyChange && options.onChangeRaw) options.onChangeRaw(newRaw, displayValue);
3361
+ const complete = checkComplete(reprocessed, resolvedSlots);
3362
+ if (notifyChange && complete && !wasComplete && options.onComplete) options.onComplete(displayValue, newRaw);
3363
+ wasComplete = complete;
3364
+ isComplete.value = complete;
3365
+ };
3366
+ const updateValue = (newMasked, cursorPos) => {
3367
+ const { slots } = getResolvedOptions(options, extractRaw(newMasked, getResolvedOptions(options, "").slots));
3368
+ const { slots: resolvedSlots, slotChar } = getResolvedOptions(options, extractRaw(newMasked, slots));
3369
+ const reprocessed = processInput(newMasked, resolvedSlots, slotChar);
3370
+ const newRaw = extractRaw(reprocessed, resolvedSlots);
3371
+ const showSlots = options.alwaysShowMask || isFocused;
3372
+ const showOnFocus = options.showMaskOnFocus !== false;
3373
+ const displayValue = buildDisplayValue(reprocessed, resolvedSlots, slotChar, showSlots && (showOnFocus || reprocessed.length > 0));
3374
+ applyValue({
3375
+ reprocessed,
3376
+ newRaw,
3377
+ displayValue,
3378
+ resolvedSlots,
3379
+ cursorPos,
3380
+ notifyChange: true
3381
+ });
3382
+ return {
3383
+ displayValue,
3384
+ newRaw,
3385
+ reprocessed,
3386
+ resolvedSlots
3387
+ };
3388
+ };
3389
+ const initializeInputValue = (inputNode) => {
3390
+ if (!inputNode.value) return false;
3391
+ const { slots: initialSlots, slotChar: initialSlotChar } = getResolvedOptions(options, "");
3392
+ const { slots: resolvedSlots, slotChar } = getResolvedOptions(options, extractRaw(processInput(inputNode.value, initialSlots, initialSlotChar), initialSlots));
3393
+ const reprocessed = processInput(inputNode.value, resolvedSlots, slotChar);
3394
+ const newRaw = extractRaw(reprocessed, resolvedSlots);
3395
+ const showSlots = options.alwaysShowMask || isFocused;
3396
+ const showOnFocus = options.showMaskOnFocus !== false;
3397
+ applyValue({
3398
+ reprocessed,
3399
+ newRaw,
3400
+ displayValue: buildDisplayValue(reprocessed, resolvedSlots, slotChar, showSlots && (showOnFocus || reprocessed.length > 0)),
3401
+ resolvedSlots,
3402
+ notifyChange: false
3403
+ });
3404
+ return true;
3405
+ };
3406
+ const pushUndoState = () => {
3407
+ const selectionStart = node?.selectionStart ?? rawInternal.length;
3408
+ const state = {
3409
+ rawValue: rawInternal,
3410
+ selectionStart
3411
+ };
3412
+ const top = undoStack[undoStack.length - 1];
3413
+ if (top && top.rawValue === state.rawValue && top.selectionStart === state.selectionStart) return;
3414
+ undoStack.push(state);
3415
+ if (undoStack.length > MAX_UNDO_HISTORY) undoStack.shift();
3416
+ redoStack = [];
3417
+ };
3418
+ const applyHistoryState = (target) => {
3419
+ const { slots, slotChar, transform } = getResolvedOptions(options, target.rawValue);
3420
+ updateValue(applyMaskToRaw(target.rawValue, slots, slotChar, transform), target.selectionStart);
3421
+ };
3422
+ const handleInput = (e) => {
3423
+ const input = e.target;
3424
+ const { slots: resolvedSlots, slotChar, transform } = getResolvedOptions(options, "");
3425
+ const prev = display;
3426
+ const curr = input.value;
3427
+ let prefixLen = 0;
3428
+ const maxPrefix = Math.min(prev.length, curr.length);
3429
+ while (prefixLen < maxPrefix && prev[prefixLen] === curr[prefixLen]) prefixLen++;
3430
+ let suffixLen = 0;
3431
+ const maxSuffix = Math.min(prev.length - prefixLen, curr.length - prefixLen);
3432
+ while (suffixLen < maxSuffix && prev[prev.length - 1 - suffixLen] === curr[curr.length - 1 - suffixLen]) suffixLen++;
3433
+ const insertedText = curr.slice(prefixLen, curr.length - suffixLen);
3434
+ const removedEnd = prev.length - suffixLen;
3435
+ const beforeRaw = extractRaw(prev.slice(0, prefixLen), resolvedSlots.slice(0, prefixLen));
3436
+ const afterRaw = extractRaw(prev.slice(removedEnd), resolvedSlots.slice(removedEnd));
3437
+ const reformatted = applyMaskToRaw(beforeRaw + insertedText + afterRaw, resolvedSlots, slotChar, transform);
3438
+ const maskedPrefix = applyMaskToRaw(beforeRaw + insertedText, resolvedSlots, slotChar, transform);
3439
+ if (reformatted !== prev) pushUndoState();
3440
+ updateValue(reformatted, maskedPrefix.length);
3441
+ };
3442
+ const clampCursorToProcessed = (input) => {
3443
+ const start = input.selectionStart ?? 0;
3444
+ if (start !== (input.selectionEnd ?? 0)) return;
3445
+ const { slots } = getResolvedOptions(options, "");
3446
+ const endPos = processed.length > 0 ? findNextEditablePosition(processed.length, slots, processed) : findNextTokenIndex(slots, 0);
3447
+ const startPos = findNextTokenIndex(slots, 0);
3448
+ if (start > endPos || start < startPos) input.setSelectionRange(endPos, endPos);
3449
+ };
3450
+ const handleFocus = () => {
3451
+ isFocused = true;
3452
+ const input = node;
3453
+ if (!input) return;
3454
+ const { slots, slotChar } = getResolvedOptions(options, "");
3455
+ if (options.showMaskOnFocus !== false || options.alwaysShowMask) {
3456
+ const nextDisplay = buildDisplayValue(processed, slots, slotChar, true);
3457
+ input.value = nextDisplay;
3458
+ display = nextDisplay;
3459
+ maskedValue.value = nextDisplay;
3460
+ }
3461
+ requestAnimationFrame(() => {
3462
+ if (input === document.activeElement) clampCursorToProcessed(input);
3463
+ });
3464
+ };
3465
+ const handleMouseUp = () => {
3466
+ const input = node;
3467
+ if (!input || input !== document.activeElement) return;
3468
+ clampCursorToProcessed(input);
3469
+ };
3470
+ const handleMouseDown = () => {
3471
+ const input = node;
3472
+ if (!input) return;
3473
+ requestAnimationFrame(() => {
3474
+ if (input !== document.activeElement) return;
3475
+ const start = input.selectionStart ?? 0;
3476
+ if (start !== (input.selectionEnd ?? 0)) return;
3477
+ const { slots } = getResolvedOptions(options, "");
3478
+ const endPos = processed.length > 0 ? findNextEditablePosition(processed.length, slots, processed) : findNextTokenIndex(slots, 0);
3479
+ if (start > endPos) input.setSelectionRange(endPos, endPos);
3480
+ });
3481
+ };
3482
+ const handleBlur = () => {
3483
+ isFocused = false;
3484
+ const input = node;
3485
+ if (!input) return;
3486
+ const { slots, slotChar } = getResolvedOptions(options, rawInternal);
3487
+ const expectedFocusDisplay = buildDisplayValue(processed, slots, slotChar, true);
3488
+ const nextProcessed = input.value === expectedFocusDisplay ? processed : processInput(input.value, slots, slotChar);
3489
+ const complete = checkComplete(nextProcessed, slots);
3490
+ if (options.autoClear && !complete && nextProcessed.length > 0) {
3491
+ input.value = "";
3492
+ processed = "";
3493
+ display = "";
3494
+ rawInternal = "";
3495
+ maskedValue.value = "";
3496
+ rawValue.value = "";
3497
+ wasComplete = false;
3498
+ isComplete.value = false;
3499
+ if (options.onChangeRaw) options.onChangeRaw("", "");
3500
+ if (options.alwaysShowMask) {
3501
+ const emptyDisplay = buildDisplayValue("", slots, slotChar, true);
3502
+ input.value = emptyDisplay;
3503
+ display = emptyDisplay;
3504
+ maskedValue.value = emptyDisplay;
3505
+ }
3506
+ return;
3507
+ }
3508
+ if (!options.alwaysShowMask && !complete) {
3509
+ if (extractRaw(nextProcessed, slots).length === 0) {
3510
+ input.value = "";
3511
+ processed = "";
3512
+ display = "";
3513
+ rawInternal = "";
3514
+ maskedValue.value = "";
3515
+ rawValue.value = "";
3516
+ wasComplete = false;
3517
+ isComplete.value = false;
3518
+ if (options.onChangeRaw) options.onChangeRaw("", "");
3519
+ return;
3520
+ }
3521
+ const nextDisplay = buildDisplayValue(nextProcessed, slots, slotChar, false);
3522
+ input.value = nextDisplay;
3523
+ display = nextDisplay;
3524
+ maskedValue.value = nextDisplay;
3525
+ }
3526
+ };
3527
+ const handleKeyDown = (e) => {
3528
+ const input = e.target;
3529
+ const { slots, slotChar, transform } = getResolvedOptions(options, rawInternal);
3530
+ const start = input.selectionStart ?? 0;
3531
+ const end = input.selectionEnd ?? 0;
3532
+ const modifier = e.metaKey || e.ctrlKey && !e.altKey;
3533
+ const key = e.key.toLowerCase();
3534
+ if (modifier && key === "z" && !e.shiftKey) {
3535
+ e.preventDefault();
3536
+ const prev = undoStack.pop();
3537
+ if (!prev) return;
3538
+ redoStack.push({
3539
+ rawValue: rawInternal,
3540
+ selectionStart: input.selectionStart ?? 0
3541
+ });
3542
+ applyHistoryState(prev);
3543
+ return;
3544
+ }
3545
+ if (modifier && (key === "z" && e.shiftKey || key === "y" && !e.shiftKey)) {
3546
+ e.preventDefault();
3547
+ const next = redoStack.pop();
3548
+ if (!next) return;
3549
+ undoStack.push({
3550
+ rawValue: rawInternal,
3551
+ selectionStart: input.selectionStart ?? 0
3552
+ });
3553
+ applyHistoryState(next);
3554
+ return;
3555
+ }
3556
+ if (e.key === "Backspace") {
3557
+ e.preventDefault();
3558
+ if (e.metaKey || e.ctrlKey && !e.altKey) {
3559
+ const clampedStart = Math.min(start, processed.length);
3560
+ const newValue = applyMaskToRaw(extractRaw(processed.slice(clampedStart), slots.slice(clampedStart)), slots, slotChar, transform);
3561
+ pushUndoState();
3562
+ updateValue(newValue, 0);
3563
+ return;
3564
+ }
3565
+ if (start !== end) {
3566
+ const clampedEnd = Math.min(end, processed.length);
3567
+ const before = processed.slice(0, start);
3568
+ const afterRaw = extractRaw(processed.slice(clampedEnd), slots.slice(clampedEnd));
3569
+ const newValue = applyMaskToRaw(extractRaw(before, slots) + afterRaw, slots, slotChar, transform);
3570
+ pushUndoState();
3571
+ updateValue(newValue, start);
3572
+ return;
3573
+ }
3574
+ if (start === 0) return;
3575
+ let deletePos = start - 1;
3576
+ while (deletePos >= 0 && slots[deletePos] && slots[deletePos].type === "literal") deletePos--;
3577
+ if (deletePos < 0) return;
3578
+ const newValue = applyMaskToRaw(extractRaw(processed.slice(0, deletePos), slots.slice(0, deletePos)) + extractRaw(processed.slice(deletePos + 1), slots.slice(deletePos + 1)), slots, slotChar, transform);
3579
+ pushUndoState();
3580
+ updateValue(newValue, deletePos);
3581
+ } else if (e.key === "Delete") {
3582
+ e.preventDefault();
3583
+ if (start !== end) {
3584
+ const clampedEnd = Math.min(end, processed.length);
3585
+ const before = processed.slice(0, start);
3586
+ const afterRaw = extractRaw(processed.slice(clampedEnd), slots.slice(clampedEnd));
3587
+ const newValue = applyMaskToRaw(extractRaw(before, slots) + afterRaw, slots, slotChar, transform);
3588
+ pushUndoState();
3589
+ updateValue(newValue, start);
3590
+ return;
3591
+ }
3592
+ let deletePos = start;
3593
+ while (deletePos < slots.length && slots[deletePos] && slots[deletePos].type === "literal") deletePos++;
3594
+ if (deletePos >= processed.length) return;
3595
+ const newValue = applyMaskToRaw(extractRaw(processed.slice(0, start), slots.slice(0, start)) + extractRaw(processed.slice(deletePos + 1), slots.slice(deletePos + 1)), slots, slotChar, transform);
3596
+ pushUndoState();
3597
+ updateValue(newValue, start);
3598
+ } else if (e.key === "ArrowRight" && !e.shiftKey) {
3599
+ const nextPos = findNextEditablePosition(start + 1, slots, input.value);
3600
+ if (nextPos !== start + 1) {
3601
+ e.preventDefault();
3602
+ input.setSelectionRange(nextPos, nextPos);
3603
+ }
3604
+ } else if (e.key === "ArrowLeft" && !e.shiftKey) {
3605
+ if (start > 0) {
3606
+ const prevToken = findPrevTokenIndex(slots, start - 1);
3607
+ if (prevToken >= 0 && prevToken !== start - 1) {
3608
+ e.preventDefault();
3609
+ input.setSelectionRange(prevToken + 1, prevToken + 1);
3610
+ }
3611
+ }
3612
+ } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
3613
+ e.preventDefault();
3614
+ let insertPos = Math.min(start, processed.length);
3615
+ while (insertPos < slots.length && slots[insertPos] && slots[insertPos].type === "literal") insertPos++;
3616
+ if (insertPos >= slots.length) return;
3617
+ const slot = slots[insertPos];
3618
+ const ch = transform ? transform(e.key) : e.key;
3619
+ if (!slot.pattern.test(ch)) return;
3620
+ const beforeRaw = extractRaw(processed.slice(0, insertPos), slots.slice(0, insertPos));
3621
+ const afterRaw = start < end ? extractRaw(processed.slice(Math.min(end, processed.length)), slots.slice(Math.min(end, processed.length))) : extractRaw(processed.slice(insertPos), slots.slice(insertPos));
3622
+ const newValue = applyMaskToRaw(beforeRaw + ch + afterRaw, slots, slotChar, transform);
3623
+ const newCursorPos = findNextEditablePosition(insertPos + 1, slots, newValue);
3624
+ pushUndoState();
3625
+ updateValue(newValue, newCursorPos);
3626
+ }
3627
+ };
3628
+ const handlePaste = (e) => {
3629
+ e.preventDefault();
3630
+ const input = e.target;
3631
+ const pastedText = e.clipboardData?.getData("text") ?? "";
3632
+ const start = input.selectionStart ?? 0;
3633
+ const end = input.selectionEnd ?? 0;
3634
+ const { slots, slotChar, transform } = getResolvedOptions(options, "");
3635
+ const clampedStart = Math.min(start, processed.length);
3636
+ const clampedEnd = Math.min(end, processed.length);
3637
+ const beforeRaw = extractRaw(processed.slice(0, clampedStart), slots.slice(0, clampedStart));
3638
+ const afterRaw = extractRaw(processed.slice(clampedEnd), slots.slice(clampedEnd));
3639
+ const newValue = applyMaskToRaw(beforeRaw + pastedText + afterRaw, slots, slotChar, transform);
3640
+ pushUndoState();
3641
+ updateValue(newValue);
3642
+ const maskedPrefix = applyMaskToRaw(beforeRaw + pastedText, slots, slotChar, transform);
3643
+ const pasteEndPos = Math.min(maskedPrefix.length, slots.length);
3644
+ if (input === document.activeElement) input.setSelectionRange(pasteEndPos, pasteEndPos);
3645
+ };
3646
+ const setAriaAttributes = (input) => {
3647
+ if (options.invalid) input.setAttribute("aria-invalid", "true");
3648
+ else input.removeAttribute("aria-invalid");
3649
+ };
3650
+ const refCallback = (newNode) => {
3651
+ const prevNode = node;
3652
+ if (prevNode) {
3653
+ prevNode.removeEventListener("input", handleInput);
3654
+ prevNode.removeEventListener("focus", handleFocus);
3655
+ prevNode.removeEventListener("blur", handleBlur);
3656
+ prevNode.removeEventListener("mousedown", handleMouseDown);
3657
+ prevNode.removeEventListener("mouseup", handleMouseUp);
3658
+ prevNode.removeEventListener("keydown", handleKeyDown);
3659
+ prevNode.removeEventListener("paste", handlePaste);
3660
+ }
3661
+ node = newNode;
3662
+ if (newNode) {
3663
+ newNode.addEventListener("input", handleInput);
3664
+ newNode.addEventListener("focus", handleFocus);
3665
+ newNode.addEventListener("blur", handleBlur);
3666
+ newNode.addEventListener("mousedown", handleMouseDown);
3667
+ newNode.addEventListener("mouseup", handleMouseUp);
3668
+ newNode.addEventListener("keydown", handleKeyDown);
3669
+ newNode.addEventListener("paste", handlePaste);
3670
+ setAriaAttributes(newNode);
3671
+ const hasInitialValue = initializeInputValue(newNode);
3672
+ if (options.alwaysShowMask && !hasInitialValue) {
3673
+ const { slots, slotChar } = getResolvedOptions(options, "");
3674
+ const displayValue = buildDisplayValue("", slots, slotChar, true);
3675
+ newNode.value = displayValue;
3676
+ display = displayValue;
3677
+ maskedValue.value = displayValue;
3678
+ }
3679
+ }
3680
+ };
3681
+ watch(() => options.invalid, () => {
3682
+ if (node) setAriaAttributes(node);
3683
+ });
3684
+ const reset = () => {
3685
+ processed = "";
3686
+ display = "";
3687
+ rawInternal = "";
3688
+ undoStack = [];
3689
+ redoStack = [];
3690
+ maskedValue.value = "";
3691
+ rawValue.value = "";
3692
+ wasComplete = false;
3693
+ isComplete.value = false;
3694
+ if (node) if (options.alwaysShowMask) {
3695
+ const { slots, slotChar } = getResolvedOptions(options, "");
3696
+ const displayValue = buildDisplayValue("", slots, slotChar, true);
3697
+ node.value = displayValue;
3698
+ display = displayValue;
3699
+ maskedValue.value = displayValue;
3700
+ } else node.value = "";
3701
+ if (options.onChangeRaw) options.onChangeRaw("", "");
3702
+ };
3703
+ return {
3704
+ ref: refCallback,
3705
+ value: maskedValue,
3706
+ rawValue,
3707
+ isComplete,
3708
+ reset
3709
+ };
3710
+ }
3711
+ //#endregion
3712
+ //#region src/use-roving-index/use-roving-index.ts
3713
+ function findNextEnabled(current, total, isItemDisabled, loop) {
3714
+ for (let i = current + 1; i < total; i += 1) if (!isItemDisabled(i)) return i;
3715
+ if (loop) {
3716
+ for (let i = 0; i < current; i += 1) if (!isItemDisabled(i)) return i;
3717
+ }
3718
+ return current;
3719
+ }
3720
+ function findPreviousEnabled(current, total, isItemDisabled, loop) {
3721
+ for (let i = current - 1; i >= 0; i -= 1) if (!isItemDisabled(i)) return i;
3722
+ if (loop) {
3723
+ for (let i = total - 1; i > current; i -= 1) if (!isItemDisabled(i)) return i;
3724
+ }
3725
+ return current;
3726
+ }
3727
+ function findFirstEnabled(total, isItemDisabled) {
3728
+ for (let i = 0; i < total; i += 1) if (!isItemDisabled(i)) return i;
3729
+ return 0;
3730
+ }
3731
+ function findLastEnabled(total, isItemDisabled) {
3732
+ for (let i = total - 1; i >= 0; i -= 1) if (!isItemDisabled(i)) return i;
3733
+ return 0;
3734
+ }
3735
+ var defaultIsItemDisabled = () => false;
3736
+ function useRovingIndex(input) {
3737
+ const { total, orientation = "horizontal", loop = true, dir = "ltr", activateOnFocus = false, columns, focusedIndex, initialIndex, onFocusChange, isItemDisabled = defaultIsItemDisabled } = input;
3738
+ const itemRefs = /* @__PURE__ */ new Map();
3739
+ const getColumns = () => toValue(columns);
3740
+ const getIsGrid = () => {
3741
+ const cols = getColumns();
3742
+ return typeof cols === "number" && cols > 0;
3743
+ };
3744
+ const [activeIndex, setActiveIndex] = useUncontrolled({
3745
+ value: focusedIndex,
3746
+ defaultValue: initialIndex !== void 0 ? initialIndex : findFirstEnabled(toValue(total), isItemDisabled),
3747
+ finalValue: 0,
3748
+ onChange: onFocusChange
3749
+ });
3750
+ watch(() => [toValue(total), activeIndex.value], ([currentTotal, currentActive]) => {
3751
+ if (currentTotal === 0) return;
3752
+ if (currentActive >= currentTotal) setActiveIndex(findLastEnabled(currentTotal, isItemDisabled));
3753
+ else if (isItemDisabled(currentActive)) setActiveIndex(findFirstEnabled(currentTotal, isItemDisabled));
3754
+ }, { immediate: true });
3755
+ const focusItem = (index) => {
3756
+ setActiveIndex(index);
3757
+ const element = itemRefs.get(index);
3758
+ if (element) {
3759
+ element.focus();
3760
+ if (activateOnFocus) element.click();
3761
+ }
3762
+ };
3763
+ const handleGridKeyDown = (event, currentIndex) => {
3764
+ const cols = getColumns();
3765
+ const total_ = toValue(total);
3766
+ const row = Math.floor(currentIndex / cols);
3767
+ const col = currentIndex % cols;
3768
+ const totalRows = Math.ceil(total_ / cols);
3769
+ let nextIndex = null;
3770
+ const isRtl = dir === "rtl";
3771
+ switch (event.key) {
3772
+ case "ArrowRight": {
3773
+ const targetCol = isRtl ? col - 1 : col + 1;
3774
+ if (targetCol >= 0 && targetCol < cols && row * cols + targetCol < total_) {
3775
+ const candidate = row * cols + targetCol;
3776
+ if (!isItemDisabled(candidate)) nextIndex = candidate;
3777
+ }
3778
+ break;
3779
+ }
3780
+ case "ArrowLeft": {
3781
+ const targetCol = isRtl ? col + 1 : col - 1;
3782
+ if (targetCol >= 0 && targetCol < cols && row * cols + targetCol < total_) {
3783
+ const candidate = row * cols + targetCol;
3784
+ if (!isItemDisabled(candidate)) nextIndex = candidate;
3785
+ }
3786
+ break;
3787
+ }
3788
+ case "ArrowDown":
3789
+ for (let r = row + 1; r < totalRows; r += 1) {
3790
+ const candidate = r * cols + col;
3791
+ if (candidate < total_ && !isItemDisabled(candidate)) {
3792
+ nextIndex = candidate;
3793
+ break;
3794
+ }
3795
+ }
3796
+ break;
3797
+ case "ArrowUp":
3798
+ for (let r = row - 1; r >= 0; r -= 1) {
3799
+ const candidate = r * cols + col;
3800
+ if (candidate < total_ && !isItemDisabled(candidate)) {
3801
+ nextIndex = candidate;
3802
+ break;
3803
+ }
3804
+ }
3805
+ break;
3806
+ case "Home":
3807
+ if (event.ctrlKey) nextIndex = findFirstEnabled(total_, isItemDisabled);
3808
+ else {
3809
+ const rowStart = row * cols;
3810
+ for (let i = rowStart; i < rowStart + cols && i < total_; i += 1) if (!isItemDisabled(i)) {
3811
+ nextIndex = i;
3812
+ break;
3813
+ }
3814
+ }
3815
+ break;
3816
+ case "End":
3817
+ if (event.ctrlKey) nextIndex = findLastEnabled(total_, isItemDisabled);
3818
+ else {
3819
+ const rowStart = row * cols;
3820
+ const rowEnd = Math.min(rowStart + cols, total_) - 1;
3821
+ for (let i = rowEnd; i >= rowStart; i -= 1) if (!isItemDisabled(i)) {
3822
+ nextIndex = i;
3823
+ break;
3824
+ }
3825
+ }
3826
+ break;
3827
+ }
3828
+ if (nextIndex !== null && nextIndex !== currentIndex) {
3829
+ event.preventDefault();
3830
+ event.stopPropagation();
3831
+ focusItem(nextIndex);
3832
+ }
3833
+ };
3834
+ const handleListKeyDown = (event, currentIndex) => {
3835
+ const total_ = toValue(total);
3836
+ const isRtl = dir === "rtl";
3837
+ let nextIndex = null;
3838
+ switch (event.key) {
3839
+ case "ArrowRight":
3840
+ if (orientation === "horizontal" || orientation === "both") nextIndex = isRtl ? findPreviousEnabled(currentIndex, total_, isItemDisabled, loop) : findNextEnabled(currentIndex, total_, isItemDisabled, loop);
3841
+ break;
3842
+ case "ArrowLeft":
3843
+ if (orientation === "horizontal" || orientation === "both") nextIndex = isRtl ? findNextEnabled(currentIndex, total_, isItemDisabled, loop) : findPreviousEnabled(currentIndex, total_, isItemDisabled, loop);
3844
+ break;
3845
+ case "ArrowDown":
3846
+ if (orientation === "vertical" || orientation === "both") nextIndex = findNextEnabled(currentIndex, total_, isItemDisabled, loop);
3847
+ break;
3848
+ case "ArrowUp":
3849
+ if (orientation === "vertical" || orientation === "both") nextIndex = findPreviousEnabled(currentIndex, total_, isItemDisabled, loop);
3850
+ break;
3851
+ case "Home":
3852
+ nextIndex = findFirstEnabled(total_, isItemDisabled);
3853
+ break;
3854
+ case "End":
3855
+ nextIndex = findLastEnabled(total_, isItemDisabled);
3856
+ break;
3857
+ }
3858
+ if (nextIndex !== null && nextIndex !== currentIndex) {
3859
+ event.preventDefault();
3860
+ event.stopPropagation();
3861
+ focusItem(nextIndex);
3862
+ }
3863
+ };
3864
+ const getItemProps = (options) => {
3865
+ const { index, onClick, onKeyDown } = options;
3866
+ return {
3867
+ tabIndex: index === activeIndex.value ? 0 : -1,
3868
+ ref: (node) => {
3869
+ const safeNode = node instanceof HTMLElement ? node : null;
3870
+ if (safeNode) itemRefs.set(index, safeNode);
3871
+ else itemRefs.delete(index);
3872
+ },
3873
+ onKeyDown: (event) => {
3874
+ onKeyDown?.(event);
3875
+ if (event.defaultPrevented) return;
3876
+ if (getIsGrid()) handleGridKeyDown(event, index);
3877
+ else handleListKeyDown(event, index);
3878
+ },
3879
+ onClick: (event) => {
3880
+ onClick?.(event);
3881
+ setActiveIndex(index);
3882
+ }
3883
+ };
3884
+ };
3885
+ return {
3886
+ getItemProps,
3887
+ focusedIndex: activeIndex,
3888
+ setFocusedIndex: setActiveIndex
3889
+ };
3890
+ }
3891
+ //#endregion
3892
+ //#region src/use-drag/use-drag.ts
3893
+ var VELOCITY_DECAY_MS = 100;
3894
+ function sign(n) {
3895
+ if (n > 0) return 1;
3896
+ if (n < 0) return -1;
3897
+ return 0;
3898
+ }
3899
+ function getThresholdVector(threshold) {
3900
+ const t = threshold ?? 0;
3901
+ if (typeof t === "number") return [t, t];
3902
+ return t;
3903
+ }
3904
+ function createInitialState() {
3905
+ return {
3906
+ isActive: false,
3907
+ pointerId: -1,
3908
+ startXY: [0, 0],
3909
+ prevXY: [0, 0],
3910
+ startTimestamp: 0,
3911
+ prevTimestamp: 0,
3912
+ thresholdMet: false,
3913
+ firstFired: false,
3914
+ lockedAxis: null,
3915
+ canceled: false,
3916
+ lastVelocity: [0, 0]
3917
+ };
3918
+ }
3919
+ function useDrag(handler, options = {}) {
3920
+ const active = ref(false);
3921
+ const state = createInitialState();
3922
+ let node = null;
3923
+ let documentController = null;
3924
+ let cleanupNode;
3925
+ const applyAxisConstraint = (v) => {
3926
+ if (options.axis === "x") return [v[0], 0];
3927
+ if (options.axis === "y") return [0, v[1]];
3928
+ if (options.axis === "lock") {
3929
+ if (state.lockedAxis === null) {
3930
+ const t = options.axisThreshold ?? 1;
3931
+ if (Math.abs(v[0]) > t || Math.abs(v[1]) > t) state.lockedAxis = Math.abs(v[0]) >= Math.abs(v[1]) ? "x" : "y";
3932
+ }
3933
+ if (state.lockedAxis === "x") return [v[0], 0];
3934
+ if (state.lockedAxis === "y") return [0, v[1]];
3935
+ }
3936
+ return v;
3937
+ };
3938
+ const resetDrag = () => {
3939
+ state.isActive = false;
3940
+ state.pointerId = -1;
3941
+ state.thresholdMet = false;
3942
+ state.firstFired = false;
3943
+ state.lockedAxis = null;
3944
+ state.canceled = false;
3945
+ active.value = false;
3946
+ document.body.style.userSelect = "";
3947
+ document.body.style.webkitUserSelect = "";
3948
+ documentController?.abort();
3949
+ documentController = null;
3950
+ };
3951
+ const cancel = () => {
3952
+ if (state.isActive) {
3953
+ state.canceled = true;
3954
+ resetDrag();
3955
+ }
3956
+ };
3957
+ const activateDrag = () => {
3958
+ active.value = true;
3959
+ document.body.style.userSelect = "none";
3960
+ document.body.style.webkitUserSelect = "none";
3961
+ };
3962
+ const onPointerDown = (event) => {
3963
+ if (options.enabled === false) return;
3964
+ if (event.button !== 0) return;
3965
+ if (state.isActive) return;
3966
+ state.isActive = true;
3967
+ state.pointerId = event.pointerId;
3968
+ state.startXY = [event.clientX, event.clientY];
3969
+ state.prevXY = [event.clientX, event.clientY];
3970
+ state.startTimestamp = event.timeStamp;
3971
+ state.prevTimestamp = event.timeStamp;
3972
+ state.thresholdMet = false;
3973
+ state.firstFired = false;
3974
+ state.lockedAxis = null;
3975
+ state.canceled = false;
3976
+ state.lastVelocity = [0, 0];
3977
+ const [tx, ty] = getThresholdVector(options.threshold);
3978
+ if (tx === 0 && ty === 0) {
3979
+ state.thresholdMet = true;
3980
+ state.firstFired = true;
3981
+ activateDrag();
3982
+ handler({
3983
+ xy: [event.clientX, event.clientY],
3984
+ initial: [event.clientX, event.clientY],
3985
+ movement: [0, 0],
3986
+ delta: [0, 0],
3987
+ distance: [0, 0],
3988
+ direction: [0, 0],
3989
+ velocity: [0, 0],
3990
+ elapsedTime: 0,
3991
+ first: true,
3992
+ last: false,
3993
+ active: true,
3994
+ tap: false,
3995
+ canceled: false,
3996
+ cancel,
3997
+ event
3998
+ });
3999
+ }
4000
+ documentController?.abort();
4001
+ documentController = new AbortController();
4002
+ const sig = documentController.signal;
4003
+ document.addEventListener("pointermove", onPointerMove, { signal: sig });
4004
+ document.addEventListener("pointerup", onPointerUp, { signal: sig });
4005
+ document.addEventListener("pointercancel", onPointerCancel, { signal: sig });
4006
+ };
4007
+ const onPointerMove = (event) => {
4008
+ if (!state.isActive || event.pointerId !== state.pointerId) return;
4009
+ const rawMovement = [event.clientX - state.startXY[0], event.clientY - state.startXY[1]];
4010
+ if (!state.thresholdMet) {
4011
+ const [tx, ty] = getThresholdVector(options.threshold);
4012
+ if (Math.abs(rawMovement[0]) < tx && Math.abs(rawMovement[1]) < ty) {
4013
+ state.prevXY = [event.clientX, event.clientY];
4014
+ state.prevTimestamp = event.timeStamp;
4015
+ return;
4016
+ }
4017
+ state.thresholdMet = true;
4018
+ activateDrag();
4019
+ }
4020
+ const movement = applyAxisConstraint(rawMovement);
4021
+ const delta = applyAxisConstraint([event.clientX - state.prevXY[0], event.clientY - state.prevXY[1]]);
4022
+ const timeDelta = event.timeStamp - state.prevTimestamp;
4023
+ const velocity = timeDelta > 0 ? [Math.abs(delta[0]) / timeDelta, Math.abs(delta[1]) / timeDelta] : state.lastVelocity;
4024
+ state.lastVelocity = velocity;
4025
+ const isFirst = !state.firstFired;
4026
+ state.firstFired = true;
4027
+ state.prevXY = [event.clientX, event.clientY];
4028
+ state.prevTimestamp = event.timeStamp;
4029
+ handler({
4030
+ xy: [event.clientX, event.clientY],
4031
+ initial: [...state.startXY],
4032
+ movement,
4033
+ delta,
4034
+ distance: [Math.abs(movement[0]), Math.abs(movement[1])],
4035
+ direction: [sign(delta[0]), sign(delta[1])],
4036
+ velocity,
4037
+ elapsedTime: event.timeStamp - state.startTimestamp,
4038
+ first: isFirst,
4039
+ last: false,
4040
+ active: true,
4041
+ tap: false,
4042
+ canceled: false,
4043
+ cancel,
4044
+ event
4045
+ });
4046
+ };
4047
+ const onPointerUp = (event) => {
4048
+ if (!state.isActive || event.pointerId !== state.pointerId) return;
4049
+ if (!state.thresholdMet) {
4050
+ if (options.filterTaps) {
4051
+ const mov = applyAxisConstraint([event.clientX - state.startXY[0], event.clientY - state.startXY[1]]);
4052
+ const dist = [Math.abs(mov[0]), Math.abs(mov[1])];
4053
+ const isTap = Math.max(dist[0], dist[1]) < (options.tapThreshold ?? 3);
4054
+ handler({
4055
+ xy: [event.clientX, event.clientY],
4056
+ initial: [...state.startXY],
4057
+ movement: mov,
4058
+ delta: mov,
4059
+ distance: dist,
4060
+ direction: [sign(mov[0]), sign(mov[1])],
4061
+ velocity: [0, 0],
4062
+ elapsedTime: event.timeStamp - state.startTimestamp,
4063
+ first: true,
4064
+ last: true,
4065
+ active: false,
4066
+ tap: isTap,
4067
+ canceled: false,
4068
+ cancel,
4069
+ event
4070
+ });
4071
+ }
4072
+ resetDrag();
4073
+ return;
4074
+ }
4075
+ const movement = applyAxisConstraint([event.clientX - state.startXY[0], event.clientY - state.startXY[1]]);
4076
+ const distance = [Math.abs(movement[0]), Math.abs(movement[1])];
4077
+ const delta = applyAxisConstraint([event.clientX - state.prevXY[0], event.clientY - state.prevXY[1]]);
4078
+ const velocity = event.timeStamp - state.prevTimestamp > VELOCITY_DECAY_MS ? [0, 0] : state.lastVelocity;
4079
+ const maxDistance = Math.max(distance[0], distance[1]);
4080
+ const tap = options.filterTaps === true && maxDistance < (options.tapThreshold ?? 3);
4081
+ handler({
4082
+ xy: [event.clientX, event.clientY],
4083
+ initial: [...state.startXY],
4084
+ movement,
4085
+ delta,
4086
+ distance,
4087
+ direction: [sign(delta[0]), sign(delta[1])],
4088
+ velocity,
4089
+ elapsedTime: event.timeStamp - state.startTimestamp,
4090
+ first: !state.firstFired,
4091
+ last: true,
4092
+ active: false,
4093
+ tap,
4094
+ canceled: false,
4095
+ cancel,
4096
+ event
4097
+ });
4098
+ resetDrag();
4099
+ };
4100
+ const onPointerCancel = (event) => {
4101
+ if (!state.isActive || event.pointerId !== state.pointerId) return;
4102
+ const movement = applyAxisConstraint([event.clientX - state.startXY[0], event.clientY - state.startXY[1]]);
4103
+ handler({
4104
+ xy: [event.clientX, event.clientY],
4105
+ initial: [...state.startXY],
4106
+ movement,
4107
+ delta: [0, 0],
4108
+ distance: [Math.abs(movement[0]), Math.abs(movement[1])],
4109
+ direction: [0, 0],
4110
+ velocity: [0, 0],
4111
+ elapsedTime: event.timeStamp - state.startTimestamp,
4112
+ first: !state.firstFired,
4113
+ last: true,
4114
+ active: false,
4115
+ tap: false,
4116
+ canceled: true,
4117
+ cancel,
4118
+ event
4119
+ });
4120
+ resetDrag();
4121
+ };
4122
+ const refCallback = (newNode) => {
4123
+ cleanupNode?.();
4124
+ cleanupNode = void 0;
4125
+ node = newNode;
4126
+ if (!node) return;
4127
+ const elementController = new AbortController();
4128
+ node.addEventListener("pointerdown", onPointerDown, { signal: elementController.signal });
4129
+ cleanupNode = () => {
4130
+ elementController.abort();
4131
+ documentController?.abort();
4132
+ documentController = null;
4133
+ if (state.isActive) {
4134
+ state.isActive = false;
4135
+ active.value = false;
4136
+ document.body.style.userSelect = "";
4137
+ document.body.style.webkitUserSelect = "";
4138
+ }
4139
+ };
4140
+ };
4141
+ onBeforeUnmount(() => {
4142
+ cleanupNode?.();
4143
+ });
4144
+ return {
4145
+ ref: refCallback,
4146
+ active
4147
+ };
4148
+ }
4149
+ //#endregion
4150
+ //#region src/use-splitter/use-splitter.ts
4151
+ function clamp$1(value, min, max) {
4152
+ return Math.min(Math.max(value, min), max);
4153
+ }
4154
+ function getMin(panel) {
4155
+ return panel.min ?? 0;
4156
+ }
4157
+ function getMax(panel) {
4158
+ return panel.max ?? 100;
4159
+ }
4160
+ function getCollapseThreshold(panel) {
4161
+ return panel.collapseThreshold ?? getMin(panel);
4162
+ }
4163
+ function createInitialInternalState() {
4164
+ return {
4165
+ isDragging: false,
4166
+ handleIndex: -1,
4167
+ startPointer: 0,
4168
+ containerSize: 0,
4169
+ startSizes: [],
4170
+ preCollapseSizes: []
4171
+ };
4172
+ }
4173
+ function checkCollapse(sizes, panels, handleIndex, delta) {
4174
+ const beforeIdx = handleIndex;
4175
+ const afterIdx = handleIndex + 1;
4176
+ const beforePanel = panels[beforeIdx];
4177
+ const afterPanel = panels[afterIdx];
4178
+ const rawBefore = sizes[beforeIdx] + delta;
4179
+ const rawAfter = sizes[afterIdx] - delta;
4180
+ if (beforePanel.collapsible && rawBefore < getCollapseThreshold(beforePanel) && rawBefore < sizes[beforeIdx]) {
4181
+ const result = [...sizes];
4182
+ result[afterIdx] += result[beforeIdx];
4183
+ result[beforeIdx] = 0;
4184
+ return result;
4185
+ }
4186
+ if (afterPanel.collapsible && rawAfter < getCollapseThreshold(afterPanel) && rawAfter < sizes[afterIdx]) {
4187
+ const result = [...sizes];
4188
+ result[beforeIdx] += result[afterIdx];
4189
+ result[afterIdx] = 0;
4190
+ return result;
4191
+ }
4192
+ return null;
4193
+ }
4194
+ function applyAdjacentOnly(sizes, panels, handleIndex, delta) {
4195
+ const result = [...sizes];
4196
+ const beforeIdx = handleIndex;
4197
+ const afterIdx = handleIndex + 1;
4198
+ const total = result[beforeIdx] + result[afterIdx];
4199
+ const effectiveBeforeMax = Math.min(getMax(panels[beforeIdx]), total - getMin(panels[afterIdx]));
4200
+ const effectiveBeforeMin = Math.max(getMin(panels[beforeIdx]), total - getMax(panels[afterIdx]));
4201
+ const newBefore = clamp$1(result[beforeIdx] + delta, effectiveBeforeMin, effectiveBeforeMax);
4202
+ result[beforeIdx] = newBefore;
4203
+ result[afterIdx] = total - newBefore;
4204
+ return result;
4205
+ }
4206
+ function redistributeNearest(sizes, panels, handleIndex, delta) {
4207
+ const result = [...sizes];
4208
+ if (delta > 0) {
4209
+ const growIdx = handleIndex;
4210
+ const maxGrow = getMax(panels[growIdx]) - result[growIdx];
4211
+ const wantedGrow = Math.min(delta, maxGrow);
4212
+ let taken = 0;
4213
+ for (let i = handleIndex + 1; i < result.length && taken < wantedGrow; i += 1) {
4214
+ const canGive = result[i] - getMin(panels[i]);
4215
+ const take = Math.min(canGive, wantedGrow - taken);
4216
+ result[i] -= take;
4217
+ taken += take;
4218
+ }
4219
+ result[growIdx] += taken;
4220
+ } else if (delta < 0) {
4221
+ const growIdx = handleIndex + 1;
4222
+ const maxGrow = getMax(panels[growIdx]) - result[growIdx];
4223
+ const wantedGrow = Math.min(Math.abs(delta), maxGrow);
4224
+ let taken = 0;
4225
+ for (let i = handleIndex; i >= 0 && taken < wantedGrow; i -= 1) {
4226
+ const canGive = result[i] - getMin(panels[i]);
4227
+ const take = Math.min(canGive, wantedGrow - taken);
4228
+ result[i] -= take;
4229
+ taken += take;
4230
+ }
4231
+ result[growIdx] += taken;
4232
+ }
4233
+ return result;
4234
+ }
4235
+ function redistributeEqual(sizes, panels, handleIndex, delta) {
4236
+ const result = [...sizes];
4237
+ if (delta > 0) {
4238
+ const growIdx = handleIndex;
4239
+ const maxGrow = getMax(panels[growIdx]) - result[growIdx];
4240
+ const wantedGrow = Math.min(delta, maxGrow);
4241
+ const donors = [];
4242
+ for (let i = handleIndex + 1; i < result.length; i += 1) if (result[i] > getMin(panels[i])) donors.push(i);
4243
+ let remaining = wantedGrow;
4244
+ while (remaining > .001 && donors.length > 0) {
4245
+ const perDonor = remaining / donors.length;
4246
+ const exhausted = [];
4247
+ for (let d = 0; d < donors.length; d += 1) {
4248
+ const idx = donors[d];
4249
+ const canGive = result[idx] - getMin(panels[idx]);
4250
+ const take = Math.min(canGive, perDonor);
4251
+ result[idx] -= take;
4252
+ remaining -= take;
4253
+ if (canGive <= perDonor + .001) exhausted.push(d);
4254
+ }
4255
+ for (let i = exhausted.length - 1; i >= 0; i -= 1) donors.splice(exhausted[i], 1);
4256
+ if (exhausted.length === 0) break;
4257
+ }
4258
+ result[growIdx] += wantedGrow - remaining;
4259
+ } else if (delta < 0) {
4260
+ const growIdx = handleIndex + 1;
4261
+ const maxGrow = getMax(panels[growIdx]) - result[growIdx];
4262
+ const wantedGrow = Math.min(Math.abs(delta), maxGrow);
4263
+ const donors = [];
4264
+ for (let i = handleIndex; i >= 0; i -= 1) if (result[i] > getMin(panels[i])) donors.push(i);
4265
+ let remaining = wantedGrow;
4266
+ while (remaining > .001 && donors.length > 0) {
4267
+ const perDonor = remaining / donors.length;
4268
+ const exhausted = [];
4269
+ for (let d = 0; d < donors.length; d += 1) {
4270
+ const idx = donors[d];
4271
+ const canGive = result[idx] - getMin(panels[idx]);
4272
+ const take = Math.min(canGive, perDonor);
4273
+ result[idx] -= take;
4274
+ remaining -= take;
4275
+ if (canGive <= perDonor + .001) exhausted.push(d);
4276
+ }
4277
+ for (let i = exhausted.length - 1; i >= 0; i -= 1) donors.splice(exhausted[i], 1);
4278
+ if (exhausted.length === 0) break;
4279
+ }
4280
+ result[growIdx] += wantedGrow - remaining;
4281
+ }
4282
+ return result;
4283
+ }
4284
+ function applyConstraints(sizes, panels, handleIndex, delta, redistribute) {
4285
+ if (typeof redistribute === "function") return redistribute({
4286
+ sizes: [...sizes],
4287
+ panels,
4288
+ handleIndex,
4289
+ delta
4290
+ });
4291
+ if (redistribute === "nearest" || redistribute === "equal") {
4292
+ const result = (redistribute === "nearest" ? redistributeNearest : redistributeEqual)(sizes, panels, handleIndex, delta);
4293
+ const beforeIdx = handleIndex;
4294
+ const afterIdx = handleIndex + 1;
4295
+ const beforePanel = panels[beforeIdx];
4296
+ const afterPanel = panels[afterIdx];
4297
+ if (beforePanel.collapsible && result[beforeIdx] < getCollapseThreshold(beforePanel) && result[beforeIdx] < sizes[beforeIdx]) {
4298
+ const freed = result[beforeIdx];
4299
+ result[afterIdx] += freed;
4300
+ result[beforeIdx] = 0;
4301
+ } else if (afterPanel.collapsible && result[afterIdx] < getCollapseThreshold(afterPanel) && result[afterIdx] < sizes[afterIdx]) {
4302
+ const freed = result[afterIdx];
4303
+ result[beforeIdx] += freed;
4304
+ result[afterIdx] = 0;
4305
+ }
4306
+ return result;
4307
+ }
4308
+ const collapsedResult = checkCollapse(sizes, panels, handleIndex, delta);
4309
+ if (collapsedResult) return collapsedResult;
4310
+ return applyAdjacentOnly(sizes, panels, handleIndex, delta);
4311
+ }
4312
+ function useSplitter(options) {
4313
+ const { panels, orientation = "horizontal", sizes: controlledSizes, onSizeChange, onResizeStart, onResizeEnd, onCollapseChange, redistribute, step = 1, shiftStep = 10, dir = "ltr", resetOnDoubleClick = true, enabled = true } = options;
4314
+ const defaultSizes = panels.map((p) => p.defaultSize);
4315
+ const [currentSizes, setCurrentSizesRaw] = useUncontrolled({
4316
+ value: controlledSizes,
4317
+ defaultValue: defaultSizes,
4318
+ finalValue: defaultSizes,
4319
+ onChange: onSizeChange
4320
+ });
4321
+ const activeHandle = ref(-1);
4322
+ const internalState = createInitialInternalState();
4323
+ let containerNode = null;
4324
+ let documentController = null;
4325
+ let frame = 0;
4326
+ let preCollapseSizes = [...defaultSizes];
4327
+ const collapsed = computed(() => currentSizes.value.map((size) => size === 0));
4328
+ const updateSizes = (newSizes) => {
4329
+ setCurrentSizesRaw(newSizes);
4330
+ };
4331
+ const collapsePanel = (panelIndex) => {
4332
+ if (!panels[panelIndex]?.collapsible) return;
4333
+ const sizesNow = currentSizes.value;
4334
+ if (sizesNow[panelIndex] === 0) return;
4335
+ preCollapseSizes = [...sizesNow];
4336
+ const newSizes = [...sizesNow];
4337
+ const freedSize = newSizes[panelIndex];
4338
+ newSizes[panelIndex] = 0;
4339
+ const neighbor = panelIndex === 0 ? 1 : panelIndex - 1;
4340
+ newSizes[neighbor] += freedSize;
4341
+ updateSizes(newSizes);
4342
+ onCollapseChange?.(panelIndex, true);
4343
+ };
4344
+ const expandPanel = (panelIndex) => {
4345
+ if (!panels[panelIndex]?.collapsible) return;
4346
+ const sizesNow = currentSizes.value;
4347
+ if (sizesNow[panelIndex] !== 0) return;
4348
+ const restoreSize = preCollapseSizes[panelIndex] || panels[panelIndex].defaultSize;
4349
+ const newSizes = [...sizesNow];
4350
+ const neighbor = panelIndex === 0 ? 1 : panelIndex - 1;
4351
+ const available = Math.max(0, newSizes[neighbor] - getMin(panels[neighbor]));
4352
+ const actualRestore = Math.min(restoreSize, available);
4353
+ if (actualRestore <= 0) return;
4354
+ newSizes[panelIndex] = actualRestore;
4355
+ newSizes[neighbor] -= actualRestore;
4356
+ updateSizes(newSizes);
4357
+ onCollapseChange?.(panelIndex, false);
4358
+ };
4359
+ const toggleCollapsePanel = (panelIndex) => {
4360
+ if (currentSizes.value[panelIndex] === 0) expandPanel(panelIndex);
4361
+ else collapsePanel(panelIndex);
4362
+ };
4363
+ const emitCollapseTransitions = (prev, next, indices, preCollapseSnapshot) => {
4364
+ for (const idx of indices) {
4365
+ const wasCollapsed = prev[idx] === 0;
4366
+ const nowCollapsed = next[idx] === 0;
4367
+ if (!wasCollapsed && nowCollapsed) {
4368
+ preCollapseSizes = [...preCollapseSnapshot];
4369
+ onCollapseChange?.(idx, true);
4370
+ } else if (wasCollapsed && !nowCollapsed) onCollapseChange?.(idx, false);
4371
+ }
4372
+ };
4373
+ const reset = (handleIndex) => {
4374
+ const prev = currentSizes.value;
4375
+ const beforeIdx = handleIndex;
4376
+ const afterIdx = handleIndex + 1;
4377
+ if (beforeIdx < 0 || afterIdx >= prev.length) return;
4378
+ const total = prev[beforeIdx] + prev[afterIdx];
4379
+ const defBefore = panels[beforeIdx].defaultSize;
4380
+ const defTotal = defBefore + panels[afterIdx].defaultSize;
4381
+ const next = applyAdjacentOnly(prev, panels, beforeIdx, (defTotal === 0 ? total / 2 : total * (defBefore / defTotal)) - prev[beforeIdx]);
4382
+ emitCollapseTransitions(prev, next, [beforeIdx, afterIdx], prev);
4383
+ updateSizes(next);
4384
+ };
4385
+ const containerRefCallback = (node) => {
4386
+ containerNode = node instanceof HTMLElement ? node : null;
4387
+ };
4388
+ const handleRefCallbacks = /* @__PURE__ */ new Map();
4389
+ const handleElementControllers = /* @__PURE__ */ new Map();
4390
+ const getHandleRefCallback = (handleIndex) => {
4391
+ const cached = handleRefCallbacks.get(handleIndex);
4392
+ if (cached) return cached;
4393
+ const callback = (rawNode) => {
4394
+ const existingController = handleElementControllers.get(handleIndex);
4395
+ if (existingController) {
4396
+ existingController.abort();
4397
+ handleElementControllers.delete(handleIndex);
4398
+ }
4399
+ const node = rawNode instanceof HTMLElement ? rawNode : null;
4400
+ if (!node) return;
4401
+ const elementController = new AbortController();
4402
+ handleElementControllers.set(handleIndex, elementController);
4403
+ const flushResize = (pointerEvent) => {
4404
+ const s = internalState;
4405
+ if (!s.containerSize) return;
4406
+ const isHorizontal = orientation === "horizontal";
4407
+ const isRtl = isHorizontal && dir === "rtl";
4408
+ const pixelDelta = (isHorizontal ? pointerEvent.clientX : pointerEvent.clientY) - s.startPointer;
4409
+ const percentDelta = (isRtl ? -pixelDelta : pixelDelta) / s.containerSize * 100;
4410
+ const newSizes = applyConstraints(s.startSizes, panels, s.handleIndex, percentDelta, redistribute);
4411
+ const prevSizes = currentSizes.value;
4412
+ emitCollapseTransitions(prevSizes, newSizes, [s.handleIndex, s.handleIndex + 1], s.startSizes);
4413
+ setCurrentSizesRaw(newSizes);
4414
+ };
4415
+ const onPointerMove = (event) => {
4416
+ if (!internalState.isDragging) return;
4417
+ cancelAnimationFrame(frame);
4418
+ frame = requestAnimationFrame(() => {
4419
+ flushResize(event);
4420
+ });
4421
+ };
4422
+ const onPointerUp = (event) => {
4423
+ const s = internalState;
4424
+ if (!s.isDragging) return;
4425
+ cancelAnimationFrame(frame);
4426
+ flushResize(event);
4427
+ s.isDragging = false;
4428
+ const finishedHandle = s.handleIndex;
4429
+ s.handleIndex = -1;
4430
+ activeHandle.value = -1;
4431
+ document.body.style.userSelect = "";
4432
+ document.body.style.webkitUserSelect = "";
4433
+ document.body.style.cursor = "";
4434
+ documentController?.abort();
4435
+ documentController = null;
4436
+ onResizeEnd?.(finishedHandle, [...currentSizes.value]);
4437
+ };
4438
+ const onPointerDown = (event) => {
4439
+ if (enabled === false) return;
4440
+ if (event.button !== 0) return;
4441
+ const container = containerNode;
4442
+ if (!container) return;
4443
+ const rect = container.getBoundingClientRect();
4444
+ const isHorizontal = orientation === "horizontal";
4445
+ const containerSize = isHorizontal ? rect.width : rect.height;
4446
+ const pointerPos = isHorizontal ? event.clientX : event.clientY;
4447
+ internalState.isDragging = true;
4448
+ internalState.handleIndex = handleIndex;
4449
+ internalState.startPointer = pointerPos;
4450
+ internalState.containerSize = containerSize;
4451
+ internalState.startSizes = [...currentSizes.value];
4452
+ internalState.preCollapseSizes = [...preCollapseSizes];
4453
+ activeHandle.value = handleIndex;
4454
+ document.body.style.userSelect = "none";
4455
+ document.body.style.webkitUserSelect = "none";
4456
+ document.body.style.cursor = isHorizontal ? "col-resize" : "row-resize";
4457
+ onResizeStart?.(handleIndex);
4458
+ documentController?.abort();
4459
+ documentController = new AbortController();
4460
+ const sig = documentController.signal;
4461
+ document.addEventListener("pointermove", onPointerMove, { signal: sig });
4462
+ document.addEventListener("pointerup", onPointerUp, { signal: sig });
4463
+ document.addEventListener("pointercancel", onPointerUp, { signal: sig });
4464
+ };
4465
+ node.addEventListener("pointerdown", onPointerDown, { signal: elementController.signal });
4466
+ };
4467
+ handleRefCallbacks.set(handleIndex, callback);
4468
+ return callback;
4469
+ };
4470
+ const getHandleProps = (input) => {
4471
+ const { index } = input;
4472
+ const orient = orientation;
4473
+ const beforeSize = currentSizes.value[index] ?? 0;
4474
+ const beforePanel = panels[index];
4475
+ const afterPanel = panels[index + 1];
4476
+ return {
4477
+ ref: getHandleRefCallback(index),
4478
+ role: "separator",
4479
+ "aria-orientation": orient,
4480
+ "aria-valuenow": Math.round(beforeSize),
4481
+ "aria-valuemin": Math.round(getMin(beforePanel)),
4482
+ "aria-valuemax": Math.round(getMax(beforePanel)),
4483
+ tabIndex: 0,
4484
+ onKeyDown: (event) => {
4485
+ if (!enabled) return;
4486
+ const isHorizontal = orient === "horizontal";
4487
+ const isRtl = dir === "rtl";
4488
+ let delta = 0;
4489
+ const currentStep = event.shiftKey ? shiftStep : step;
4490
+ switch (event.key) {
4491
+ case "ArrowLeft":
4492
+ if (!isHorizontal) return;
4493
+ delta = isRtl ? currentStep : -currentStep;
4494
+ break;
4495
+ case "ArrowRight":
4496
+ if (!isHorizontal) return;
4497
+ delta = isRtl ? -currentStep : currentStep;
4498
+ break;
4499
+ case "ArrowUp":
4500
+ if (isHorizontal) return;
4501
+ delta = -currentStep;
4502
+ break;
4503
+ case "ArrowDown":
4504
+ if (isHorizontal) return;
4505
+ delta = currentStep;
4506
+ break;
4507
+ case "Home":
4508
+ delta = -(currentSizes.value[index] - getMin(beforePanel));
4509
+ break;
4510
+ case "End":
4511
+ delta = getMax(beforePanel) - currentSizes.value[index];
4512
+ break;
4513
+ case "Enter": {
4514
+ const beforeCollapsible = beforePanel?.collapsible;
4515
+ const afterCollapsible = afterPanel?.collapsible;
4516
+ if (beforeCollapsible && currentSizes.value[index] <= currentSizes.value[index + 1]) {
4517
+ toggleCollapsePanel(index);
4518
+ event.preventDefault();
4519
+ return;
4520
+ }
4521
+ if (afterCollapsible) {
4522
+ toggleCollapsePanel(index + 1);
4523
+ event.preventDefault();
4524
+ return;
4525
+ }
4526
+ if (beforeCollapsible) {
4527
+ toggleCollapsePanel(index);
4528
+ event.preventDefault();
4529
+ return;
4530
+ }
4531
+ return;
4532
+ }
4533
+ default: return;
4534
+ }
4535
+ event.preventDefault();
4536
+ if (delta !== 0) {
4537
+ const newSizes = applyConstraints(currentSizes.value, panels, index, delta, redistribute);
4538
+ emitCollapseTransitions(currentSizes.value, newSizes, [index, index + 1], currentSizes.value);
4539
+ updateSizes(newSizes);
4540
+ }
4541
+ },
4542
+ onDoubleClick: () => {
4543
+ if (!enabled || !resetOnDoubleClick) return;
4544
+ reset(index);
4545
+ },
4546
+ "data-active": activeHandle.value === index || void 0,
4547
+ "data-orientation": orient
4548
+ };
4549
+ };
4550
+ onBeforeUnmount(() => {
4551
+ documentController?.abort();
4552
+ documentController = null;
4553
+ handleElementControllers.forEach((controller) => controller.abort());
4554
+ handleElementControllers.clear();
4555
+ cancelAnimationFrame(frame);
4556
+ if (internalState.isDragging) {
4557
+ internalState.isDragging = false;
4558
+ document.body.style.userSelect = "";
4559
+ document.body.style.webkitUserSelect = "";
4560
+ document.body.style.cursor = "";
4561
+ }
4562
+ });
4563
+ return {
4564
+ ref: containerRefCallback,
4565
+ sizes: currentSizes,
4566
+ collapsed,
4567
+ activeHandle,
4568
+ getHandleProps,
4569
+ setSizes: updateSizes,
4570
+ collapse: collapsePanel,
4571
+ expand: expandPanel,
4572
+ toggleCollapse: toggleCollapsePanel,
4573
+ reset
4574
+ };
4575
+ }
4576
+ //#endregion
4577
+ export { DOTS, FOCUS_SELECTOR, assignRef, clamp, clampUseMovePosition, createCollapse, findTabbableDescendants, focusable, formatMask, generatePattern, getElementContentSize, getHotkeyHandler, isFixed, isMaskComplete, isPinned, isPinnedOrReleased, isReleased, lowerFirst, mergeRefs, normalizeRadialValue, randomId, range, readLocalStorageValue, readSessionStorageValue, readonlySetLikeToSet, scopeTab, shallowEqual, tabbable, unformatMask, upperFirst, useCallbackRef, useClickOutside, useClipboard, useCollapse, useColorScheme, useCounter, useDebouncedCallback, useDebouncedState, useDebouncedValue, useDidUpdate, useDisclosure, useDocumentTitle, useDocumentVisibility, useDrag, useElementSize, useEventListener, useEyeDropper, useFavicon, useFetch, useFileDialog, useFloatingWindow, useFocusReturn, useFocusTrap, useFocusWithin, useForceUpdate, useFullscreenDocument, useFullscreenElement, useHash, useHeadroom, useHorizontalCollapse, useHotkeys, useHover, useId, useIdle, useInViewport, useInputState, useIntersection, useInterval, useIsFirstRender, useIsomorphicEffect, useListState, useLocalStorage, useLogger, useLongPress, useMap, useMask, useMediaQuery, useMergedRef, useMounted, useMouse, useMousePosition, useMove, useMutationObserver, useMutationObserverTarget, useNetwork, useOrientation, useOs, usePageLeave, usePagination, usePrevious, useQueue, useRadialMove, useReducedMotion, useResizeObserver, useRovingIndex, useScrollDirection, useScrollIntoView, useScrollSpy, useScroller, useSelection, useSessionStorage, useSet, useSetState, useShallowEffect, useSplitter, useStateHistory, useTextSelection, useThrottledCallback, useThrottledState, useThrottledValue, useTimeout, useToggle, useUncontrolled, useValidatedState, useViewportSize, useWindowEvent, useWindowScroll };
4578
+
4579
+ //# sourceMappingURL=index.mjs.map