@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.
- package/cjs/index.cjs +4696 -0
- package/cjs/index.cjs.map +1 -0
- package/esm/index.mjs +4579 -0
- package/esm/index.mjs.map +1 -0
- package/lib/index.d.mts +141 -0
- package/lib/index.d.ts +141 -0
- package/lib/use-click-outside/use-click-outside.d.ts +4 -0
- package/lib/use-clipboard/use-clipboard.d.ts +11 -0
- package/lib/use-collapse/use-collapse.d.ts +38 -0
- package/lib/use-collapse/use-horizontal-collapse.d.ts +4 -0
- package/lib/use-color-scheme/use-color-scheme.d.ts +4 -0
- package/lib/use-counter/use-counter.d.ts +14 -0
- package/lib/use-debounced-callback/use-debounced-callback.d.ts +12 -0
- package/lib/use-debounced-state/use-debounced-state.d.ts +6 -0
- package/lib/use-debounced-value/use-debounced-value.d.ts +14 -0
- package/lib/use-did-update/use-did-update.d.ts +2 -0
- package/lib/use-disclosure/use-disclosure.d.ts +13 -0
- package/lib/use-document-title/use-document-title.d.ts +2 -0
- package/lib/use-document-visibility/use-document-visibility.d.ts +2 -0
- package/lib/use-drag/use-drag.d.ts +56 -0
- package/lib/use-event-listener/use-event-listener.d.ts +2 -0
- package/lib/use-eye-dropper/use-eye-dropper.d.ts +12 -0
- package/lib/use-favicon/use-favicon.d.ts +2 -0
- package/lib/use-fetch/use-fetch.d.ts +12 -0
- package/lib/use-file-dialog/use-file-dialog.d.ts +25 -0
- package/lib/use-floating-window/use-floating-window.d.ts +30 -0
- package/lib/use-focus-return/use-focus-return.d.ts +6 -0
- package/lib/use-focus-trap/scope-tab.d.ts +1 -0
- package/lib/use-focus-trap/tabbable.d.ts +4 -0
- package/lib/use-focus-trap/use-focus-trap.d.ts +5 -0
- package/lib/use-focus-within/use-focus-within.d.ts +10 -0
- package/lib/use-force-update/use-force-update.d.ts +2 -0
- package/lib/use-fullscreen/use-fullscreen.d.ts +12 -0
- package/lib/use-hash/use-hash.d.ts +6 -0
- package/lib/use-headroom/use-headroom.d.ts +27 -0
- package/lib/use-hotkeys/parse-hotkey.d.ts +20 -0
- package/lib/use-hotkeys/use-hotkeys.d.ts +15 -0
- package/lib/use-hover/use-hover.d.ts +6 -0
- package/lib/use-id/use-id.d.ts +2 -0
- package/lib/use-idle/use-idle.d.ts +6 -0
- package/lib/use-in-viewport/use-in-viewport.d.ts +6 -0
- package/lib/use-input-state/use-input-state.d.ts +6 -0
- package/lib/use-intersection/use-intersection.d.ts +6 -0
- package/lib/use-interval/use-interval.d.ts +16 -0
- package/lib/use-is-first-render/use-is-first-render.d.ts +2 -0
- package/lib/use-isomorphic-effect/use-isomorphic-effect.d.ts +1 -0
- package/lib/use-list-state/use-list-state.d.ts +25 -0
- package/lib/use-local-storage/create-storage.d.ts +23 -0
- package/lib/use-local-storage/use-local-storage.d.ts +3 -0
- package/lib/use-logger/use-logger.d.ts +2 -0
- package/lib/use-long-press/use-long-press.d.ts +20 -0
- package/lib/use-map/use-map.d.ts +1 -0
- package/lib/use-mask/use-mask.d.ts +57 -0
- package/lib/use-media-query/use-media-query.d.ts +5 -0
- package/lib/use-merged-ref/use-merged-ref.d.ts +6 -0
- package/lib/use-mounted/use-mounted.d.ts +2 -0
- package/lib/use-mouse/use-mouse.d.ts +15 -0
- package/lib/use-move/use-move.d.ts +17 -0
- package/lib/use-mutation-observer/use-mutation-observer.d.ts +3 -0
- package/lib/use-network/use-network.d.ts +11 -0
- package/lib/use-orientation/use-orientation.d.ts +23 -0
- package/lib/use-os/use-os.d.ts +6 -0
- package/lib/use-page-leave/use-page-leave.d.ts +2 -0
- package/lib/use-pagination/use-pagination.d.ts +20 -0
- package/lib/use-previous/use-previous.d.ts +2 -0
- package/lib/use-queue/use-queue.d.ts +20 -0
- package/lib/use-radial-move/use-radial-move.d.ts +13 -0
- package/lib/use-reduced-motion/use-reduced-motion.d.ts +3 -0
- package/lib/use-resize-observer/use-resize-observer.d.ts +13 -0
- package/lib/use-roving-index/use-roving-index.d.ts +45 -0
- package/lib/use-scroll-direction/use-scroll-direction.d.ts +3 -0
- package/lib/use-scroll-into-view/use-scroll-into-view.d.ts +32 -0
- package/lib/use-scroll-spy/use-scroll-spy.d.ts +30 -0
- package/lib/use-scroller/use-scroller.d.ts +25 -0
- package/lib/use-selection/use-selection.d.ts +27 -0
- package/lib/use-session-storage/use-session-storage.d.ts +3 -0
- package/lib/use-set/use-set.d.ts +9 -0
- package/lib/use-set-state/use-set-state.d.ts +4 -0
- package/lib/use-shallow-effect/use-shallow-effect.d.ts +2 -0
- package/lib/use-splitter/use-splitter.d.ts +94 -0
- package/lib/use-state-history/use-state-history.d.ts +17 -0
- package/lib/use-text-selection/use-text-selection.d.ts +2 -0
- package/lib/use-throttled-callback/use-throttled-callback.d.ts +2 -0
- package/lib/use-throttled-state/use-throttled-state.d.ts +3 -0
- package/lib/use-throttled-value/use-throttled-value.d.ts +2 -0
- package/lib/use-timeout/use-timeout.d.ts +8 -0
- package/lib/use-toggle/use-toggle.d.ts +4 -0
- package/lib/use-uncontrolled/use-uncontrolled.d.ts +13 -0
- package/lib/use-validated-state/use-validated-state.d.ts +16 -0
- package/lib/use-viewport-size/use-viewport-size.d.ts +6 -0
- package/lib/use-window-event/use-window-event.d.ts +2 -0
- package/lib/use-window-scroll/use-window-scroll.d.ts +8 -0
- package/lib/utils/clamp/clamp.d.ts +1 -0
- package/lib/utils/index.d.ts +7 -0
- package/lib/utils/lower-first/lower-first.d.ts +1 -0
- package/lib/utils/random-id/random-id.d.ts +1 -0
- package/lib/utils/range/range.d.ts +1 -0
- package/lib/utils/shallow-equal/shallow-equal.d.ts +1 -0
- package/lib/utils/upper-first/upper-first.d.ts +1 -0
- package/lib/utils/use-callback-ref/use-callback-ref.d.ts +2 -0
- 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
|