@omnitron-dev/prism 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -0
  3. package/bin/prism.js +13 -0
  4. package/dist/accessibility/index.d.ts +157 -0
  5. package/dist/accessibility/index.js +186 -0
  6. package/dist/accessibility/index.js.map +1 -0
  7. package/dist/blocks/index.d.ts +1239 -0
  8. package/dist/blocks/index.js +1712 -0
  9. package/dist/blocks/index.js.map +1 -0
  10. package/dist/chunk-77KIJLPP.js +37 -0
  11. package/dist/chunk-77KIJLPP.js.map +1 -0
  12. package/dist/chunk-BTIT7WYH.js +339 -0
  13. package/dist/chunk-BTIT7WYH.js.map +1 -0
  14. package/dist/chunk-BV32OJ2A.js +1409 -0
  15. package/dist/chunk-BV32OJ2A.js.map +1 -0
  16. package/dist/chunk-DDY7TLUI.js +139 -0
  17. package/dist/chunk-DDY7TLUI.js.map +1 -0
  18. package/dist/chunk-DXXZ3ITR.js +4227 -0
  19. package/dist/chunk-DXXZ3ITR.js.map +1 -0
  20. package/dist/chunk-E3XANPTO.js +2319 -0
  21. package/dist/chunk-E3XANPTO.js.map +1 -0
  22. package/dist/chunk-FU52GL2E.js +3 -0
  23. package/dist/chunk-FU52GL2E.js.map +1 -0
  24. package/dist/chunk-GYDT5EKX.js +16505 -0
  25. package/dist/chunk-GYDT5EKX.js.map +1 -0
  26. package/dist/chunk-HO2GKTWJ.js +28 -0
  27. package/dist/chunk-HO2GKTWJ.js.map +1 -0
  28. package/dist/chunk-JDTC2SBY.js +140 -0
  29. package/dist/chunk-JDTC2SBY.js.map +1 -0
  30. package/dist/chunk-JNU4QHJK.js +6 -0
  31. package/dist/chunk-JNU4QHJK.js.map +1 -0
  32. package/dist/chunk-LAEY5USO.js +2621 -0
  33. package/dist/chunk-LAEY5USO.js.map +1 -0
  34. package/dist/chunk-UR6X3W5I.js +530 -0
  35. package/dist/chunk-UR6X3W5I.js.map +1 -0
  36. package/dist/chunk-WC2WM2JD.js +883 -0
  37. package/dist/chunk-WC2WM2JD.js.map +1 -0
  38. package/dist/chunk-XWL6J6IO.js +40 -0
  39. package/dist/chunk-XWL6J6IO.js.map +1 -0
  40. package/dist/cli/index.js +2695 -0
  41. package/dist/cli/index.js.map +1 -0
  42. package/dist/config-BA6IeTq9.d.ts +100 -0
  43. package/dist/core/index.d.ts +454 -0
  44. package/dist/core/index.js +9 -0
  45. package/dist/core/index.js.map +1 -0
  46. package/dist/forms/index.d.ts +562 -0
  47. package/dist/forms/index.js +545 -0
  48. package/dist/forms/index.js.map +1 -0
  49. package/dist/hooks/index.d.ts +7 -0
  50. package/dist/hooks/index.js +10 -0
  51. package/dist/hooks/index.js.map +1 -0
  52. package/dist/http/index.d.ts +233 -0
  53. package/dist/http/index.js +282 -0
  54. package/dist/http/index.js.map +1 -0
  55. package/dist/index-odhPSv9I.d.ts +2491 -0
  56. package/dist/index.css +131 -0
  57. package/dist/index.css.map +1 -0
  58. package/dist/index.d.ts +9109 -0
  59. package/dist/index.js +13280 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/layouts/index.d.ts +854 -0
  62. package/dist/layouts/index.js +6 -0
  63. package/dist/layouts/index.js.map +1 -0
  64. package/dist/netron/index.d.ts +4 -0
  65. package/dist/netron/index.js +4 -0
  66. package/dist/netron/index.js.map +1 -0
  67. package/dist/registry/index.d.ts +352 -0
  68. package/dist/registry/index.js +4 -0
  69. package/dist/registry/index.js.map +1 -0
  70. package/dist/registry-BrDNftd5.d.ts +574 -0
  71. package/dist/settings-plpR26Xk.d.ts +455 -0
  72. package/dist/state/index.d.ts +981 -0
  73. package/dist/state/index.js +5 -0
  74. package/dist/state/index.js.map +1 -0
  75. package/dist/theme/index.d.ts +1049 -0
  76. package/dist/theme/index.js +5 -0
  77. package/dist/theme/index.js.map +1 -0
  78. package/dist/theme-CrXLfP1c.d.ts +389 -0
  79. package/dist/types/index.d.ts +146 -0
  80. package/dist/types/index.js +5 -0
  81. package/dist/types/index.js.map +1 -0
  82. package/dist/use-timeout-D7U3EAtH.d.ts +808 -0
  83. package/package.json +194 -0
@@ -0,0 +1,2319 @@
1
+ import { useIsClient } from './chunk-WC2WM2JD.js';
2
+ import { PRESET_NAMES } from './chunk-DXXZ3ITR.js';
3
+ import { useLayoutEffect, useEffect, useState, useRef, useCallback, useMemo, useSyncExternalStore } from 'react';
4
+ import Popover from '@mui/material/Popover';
5
+ import { styled, alpha } from '@mui/material/styles';
6
+ import { listClasses } from '@mui/material/List';
7
+ import { menuItemClasses } from '@mui/material/MenuItem';
8
+ import { jsxs, jsx } from 'react/jsx-runtime';
9
+
10
+ function useAsync(asyncFn, options = {}) {
11
+ const { initialData = null, immediate = false, onSuccess, onError } = options;
12
+ const [state, setState] = useState({
13
+ data: initialData,
14
+ loading: immediate,
15
+ error: null
16
+ });
17
+ const isMounted = useRef(true);
18
+ const executingRef = useRef(false);
19
+ useEffect(() => {
20
+ isMounted.current = true;
21
+ return () => {
22
+ isMounted.current = false;
23
+ };
24
+ }, []);
25
+ const execute = useCallback(
26
+ async (...args) => {
27
+ if (executingRef.current) {
28
+ return Promise.reject(new Error("Operation already in progress"));
29
+ }
30
+ executingRef.current = true;
31
+ if (isMounted.current) {
32
+ setState((prev) => ({ ...prev, loading: true, error: null }));
33
+ }
34
+ try {
35
+ const result = await asyncFn(...args);
36
+ if (isMounted.current) {
37
+ setState({ data: result, loading: false, error: null });
38
+ onSuccess?.(result);
39
+ }
40
+ return result;
41
+ } catch (err) {
42
+ const error = err instanceof Error ? err : new Error(String(err));
43
+ if (isMounted.current) {
44
+ setState((prev) => ({ ...prev, loading: false, error }));
45
+ onError?.(error);
46
+ }
47
+ throw error;
48
+ } finally {
49
+ executingRef.current = false;
50
+ }
51
+ },
52
+ [asyncFn, onSuccess, onError]
53
+ );
54
+ const reset = useCallback(() => {
55
+ setState({ data: initialData, loading: false, error: null });
56
+ }, [initialData]);
57
+ const setData = useCallback((data) => {
58
+ setState((prev) => ({ ...prev, data }));
59
+ }, []);
60
+ const setError = useCallback((error) => {
61
+ setState((prev) => ({ ...prev, error }));
62
+ }, []);
63
+ useEffect(() => {
64
+ if (immediate) {
65
+ execute(...[]).catch(() => {
66
+ });
67
+ }
68
+ }, []);
69
+ return useMemo(
70
+ () => ({
71
+ ...state,
72
+ execute,
73
+ reset,
74
+ setData,
75
+ setError
76
+ }),
77
+ [state, execute, reset, setData, setError]
78
+ );
79
+ }
80
+ function useAsyncFn(asyncFn) {
81
+ const [loading, setLoading] = useState(false);
82
+ const [error, setError] = useState(null);
83
+ const isMounted = useRef(true);
84
+ useEffect(() => {
85
+ isMounted.current = true;
86
+ return () => {
87
+ isMounted.current = false;
88
+ };
89
+ }, []);
90
+ const execute = useCallback(
91
+ async (...args) => {
92
+ setLoading(true);
93
+ setError(null);
94
+ try {
95
+ const result = await asyncFn(...args);
96
+ if (isMounted.current) {
97
+ setLoading(false);
98
+ }
99
+ return result;
100
+ } catch (err) {
101
+ const caughtError = err instanceof Error ? err : new Error(String(err));
102
+ if (isMounted.current) {
103
+ setLoading(false);
104
+ setError(caughtError);
105
+ }
106
+ return void 0;
107
+ }
108
+ },
109
+ [asyncFn]
110
+ );
111
+ return { execute, loading, error };
112
+ }
113
+ function useScrollPosition(options = {}) {
114
+ const { element = null, throttle = 100, threshold = 0, bottomOffset = 10 } = options;
115
+ const [position, setPosition] = useState({
116
+ x: 0,
117
+ y: 0,
118
+ directionX: 0,
119
+ directionY: 0,
120
+ isScrolled: false,
121
+ isAtTop: true,
122
+ isAtBottom: false
123
+ });
124
+ const lastPosition = useRef({ x: 0, y: 0 });
125
+ const ticking = useRef(false);
126
+ const updatePosition = useCallback(() => {
127
+ if (typeof window === "undefined") return;
128
+ const scrollX = element ? element.scrollLeft : window.scrollX;
129
+ const scrollY = element ? element.scrollTop : window.scrollY;
130
+ const maxScrollY = element ? element.scrollHeight - element.clientHeight : document.documentElement.scrollHeight - window.innerHeight;
131
+ const directionX = scrollX > lastPosition.current.x ? 1 : scrollX < lastPosition.current.x ? -1 : 0;
132
+ const directionY = scrollY > lastPosition.current.y ? 1 : scrollY < lastPosition.current.y ? -1 : 0;
133
+ lastPosition.current = { x: scrollX, y: scrollY };
134
+ setPosition({
135
+ x: scrollX,
136
+ y: scrollY,
137
+ directionX,
138
+ directionY,
139
+ isScrolled: scrollY > threshold,
140
+ isAtTop: scrollY <= 0,
141
+ isAtBottom: scrollY >= maxScrollY - bottomOffset
142
+ });
143
+ ticking.current = false;
144
+ }, [element, threshold, bottomOffset]);
145
+ const handleScroll = useCallback(() => {
146
+ if (!ticking.current) {
147
+ if (throttle > 0) {
148
+ window.requestAnimationFrame(() => {
149
+ updatePosition();
150
+ });
151
+ } else {
152
+ updatePosition();
153
+ }
154
+ ticking.current = true;
155
+ if (throttle > 0) {
156
+ setTimeout(() => {
157
+ ticking.current = false;
158
+ }, throttle);
159
+ }
160
+ }
161
+ }, [throttle, updatePosition]);
162
+ useEffect(() => {
163
+ if (typeof window === "undefined") return void 0;
164
+ const target = element ?? window;
165
+ updatePosition();
166
+ target.addEventListener("scroll", handleScroll, { passive: true });
167
+ return () => {
168
+ target.removeEventListener("scroll", handleScroll);
169
+ };
170
+ }, [element, handleScroll, updatePosition]);
171
+ return position;
172
+ }
173
+ function useScrollToTop(options = {}) {
174
+ const { threshold = 300 } = options;
175
+ const { y } = useScrollPosition({ threshold });
176
+ const scrollToTop = useCallback(() => {
177
+ window.scrollTo({ top: 0, behavior: "smooth" });
178
+ }, []);
179
+ return {
180
+ scrollToTop,
181
+ showButton: y > threshold
182
+ };
183
+ }
184
+ function useScrollLock() {
185
+ const [isLocked, setIsLocked] = useState(false);
186
+ const scrollY = useRef(0);
187
+ const lock = useCallback(() => {
188
+ if (typeof document === "undefined") return;
189
+ scrollY.current = window.scrollY;
190
+ document.body.style.position = "fixed";
191
+ document.body.style.top = `-${scrollY.current}px`;
192
+ document.body.style.width = "100%";
193
+ document.body.style.overflow = "hidden";
194
+ setIsLocked(true);
195
+ }, []);
196
+ const unlock = useCallback(() => {
197
+ if (typeof document === "undefined") return;
198
+ document.body.style.position = "";
199
+ document.body.style.top = "";
200
+ document.body.style.width = "";
201
+ document.body.style.overflow = "";
202
+ window.scrollTo(0, scrollY.current);
203
+ setIsLocked(false);
204
+ }, []);
205
+ useEffect(
206
+ () => () => {
207
+ if (isLocked) {
208
+ document.body.style.position = "";
209
+ document.body.style.top = "";
210
+ document.body.style.width = "";
211
+ document.body.style.overflow = "";
212
+ }
213
+ },
214
+ [isLocked]
215
+ );
216
+ return { lock, unlock, isLocked };
217
+ }
218
+ var defaultBreakpoints = {
219
+ xs: 0,
220
+ sm: 600,
221
+ md: 900,
222
+ lg: 1200,
223
+ xl: 1536
224
+ };
225
+ function useWindowSize(options = {}) {
226
+ const { breakpoints: customBreakpoints, debounce = 100, initialWidth = 1200, initialHeight = 800 } = options;
227
+ const breakpoints = { ...defaultBreakpoints, ...customBreakpoints };
228
+ const getSize = useCallback(() => {
229
+ if (typeof window === "undefined") {
230
+ return {
231
+ width: initialWidth,
232
+ height: initialHeight,
233
+ isMobile: initialWidth < breakpoints.sm,
234
+ isTablet: initialWidth >= breakpoints.sm && initialWidth < breakpoints.md,
235
+ isDesktop: initialWidth >= breakpoints.md,
236
+ isLargeDesktop: initialWidth >= breakpoints.lg
237
+ };
238
+ }
239
+ const width = window.innerWidth;
240
+ const height = window.innerHeight;
241
+ return {
242
+ width,
243
+ height,
244
+ isMobile: width < breakpoints.sm,
245
+ isTablet: width >= breakpoints.sm && width < breakpoints.md,
246
+ isDesktop: width >= breakpoints.md,
247
+ isLargeDesktop: width >= breakpoints.lg
248
+ };
249
+ }, [breakpoints.sm, breakpoints.md, breakpoints.lg, initialWidth, initialHeight]);
250
+ const [size, setSize] = useState(getSize);
251
+ const timeoutRef = useRef(null);
252
+ useEffect(() => {
253
+ if (typeof window === "undefined") return void 0;
254
+ const handleResize = () => {
255
+ if (debounce > 0) {
256
+ if (timeoutRef.current) {
257
+ clearTimeout(timeoutRef.current);
258
+ }
259
+ timeoutRef.current = setTimeout(() => {
260
+ setSize(getSize());
261
+ }, debounce);
262
+ } else {
263
+ setSize(getSize());
264
+ }
265
+ };
266
+ setSize(getSize());
267
+ window.addEventListener("resize", handleResize);
268
+ return () => {
269
+ window.removeEventListener("resize", handleResize);
270
+ if (timeoutRef.current) {
271
+ clearTimeout(timeoutRef.current);
272
+ }
273
+ };
274
+ }, [debounce, getSize]);
275
+ return size;
276
+ }
277
+ function useResponsiveQuery(query) {
278
+ const [matches, setMatches] = useState(() => {
279
+ if (typeof window === "undefined") return false;
280
+ return window.matchMedia(query).matches;
281
+ });
282
+ useEffect(() => {
283
+ if (typeof window === "undefined") return void 0;
284
+ const mediaQuery = window.matchMedia(query);
285
+ const handleChange = (event) => {
286
+ setMatches(event.matches);
287
+ };
288
+ setMatches(mediaQuery.matches);
289
+ if (mediaQuery.addEventListener) {
290
+ mediaQuery.addEventListener("change", handleChange);
291
+ return () => mediaQuery.removeEventListener("change", handleChange);
292
+ }
293
+ mediaQuery.addListener(handleChange);
294
+ return () => mediaQuery.removeListener(handleChange);
295
+ }, [query]);
296
+ return matches;
297
+ }
298
+ function useBreakpoint(customBreakpoints) {
299
+ const breakpoints = { ...defaultBreakpoints, ...customBreakpoints };
300
+ const { width } = useWindowSize({ breakpoints: customBreakpoints });
301
+ if (width >= breakpoints.xl) return "xl";
302
+ if (width >= breakpoints.lg) return "lg";
303
+ if (width >= breakpoints.md) return "md";
304
+ if (width >= breakpoints.sm) return "sm";
305
+ return "xs";
306
+ }
307
+ function useBreakpointChecks(customBreakpoints) {
308
+ const breakpoints = useMemo(() => ({ ...defaultBreakpoints, ...customBreakpoints }), [customBreakpoints]);
309
+ const { width } = useWindowSize({ breakpoints: customBreakpoints });
310
+ const orderedBreakpoints = ["xs", "sm", "md", "lg", "xl"];
311
+ const getNextBreakpoint = (bp) => {
312
+ const index = orderedBreakpoints.indexOf(bp);
313
+ return index < orderedBreakpoints.length - 1 ? orderedBreakpoints[index + 1] : null;
314
+ };
315
+ const isUp = useCallback(
316
+ (breakpoint) => width >= breakpoints[breakpoint],
317
+ [width, breakpoints]
318
+ );
319
+ const isDown = useCallback(
320
+ (breakpoint) => width < breakpoints[breakpoint],
321
+ [width, breakpoints]
322
+ );
323
+ const isOnly = useCallback(
324
+ (breakpoint) => {
325
+ const next = getNextBreakpoint(breakpoint);
326
+ const min = breakpoints[breakpoint];
327
+ const max = next ? breakpoints[next] : Infinity;
328
+ return width >= min && width < max;
329
+ },
330
+ [width, breakpoints]
331
+ );
332
+ const isBetween = useCallback(
333
+ (start, end) => width >= breakpoints[start] && width < breakpoints[end],
334
+ [width, breakpoints]
335
+ );
336
+ return { isUp, isDown, isOnly, isBetween };
337
+ }
338
+ var defaultValues = {
339
+ top: 0,
340
+ right: 0,
341
+ bottom: 0,
342
+ left: 0,
343
+ x: 0,
344
+ y: 0,
345
+ width: 0,
346
+ height: 0,
347
+ scrollWidth: 0,
348
+ scrollHeight: 0
349
+ };
350
+ function useClientRect(inputRef, eventType) {
351
+ const internalRef = useRef(null);
352
+ const elementRef = inputRef ?? internalRef;
353
+ const [rect, setRect] = useState(defaultValues);
354
+ const update = useCallback(() => {
355
+ const element = elementRef.current;
356
+ if (!element) {
357
+ setRect(defaultValues);
358
+ return;
359
+ }
360
+ const domRect = element.getBoundingClientRect();
361
+ setRect({
362
+ top: domRect.top,
363
+ right: domRect.right,
364
+ bottom: domRect.bottom,
365
+ left: domRect.left,
366
+ x: domRect.x,
367
+ y: domRect.y,
368
+ width: domRect.width,
369
+ height: domRect.height,
370
+ scrollWidth: element.scrollWidth,
371
+ scrollHeight: element.scrollHeight
372
+ });
373
+ }, [elementRef]);
374
+ useEffect(() => {
375
+ const element = elementRef.current;
376
+ update();
377
+ if (!element || typeof window === "undefined") return void 0;
378
+ const resizeObserver = new ResizeObserver(() => {
379
+ update();
380
+ });
381
+ resizeObserver.observe(element);
382
+ const target = eventType === "scroll" ? element : window;
383
+ const event = eventType ?? "resize";
384
+ const handleEvent = () => {
385
+ update();
386
+ };
387
+ target.addEventListener(event, handleEvent, { passive: true });
388
+ return () => {
389
+ resizeObserver.disconnect();
390
+ target.removeEventListener(event, handleEvent);
391
+ };
392
+ }, [elementRef, eventType, update]);
393
+ return {
394
+ ...rect,
395
+ elementRef,
396
+ update
397
+ };
398
+ }
399
+ function usePopoverHover(inputRef) {
400
+ const internalRef = useRef(null);
401
+ const elementRef = inputRef ?? internalRef;
402
+ const [open, setOpen] = useState(false);
403
+ const onOpen = useCallback(() => {
404
+ setOpen(true);
405
+ }, []);
406
+ const onClose = useCallback(() => {
407
+ setOpen(false);
408
+ }, []);
409
+ const anchorEl = open ? elementRef.current : null;
410
+ return {
411
+ open,
412
+ anchorEl,
413
+ onOpen,
414
+ onClose,
415
+ elementRef,
416
+ setOpen
417
+ };
418
+ }
419
+ var POPOVER_DISTANCE = 0.75;
420
+ function calculateAnchorOrigin(arrow = "top-right") {
421
+ const configs = {
422
+ "top-left": {
423
+ paperStyles: { ml: -POPOVER_DISTANCE },
424
+ anchorOrigin: { vertical: "bottom", horizontal: "left" },
425
+ transformOrigin: { vertical: "top", horizontal: "left" }
426
+ },
427
+ "top-center": {
428
+ paperStyles: void 0,
429
+ anchorOrigin: { vertical: "bottom", horizontal: "center" },
430
+ transformOrigin: { vertical: "top", horizontal: "center" }
431
+ },
432
+ "top-right": {
433
+ paperStyles: { ml: POPOVER_DISTANCE },
434
+ anchorOrigin: { vertical: "bottom", horizontal: "right" },
435
+ transformOrigin: { vertical: "top", horizontal: "right" }
436
+ },
437
+ "bottom-left": {
438
+ paperStyles: { ml: -POPOVER_DISTANCE },
439
+ anchorOrigin: { vertical: "top", horizontal: "left" },
440
+ transformOrigin: { vertical: "bottom", horizontal: "left" }
441
+ },
442
+ "bottom-center": {
443
+ paperStyles: void 0,
444
+ anchorOrigin: { vertical: "top", horizontal: "center" },
445
+ transformOrigin: { vertical: "bottom", horizontal: "center" }
446
+ },
447
+ "bottom-right": {
448
+ paperStyles: { ml: POPOVER_DISTANCE },
449
+ anchorOrigin: { vertical: "top", horizontal: "right" },
450
+ transformOrigin: { vertical: "bottom", horizontal: "right" }
451
+ },
452
+ "left-top": {
453
+ paperStyles: { mt: -POPOVER_DISTANCE },
454
+ anchorOrigin: { vertical: "top", horizontal: "right" },
455
+ transformOrigin: { vertical: "top", horizontal: "left" }
456
+ },
457
+ "left-center": {
458
+ paperStyles: void 0,
459
+ anchorOrigin: { vertical: "center", horizontal: "right" },
460
+ transformOrigin: { vertical: "center", horizontal: "left" }
461
+ },
462
+ "left-bottom": {
463
+ paperStyles: { mt: POPOVER_DISTANCE },
464
+ anchorOrigin: { vertical: "bottom", horizontal: "right" },
465
+ transformOrigin: { vertical: "bottom", horizontal: "left" }
466
+ },
467
+ "right-top": {
468
+ paperStyles: { mt: -POPOVER_DISTANCE },
469
+ anchorOrigin: { vertical: "top", horizontal: "left" },
470
+ transformOrigin: { vertical: "top", horizontal: "right" }
471
+ },
472
+ "right-center": {
473
+ paperStyles: void 0,
474
+ anchorOrigin: { vertical: "center", horizontal: "left" },
475
+ transformOrigin: { vertical: "center", horizontal: "right" }
476
+ },
477
+ "right-bottom": {
478
+ paperStyles: { mt: POPOVER_DISTANCE },
479
+ anchorOrigin: { vertical: "bottom", horizontal: "left" },
480
+ transformOrigin: { vertical: "bottom", horizontal: "right" }
481
+ }
482
+ };
483
+ return configs[arrow] || configs["top-right"];
484
+ }
485
+ var Arrow = styled("span", {
486
+ shouldForwardProp: (prop) => prop !== "ownerState"
487
+ })(({ theme, ownerState }) => {
488
+ const { size, offset, placement } = ownerState;
489
+ const directions = {
490
+ top: { top: 0, rotate: "135deg", translate: "0 -50%" },
491
+ bottom: { bottom: 0, rotate: "-45deg", translate: "0 50%" },
492
+ left: { left: 0, rotate: "45deg", translate: "-50% 0" },
493
+ right: { right: 0, rotate: "-135deg", translate: "50% 0" }
494
+ };
495
+ const getDirection = () => {
496
+ if (placement.startsWith("top-")) return directions.top;
497
+ if (placement.startsWith("bottom-")) return directions.bottom;
498
+ if (placement.startsWith("left-")) return directions.left;
499
+ if (placement.startsWith("right-")) return directions.right;
500
+ return {};
501
+ };
502
+ const getPosition = () => {
503
+ if (placement.endsWith("-left")) return { left: offset };
504
+ if (placement.endsWith("-right")) return { right: offset };
505
+ if (placement.endsWith("-top")) return { top: offset };
506
+ if (placement.endsWith("-bottom")) return { bottom: offset };
507
+ if (placement.endsWith("-center")) {
508
+ if (placement.startsWith("top-") || placement.startsWith("bottom-")) {
509
+ return { left: 0, right: 0, margin: "auto" };
510
+ }
511
+ return { top: 0, bottom: 0, margin: "auto" };
512
+ }
513
+ return {};
514
+ };
515
+ return {
516
+ width: size,
517
+ height: size,
518
+ position: "absolute",
519
+ borderBottomLeftRadius: size / 4,
520
+ clipPath: "polygon(0% 0%, 100% 100%, 0% 100%)",
521
+ backgroundColor: theme.palette.background.paper,
522
+ border: `solid 1px ${alpha(theme.palette.grey[500], 0.12)}`,
523
+ ...getDirection(),
524
+ ...getPosition()
525
+ };
526
+ });
527
+ function CustomPopover({
528
+ open,
529
+ onClose,
530
+ children,
531
+ anchorEl,
532
+ arrow,
533
+ minWidth = 140,
534
+ slotProps,
535
+ ...other
536
+ }) {
537
+ const arrowSize = arrow?.size ?? 14;
538
+ const arrowOffset = arrow?.offset ?? 17;
539
+ const arrowPlacement = arrow?.placement ?? "top-right";
540
+ const hideArrow = arrow?.hide ?? false;
541
+ const { paperStyles, anchorOrigin, transformOrigin } = calculateAnchorOrigin(arrowPlacement);
542
+ const isOpen = Boolean(open);
543
+ return /* @__PURE__ */ jsxs(
544
+ Popover,
545
+ {
546
+ open: isOpen,
547
+ anchorEl,
548
+ onClose,
549
+ anchorOrigin,
550
+ transformOrigin,
551
+ slotProps: {
552
+ ...slotProps,
553
+ paper: {
554
+ ...typeof slotProps?.paper === "object" ? slotProps.paper : {},
555
+ sx: [
556
+ paperStyles,
557
+ {
558
+ overflow: "inherit",
559
+ [`& .${listClasses.root}`]: { minWidth },
560
+ [`& .${menuItemClasses.root}`]: { gap: 2 }
561
+ },
562
+ ...typeof slotProps?.paper === "object" && slotProps.paper && "sx" in slotProps.paper ? Array.isArray(slotProps.paper.sx) ? slotProps.paper.sx : [slotProps.paper.sx] : []
563
+ ]
564
+ }
565
+ },
566
+ ...other,
567
+ children: [
568
+ !hideArrow && /* @__PURE__ */ jsx(
569
+ Arrow,
570
+ {
571
+ ownerState: {
572
+ size: arrowSize,
573
+ offset: arrowOffset,
574
+ placement: arrowPlacement
575
+ },
576
+ sx: arrow?.sx
577
+ }
578
+ ),
579
+ children
580
+ ]
581
+ }
582
+ );
583
+ }
584
+ function usePopover() {
585
+ const [anchorEl, setAnchorEl] = useState(null);
586
+ const onOpen = useCallback((event) => {
587
+ setAnchorEl(event.currentTarget);
588
+ }, []);
589
+ const onClose = useCallback(() => {
590
+ setAnchorEl(null);
591
+ }, []);
592
+ return {
593
+ open: Boolean(anchorEl),
594
+ anchorEl,
595
+ onOpen,
596
+ onClose,
597
+ setAnchorEl
598
+ };
599
+ }
600
+
601
+ // src/utils/cookies.ts
602
+ function cookiesAvailable() {
603
+ if (typeof document === "undefined") {
604
+ return false;
605
+ }
606
+ try {
607
+ document.cookie = "__test__=1";
608
+ const result = document.cookie.includes("__test__=1");
609
+ document.cookie = "__test__=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
610
+ return result;
611
+ } catch {
612
+ return false;
613
+ }
614
+ }
615
+ function getCookie(key) {
616
+ if (typeof document === "undefined") {
617
+ return null;
618
+ }
619
+ try {
620
+ const name = `${key}=`;
621
+ const decodedCookie = decodeURIComponent(document.cookie);
622
+ const cookies = decodedCookie.split(";");
623
+ for (const cookie of cookies) {
624
+ const c = cookie.trim();
625
+ if (c.startsWith(name)) {
626
+ const value = c.substring(name.length);
627
+ return JSON.parse(value);
628
+ }
629
+ }
630
+ return null;
631
+ } catch {
632
+ return null;
633
+ }
634
+ }
635
+ function setCookie(key, value, options = {}) {
636
+ if (typeof document === "undefined") {
637
+ return;
638
+ }
639
+ const { secure = false, daysUntilExpiration = 30, sameSite = "lax", domain, path = "/" } = options;
640
+ try {
641
+ const serializedValue = JSON.stringify(value);
642
+ let cookieString = `${key}=${encodeURIComponent(serializedValue)}`;
643
+ if (daysUntilExpiration) {
644
+ const date = /* @__PURE__ */ new Date();
645
+ date.setTime(date.getTime() + daysUntilExpiration * 24 * 60 * 60 * 1e3);
646
+ cookieString += `; expires=${date.toUTCString()}`;
647
+ }
648
+ cookieString += `; path=${path}`;
649
+ cookieString += `; SameSite=${sameSite}`;
650
+ if (secure) {
651
+ cookieString += "; Secure";
652
+ }
653
+ if (domain) {
654
+ cookieString += `; domain=${domain}`;
655
+ }
656
+ document.cookie = cookieString;
657
+ } catch (error) {
658
+ console.warn(`Failed to set cookie "${key}":`, error);
659
+ }
660
+ }
661
+ function removeCookie(key, options = {}) {
662
+ if (typeof document === "undefined") {
663
+ return;
664
+ }
665
+ const { domain, path = "/" } = options;
666
+ let cookieString = `${key}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}`;
667
+ if (domain) {
668
+ cookieString += `; domain=${domain}`;
669
+ }
670
+ document.cookie = cookieString;
671
+ }
672
+
673
+ // src/hooks/use-cookies.ts
674
+ function useCookies(key, initialState, options) {
675
+ const { initializeWithValue = true, ...cookieOptions } = options ?? {};
676
+ const [state, setStateInternal] = useState(initialState);
677
+ useEffect(() => {
678
+ const storedValue = getCookie(key);
679
+ const isObject = initialState !== null && typeof initialState === "object";
680
+ if (storedValue !== null) {
681
+ if (isObject) {
682
+ setStateInternal((prev) => ({ ...prev, ...storedValue }));
683
+ } else {
684
+ setStateInternal(storedValue);
685
+ }
686
+ } else if (initializeWithValue) {
687
+ setCookie(key, initialState, cookieOptions);
688
+ }
689
+ }, []);
690
+ const isObjectState = initialState !== null && typeof initialState === "object";
691
+ const updateState = useCallback(
692
+ (newState) => {
693
+ if (isObjectState) {
694
+ setStateInternal((prev) => {
695
+ const updatedState = { ...prev, ...newState };
696
+ setCookie(key, updatedState, cookieOptions);
697
+ return updatedState;
698
+ });
699
+ } else {
700
+ setCookie(key, newState, cookieOptions);
701
+ setStateInternal(newState);
702
+ }
703
+ },
704
+ [cookieOptions, isObjectState, key]
705
+ );
706
+ const updateField = useCallback(
707
+ (fieldName, updateValue) => {
708
+ if (isObjectState) {
709
+ updateState({ [fieldName]: updateValue });
710
+ } else {
711
+ console.warn("[useCookies] setField is only available for object states. Use setState instead.");
712
+ }
713
+ },
714
+ [isObjectState, updateState]
715
+ );
716
+ const resetState = useCallback(
717
+ (defaultState) => {
718
+ setStateInternal(defaultState ?? initialState);
719
+ removeCookie(key, { path: cookieOptions.path, domain: cookieOptions.domain });
720
+ },
721
+ [initialState, key, cookieOptions.path, cookieOptions.domain]
722
+ );
723
+ return useMemo(
724
+ () => ({
725
+ state,
726
+ setState: updateState,
727
+ setField: updateField,
728
+ resetState
729
+ }),
730
+ [state, updateState, updateField, resetState]
731
+ );
732
+ }
733
+ function useDoubleClick({ click, doubleClick, timeout = 250 }) {
734
+ const clickTimeout = useRef(null);
735
+ const clearClickTimeout = useCallback(() => {
736
+ if (clickTimeout.current) {
737
+ clearTimeout(clickTimeout.current);
738
+ clickTimeout.current = null;
739
+ }
740
+ }, []);
741
+ const handleEvent = useCallback(
742
+ (event) => {
743
+ clearClickTimeout();
744
+ if (click && event.detail === 1) {
745
+ clickTimeout.current = setTimeout(() => {
746
+ click(event);
747
+ }, timeout);
748
+ }
749
+ if (event.detail % 2 === 0) {
750
+ doubleClick(event);
751
+ }
752
+ },
753
+ [click, doubleClick, timeout, clearClickTimeout]
754
+ );
755
+ useEffect(
756
+ () => () => {
757
+ clearClickTimeout();
758
+ },
759
+ [clearClickTimeout]
760
+ );
761
+ return handleEvent;
762
+ }
763
+ function parseThreshold(input) {
764
+ if (typeof input === "string") {
765
+ if (!input.endsWith("%")) {
766
+ throw new Error('[useBackToTop] String threshold must end with % (e.g., "90%")');
767
+ }
768
+ const value = Number(input.slice(0, -1));
769
+ if (isNaN(value)) {
770
+ throw new Error("[useBackToTop] Invalid percentage value");
771
+ }
772
+ return { value, type: "percentage" };
773
+ }
774
+ return { value: input, type: "pixels" };
775
+ }
776
+ function useBackToTop(threshold = "90%", debounce = false) {
777
+ const [isVisible, setIsVisible] = useState(false);
778
+ const parsedThreshold = useMemo(() => parseThreshold(threshold), [threshold]);
779
+ const handleScroll = useCallback(() => {
780
+ if (typeof window === "undefined") return;
781
+ const windowHeight = window.innerHeight;
782
+ const scrollY = Math.round(window.scrollY);
783
+ const documentHeight = document.body.offsetHeight;
784
+ const maxScroll = documentHeight - windowHeight;
785
+ const scrollProgress = maxScroll > 0 ? Math.round(scrollY / maxScroll * 100) : 0;
786
+ if (parsedThreshold.type === "percentage") {
787
+ setIsVisible(scrollProgress >= parsedThreshold.value);
788
+ } else {
789
+ const distanceFromBottom = documentHeight - windowHeight - scrollY;
790
+ setIsVisible(distanceFromBottom <= parsedThreshold.value);
791
+ }
792
+ }, [parsedThreshold]);
793
+ const debounceTimeoutRef = useRef(null);
794
+ const debouncedHandleScroll = useCallback(() => {
795
+ if (debounceTimeoutRef.current !== null) clearTimeout(debounceTimeoutRef.current);
796
+ debounceTimeoutRef.current = setTimeout(handleScroll, 100);
797
+ }, [handleScroll]);
798
+ useEffect(() => {
799
+ if (typeof window === "undefined") return void 0;
800
+ const scrollHandler = debounce ? debouncedHandleScroll : handleScroll;
801
+ handleScroll();
802
+ window.addEventListener("scroll", scrollHandler, { passive: true });
803
+ return () => {
804
+ window.removeEventListener("scroll", scrollHandler);
805
+ if (debounceTimeoutRef.current !== null) clearTimeout(debounceTimeoutRef.current);
806
+ };
807
+ }, [debounce, debouncedHandleScroll, handleScroll]);
808
+ const onBackToTop = useCallback(() => {
809
+ if (typeof window === "undefined") return;
810
+ window.scrollTo({ top: 0, behavior: "smooth" });
811
+ }, []);
812
+ return { isVisible, onBackToTop, setIsVisible };
813
+ }
814
+ function useCountdownSeconds(initialSeconds) {
815
+ const [value, setValue] = useState(initialSeconds);
816
+ const [isCounting, setIsCounting] = useState(false);
817
+ const start = useCallback(() => {
818
+ setIsCounting(true);
819
+ }, []);
820
+ const reset = useCallback(() => {
821
+ setIsCounting(false);
822
+ setValue(initialSeconds);
823
+ }, [initialSeconds]);
824
+ useEffect(() => {
825
+ if (!isCounting) return void 0;
826
+ const intervalId = setInterval(() => {
827
+ setValue((prev) => {
828
+ if (prev <= 1) {
829
+ setIsCounting(false);
830
+ return 0;
831
+ }
832
+ return prev - 1;
833
+ });
834
+ }, 1e3);
835
+ return () => {
836
+ clearInterval(intervalId);
837
+ };
838
+ }, [isCounting]);
839
+ return useMemo(
840
+ () => ({
841
+ value,
842
+ setValue,
843
+ isCounting,
844
+ start,
845
+ reset
846
+ }),
847
+ [value, isCounting, start, reset]
848
+ );
849
+ }
850
+ function formatTime(value) {
851
+ return String(value).length === 1 ? `0${value}` : `${value}`;
852
+ }
853
+ function calculateTimeDifference(futureDate, currentDate) {
854
+ const distance = futureDate.getTime() - currentDate.getTime();
855
+ if (distance < 0) {
856
+ return { days: 0, hours: 0, minutes: 0, seconds: 0 };
857
+ }
858
+ return {
859
+ days: Math.floor(distance / (1e3 * 60 * 60 * 24)),
860
+ hours: Math.floor(distance % (1e3 * 60 * 60 * 24) / (1e3 * 60 * 60)),
861
+ minutes: Math.floor(distance % (1e3 * 60 * 60) / (1e3 * 60)),
862
+ seconds: Math.floor(distance % (1e3 * 60) / 1e3)
863
+ };
864
+ }
865
+ function useCountdownDate(targetDate, placeholder = "- -") {
866
+ const [value, setValue] = useState({
867
+ days: placeholder,
868
+ hours: placeholder,
869
+ minutes: placeholder,
870
+ seconds: placeholder
871
+ });
872
+ const handleUpdate = useCallback(() => {
873
+ const now = /* @__PURE__ */ new Date();
874
+ const { days, hours, minutes, seconds } = calculateTimeDifference(targetDate, now);
875
+ setValue({
876
+ days: formatTime(days),
877
+ hours: formatTime(hours),
878
+ minutes: formatTime(minutes),
879
+ seconds: formatTime(seconds)
880
+ });
881
+ }, [targetDate]);
882
+ useEffect(() => {
883
+ handleUpdate();
884
+ const interval = setInterval(handleUpdate, 1e3);
885
+ return () => clearInterval(interval);
886
+ }, [handleUpdate]);
887
+ return value;
888
+ }
889
+ function useScrollOffsetTop(defaultValue = 0) {
890
+ const elementRef = useRef(null);
891
+ const [offsetTop, setOffsetTop] = useState(false);
892
+ const handleScroll = useCallback(() => {
893
+ if (typeof window === "undefined") return;
894
+ const windowScrollY = window.scrollY;
895
+ if (elementRef.current) {
896
+ const elementOffsetTop = elementRef.current.offsetTop;
897
+ setOffsetTop(windowScrollY > elementOffsetTop - defaultValue);
898
+ } else {
899
+ setOffsetTop(windowScrollY > defaultValue);
900
+ }
901
+ }, [defaultValue]);
902
+ useEffect(() => {
903
+ if (typeof window === "undefined") return void 0;
904
+ handleScroll();
905
+ window.addEventListener("scroll", handleScroll, { passive: true });
906
+ return () => {
907
+ window.removeEventListener("scroll", handleScroll);
908
+ };
909
+ }, [handleScroll]);
910
+ return useMemo(
911
+ () => ({
912
+ elementRef,
913
+ offsetTop
914
+ }),
915
+ [offsetTop]
916
+ );
917
+ }
918
+ var DEFAULT_PARAM_NAMES = {
919
+ preset: "preset",
920
+ mode: "mode",
921
+ primary: "primary",
922
+ direction: "dir",
923
+ density: "density",
924
+ contrast: "contrast"
925
+ };
926
+ var VALID_MODES = ["light", "dark", "system"];
927
+ var VALID_DIRECTIONS = ["ltr", "rtl"];
928
+ var VALID_DENSITIES = ["compact", "standard", "comfortable"];
929
+ var VALID_CONTRASTS = ["default", "high"];
930
+ function isValidPreset(value) {
931
+ return value !== null && PRESET_NAMES.includes(value);
932
+ }
933
+ function isValidMode(value) {
934
+ return value !== null && VALID_MODES.includes(value);
935
+ }
936
+ function isValidDirection(value) {
937
+ return value !== null && VALID_DIRECTIONS.includes(value);
938
+ }
939
+ function isValidDensity(value) {
940
+ return value !== null && VALID_DENSITIES.includes(value);
941
+ }
942
+ function isValidContrast(value) {
943
+ return value !== null && VALID_CONTRASTS.includes(value);
944
+ }
945
+ function isValidHexColor(value) {
946
+ if (!value) return false;
947
+ return /^#[0-9A-Fa-f]{6}$/.test(value);
948
+ }
949
+ function useConfigFromQuery(options = {}) {
950
+ const { paramNames = DEFAULT_PARAM_NAMES, onConfigChange, syncToUrl = false } = options;
951
+ const params = { ...DEFAULT_PARAM_NAMES, ...paramNames };
952
+ const configFromUrl = useMemo(() => {
953
+ if (typeof window === "undefined") return {};
954
+ const searchParams = new URLSearchParams(window.location.search);
955
+ const config = {};
956
+ const presetValue = searchParams.get(params.preset);
957
+ if (isValidPreset(presetValue)) {
958
+ config.preset = presetValue;
959
+ }
960
+ const modeValue = searchParams.get(params.mode);
961
+ if (isValidMode(modeValue)) {
962
+ config.mode = modeValue;
963
+ }
964
+ const primaryValue = searchParams.get(params.primary);
965
+ if (isValidHexColor(primaryValue)) {
966
+ config.primary = primaryValue;
967
+ }
968
+ const directionValue = searchParams.get(params.direction);
969
+ if (isValidDirection(directionValue)) {
970
+ config.direction = directionValue;
971
+ }
972
+ const densityValue = searchParams.get(params.density);
973
+ if (isValidDensity(densityValue)) {
974
+ config.density = densityValue;
975
+ }
976
+ const contrastValue = searchParams.get(params.contrast);
977
+ if (isValidContrast(contrastValue)) {
978
+ config.contrast = contrastValue;
979
+ }
980
+ return config;
981
+ }, [params.preset, params.mode, params.primary, params.direction, params.density, params.contrast]);
982
+ useEffect(() => {
983
+ if (onConfigChange && Object.keys(configFromUrl).length > 0) {
984
+ onConfigChange(configFromUrl);
985
+ }
986
+ }, [configFromUrl, onConfigChange]);
987
+ const updateUrl = useCallback(
988
+ (values) => {
989
+ if (typeof window === "undefined") return;
990
+ const searchParams = new URLSearchParams(window.location.search);
991
+ if (values.preset !== void 0) {
992
+ if (values.preset) {
993
+ searchParams.set(params.preset, values.preset);
994
+ } else {
995
+ searchParams.delete(params.preset);
996
+ }
997
+ }
998
+ if (values.mode !== void 0) {
999
+ if (values.mode) {
1000
+ searchParams.set(params.mode, values.mode);
1001
+ } else {
1002
+ searchParams.delete(params.mode);
1003
+ }
1004
+ }
1005
+ if (values.primary !== void 0) {
1006
+ if (values.primary) {
1007
+ searchParams.set(params.primary, values.primary);
1008
+ } else {
1009
+ searchParams.delete(params.primary);
1010
+ }
1011
+ }
1012
+ if (values.direction !== void 0) {
1013
+ if (values.direction) {
1014
+ searchParams.set(params.direction, values.direction);
1015
+ } else {
1016
+ searchParams.delete(params.direction);
1017
+ }
1018
+ }
1019
+ if (values.density !== void 0) {
1020
+ if (values.density) {
1021
+ searchParams.set(params.density, values.density);
1022
+ } else {
1023
+ searchParams.delete(params.density);
1024
+ }
1025
+ }
1026
+ if (values.contrast !== void 0) {
1027
+ if (values.contrast) {
1028
+ searchParams.set(params.contrast, values.contrast);
1029
+ } else {
1030
+ searchParams.delete(params.contrast);
1031
+ }
1032
+ }
1033
+ const newUrl = searchParams.toString() ? `${window.location.pathname}?${searchParams.toString()}` : window.location.pathname;
1034
+ window.history.replaceState({}, "", newUrl);
1035
+ },
1036
+ [params]
1037
+ );
1038
+ const clearUrl = useCallback(() => {
1039
+ if (typeof window === "undefined") return;
1040
+ const searchParams = new URLSearchParams(window.location.search);
1041
+ searchParams.delete(params.preset);
1042
+ searchParams.delete(params.mode);
1043
+ searchParams.delete(params.primary);
1044
+ searchParams.delete(params.direction);
1045
+ searchParams.delete(params.density);
1046
+ searchParams.delete(params.contrast);
1047
+ const newUrl = searchParams.toString() ? `${window.location.pathname}?${searchParams.toString()}` : window.location.pathname;
1048
+ window.history.replaceState({}, "", newUrl);
1049
+ }, [params]);
1050
+ const generateUrl = useCallback(
1051
+ (values, baseUrl) => {
1052
+ const base = baseUrl ?? (typeof window !== "undefined" ? window.location.origin + window.location.pathname : "");
1053
+ const searchParams = new URLSearchParams();
1054
+ if (values.preset) {
1055
+ searchParams.set(params.preset, values.preset);
1056
+ }
1057
+ if (values.mode) {
1058
+ searchParams.set(params.mode, values.mode);
1059
+ }
1060
+ if (values.primary) {
1061
+ searchParams.set(params.primary, values.primary);
1062
+ }
1063
+ if (values.direction) {
1064
+ searchParams.set(params.direction, values.direction);
1065
+ }
1066
+ if (values.density) {
1067
+ searchParams.set(params.density, values.density);
1068
+ }
1069
+ if (values.contrast) {
1070
+ searchParams.set(params.contrast, values.contrast);
1071
+ }
1072
+ const queryString = searchParams.toString();
1073
+ return queryString ? `${base}?${queryString}` : base;
1074
+ },
1075
+ [params]
1076
+ );
1077
+ const hasUrlConfig = Object.keys(configFromUrl).length > 0;
1078
+ return {
1079
+ configFromUrl,
1080
+ updateUrl,
1081
+ clearUrl,
1082
+ generateUrl,
1083
+ hasUrlConfig
1084
+ };
1085
+ }
1086
+ function useImageDimensions(src, options = {}) {
1087
+ const { crossOrigin, timeout = 1e4, immediate = true } = options;
1088
+ const [dimensions, setDimensions] = useState(null);
1089
+ const [loading, setLoading] = useState(false);
1090
+ const [error, setError] = useState(null);
1091
+ const loadImage = useCallback(() => {
1092
+ if (!src) {
1093
+ setDimensions(null);
1094
+ setLoading(false);
1095
+ setError(null);
1096
+ return void 0;
1097
+ }
1098
+ setLoading(true);
1099
+ setError(null);
1100
+ const img = new Image();
1101
+ let timeoutId = null;
1102
+ let cancelled = false;
1103
+ const cleanup = () => {
1104
+ cancelled = true;
1105
+ if (timeoutId) {
1106
+ clearTimeout(timeoutId);
1107
+ }
1108
+ img.onload = null;
1109
+ img.onerror = null;
1110
+ };
1111
+ img.onload = () => {
1112
+ if (cancelled) return;
1113
+ cleanup();
1114
+ const { naturalWidth: width, naturalHeight: height } = img;
1115
+ setDimensions({
1116
+ width,
1117
+ height,
1118
+ aspectRatio: height > 0 ? width / height : 1
1119
+ });
1120
+ setLoading(false);
1121
+ setError(null);
1122
+ };
1123
+ img.onerror = () => {
1124
+ if (cancelled) return;
1125
+ cleanup();
1126
+ setDimensions(null);
1127
+ setLoading(false);
1128
+ setError(new Error(`Failed to load image: ${src}`));
1129
+ };
1130
+ timeoutId = setTimeout(() => {
1131
+ if (cancelled) return;
1132
+ cleanup();
1133
+ setDimensions(null);
1134
+ setLoading(false);
1135
+ setError(new Error(`Image load timeout: ${src}`));
1136
+ }, timeout);
1137
+ if (crossOrigin) {
1138
+ img.crossOrigin = crossOrigin;
1139
+ }
1140
+ img.src = src;
1141
+ return cleanup;
1142
+ }, [src, crossOrigin, timeout]);
1143
+ useEffect(() => {
1144
+ if (!immediate) return void 0;
1145
+ return loadImage();
1146
+ }, [loadImage, immediate]);
1147
+ const retry = useCallback(() => {
1148
+ loadImage();
1149
+ }, [loadImage]);
1150
+ return {
1151
+ dimensions,
1152
+ loading,
1153
+ error,
1154
+ retry
1155
+ };
1156
+ }
1157
+ function useMultipleImageDimensions(urls, options = {}) {
1158
+ const { crossOrigin, timeout = 1e4, immediate = true } = options;
1159
+ const [results, setResults] = useState(/* @__PURE__ */ new Map());
1160
+ useEffect(() => {
1161
+ if (!immediate) return void 0;
1162
+ const cleanups = [];
1163
+ urls.forEach((url) => {
1164
+ if (!url) return;
1165
+ setResults((prev) => {
1166
+ const next = new Map(prev);
1167
+ next.set(url, { dimensions: null, loading: true, error: null });
1168
+ return next;
1169
+ });
1170
+ const img = new Image();
1171
+ let timeoutId = null;
1172
+ let cancelled = false;
1173
+ const cleanup = () => {
1174
+ cancelled = true;
1175
+ if (timeoutId) {
1176
+ clearTimeout(timeoutId);
1177
+ }
1178
+ img.onload = null;
1179
+ img.onerror = null;
1180
+ };
1181
+ cleanups.push(cleanup);
1182
+ img.onload = () => {
1183
+ if (cancelled) return;
1184
+ cleanup();
1185
+ const { naturalWidth: width, naturalHeight: height } = img;
1186
+ setResults((prev) => {
1187
+ const next = new Map(prev);
1188
+ next.set(url, {
1189
+ dimensions: { width, height, aspectRatio: height > 0 ? width / height : 1 },
1190
+ loading: false,
1191
+ error: null
1192
+ });
1193
+ return next;
1194
+ });
1195
+ };
1196
+ img.onerror = () => {
1197
+ if (cancelled) return;
1198
+ cleanup();
1199
+ setResults((prev) => {
1200
+ const next = new Map(prev);
1201
+ next.set(url, {
1202
+ dimensions: null,
1203
+ loading: false,
1204
+ error: new Error(`Failed to load: ${url}`)
1205
+ });
1206
+ return next;
1207
+ });
1208
+ };
1209
+ timeoutId = setTimeout(() => {
1210
+ if (cancelled) return;
1211
+ cleanup();
1212
+ setResults((prev) => {
1213
+ const next = new Map(prev);
1214
+ next.set(url, {
1215
+ dimensions: null,
1216
+ loading: false,
1217
+ error: new Error(`Timeout: ${url}`)
1218
+ });
1219
+ return next;
1220
+ });
1221
+ }, timeout);
1222
+ if (crossOrigin) {
1223
+ img.crossOrigin = crossOrigin;
1224
+ }
1225
+ img.src = url;
1226
+ });
1227
+ return () => {
1228
+ cleanups.forEach((cleanup) => cleanup());
1229
+ };
1230
+ }, [urls.join(","), crossOrigin, timeout, immediate]);
1231
+ return urls.map((url) => {
1232
+ if (!url) {
1233
+ return {
1234
+ dimensions: null,
1235
+ loading: false,
1236
+ error: null,
1237
+ retry: () => {
1238
+ }
1239
+ };
1240
+ }
1241
+ const result = results.get(url);
1242
+ return {
1243
+ dimensions: result?.dimensions ?? null,
1244
+ loading: result?.loading ?? false,
1245
+ error: result?.error ?? null,
1246
+ retry: () => {
1247
+ setResults((prev) => {
1248
+ const next = new Map(prev);
1249
+ next.delete(url);
1250
+ return next;
1251
+ });
1252
+ }
1253
+ };
1254
+ });
1255
+ }
1256
+ function usePasswordVisibility(options = {}) {
1257
+ const { initialVisible = false } = options;
1258
+ const [visible, setVisible] = useState(initialVisible);
1259
+ const toggle = useCallback(() => {
1260
+ setVisible((prev) => !prev);
1261
+ }, []);
1262
+ const show = useCallback(() => {
1263
+ setVisible(true);
1264
+ }, []);
1265
+ const hide = useCallback(() => {
1266
+ setVisible(false);
1267
+ }, []);
1268
+ return useMemo(
1269
+ () => ({
1270
+ visible,
1271
+ toggle,
1272
+ show,
1273
+ hide,
1274
+ type: visible ? "text" : "password"
1275
+ }),
1276
+ [visible, toggle, show, hide]
1277
+ );
1278
+ }
1279
+ function useThrottle(value, delay, options = {}) {
1280
+ const { leading = true, trailing = true } = options;
1281
+ const [throttledValue, setThrottledValue] = useState(value);
1282
+ const lastExecuted = useRef(0);
1283
+ const timeoutRef = useRef(null);
1284
+ const lastValue = useRef(value);
1285
+ useEffect(() => {
1286
+ lastValue.current = value;
1287
+ const now = Date.now();
1288
+ const elapsed = now - lastExecuted.current;
1289
+ const execute = () => {
1290
+ lastExecuted.current = Date.now();
1291
+ setThrottledValue(lastValue.current);
1292
+ };
1293
+ if (timeoutRef.current) {
1294
+ clearTimeout(timeoutRef.current);
1295
+ timeoutRef.current = null;
1296
+ }
1297
+ if (elapsed >= delay) {
1298
+ if (leading) {
1299
+ execute();
1300
+ } else if (trailing) {
1301
+ timeoutRef.current = setTimeout(execute, delay);
1302
+ }
1303
+ } else if (trailing) {
1304
+ timeoutRef.current = setTimeout(execute, delay - elapsed);
1305
+ }
1306
+ return () => {
1307
+ if (timeoutRef.current) {
1308
+ clearTimeout(timeoutRef.current);
1309
+ }
1310
+ };
1311
+ }, [value, delay, leading, trailing]);
1312
+ return throttledValue;
1313
+ }
1314
+ function useThrottleCallback(callback, delay, options = {}) {
1315
+ const { leading = true, trailing = true } = options;
1316
+ const lastExecuted = useRef(0);
1317
+ const timeoutRef = useRef(null);
1318
+ const lastArgs = useRef(null);
1319
+ const callbackRef = useRef(callback);
1320
+ useEffect(() => {
1321
+ callbackRef.current = callback;
1322
+ }, [callback]);
1323
+ useEffect(
1324
+ () => () => {
1325
+ if (timeoutRef.current) {
1326
+ clearTimeout(timeoutRef.current);
1327
+ }
1328
+ },
1329
+ []
1330
+ );
1331
+ return useCallback(
1332
+ ((...args) => {
1333
+ lastArgs.current = args;
1334
+ const now = Date.now();
1335
+ const elapsed = now - lastExecuted.current;
1336
+ const execute = () => {
1337
+ lastExecuted.current = Date.now();
1338
+ if (lastArgs.current) {
1339
+ callbackRef.current(...lastArgs.current);
1340
+ }
1341
+ };
1342
+ if (timeoutRef.current) {
1343
+ clearTimeout(timeoutRef.current);
1344
+ timeoutRef.current = null;
1345
+ }
1346
+ if (elapsed >= delay) {
1347
+ if (leading) {
1348
+ execute();
1349
+ } else if (trailing) {
1350
+ timeoutRef.current = setTimeout(execute, delay);
1351
+ }
1352
+ } else if (trailing) {
1353
+ timeoutRef.current = setTimeout(execute, delay - elapsed);
1354
+ }
1355
+ }),
1356
+ [delay, leading, trailing]
1357
+ );
1358
+ }
1359
+ function subscribe(callback) {
1360
+ window.addEventListener("online", callback);
1361
+ window.addEventListener("offline", callback);
1362
+ return () => {
1363
+ window.removeEventListener("online", callback);
1364
+ window.removeEventListener("offline", callback);
1365
+ };
1366
+ }
1367
+ function getSnapshot() {
1368
+ return navigator.onLine;
1369
+ }
1370
+ function getServerSnapshot() {
1371
+ return true;
1372
+ }
1373
+ function useOnlineStatus() {
1374
+ const isOnline = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
1375
+ const [lastChanged, setLastChanged] = useState(null);
1376
+ const handleStatusChange = useCallback(() => {
1377
+ setLastChanged(Date.now());
1378
+ }, []);
1379
+ useEffect(() => {
1380
+ window.addEventListener("online", handleStatusChange);
1381
+ window.addEventListener("offline", handleStatusChange);
1382
+ return () => {
1383
+ window.removeEventListener("online", handleStatusChange);
1384
+ window.removeEventListener("offline", handleStatusChange);
1385
+ };
1386
+ }, [handleStatusChange]);
1387
+ return {
1388
+ isOnline,
1389
+ isOffline: !isOnline,
1390
+ lastChanged
1391
+ };
1392
+ }
1393
+ function useIntersectionObserver(options = {}) {
1394
+ const { root = null, rootMargin = "0px", threshold = 0, triggerOnce = false, enabled = true } = options;
1395
+ const [entry, setEntry] = useState(null);
1396
+ const elementRef = useRef(null);
1397
+ const observerRef = useRef(null);
1398
+ const frozenRef = useRef(false);
1399
+ const disconnect = useCallback(() => {
1400
+ if (observerRef.current) {
1401
+ observerRef.current.disconnect();
1402
+ observerRef.current = null;
1403
+ }
1404
+ }, []);
1405
+ const ref = useCallback(
1406
+ (element) => {
1407
+ disconnect();
1408
+ elementRef.current = element;
1409
+ if (!enabled || frozenRef.current || !element) {
1410
+ return;
1411
+ }
1412
+ if (typeof IntersectionObserver === "undefined") {
1413
+ setEntry({
1414
+ isIntersecting: true,
1415
+ intersectionRatio: 1,
1416
+ boundingClientRect: element.getBoundingClientRect(),
1417
+ intersectionRect: element.getBoundingClientRect(),
1418
+ rootBounds: null,
1419
+ target: element,
1420
+ time: Date.now()
1421
+ });
1422
+ return;
1423
+ }
1424
+ observerRef.current = new IntersectionObserver(
1425
+ ([observerEntry]) => {
1426
+ setEntry(observerEntry);
1427
+ if (triggerOnce && observerEntry.isIntersecting) {
1428
+ frozenRef.current = true;
1429
+ disconnect();
1430
+ }
1431
+ },
1432
+ { root, rootMargin, threshold }
1433
+ );
1434
+ observerRef.current.observe(element);
1435
+ },
1436
+ [enabled, root, rootMargin, threshold, triggerOnce, disconnect]
1437
+ );
1438
+ useEffect(
1439
+ () => () => {
1440
+ disconnect();
1441
+ },
1442
+ [disconnect]
1443
+ );
1444
+ return useMemo(
1445
+ () => ({
1446
+ ref,
1447
+ entry,
1448
+ isIntersecting: entry?.isIntersecting ?? false,
1449
+ disconnect
1450
+ }),
1451
+ [entry, disconnect]
1452
+ );
1453
+ }
1454
+ function isInputElement(element) {
1455
+ if (!element || !(element instanceof HTMLElement)) {
1456
+ return false;
1457
+ }
1458
+ const tagName = element.tagName.toLowerCase();
1459
+ if (tagName === "input" || tagName === "textarea" || tagName === "select") {
1460
+ return true;
1461
+ }
1462
+ return element.isContentEditable;
1463
+ }
1464
+ function matchesShortcut(event, shortcut) {
1465
+ const eventKey = event.key.toLowerCase();
1466
+ const shortcutKey = shortcut.key.toLowerCase();
1467
+ if (eventKey !== shortcutKey) {
1468
+ return false;
1469
+ }
1470
+ const ctrlOrMeta = event.ctrlKey || event.metaKey;
1471
+ if (shortcut.ctrl && !ctrlOrMeta) return false;
1472
+ if (shortcut.meta && !event.metaKey) return false;
1473
+ if (shortcut.shift && !event.shiftKey) return false;
1474
+ if (shortcut.alt && !event.altKey) return false;
1475
+ if (!shortcut.ctrl && !shortcut.meta && ctrlOrMeta) return false;
1476
+ if (!shortcut.shift && event.shiftKey) return false;
1477
+ if (!shortcut.alt && event.altKey) return false;
1478
+ return true;
1479
+ }
1480
+ function useKeyboardShortcut(shortcut, callback, options = {}) {
1481
+ const {
1482
+ enabled = true,
1483
+ preventDefault = true,
1484
+ stopPropagation = false,
1485
+ target = typeof document !== "undefined" ? document : null,
1486
+ event = "keydown",
1487
+ ignoreInputs = false
1488
+ } = options;
1489
+ const callbackRef = useRef(callback);
1490
+ useEffect(() => {
1491
+ callbackRef.current = callback;
1492
+ }, [callback]);
1493
+ const handleKeyEvent = useCallback(
1494
+ (e) => {
1495
+ if (!enabled) return;
1496
+ const keyEvent = e;
1497
+ if (ignoreInputs && isInputElement(keyEvent.target)) {
1498
+ return;
1499
+ }
1500
+ if (matchesShortcut(keyEvent, shortcut)) {
1501
+ if (preventDefault) {
1502
+ keyEvent.preventDefault();
1503
+ }
1504
+ if (stopPropagation) {
1505
+ keyEvent.stopPropagation();
1506
+ }
1507
+ callbackRef.current(keyEvent);
1508
+ }
1509
+ },
1510
+ [enabled, shortcut, preventDefault, stopPropagation, ignoreInputs]
1511
+ );
1512
+ useEffect(() => {
1513
+ if (!target || !enabled) return void 0;
1514
+ target.addEventListener(event, handleKeyEvent);
1515
+ return () => {
1516
+ target.removeEventListener(event, handleKeyEvent);
1517
+ };
1518
+ }, [target, event, handleKeyEvent, enabled]);
1519
+ }
1520
+ function useEscapeKey(callback, options = {}) {
1521
+ useKeyboardShortcut({ key: "Escape" }, callback, {
1522
+ ...options,
1523
+ ignoreInputs: false
1524
+ // Escape should work even in inputs
1525
+ });
1526
+ }
1527
+ function useEnterKey(callback, options = {}) {
1528
+ useKeyboardShortcut({ key: "Enter" }, callback, options);
1529
+ }
1530
+ var FOCUSABLE_SELECTOR = [
1531
+ "a[href]",
1532
+ "button:not([disabled])",
1533
+ 'input:not([disabled]):not([type="hidden"])',
1534
+ "select:not([disabled])",
1535
+ "textarea:not([disabled])",
1536
+ '[tabindex]:not([tabindex="-1"])',
1537
+ '[contenteditable="true"]'
1538
+ ].join(",");
1539
+ function useFocusTrap(options = {}) {
1540
+ const { enabled = true, autoFocus = true, restoreFocus = true, focusableSelector = FOCUSABLE_SELECTOR } = options;
1541
+ const containerRef = useRef(null);
1542
+ const previousActiveElement = useRef(null);
1543
+ const getFocusableElements = useCallback(() => {
1544
+ if (!containerRef.current) return [];
1545
+ return Array.from(containerRef.current.querySelectorAll(focusableSelector)).filter(
1546
+ (el) => el.offsetParent !== null
1547
+ );
1548
+ }, [focusableSelector]);
1549
+ const focusFirst = useCallback(() => {
1550
+ const elements = getFocusableElements();
1551
+ if (elements.length > 0) {
1552
+ elements[0].focus();
1553
+ }
1554
+ }, [getFocusableElements]);
1555
+ const focusLast = useCallback(() => {
1556
+ const elements = getFocusableElements();
1557
+ if (elements.length > 0) {
1558
+ elements[elements.length - 1].focus();
1559
+ }
1560
+ }, [getFocusableElements]);
1561
+ useEffect(() => {
1562
+ if (!enabled || !containerRef.current) return void 0;
1563
+ const handleKeyDown = (event) => {
1564
+ if (event.key !== "Tab") return;
1565
+ const elements = getFocusableElements();
1566
+ if (elements.length === 0) return;
1567
+ const firstElement = elements[0];
1568
+ const lastElement = elements[elements.length - 1];
1569
+ const activeElement = document.activeElement;
1570
+ if (event.shiftKey && activeElement === firstElement) {
1571
+ event.preventDefault();
1572
+ lastElement.focus();
1573
+ return;
1574
+ }
1575
+ if (!event.shiftKey && activeElement === lastElement) {
1576
+ event.preventDefault();
1577
+ firstElement.focus();
1578
+ }
1579
+ };
1580
+ const container = containerRef.current;
1581
+ container.addEventListener("keydown", handleKeyDown);
1582
+ return () => {
1583
+ container.removeEventListener("keydown", handleKeyDown);
1584
+ };
1585
+ }, [enabled, getFocusableElements]);
1586
+ useEffect(() => {
1587
+ if (enabled) {
1588
+ if (restoreFocus) {
1589
+ previousActiveElement.current = document.activeElement;
1590
+ }
1591
+ if (autoFocus) {
1592
+ const timeoutId = setTimeout(focusFirst, 0);
1593
+ return () => clearTimeout(timeoutId);
1594
+ }
1595
+ } else if (restoreFocus && previousActiveElement.current) {
1596
+ previousActiveElement.current.focus();
1597
+ previousActiveElement.current = null;
1598
+ }
1599
+ return void 0;
1600
+ }, [enabled, autoFocus, restoreFocus, focusFirst]);
1601
+ const ref = useCallback((node) => {
1602
+ containerRef.current = node;
1603
+ }, []);
1604
+ return { ref, focusFirst, focusLast };
1605
+ }
1606
+ function useUpdateEffect(effect, deps) {
1607
+ const isFirstMount = useRef(true);
1608
+ useEffect(() => {
1609
+ if (isFirstMount.current) {
1610
+ isFirstMount.current = false;
1611
+ return void 0;
1612
+ }
1613
+ return effect();
1614
+ }, deps);
1615
+ }
1616
+ function useUpdateLayoutEffect(effect, deps) {
1617
+ const isFirstMount = useRef(true);
1618
+ useEffect(() => {
1619
+ if (isFirstMount.current) {
1620
+ isFirstMount.current = false;
1621
+ return void 0;
1622
+ }
1623
+ return effect();
1624
+ }, deps);
1625
+ }
1626
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
1627
+ function getStorageValue(key, defaultValue, deserializer) {
1628
+ if (typeof window === "undefined") {
1629
+ return defaultValue;
1630
+ }
1631
+ try {
1632
+ const item = window.sessionStorage.getItem(key);
1633
+ if (item === null) {
1634
+ return defaultValue;
1635
+ }
1636
+ return deserializer(item);
1637
+ } catch (error) {
1638
+ console.warn(`Error reading sessionStorage key "${key}":`, error);
1639
+ return defaultValue;
1640
+ }
1641
+ }
1642
+ function useSessionStorage(key, defaultValue, options = {}) {
1643
+ const { serializer = JSON.stringify, deserializer = JSON.parse } = options;
1644
+ const isClient = useIsClient();
1645
+ const [state, setStateInternal] = useState(() => {
1646
+ if (typeof window === "undefined") {
1647
+ return defaultValue;
1648
+ }
1649
+ return getStorageValue(key, defaultValue, deserializer);
1650
+ });
1651
+ const [hasValue, setHasValue] = useState(() => {
1652
+ if (typeof window === "undefined") {
1653
+ return false;
1654
+ }
1655
+ return window.sessionStorage.getItem(key) !== null;
1656
+ });
1657
+ const setState = useCallback(
1658
+ (value) => {
1659
+ try {
1660
+ const newValue = value instanceof Function ? value(state) : value;
1661
+ window.sessionStorage.setItem(key, serializer(newValue));
1662
+ setStateInternal(newValue);
1663
+ setHasValue(true);
1664
+ window.dispatchEvent(
1665
+ new StorageEvent("storage", {
1666
+ key,
1667
+ newValue: serializer(newValue),
1668
+ storageArea: window.sessionStorage
1669
+ })
1670
+ );
1671
+ } catch (error) {
1672
+ console.warn(`Error setting sessionStorage key "${key}":`, error);
1673
+ }
1674
+ },
1675
+ [key, serializer, state]
1676
+ );
1677
+ const remove = useCallback(() => {
1678
+ try {
1679
+ window.sessionStorage.removeItem(key);
1680
+ setStateInternal(defaultValue);
1681
+ setHasValue(false);
1682
+ window.dispatchEvent(
1683
+ new StorageEvent("storage", {
1684
+ key,
1685
+ newValue: null,
1686
+ storageArea: window.sessionStorage
1687
+ })
1688
+ );
1689
+ } catch (error) {
1690
+ console.warn(`Error removing sessionStorage key "${key}":`, error);
1691
+ }
1692
+ }, [key, defaultValue]);
1693
+ useEffect(() => {
1694
+ if (!isClient) return void 0;
1695
+ const value = getStorageValue(key, defaultValue, deserializer);
1696
+ setStateInternal(value);
1697
+ setHasValue(window.sessionStorage.getItem(key) !== null);
1698
+ return void 0;
1699
+ }, [key, isClient, defaultValue, deserializer]);
1700
+ useEffect(() => {
1701
+ if (!isClient) return void 0;
1702
+ const handleStorageChange = (event) => {
1703
+ if (event.key === key && event.storageArea === window.sessionStorage) {
1704
+ if (event.newValue === null) {
1705
+ setStateInternal(defaultValue);
1706
+ setHasValue(false);
1707
+ } else {
1708
+ try {
1709
+ setStateInternal(deserializer(event.newValue));
1710
+ setHasValue(true);
1711
+ } catch {
1712
+ }
1713
+ }
1714
+ }
1715
+ };
1716
+ window.addEventListener("storage", handleStorageChange);
1717
+ return () => {
1718
+ window.removeEventListener("storage", handleStorageChange);
1719
+ };
1720
+ }, [key, isClient, defaultValue, deserializer]);
1721
+ return {
1722
+ state,
1723
+ setState,
1724
+ remove,
1725
+ hasValue
1726
+ };
1727
+ }
1728
+ function useArray(initialValue = []) {
1729
+ const [value, setValue] = useState(initialValue);
1730
+ const push = useCallback((item) => {
1731
+ setValue((arr) => [...arr, item]);
1732
+ }, []);
1733
+ const pushMany = useCallback((items) => {
1734
+ setValue((arr) => [...arr, ...items]);
1735
+ }, []);
1736
+ const remove = useCallback((itemOrPredicate) => {
1737
+ setValue((arr) => {
1738
+ const predicate = typeof itemOrPredicate === "function" ? itemOrPredicate : (item) => item === itemOrPredicate;
1739
+ const index = arr.findIndex(predicate);
1740
+ if (index === -1) return arr;
1741
+ return [...arr.slice(0, index), ...arr.slice(index + 1)];
1742
+ });
1743
+ }, []);
1744
+ const removeAt = useCallback((index) => {
1745
+ setValue((arr) => {
1746
+ if (index < 0 || index >= arr.length) return arr;
1747
+ return [...arr.slice(0, index), ...arr.slice(index + 1)];
1748
+ });
1749
+ }, []);
1750
+ const removeWhere = useCallback((predicate) => {
1751
+ setValue((arr) => arr.filter((item) => !predicate(item)));
1752
+ }, []);
1753
+ const updateAt = useCallback((index, item) => {
1754
+ setValue((arr) => {
1755
+ if (index < 0 || index >= arr.length) return arr;
1756
+ return [...arr.slice(0, index), item, ...arr.slice(index + 1)];
1757
+ });
1758
+ }, []);
1759
+ const updateAtPartial = useCallback((index, partial) => {
1760
+ setValue((arr) => {
1761
+ if (index < 0 || index >= arr.length) return arr;
1762
+ const item = arr[index];
1763
+ if (typeof item !== "object" || item === null) {
1764
+ console.warn("updateAtPartial only works with object items");
1765
+ return arr;
1766
+ }
1767
+ return [...arr.slice(0, index), { ...item, ...partial }, ...arr.slice(index + 1)];
1768
+ });
1769
+ }, []);
1770
+ const updateWhere = useCallback((predicate, update) => {
1771
+ setValue(
1772
+ (arr) => arr.map((item) => {
1773
+ if (!predicate(item)) return item;
1774
+ return typeof update === "function" ? update(item) : update;
1775
+ })
1776
+ );
1777
+ }, []);
1778
+ const insertAt = useCallback((index, item) => {
1779
+ setValue((arr) => {
1780
+ const normalizedIndex = Math.max(0, Math.min(index, arr.length));
1781
+ return [...arr.slice(0, normalizedIndex), item, ...arr.slice(normalizedIndex)];
1782
+ });
1783
+ }, []);
1784
+ const move = useCallback((fromIndex, toIndex) => {
1785
+ setValue((arr) => {
1786
+ if (fromIndex < 0 || fromIndex >= arr.length || toIndex < 0 || toIndex >= arr.length || fromIndex === toIndex) {
1787
+ return arr;
1788
+ }
1789
+ const newArr = [...arr];
1790
+ const [item] = newArr.splice(fromIndex, 1);
1791
+ newArr.splice(toIndex, 0, item);
1792
+ return newArr;
1793
+ });
1794
+ }, []);
1795
+ const swap = useCallback((indexA, indexB) => {
1796
+ setValue((arr) => {
1797
+ if (indexA < 0 || indexA >= arr.length || indexB < 0 || indexB >= arr.length || indexA === indexB) {
1798
+ return arr;
1799
+ }
1800
+ const newArr = [...arr];
1801
+ [newArr[indexA], newArr[indexB]] = [newArr[indexB], newArr[indexA]];
1802
+ return newArr;
1803
+ });
1804
+ }, []);
1805
+ const clear = useCallback(() => {
1806
+ setValue([]);
1807
+ }, []);
1808
+ const reset = useCallback(() => {
1809
+ setValue(initialValue);
1810
+ }, [initialValue]);
1811
+ const reverse = useCallback(() => {
1812
+ setValue((arr) => [...arr].reverse());
1813
+ }, []);
1814
+ const sort = useCallback((compareFn) => {
1815
+ setValue((arr) => [...arr].sort(compareFn));
1816
+ }, []);
1817
+ const filter = useCallback((predicate) => value.filter(predicate), [value]);
1818
+ const find = useCallback((predicate) => value.find(predicate), [value]);
1819
+ const findIndex = useCallback((predicate) => value.findIndex(predicate), [value]);
1820
+ const includes = useCallback((item) => value.includes(item), [value]);
1821
+ const computed = useMemo(
1822
+ () => ({
1823
+ length: value.length,
1824
+ isEmpty: value.length === 0,
1825
+ first: value[0],
1826
+ last: value[value.length - 1]
1827
+ }),
1828
+ [value]
1829
+ );
1830
+ return {
1831
+ value,
1832
+ setValue,
1833
+ push,
1834
+ pushMany,
1835
+ remove,
1836
+ removeAt,
1837
+ removeWhere,
1838
+ updateAt,
1839
+ updateAtPartial,
1840
+ updateWhere,
1841
+ insertAt,
1842
+ move,
1843
+ swap,
1844
+ clear,
1845
+ reset,
1846
+ reverse,
1847
+ sort,
1848
+ filter,
1849
+ find,
1850
+ findIndex,
1851
+ includes,
1852
+ ...computed
1853
+ };
1854
+ }
1855
+ var defaultRetryDelay = (attempt) => Math.min(1e3 * 2 ** attempt, 3e4);
1856
+ function useMutation(mutationFn, options = {}) {
1857
+ const { onMutate, onSuccess, onError, onSettled, retry = 0, retryDelay = defaultRetryDelay } = options;
1858
+ const [state, setState] = useState({
1859
+ data: void 0,
1860
+ error: void 0,
1861
+ isLoading: false,
1862
+ isSuccess: false,
1863
+ isError: false,
1864
+ isIdle: true,
1865
+ status: "idle"
1866
+ });
1867
+ const mutationIdRef = useRef(0);
1868
+ const mutate = useCallback(
1869
+ (variables, callOptions) => {
1870
+ const currentId = ++mutationIdRef.current;
1871
+ const executeWithRetry = async (attempt) => {
1872
+ if (mutationIdRef.current !== currentId) return;
1873
+ setState({
1874
+ data: void 0,
1875
+ error: void 0,
1876
+ isLoading: true,
1877
+ isSuccess: false,
1878
+ isError: false,
1879
+ isIdle: false,
1880
+ status: "loading"
1881
+ });
1882
+ try {
1883
+ await onMutate?.(variables);
1884
+ const data = await mutationFn(variables);
1885
+ if (mutationIdRef.current !== currentId) return;
1886
+ setState({
1887
+ data,
1888
+ error: void 0,
1889
+ isLoading: false,
1890
+ isSuccess: true,
1891
+ isError: false,
1892
+ isIdle: false,
1893
+ status: "success"
1894
+ });
1895
+ await onSuccess?.(data, variables);
1896
+ await callOptions?.onSuccess?.(data);
1897
+ await onSettled?.(data, void 0, variables);
1898
+ await callOptions?.onSettled?.(data, void 0);
1899
+ } catch (err) {
1900
+ if (mutationIdRef.current !== currentId) return;
1901
+ const error = err;
1902
+ const maxRetries = typeof retry === "boolean" ? retry ? 3 : 0 : retry;
1903
+ if (attempt < maxRetries) {
1904
+ const delay = typeof retryDelay === "function" ? retryDelay(attempt) : retryDelay;
1905
+ await new Promise((resolve) => setTimeout(resolve, delay));
1906
+ await executeWithRetry(attempt + 1);
1907
+ return;
1908
+ }
1909
+ setState({
1910
+ data: void 0,
1911
+ error,
1912
+ isLoading: false,
1913
+ isSuccess: false,
1914
+ isError: true,
1915
+ isIdle: false,
1916
+ status: "error"
1917
+ });
1918
+ await onError?.(error, variables);
1919
+ await callOptions?.onError?.(error);
1920
+ await onSettled?.(void 0, error, variables);
1921
+ await callOptions?.onSettled?.(void 0, error);
1922
+ }
1923
+ };
1924
+ executeWithRetry(0);
1925
+ },
1926
+ [mutationFn, onMutate, onSuccess, onError, onSettled, retry, retryDelay]
1927
+ );
1928
+ const mutateAsync = useCallback(
1929
+ (variables) => new Promise((resolve, reject) => {
1930
+ mutate(variables, {
1931
+ onSuccess: resolve,
1932
+ onError: reject
1933
+ });
1934
+ }),
1935
+ [mutate]
1936
+ );
1937
+ const reset = useCallback(() => {
1938
+ mutationIdRef.current++;
1939
+ setState({
1940
+ data: void 0,
1941
+ error: void 0,
1942
+ isLoading: false,
1943
+ isSuccess: false,
1944
+ isError: false,
1945
+ isIdle: true,
1946
+ status: "idle"
1947
+ });
1948
+ }, []);
1949
+ return {
1950
+ ...state,
1951
+ mutate,
1952
+ mutateAsync,
1953
+ reset
1954
+ };
1955
+ }
1956
+ var defaultRetryDelay2 = (attempt) => Math.min(1e3 * 2 ** attempt, 3e4);
1957
+ function useLazyQuery(queryFn, options = {}) {
1958
+ const {
1959
+ onSuccess,
1960
+ onError,
1961
+ onSettled,
1962
+ cacheTime = 0,
1963
+ staleTime = 0,
1964
+ retry = 0,
1965
+ retryDelay = defaultRetryDelay2,
1966
+ initialData
1967
+ } = options;
1968
+ const [state, setState] = useState({
1969
+ data: initialData,
1970
+ error: void 0,
1971
+ isLoading: false,
1972
+ isSuccess: !!initialData,
1973
+ isError: false,
1974
+ isCalled: !!initialData,
1975
+ isFetching: false,
1976
+ isRefetching: false
1977
+ });
1978
+ const queryIdRef = useRef(0);
1979
+ const lastVariablesRef = useRef(null);
1980
+ const cacheRef = useRef(/* @__PURE__ */ new Map());
1981
+ const getCacheKey = useCallback((variables) => JSON.stringify(variables), []);
1982
+ const isCacheValid = useCallback(
1983
+ (entry) => {
1984
+ if (!entry || cacheTime === 0) return false;
1985
+ const age = Date.now() - entry.timestamp;
1986
+ return age < cacheTime;
1987
+ },
1988
+ [cacheTime]
1989
+ );
1990
+ const isCacheFresh = useCallback(
1991
+ (entry) => {
1992
+ if (!entry || staleTime === 0) return false;
1993
+ const age = Date.now() - entry.timestamp;
1994
+ return age < staleTime;
1995
+ },
1996
+ [staleTime]
1997
+ );
1998
+ const query = useCallback(
1999
+ async (variables) => {
2000
+ const currentId = ++queryIdRef.current;
2001
+ lastVariablesRef.current = variables;
2002
+ const cacheKey = getCacheKey(variables);
2003
+ const cached = cacheRef.current.get(cacheKey);
2004
+ if (isCacheFresh(cached)) {
2005
+ setState((prev) => ({
2006
+ ...prev,
2007
+ data: cached.data,
2008
+ isSuccess: true,
2009
+ isCalled: true
2010
+ }));
2011
+ return cached.data;
2012
+ }
2013
+ if (isCacheValid(cached)) {
2014
+ setState({
2015
+ data: cached.data,
2016
+ error: void 0,
2017
+ isLoading: false,
2018
+ isSuccess: true,
2019
+ isError: false,
2020
+ isCalled: true,
2021
+ isFetching: true,
2022
+ isRefetching: true
2023
+ });
2024
+ } else {
2025
+ setState({
2026
+ data: void 0,
2027
+ error: void 0,
2028
+ isLoading: true,
2029
+ isSuccess: false,
2030
+ isError: false,
2031
+ isCalled: true,
2032
+ isFetching: true,
2033
+ isRefetching: false
2034
+ });
2035
+ }
2036
+ const executeWithRetry = async (attempt) => {
2037
+ try {
2038
+ const data = await queryFn(variables);
2039
+ if (queryIdRef.current !== currentId) {
2040
+ return data;
2041
+ }
2042
+ cacheRef.current.set(cacheKey, {
2043
+ data,
2044
+ timestamp: Date.now(),
2045
+ variables
2046
+ });
2047
+ setState({
2048
+ data,
2049
+ error: void 0,
2050
+ isLoading: false,
2051
+ isSuccess: true,
2052
+ isError: false,
2053
+ isCalled: true,
2054
+ isFetching: false,
2055
+ isRefetching: false
2056
+ });
2057
+ await onSuccess?.(data, variables);
2058
+ await onSettled?.(data, void 0, variables);
2059
+ return data;
2060
+ } catch (err) {
2061
+ if (queryIdRef.current !== currentId) {
2062
+ throw err;
2063
+ }
2064
+ const error = err;
2065
+ const maxRetries = typeof retry === "boolean" ? retry ? 3 : 0 : retry;
2066
+ if (attempt < maxRetries) {
2067
+ const delay = typeof retryDelay === "function" ? retryDelay(attempt) : retryDelay;
2068
+ await new Promise((resolve) => setTimeout(resolve, delay));
2069
+ return executeWithRetry(attempt + 1);
2070
+ }
2071
+ setState({
2072
+ data: void 0,
2073
+ error,
2074
+ isLoading: false,
2075
+ isSuccess: false,
2076
+ isError: true,
2077
+ isCalled: true,
2078
+ isFetching: false,
2079
+ isRefetching: false
2080
+ });
2081
+ await onError?.(error, variables);
2082
+ await onSettled?.(void 0, error, variables);
2083
+ throw error;
2084
+ }
2085
+ };
2086
+ return executeWithRetry(0);
2087
+ },
2088
+ [queryFn, getCacheKey, isCacheFresh, isCacheValid, onSuccess, onError, onSettled, retry, retryDelay]
2089
+ );
2090
+ const refetch = useCallback(async () => {
2091
+ if (lastVariablesRef.current === null) {
2092
+ return void 0;
2093
+ }
2094
+ return query(lastVariablesRef.current);
2095
+ }, [query]);
2096
+ const reset = useCallback(() => {
2097
+ queryIdRef.current++;
2098
+ lastVariablesRef.current = null;
2099
+ cacheRef.current.clear();
2100
+ setState({
2101
+ data: initialData,
2102
+ error: void 0,
2103
+ isLoading: false,
2104
+ isSuccess: !!initialData,
2105
+ isError: false,
2106
+ isCalled: !!initialData,
2107
+ isFetching: false,
2108
+ isRefetching: false
2109
+ });
2110
+ }, [initialData]);
2111
+ const setData = useCallback((data) => {
2112
+ setState((prev) => {
2113
+ const newData = typeof data === "function" ? data(prev.data) : data;
2114
+ return {
2115
+ ...prev,
2116
+ data: newData,
2117
+ isSuccess: true
2118
+ };
2119
+ });
2120
+ }, []);
2121
+ return {
2122
+ ...state,
2123
+ query,
2124
+ refetch,
2125
+ reset,
2126
+ setData
2127
+ };
2128
+ }
2129
+ var defaultRetryDelay3 = (attempt) => Math.min(1e3 * 2 ** attempt, 3e4);
2130
+ function useInfiniteScroll(fetchFn, options = {}) {
2131
+ const {
2132
+ onSuccess,
2133
+ onError,
2134
+ initialCursor,
2135
+ pageSize = 20,
2136
+ retry = 0,
2137
+ retryDelay = defaultRetryDelay3,
2138
+ observerOptions = { threshold: 0.1 }
2139
+ } = options;
2140
+ const [state, setState] = useState({
2141
+ items: [],
2142
+ pages: [],
2143
+ error: void 0,
2144
+ isLoading: false,
2145
+ isFetchingMore: false,
2146
+ hasNextPage: true,
2147
+ isEmpty: true,
2148
+ totalCount: void 0
2149
+ });
2150
+ const fetchIdRef = useRef(0);
2151
+ const cursorRef = useRef(initialCursor);
2152
+ const observerRef = useRef(null);
2153
+ const sentinelElementRef = useRef(null);
2154
+ const isMountedRef = useRef(true);
2155
+ useEffect(() => {
2156
+ isMountedRef.current = true;
2157
+ return () => {
2158
+ isMountedRef.current = false;
2159
+ if (observerRef.current) {
2160
+ observerRef.current.disconnect();
2161
+ }
2162
+ };
2163
+ }, []);
2164
+ const fetchPage = useCallback(
2165
+ async (cursor, isRefresh = false) => {
2166
+ const currentId = ++fetchIdRef.current;
2167
+ const executeWithRetry = async (attempt) => {
2168
+ if (!isMountedRef.current) return;
2169
+ setState((prev) => ({
2170
+ ...prev,
2171
+ isLoading: isRefresh && prev.pages.length === 0,
2172
+ isFetchingMore: !isRefresh || prev.pages.length > 0,
2173
+ error: void 0
2174
+ }));
2175
+ try {
2176
+ const page = await fetchFn({ cursor, pageSize });
2177
+ if (fetchIdRef.current !== currentId || !isMountedRef.current) return;
2178
+ setState((prev) => {
2179
+ const newPages = isRefresh ? [page] : [...prev.pages, page];
2180
+ const newItems = newPages.flatMap((p) => p.items);
2181
+ return {
2182
+ items: newItems,
2183
+ pages: newPages,
2184
+ error: void 0,
2185
+ isLoading: false,
2186
+ isFetchingMore: false,
2187
+ hasNextPage: page.pageInfo.hasNextPage,
2188
+ isEmpty: newItems.length === 0,
2189
+ totalCount: page.pageInfo.totalCount
2190
+ };
2191
+ });
2192
+ cursorRef.current = page.pageInfo.endCursor;
2193
+ await onSuccess?.(page);
2194
+ } catch (err) {
2195
+ if (fetchIdRef.current !== currentId || !isMountedRef.current) return;
2196
+ const error = err;
2197
+ const maxRetries = typeof retry === "boolean" ? retry ? 3 : 0 : retry;
2198
+ if (attempt < maxRetries) {
2199
+ const delay = typeof retryDelay === "function" ? retryDelay(attempt) : retryDelay;
2200
+ await new Promise((resolve) => setTimeout(resolve, delay));
2201
+ await executeWithRetry(attempt + 1);
2202
+ return;
2203
+ }
2204
+ setState((prev) => ({
2205
+ ...prev,
2206
+ error,
2207
+ isLoading: false,
2208
+ isFetchingMore: false
2209
+ }));
2210
+ await onError?.(error);
2211
+ }
2212
+ };
2213
+ return executeWithRetry(0);
2214
+ },
2215
+ [fetchFn, pageSize, onSuccess, onError, retry, retryDelay]
2216
+ );
2217
+ const fetchNextPage = useCallback(async () => {
2218
+ if (state.isFetchingMore || state.isLoading || !state.hasNextPage) return;
2219
+ await fetchPage(cursorRef.current);
2220
+ }, [fetchPage, state.isFetchingMore, state.isLoading, state.hasNextPage]);
2221
+ const refresh = useCallback(async () => {
2222
+ cursorRef.current = initialCursor;
2223
+ await fetchPage(initialCursor, true);
2224
+ }, [fetchPage, initialCursor]);
2225
+ const reset = useCallback(() => {
2226
+ fetchIdRef.current++;
2227
+ cursorRef.current = initialCursor;
2228
+ setState({
2229
+ items: [],
2230
+ pages: [],
2231
+ error: void 0,
2232
+ isLoading: false,
2233
+ isFetchingMore: false,
2234
+ hasNextPage: true,
2235
+ isEmpty: true,
2236
+ totalCount: void 0
2237
+ });
2238
+ }, [initialCursor]);
2239
+ const prependItems = useCallback((newItems) => {
2240
+ setState((prev) => ({
2241
+ ...prev,
2242
+ items: [...newItems, ...prev.items],
2243
+ isEmpty: newItems.length === 0 && prev.items.length === 0
2244
+ }));
2245
+ }, []);
2246
+ const appendItems = useCallback((newItems) => {
2247
+ setState((prev) => ({
2248
+ ...prev,
2249
+ items: [...prev.items, ...newItems],
2250
+ isEmpty: prev.items.length === 0 && newItems.length === 0
2251
+ }));
2252
+ }, []);
2253
+ const removeItem = useCallback((predicate) => {
2254
+ setState((prev) => {
2255
+ const newItems = prev.items.filter((item) => !predicate(item));
2256
+ return {
2257
+ ...prev,
2258
+ items: newItems,
2259
+ isEmpty: newItems.length === 0
2260
+ };
2261
+ });
2262
+ }, []);
2263
+ const updateItem = useCallback(
2264
+ (predicate, update) => {
2265
+ setState((prev) => ({
2266
+ ...prev,
2267
+ items: prev.items.map((item) => {
2268
+ if (!predicate(item)) return item;
2269
+ if (typeof update === "function") {
2270
+ return update(item);
2271
+ }
2272
+ return { ...item, ...update };
2273
+ })
2274
+ }));
2275
+ },
2276
+ []
2277
+ );
2278
+ const sentinelRef = useCallback(
2279
+ (element) => {
2280
+ if (observerRef.current) {
2281
+ observerRef.current.disconnect();
2282
+ }
2283
+ sentinelElementRef.current = element;
2284
+ if (!element) return;
2285
+ observerRef.current = new IntersectionObserver((entries) => {
2286
+ if (entries[0]?.isIntersecting) {
2287
+ fetchNextPage();
2288
+ }
2289
+ }, observerOptions);
2290
+ observerRef.current.observe(element);
2291
+ },
2292
+ [fetchNextPage, observerOptions]
2293
+ );
2294
+ useEffect(() => {
2295
+ fetchPage(initialCursor, true);
2296
+ }, []);
2297
+ return {
2298
+ items: state.items,
2299
+ pages: state.pages,
2300
+ error: state.error,
2301
+ isLoading: state.isLoading,
2302
+ isFetchingMore: state.isFetchingMore,
2303
+ hasNextPage: state.hasNextPage,
2304
+ isEmpty: state.isEmpty,
2305
+ totalCount: state.totalCount,
2306
+ fetchNextPage,
2307
+ refresh,
2308
+ reset,
2309
+ sentinelRef,
2310
+ prependItems,
2311
+ appendItems,
2312
+ removeItem,
2313
+ updateItem
2314
+ };
2315
+ }
2316
+
2317
+ export { CustomPopover, cookiesAvailable, getCookie, removeCookie, setCookie, useArray, useAsync, useAsyncFn, useBackToTop, useBreakpoint, useBreakpointChecks, useClientRect, useConfigFromQuery, useCookies, useCountdownDate, useCountdownSeconds, useDoubleClick, useEnterKey, useEscapeKey, useFocusTrap, useImageDimensions, useInfiniteScroll, useIntersectionObserver, useIsomorphicLayoutEffect, useKeyboardShortcut, useLazyQuery, useMultipleImageDimensions, useMutation, useOnlineStatus, usePasswordVisibility, usePopover, usePopoverHover, useResponsiveQuery, useScrollLock, useScrollOffsetTop, useScrollPosition, useScrollToTop, useSessionStorage, useThrottle, useThrottleCallback, useUpdateEffect, useUpdateLayoutEffect, useWindowSize };
2318
+ //# sourceMappingURL=chunk-E3XANPTO.js.map
2319
+ //# sourceMappingURL=chunk-E3XANPTO.js.map