@develemit/web-hooks 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +311 -0
  3. package/dist/auto-grow.cjs +60 -0
  4. package/dist/auto-grow.d.cts +14 -0
  5. package/dist/auto-grow.d.ts +14 -0
  6. package/dist/auto-grow.js +9 -0
  7. package/dist/chunk-4PVVTQ5V.js +74 -0
  8. package/dist/chunk-5CA5RIMH.js +34 -0
  9. package/dist/chunk-5KIH2XLV.js +136 -0
  10. package/dist/chunk-5XRVPZHD.js +125 -0
  11. package/dist/chunk-6KCRVSLS.js +80 -0
  12. package/dist/chunk-DNU57XEJ.js +82 -0
  13. package/dist/chunk-DQBKU7HI.js +46 -0
  14. package/dist/chunk-EXEJI4FK.js +43 -0
  15. package/dist/chunk-FE3BQD2I.js +44 -0
  16. package/dist/chunk-HTVNN2NM.js +29 -0
  17. package/dist/chunk-IWQDAJEP.js +69 -0
  18. package/dist/chunk-JG3GPTMY.js +101 -0
  19. package/dist/chunk-LZKAGDER.js +22 -0
  20. package/dist/chunk-NKLEB5TR.js +98 -0
  21. package/dist/chunk-S4YKMGQE.js +23 -0
  22. package/dist/chunk-TNEJ34T5.js +86 -0
  23. package/dist/chunk-UJ366T3Y.js +146 -0
  24. package/dist/chunk-UPVNSGIK.js +72 -0
  25. package/dist/chunk-WVM2LTWQ.js +42 -0
  26. package/dist/chunk-WXL22EWK.js +21 -0
  27. package/dist/chunk-YFMMSLMB.js +41 -0
  28. package/dist/chunk-Z3X27PCA.js +108 -0
  29. package/dist/clipboard.cjs +18 -0
  30. package/dist/clipboard.d.cts +10 -1
  31. package/dist/clipboard.d.ts +10 -1
  32. package/dist/clipboard.js +8 -57
  33. package/dist/debounce.cjs +96 -0
  34. package/dist/debounce.d.cts +21 -0
  35. package/dist/debounce.d.ts +21 -0
  36. package/dist/debounce.js +11 -0
  37. package/dist/drawer-swipe.cjs +16 -4
  38. package/dist/drawer-swipe.d.cts +7 -3
  39. package/dist/drawer-swipe.d.ts +7 -3
  40. package/dist/drawer-swipe.js +16 -101
  41. package/dist/escape.cjs +1 -0
  42. package/dist/escape.js +3 -17
  43. package/dist/focus-trap.cjs +3 -1
  44. package/dist/focus-trap.js +6 -72
  45. package/dist/hotkey.cjs +127 -0
  46. package/dist/hotkey.d.cts +31 -0
  47. package/dist/hotkey.d.ts +31 -0
  48. package/dist/hotkey.js +15 -0
  49. package/dist/index.cjs +1207 -7
  50. package/dist/index.d.cts +20 -60
  51. package/dist/index.d.ts +20 -60
  52. package/dist/index.js +167 -247
  53. package/dist/keyboard-inset.cjs +113 -0
  54. package/dist/keyboard-inset.d.cts +25 -0
  55. package/dist/keyboard-inset.d.ts +25 -0
  56. package/dist/keyboard-inset.js +11 -0
  57. package/dist/media-query.cjs +90 -0
  58. package/dist/media-query.d.cts +12 -0
  59. package/dist/media-query.d.ts +12 -0
  60. package/dist/media-query.js +17 -0
  61. package/dist/online-status.cjs +46 -0
  62. package/dist/online-status.d.cts +3 -0
  63. package/dist/online-status.d.ts +3 -0
  64. package/dist/online-status.js +7 -0
  65. package/dist/outside-press.cjs +73 -0
  66. package/dist/outside-press.d.cts +17 -0
  67. package/dist/outside-press.d.ts +17 -0
  68. package/dist/outside-press.js +11 -0
  69. package/dist/push.cjs +201 -0
  70. package/dist/push.d.cts +37 -0
  71. package/dist/push.d.ts +37 -0
  72. package/dist/push.js +14 -0
  73. package/dist/pwa.cjs +198 -0
  74. package/dist/pwa.d.cts +35 -0
  75. package/dist/pwa.d.ts +35 -0
  76. package/dist/pwa.js +22 -0
  77. package/dist/scroll-lock.cjs +107 -0
  78. package/dist/scroll-lock.d.cts +8 -0
  79. package/dist/scroll-lock.d.ts +8 -0
  80. package/dist/scroll-lock.js +11 -0
  81. package/dist/service-worker.cjs +128 -0
  82. package/dist/service-worker.d.cts +23 -0
  83. package/dist/service-worker.d.ts +23 -0
  84. package/dist/service-worker.js +11 -0
  85. package/dist/share.cjs +139 -0
  86. package/dist/share.d.cts +23 -0
  87. package/dist/share.d.ts +23 -0
  88. package/dist/share.js +16 -0
  89. package/dist/storage-state.cjs +161 -0
  90. package/dist/storage-state.d.cts +14 -0
  91. package/dist/storage-state.d.ts +14 -0
  92. package/dist/storage-state.js +7 -0
  93. package/dist/unsaved-guard.cjs +48 -0
  94. package/dist/unsaved-guard.d.cts +5 -0
  95. package/dist/unsaved-guard.d.ts +5 -0
  96. package/dist/unsaved-guard.js +9 -0
  97. package/dist/visibility-polling.cjs +98 -0
  98. package/dist/visibility-polling.d.cts +14 -0
  99. package/dist/visibility-polling.d.ts +14 -0
  100. package/dist/visibility-polling.js +9 -0
  101. package/package.json +85 -2
package/dist/index.d.cts CHANGED
@@ -1,60 +1,20 @@
1
- import { RefObject } from 'react';
2
-
3
- type SwipePoint = {
4
- x: number;
5
- y: number;
6
- time: number;
7
- };
8
- declare const BACK_ZONE_PX = 60;
9
- declare const FORWARD_ZONE_PX = 30;
10
- declare const OPEN_DISTANCE_PX = 80;
11
- declare const CLOSE_DISTANCE_PX = 60;
12
- declare const VERTICAL_CANCEL_PX = 40;
13
- declare const MAX_SWIPE_DURATION_MS = 450;
14
- type SwipeIntent = 'open' | 'close' | null;
15
- declare function isInOpenZone(x: number, viewportWidth: number): boolean;
16
- declare function resolveSwipeIntent(start: SwipePoint, end: SwipePoint, drawerOpen: boolean, viewportWidth: number): SwipeIntent;
17
- declare function isInsideHorizontalScroller(target: EventTarget | null): boolean;
18
-
19
- type UseDrawerSwipeOptions = {
20
- drawerOpen: boolean;
21
- onOpen: () => void;
22
- onClose: () => void;
23
- enabled?: boolean;
24
- maxViewportWidth?: number;
25
- };
26
- declare function useDrawerSwipe({ drawerOpen, onOpen, onClose, enabled, maxViewportWidth, }: UseDrawerSwipeOptions): void;
27
-
28
- declare const FOCUSABLE_SELECTOR = "a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
29
- declare function focusableWithin(container: HTMLElement): HTMLElement[];
30
- /** The element Tab must be redirected to, or null when the browser's own move is fine. */
31
- declare function nextFocusTarget(items: HTMLElement[], current: Element | null, shiftKey: boolean, container: HTMLElement): HTMLElement | null;
32
-
33
- type UseFocusTrapOptions = {
34
- active: boolean;
35
- initialFocusRef?: RefObject<HTMLElement | null>;
36
- /** Wins over the captured opener. Safari leaves <body> focused after a tap on a button. */
37
- returnFocusRef?: RefObject<HTMLElement | null>;
38
- restoreFocus?: boolean;
39
- };
40
- declare function useFocusTrap(containerRef: RefObject<HTMLElement | null>, { active, initialFocusRef, returnFocusRef, restoreFocus, }: UseFocusTrapOptions): void;
41
-
42
- declare function useEscape(onEscape: () => void, active?: boolean): void;
43
-
44
- type CopyResult = {
45
- ok: true;
46
- } | {
47
- ok: false;
48
- reason: 'unavailable' | 'denied';
49
- };
50
- declare function copyText(text: string): Promise<CopyResult>;
51
-
52
- type CopyStatus = 'idle' | 'copied' | 'failed';
53
- declare function useCopyFeedback({ resetMs }?: {
54
- resetMs?: number;
55
- }): {
56
- copy: (text: string) => Promise<CopyResult>;
57
- status: CopyStatus;
58
- };
59
-
60
- export { BACK_ZONE_PX, CLOSE_DISTANCE_PX, type CopyResult, type CopyStatus, FOCUSABLE_SELECTOR, FORWARD_ZONE_PX, MAX_SWIPE_DURATION_MS, OPEN_DISTANCE_PX, type SwipeIntent, type SwipePoint, type UseDrawerSwipeOptions, type UseFocusTrapOptions, VERTICAL_CANCEL_PX, copyText, focusableWithin, isInOpenZone, isInsideHorizontalScroller, nextFocusTarget, resolveSwipeIntent, useCopyFeedback, useDrawerSwipe, useEscape, useFocusTrap };
1
+ export { BACK_ZONE_PX, CLOSE_DISTANCE_PX, DEFAULT_IGNORE_SELECTOR, FORWARD_ZONE_PX, MAX_SWIPE_DURATION_MS, OPEN_DISTANCE_PX, SwipeIntent, SwipePoint, UseDrawerSwipeOptions, VERTICAL_CANCEL_PX, isInIgnoredRegion, isInOpenZone, isInsideHorizontalScroller, resolveSwipeIntent, useDrawerSwipe } from './drawer-swipe.cjs';
2
+ export { FOCUSABLE_SELECTOR, UseFocusTrapOptions, focusableWithin, nextFocusTarget, useFocusTrap } from './focus-trap.cjs';
3
+ export { useEscape } from './escape.cjs';
4
+ export { CopyResult, CopyStatus, ReadResult, copyText, readText, useCopyFeedback } from './clipboard.cjs';
5
+ export { lockScroll, unlockScroll, useScrollLock } from './scroll-lock.cjs';
6
+ export { COARSE_POINTER_QUERY, REDUCED_MOTION_QUERY, UseMediaQueryOptions, useCoarsePointer, useMediaQuery, useReducedMotion } from './media-query.cjs';
7
+ export { UseOutsidePressOptions, isOutside, isPrimaryPress, useOutsidePress } from './outside-press.cjs';
8
+ export { UseVisibilityPollingOptions, nextDelay, useVisibilityPolling } from './visibility-polling.cjs';
9
+ export { DebouncedCallback, Debouncer, createDebouncer, useDebouncedCallback, useDebouncedValue } from './debounce.cjs';
10
+ export { StorageKind, StorageStateSetter, UseStorageStateOptions, useStorageState } from './storage-state.cjs';
11
+ export { handleBeforeUnload, useUnsavedChangesGuard } from './unsaved-guard.cjs';
12
+ export { ParsedHotkey, UseHotkeyOptions, detectApple, isEditableTarget, matchHotkey, parseHotkey, useHotkey } from './hotkey.cjs';
13
+ export { NextHeight, UseAutoGrowTextareaOptions, nextHeight, useAutoGrowTextarea } from './auto-grow.cjs';
14
+ export { InstallPrompt, Platform, PlatformEnv, PromptOutcome, detectPlatform, isIos, isIosSafari, isStandalone, startInstallPromptCapture, useInstallPrompt, useIsStandalone } from './pwa.cjs';
15
+ export { useOnlineStatus } from './online-status.cjs';
16
+ export { ServiceWorkerState, UpdateStateInput, UseServiceWorkerOptions, deriveUpdateState, unregisterAll, useServiceWorker } from './service-worker.cjs';
17
+ export { ShareInput, ShareResult, ShareStatus, canShareFiles, isShareCancel, shareOrCopy, shareTextFor, useShareFeedback } from './share.cjs';
18
+ export { InsetReading, UseKeyboardInsetOptions, computeKeyboardInset, isEditableElement, useKeyboardInset } from './keyboard-inset.cjs';
19
+ export { PushEnv, PushPermission, PushSubscriptionState, PushSupport, ResubscribeInput, UsePushSubscriptionOptions, getPushSupport, shouldResubscribe, urlBase64ToUint8Array, usePushSubscription } from './push.cjs';
20
+ import 'react';
package/dist/index.d.ts CHANGED
@@ -1,60 +1,20 @@
1
- import { RefObject } from 'react';
2
-
3
- type SwipePoint = {
4
- x: number;
5
- y: number;
6
- time: number;
7
- };
8
- declare const BACK_ZONE_PX = 60;
9
- declare const FORWARD_ZONE_PX = 30;
10
- declare const OPEN_DISTANCE_PX = 80;
11
- declare const CLOSE_DISTANCE_PX = 60;
12
- declare const VERTICAL_CANCEL_PX = 40;
13
- declare const MAX_SWIPE_DURATION_MS = 450;
14
- type SwipeIntent = 'open' | 'close' | null;
15
- declare function isInOpenZone(x: number, viewportWidth: number): boolean;
16
- declare function resolveSwipeIntent(start: SwipePoint, end: SwipePoint, drawerOpen: boolean, viewportWidth: number): SwipeIntent;
17
- declare function isInsideHorizontalScroller(target: EventTarget | null): boolean;
18
-
19
- type UseDrawerSwipeOptions = {
20
- drawerOpen: boolean;
21
- onOpen: () => void;
22
- onClose: () => void;
23
- enabled?: boolean;
24
- maxViewportWidth?: number;
25
- };
26
- declare function useDrawerSwipe({ drawerOpen, onOpen, onClose, enabled, maxViewportWidth, }: UseDrawerSwipeOptions): void;
27
-
28
- declare const FOCUSABLE_SELECTOR = "a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
29
- declare function focusableWithin(container: HTMLElement): HTMLElement[];
30
- /** The element Tab must be redirected to, or null when the browser's own move is fine. */
31
- declare function nextFocusTarget(items: HTMLElement[], current: Element | null, shiftKey: boolean, container: HTMLElement): HTMLElement | null;
32
-
33
- type UseFocusTrapOptions = {
34
- active: boolean;
35
- initialFocusRef?: RefObject<HTMLElement | null>;
36
- /** Wins over the captured opener. Safari leaves <body> focused after a tap on a button. */
37
- returnFocusRef?: RefObject<HTMLElement | null>;
38
- restoreFocus?: boolean;
39
- };
40
- declare function useFocusTrap(containerRef: RefObject<HTMLElement | null>, { active, initialFocusRef, returnFocusRef, restoreFocus, }: UseFocusTrapOptions): void;
41
-
42
- declare function useEscape(onEscape: () => void, active?: boolean): void;
43
-
44
- type CopyResult = {
45
- ok: true;
46
- } | {
47
- ok: false;
48
- reason: 'unavailable' | 'denied';
49
- };
50
- declare function copyText(text: string): Promise<CopyResult>;
51
-
52
- type CopyStatus = 'idle' | 'copied' | 'failed';
53
- declare function useCopyFeedback({ resetMs }?: {
54
- resetMs?: number;
55
- }): {
56
- copy: (text: string) => Promise<CopyResult>;
57
- status: CopyStatus;
58
- };
59
-
60
- export { BACK_ZONE_PX, CLOSE_DISTANCE_PX, type CopyResult, type CopyStatus, FOCUSABLE_SELECTOR, FORWARD_ZONE_PX, MAX_SWIPE_DURATION_MS, OPEN_DISTANCE_PX, type SwipeIntent, type SwipePoint, type UseDrawerSwipeOptions, type UseFocusTrapOptions, VERTICAL_CANCEL_PX, copyText, focusableWithin, isInOpenZone, isInsideHorizontalScroller, nextFocusTarget, resolveSwipeIntent, useCopyFeedback, useDrawerSwipe, useEscape, useFocusTrap };
1
+ export { BACK_ZONE_PX, CLOSE_DISTANCE_PX, DEFAULT_IGNORE_SELECTOR, FORWARD_ZONE_PX, MAX_SWIPE_DURATION_MS, OPEN_DISTANCE_PX, SwipeIntent, SwipePoint, UseDrawerSwipeOptions, VERTICAL_CANCEL_PX, isInIgnoredRegion, isInOpenZone, isInsideHorizontalScroller, resolveSwipeIntent, useDrawerSwipe } from './drawer-swipe.js';
2
+ export { FOCUSABLE_SELECTOR, UseFocusTrapOptions, focusableWithin, nextFocusTarget, useFocusTrap } from './focus-trap.js';
3
+ export { useEscape } from './escape.js';
4
+ export { CopyResult, CopyStatus, ReadResult, copyText, readText, useCopyFeedback } from './clipboard.js';
5
+ export { lockScroll, unlockScroll, useScrollLock } from './scroll-lock.js';
6
+ export { COARSE_POINTER_QUERY, REDUCED_MOTION_QUERY, UseMediaQueryOptions, useCoarsePointer, useMediaQuery, useReducedMotion } from './media-query.js';
7
+ export { UseOutsidePressOptions, isOutside, isPrimaryPress, useOutsidePress } from './outside-press.js';
8
+ export { UseVisibilityPollingOptions, nextDelay, useVisibilityPolling } from './visibility-polling.js';
9
+ export { DebouncedCallback, Debouncer, createDebouncer, useDebouncedCallback, useDebouncedValue } from './debounce.js';
10
+ export { StorageKind, StorageStateSetter, UseStorageStateOptions, useStorageState } from './storage-state.js';
11
+ export { handleBeforeUnload, useUnsavedChangesGuard } from './unsaved-guard.js';
12
+ export { ParsedHotkey, UseHotkeyOptions, detectApple, isEditableTarget, matchHotkey, parseHotkey, useHotkey } from './hotkey.js';
13
+ export { NextHeight, UseAutoGrowTextareaOptions, nextHeight, useAutoGrowTextarea } from './auto-grow.js';
14
+ export { InstallPrompt, Platform, PlatformEnv, PromptOutcome, detectPlatform, isIos, isIosSafari, isStandalone, startInstallPromptCapture, useInstallPrompt, useIsStandalone } from './pwa.js';
15
+ export { useOnlineStatus } from './online-status.js';
16
+ export { ServiceWorkerState, UpdateStateInput, UseServiceWorkerOptions, deriveUpdateState, unregisterAll, useServiceWorker } from './service-worker.js';
17
+ export { ShareInput, ShareResult, ShareStatus, canShareFiles, isShareCancel, shareOrCopy, shareTextFor, useShareFeedback } from './share.js';
18
+ export { InsetReading, UseKeyboardInsetOptions, computeKeyboardInset, isEditableElement, useKeyboardInset } from './keyboard-inset.js';
19
+ export { PushEnv, PushPermission, PushSubscriptionState, PushSupport, ResubscribeInput, UsePushSubscriptionOptions, getPushSupport, shouldResubscribe, urlBase64ToUint8Array, usePushSubscription } from './push.js';
20
+ import 'react';
package/dist/index.js CHANGED
@@ -1,265 +1,185 @@
1
- // src/drawer-swipe/swipe-intent.ts
2
- var BACK_ZONE_PX = 60;
3
- var FORWARD_ZONE_PX = 30;
4
- var OPEN_DISTANCE_PX = 80;
5
- var CLOSE_DISTANCE_PX = 60;
6
- var VERTICAL_CANCEL_PX = 40;
7
- var MAX_SWIPE_DURATION_MS = 450;
8
- var HORIZONTAL_DOMINANCE = 1.5;
9
- function isInOpenZone(x, viewportWidth) {
10
- return x > BACK_ZONE_PX && x < viewportWidth - FORWARD_ZONE_PX;
11
- }
12
- function resolveSwipeIntent(start, end, drawerOpen, viewportWidth) {
13
- const dx = end.x - start.x;
14
- const dy = end.y - start.y;
15
- if (end.time - start.time > MAX_SWIPE_DURATION_MS) return null;
16
- if (Math.abs(dx) < Math.abs(dy) * HORIZONTAL_DOMINANCE) return null;
17
- if (drawerOpen) {
18
- return dx <= -CLOSE_DISTANCE_PX ? "close" : null;
19
- }
20
- if (dx < OPEN_DISTANCE_PX) return null;
21
- return isInOpenZone(start.x, viewportWidth) ? "open" : null;
22
- }
23
- function isInsideHorizontalScroller(target) {
24
- let node = target instanceof Element ? target : null;
25
- while (node && node !== document.body) {
26
- const { overflowX } = window.getComputedStyle(node);
27
- if ((overflowX === "auto" || overflowX === "scroll") && node.scrollWidth > node.clientWidth) {
28
- return true;
29
- }
30
- node = node.parentElement;
31
- }
32
- return false;
33
- }
34
-
35
- // src/drawer-swipe/use-drawer-swipe.ts
36
- import { useEffect, useRef } from "react";
37
- function isWideViewport(maxViewportWidth) {
38
- return window.matchMedia(`(min-width: ${maxViewportWidth}px)`).matches;
39
- }
40
- function useDrawerSwipe({
41
- drawerOpen,
42
- onOpen,
43
- onClose,
44
- enabled = true,
45
- maxViewportWidth = 768
46
- }) {
47
- const start = useRef(null);
48
- const handlers = useRef({ drawerOpen, onOpen, onClose, maxViewportWidth });
49
- handlers.current = { drawerOpen, onOpen, onClose, maxViewportWidth };
50
- useEffect(() => {
51
- if (!enabled) return;
52
- function handleStart(event) {
53
- start.current = null;
54
- if (event.touches.length !== 1) return;
55
- if (isWideViewport(handlers.current.maxViewportWidth)) return;
56
- if (!handlers.current.drawerOpen && isInsideHorizontalScroller(event.target)) {
57
- return;
58
- }
59
- const touch = event.touches[0];
60
- if (!touch) return;
61
- start.current = { x: touch.clientX, y: touch.clientY, time: Date.now() };
62
- }
63
- function handleMove(event) {
64
- const origin = start.current;
65
- const touch = event.touches[0];
66
- if (!origin || !touch) return;
67
- if (Math.abs(touch.clientY - origin.y) > VERTICAL_CANCEL_PX) {
68
- start.current = null;
69
- }
70
- }
71
- function handleEnd(event) {
72
- const origin = start.current;
73
- start.current = null;
74
- const touch = event.changedTouches[0];
75
- if (!origin || !touch) return;
76
- const { drawerOpen: drawerOpen2, onOpen: onOpen2, onClose: onClose2 } = handlers.current;
77
- const intent = resolveSwipeIntent(
78
- origin,
79
- { x: touch.clientX, y: touch.clientY, time: Date.now() },
80
- drawerOpen2,
81
- window.innerWidth
82
- );
83
- if (intent === "open") onOpen2();
84
- if (intent === "close") onClose2();
85
- }
86
- function handleCancel() {
87
- start.current = null;
88
- }
89
- document.addEventListener("touchstart", handleStart, { passive: true });
90
- document.addEventListener("touchmove", handleMove, { passive: true });
91
- document.addEventListener("touchend", handleEnd, { passive: true });
92
- document.addEventListener("touchcancel", handleCancel, { passive: true });
93
- return () => {
94
- document.removeEventListener("touchstart", handleStart);
95
- document.removeEventListener("touchmove", handleMove);
96
- document.removeEventListener("touchend", handleEnd);
97
- document.removeEventListener("touchcancel", handleCancel);
98
- };
99
- }, [enabled]);
100
- }
101
-
102
- // src/focus-trap/focusables.ts
103
- var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
104
- function focusableWithin(container) {
105
- return Array.from(
106
- container.querySelectorAll(FOCUSABLE_SELECTOR)
107
- ).filter((el) => !el.closest("[hidden], [inert]"));
108
- }
109
- function nextFocusTarget(items, current, shiftKey, container) {
110
- const first = items[0];
111
- const last = items[items.length - 1];
112
- if (!first || !last) return null;
113
- if (!current || !container.contains(current)) return shiftKey ? last : first;
114
- if (shiftKey && (current === first || current === container)) return last;
115
- if (!shiftKey && current === last) return first;
116
- return null;
117
- }
118
-
119
- // src/focus-trap/use-focus-trap.ts
120
- import { useEffect as useEffect2, useRef as useRef2 } from "react";
121
- var activeTraps = [];
122
- function useFocusTrap(containerRef, {
123
- active,
124
- initialFocusRef,
125
- returnFocusRef,
126
- restoreFocus = true
127
- }) {
128
- const openerRef = useRef2(null);
129
- if (active && !openerRef.current && typeof document !== "undefined") {
130
- openerRef.current = document.activeElement;
131
- }
132
- useEffect2(() => {
133
- const container = containerRef.current;
134
- if (!active || !container) return;
135
- const token = {};
136
- activeTraps.push(token);
137
- if (!container.contains(document.activeElement)) {
138
- const target = initialFocusRef?.current ?? focusableWithin(container)[0] ?? container;
139
- if (target === container && !container.hasAttribute("tabindex")) {
140
- container.setAttribute("tabindex", "-1");
141
- }
142
- target.focus();
143
- }
144
- function onKeyDown(event) {
145
- if (event.key !== "Tab" || !container) return;
146
- if (activeTraps[activeTraps.length - 1] !== token) return;
147
- const items = focusableWithin(container);
148
- if (items.length === 0) {
149
- event.preventDefault();
150
- return;
151
- }
152
- const target = nextFocusTarget(
153
- items,
154
- document.activeElement,
155
- event.shiftKey,
156
- container
157
- );
158
- if (target) {
159
- event.preventDefault();
160
- target.focus();
161
- }
162
- }
163
- document.addEventListener("keydown", onKeyDown);
164
- return () => {
165
- document.removeEventListener("keydown", onKeyDown);
166
- activeTraps.splice(activeTraps.indexOf(token), 1);
167
- const opener = returnFocusRef?.current ?? openerRef.current;
168
- openerRef.current = null;
169
- if (restoreFocus && opener?.isConnected) opener.focus();
170
- };
171
- }, [active, containerRef, initialFocusRef, returnFocusRef, restoreFocus]);
172
- }
173
-
174
- // src/escape/use-escape.ts
175
- import { useEffect as useEffect3, useRef as useRef3 } from "react";
176
- function useEscape(onEscape, active = true) {
177
- const handlerRef = useRef3(onEscape);
178
- useEffect3(() => {
179
- handlerRef.current = onEscape;
180
- });
181
- useEffect3(() => {
182
- if (!active) return;
183
- function onKeyDown(event) {
184
- if (event.key === "Escape") handlerRef.current();
185
- }
186
- document.addEventListener("keydown", onKeyDown);
187
- return () => document.removeEventListener("keydown", onKeyDown);
188
- }, [active]);
189
- }
190
-
191
- // src/clipboard/copy-text.ts
192
- async function copyText(text) {
193
- const hasClipboardApi = typeof navigator !== "undefined" && !!navigator.clipboard?.writeText && typeof window !== "undefined" && window.isSecureContext;
194
- if (hasClipboardApi) {
195
- try {
196
- await navigator.clipboard.writeText(text);
197
- return { ok: true };
198
- } catch {
199
- }
200
- }
201
- if (execCommandCopy(text)) return { ok: true };
202
- return { ok: false, reason: hasClipboardApi ? "denied" : "unavailable" };
203
- }
204
- function execCommandCopy(text) {
205
- if (typeof document === "undefined") return false;
206
- const textarea = document.createElement("textarea");
207
- textarea.value = text;
208
- textarea.readOnly = true;
209
- textarea.style.position = "fixed";
210
- textarea.style.top = "-1000px";
211
- textarea.style.left = "-1000px";
212
- textarea.style.fontSize = "16px";
213
- document.body.appendChild(textarea);
214
- try {
215
- textarea.select();
216
- textarea.setSelectionRange(0, text.length);
217
- return document.execCommand("copy");
218
- } catch {
219
- return false;
220
- } finally {
221
- document.body.removeChild(textarea);
222
- }
223
- }
224
-
225
- // src/clipboard/use-copy-feedback.ts
226
- import { useCallback, useEffect as useEffect4, useRef as useRef4, useState } from "react";
227
- function useCopyFeedback({ resetMs = 1500 } = {}) {
228
- const [status, setStatus] = useState("idle");
229
- const timerRef = useRef4(void 0);
230
- const clearTimer = useCallback(() => {
231
- if (timerRef.current !== void 0) clearTimeout(timerRef.current);
232
- timerRef.current = void 0;
233
- }, []);
234
- useEffect4(() => clearTimer, [clearTimer]);
235
- const copy = useCallback(
236
- async (text) => {
237
- const result = await copyText(text);
238
- clearTimer();
239
- setStatus(result.ok ? "copied" : "failed");
240
- timerRef.current = setTimeout(() => setStatus("idle"), resetMs);
241
- return result;
242
- },
243
- [clearTimer, resetMs]
244
- );
245
- return { copy, status };
246
- }
1
+ "use client";
2
+ import {
3
+ deriveUpdateState,
4
+ unregisterAll,
5
+ useServiceWorker
6
+ } from "./chunk-JG3GPTMY.js";
7
+ import {
8
+ canShareFiles,
9
+ isShareCancel,
10
+ shareOrCopy,
11
+ shareTextFor,
12
+ useShareFeedback
13
+ } from "./chunk-4PVVTQ5V.js";
14
+ import {
15
+ computeKeyboardInset,
16
+ isEditableElement,
17
+ useKeyboardInset
18
+ } from "./chunk-TNEJ34T5.js";
19
+ import {
20
+ getPushSupport,
21
+ shouldResubscribe,
22
+ urlBase64ToUint8Array,
23
+ usePushSubscription
24
+ } from "./chunk-UJ366T3Y.js";
25
+ import {
26
+ nextDelay,
27
+ useVisibilityPolling
28
+ } from "./chunk-UPVNSGIK.js";
29
+ import {
30
+ createDebouncer,
31
+ useDebouncedCallback,
32
+ useDebouncedValue
33
+ } from "./chunk-IWQDAJEP.js";
34
+ import {
35
+ useStorageState
36
+ } from "./chunk-5KIH2XLV.js";
37
+ import {
38
+ handleBeforeUnload,
39
+ useUnsavedChangesGuard
40
+ } from "./chunk-LZKAGDER.js";
41
+ import {
42
+ detectApple,
43
+ isEditableTarget,
44
+ matchHotkey,
45
+ parseHotkey,
46
+ useHotkey
47
+ } from "./chunk-NKLEB5TR.js";
48
+ import {
49
+ nextHeight,
50
+ useAutoGrowTextarea
51
+ } from "./chunk-5CA5RIMH.js";
52
+ import {
53
+ startInstallPromptCapture,
54
+ useInstallPrompt,
55
+ useIsStandalone
56
+ } from "./chunk-Z3X27PCA.js";
57
+ import {
58
+ detectPlatform,
59
+ isIos,
60
+ isIosSafari,
61
+ isStandalone
62
+ } from "./chunk-YFMMSLMB.js";
63
+ import {
64
+ useOnlineStatus
65
+ } from "./chunk-WXL22EWK.js";
66
+ import {
67
+ BACK_ZONE_PX,
68
+ CLOSE_DISTANCE_PX,
69
+ DEFAULT_IGNORE_SELECTOR,
70
+ FORWARD_ZONE_PX,
71
+ MAX_SWIPE_DURATION_MS,
72
+ OPEN_DISTANCE_PX,
73
+ VERTICAL_CANCEL_PX,
74
+ isInIgnoredRegion,
75
+ isInOpenZone,
76
+ isInsideHorizontalScroller,
77
+ resolveSwipeIntent,
78
+ useDrawerSwipe
79
+ } from "./chunk-5XRVPZHD.js";
80
+ import {
81
+ FOCUSABLE_SELECTOR,
82
+ focusableWithin,
83
+ nextFocusTarget,
84
+ useFocusTrap
85
+ } from "./chunk-DNU57XEJ.js";
86
+ import {
87
+ useEscape
88
+ } from "./chunk-S4YKMGQE.js";
89
+ import {
90
+ readText,
91
+ useCopyFeedback
92
+ } from "./chunk-EXEJI4FK.js";
93
+ import {
94
+ copyText
95
+ } from "./chunk-FE3BQD2I.js";
96
+ import {
97
+ lockScroll,
98
+ unlockScroll,
99
+ useScrollLock
100
+ } from "./chunk-6KCRVSLS.js";
101
+ import {
102
+ useCoarsePointer,
103
+ useMediaQuery,
104
+ useReducedMotion
105
+ } from "./chunk-HTVNN2NM.js";
106
+ import {
107
+ COARSE_POINTER_QUERY,
108
+ REDUCED_MOTION_QUERY
109
+ } from "./chunk-WVM2LTWQ.js";
110
+ import {
111
+ isOutside,
112
+ isPrimaryPress,
113
+ useOutsidePress
114
+ } from "./chunk-DQBKU7HI.js";
247
115
  export {
248
116
  BACK_ZONE_PX,
249
117
  CLOSE_DISTANCE_PX,
118
+ COARSE_POINTER_QUERY,
119
+ DEFAULT_IGNORE_SELECTOR,
250
120
  FOCUSABLE_SELECTOR,
251
121
  FORWARD_ZONE_PX,
252
122
  MAX_SWIPE_DURATION_MS,
253
123
  OPEN_DISTANCE_PX,
124
+ REDUCED_MOTION_QUERY,
254
125
  VERTICAL_CANCEL_PX,
126
+ canShareFiles,
127
+ computeKeyboardInset,
255
128
  copyText,
129
+ createDebouncer,
130
+ deriveUpdateState,
131
+ detectApple,
132
+ detectPlatform,
256
133
  focusableWithin,
134
+ getPushSupport,
135
+ handleBeforeUnload,
136
+ isEditableElement,
137
+ isEditableTarget,
138
+ isInIgnoredRegion,
257
139
  isInOpenZone,
258
140
  isInsideHorizontalScroller,
141
+ isIos,
142
+ isIosSafari,
143
+ isOutside,
144
+ isPrimaryPress,
145
+ isShareCancel,
146
+ isStandalone,
147
+ lockScroll,
148
+ matchHotkey,
149
+ nextDelay,
259
150
  nextFocusTarget,
151
+ nextHeight,
152
+ parseHotkey,
153
+ readText,
260
154
  resolveSwipeIntent,
155
+ shareOrCopy,
156
+ shareTextFor,
157
+ shouldResubscribe,
158
+ startInstallPromptCapture,
159
+ unlockScroll,
160
+ unregisterAll,
161
+ urlBase64ToUint8Array,
162
+ useAutoGrowTextarea,
163
+ useCoarsePointer,
261
164
  useCopyFeedback,
165
+ useDebouncedCallback,
166
+ useDebouncedValue,
262
167
  useDrawerSwipe,
263
168
  useEscape,
264
- useFocusTrap
169
+ useFocusTrap,
170
+ useHotkey,
171
+ useInstallPrompt,
172
+ useIsStandalone,
173
+ useKeyboardInset,
174
+ useMediaQuery,
175
+ useOnlineStatus,
176
+ useOutsidePress,
177
+ usePushSubscription,
178
+ useReducedMotion,
179
+ useScrollLock,
180
+ useServiceWorker,
181
+ useShareFeedback,
182
+ useStorageState,
183
+ useUnsavedChangesGuard,
184
+ useVisibilityPolling
265
185
  };