@ox0/hooks 0.1.0 → 0.2.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.
- package/LICENSE +21 -0
- package/README.md +225 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +642 -9
- package/dist/use-before-unload-warning.d.ts +6 -0
- package/dist/use-before-unload-warning.d.ts.map +1 -0
- package/dist/use-breakpoint.d.ts +12 -0
- package/dist/use-breakpoint.d.ts.map +1 -0
- package/dist/use-container-size.d.ts +18 -0
- package/dist/use-container-size.d.ts.map +1 -0
- package/dist/use-controllable-state.d.ts +15 -0
- package/dist/use-controllable-state.d.ts.map +1 -0
- package/dist/use-controllable-state.test.d.ts +2 -0
- package/dist/use-controllable-state.test.d.ts.map +1 -0
- package/dist/use-copy-to-clipboard.d.ts +6 -0
- package/dist/use-copy-to-clipboard.d.ts.map +1 -0
- package/dist/use-debounced-value.d.ts +2 -0
- package/dist/use-debounced-value.d.ts.map +1 -0
- package/dist/use-debounced-value.test.d.ts +2 -0
- package/dist/use-debounced-value.test.d.ts.map +1 -0
- package/dist/use-deferred-presence.d.ts +15 -0
- package/dist/use-deferred-presence.d.ts.map +1 -0
- package/dist/use-disclosure.d.ts +8 -0
- package/dist/use-disclosure.d.ts.map +1 -0
- package/dist/use-disclosure.test.d.ts +2 -0
- package/dist/use-disclosure.test.d.ts.map +1 -0
- package/dist/use-event-listener.d.ts +5 -0
- package/dist/use-event-listener.d.ts.map +1 -0
- package/dist/use-hover.d.ts +5 -0
- package/dist/use-hover.d.ts.map +1 -0
- package/dist/use-interval.d.ts +2 -0
- package/dist/use-interval.d.ts.map +1 -0
- package/dist/use-key-down.d.ts +9 -0
- package/dist/use-key-down.d.ts.map +1 -0
- package/dist/use-long-press.d.ts +23 -0
- package/dist/use-long-press.d.ts.map +1 -0
- package/dist/use-media-query.d.ts +2 -0
- package/dist/use-media-query.d.ts.map +1 -0
- package/dist/use-media-query.test.d.ts +2 -0
- package/dist/use-media-query.test.d.ts.map +1 -0
- package/dist/use-navigator-online.d.ts +3 -0
- package/dist/use-navigator-online.d.ts.map +1 -0
- package/dist/use-now.d.ts +6 -0
- package/dist/use-now.d.ts.map +1 -0
- package/dist/use-os.d.ts +8 -0
- package/dist/use-os.d.ts.map +1 -0
- package/dist/use-pointer-coarse.d.ts +3 -0
- package/dist/use-pointer-coarse.d.ts.map +1 -0
- package/dist/use-prefers-reduced-motion.d.ts +3 -0
- package/dist/use-prefers-reduced-motion.d.ts.map +1 -0
- package/dist/use-press.d.ts +3 -0
- package/dist/use-press.d.ts.map +1 -0
- package/dist/use-previous.d.ts +2 -0
- package/dist/use-previous.d.ts.map +1 -0
- package/dist/use-stored-state.d.ts +23 -0
- package/dist/use-stored-state.d.ts.map +1 -0
- package/dist/use-stored-state.test.d.ts +2 -0
- package/dist/use-stored-state.test.d.ts.map +1 -0
- package/dist/use-timeout.d.ts +2 -0
- package/dist/use-timeout.d.ts.map +1 -0
- package/dist/use-viewport.d.ts +12 -0
- package/dist/use-viewport.d.ts.map +1 -0
- package/dist/use-window-size.d.ts +7 -0
- package/dist/use-window-size.d.ts.map +1 -0
- package/package.json +11 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,87 @@
|
|
|
1
1
|
import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react";
|
|
2
|
+
import * as __WEBPACK_EXTERNAL_MODULE__react_aria_interactions_8422cce9__ from "@react-aria/interactions";
|
|
3
|
+
function useBeforeUnloadWarning(enabled) {
|
|
4
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
5
|
+
if (!enabled || "undefined" == typeof window) return;
|
|
6
|
+
const handle = (event)=>{
|
|
7
|
+
event.preventDefault();
|
|
8
|
+
event.returnValue = "";
|
|
9
|
+
};
|
|
10
|
+
window.addEventListener("beforeunload", handle);
|
|
11
|
+
return ()=>window.removeEventListener("beforeunload", handle);
|
|
12
|
+
}, [
|
|
13
|
+
enabled
|
|
14
|
+
]);
|
|
15
|
+
}
|
|
16
|
+
const MOBILE_MAX = 767;
|
|
17
|
+
const TABLET_MAX = 1023;
|
|
18
|
+
function getBreakpoint() {
|
|
19
|
+
if ("undefined" == typeof window) return "desktop";
|
|
20
|
+
if (window.matchMedia(`(max-width: ${MOBILE_MAX}px)`).matches) return "mobile";
|
|
21
|
+
if (window.matchMedia(`(max-width: ${TABLET_MAX}px)`).matches) return "tablet";
|
|
22
|
+
return "desktop";
|
|
23
|
+
}
|
|
24
|
+
function toState(breakpoint) {
|
|
25
|
+
return {
|
|
26
|
+
breakpoint,
|
|
27
|
+
isMobile: "mobile" === breakpoint,
|
|
28
|
+
isTablet: "tablet" === breakpoint,
|
|
29
|
+
isDesktop: "desktop" === breakpoint,
|
|
30
|
+
isMobileOrTablet: "desktop" !== breakpoint,
|
|
31
|
+
isTabletOrDesktop: "mobile" !== breakpoint
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function useBreakpoint() {
|
|
35
|
+
const [state, setState] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(()=>toState(getBreakpoint()));
|
|
36
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
37
|
+
if ("undefined" == typeof window) return;
|
|
38
|
+
const mobileQuery = window.matchMedia(`(max-width: ${MOBILE_MAX}px)`);
|
|
39
|
+
const tabletQuery = window.matchMedia(`(max-width: ${TABLET_MAX}px)`);
|
|
40
|
+
const handleChange = ()=>{
|
|
41
|
+
setState((prev)=>{
|
|
42
|
+
const next = getBreakpoint();
|
|
43
|
+
return prev.breakpoint === next ? prev : toState(next);
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
handleChange();
|
|
47
|
+
mobileQuery.addEventListener("change", handleChange);
|
|
48
|
+
tabletQuery.addEventListener("change", handleChange);
|
|
49
|
+
return ()=>{
|
|
50
|
+
mobileQuery.removeEventListener("change", handleChange);
|
|
51
|
+
tabletQuery.removeEventListener("change", handleChange);
|
|
52
|
+
};
|
|
53
|
+
}, []);
|
|
54
|
+
return state;
|
|
55
|
+
}
|
|
56
|
+
function useContainerSize() {
|
|
57
|
+
const ref = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(null);
|
|
58
|
+
const [size, setSize] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)({
|
|
59
|
+
width: 0,
|
|
60
|
+
height: 0
|
|
61
|
+
});
|
|
62
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
63
|
+
const el = ref.current;
|
|
64
|
+
if (!el) return;
|
|
65
|
+
const observer = new ResizeObserver((entries)=>{
|
|
66
|
+
const rect = entries[0]?.contentRect;
|
|
67
|
+
if (rect) setSize({
|
|
68
|
+
width: rect.width,
|
|
69
|
+
height: rect.height
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
observer.observe(el);
|
|
73
|
+
const rect = el.getBoundingClientRect();
|
|
74
|
+
setSize({
|
|
75
|
+
width: rect.width,
|
|
76
|
+
height: rect.height
|
|
77
|
+
});
|
|
78
|
+
return ()=>observer.disconnect();
|
|
79
|
+
}, []);
|
|
80
|
+
return [
|
|
81
|
+
ref,
|
|
82
|
+
size
|
|
83
|
+
];
|
|
84
|
+
}
|
|
2
85
|
function useControllableState(options) {
|
|
3
86
|
const { defaultValue, onChange, value } = options;
|
|
4
87
|
const [uncontrolledValue, setUncontrolledValue] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(defaultValue);
|
|
@@ -19,6 +102,27 @@ function useControllableState(options) {
|
|
|
19
102
|
setValue
|
|
20
103
|
];
|
|
21
104
|
}
|
|
105
|
+
function useCopyToClipboard(resetMs = 2000) {
|
|
106
|
+
const [copied, setCopied] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(false);
|
|
107
|
+
const timerRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(null);
|
|
108
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>()=>{
|
|
109
|
+
if (null !== timerRef.current) clearTimeout(timerRef.current);
|
|
110
|
+
}, []);
|
|
111
|
+
const copy = (0, __WEBPACK_EXTERNAL_MODULE_react__.useCallback)(async (text)=>{
|
|
112
|
+
try {
|
|
113
|
+
await navigator.clipboard.writeText(text);
|
|
114
|
+
setCopied(true);
|
|
115
|
+
if (null !== timerRef.current) clearTimeout(timerRef.current);
|
|
116
|
+
timerRef.current = setTimeout(()=>setCopied(false), resetMs);
|
|
117
|
+
} catch {}
|
|
118
|
+
}, [
|
|
119
|
+
resetMs
|
|
120
|
+
]);
|
|
121
|
+
return {
|
|
122
|
+
copy,
|
|
123
|
+
copied
|
|
124
|
+
};
|
|
125
|
+
}
|
|
22
126
|
function useDebouncedValue(value, delay = 200) {
|
|
23
127
|
const [debouncedValue, setDebouncedValue] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(value);
|
|
24
128
|
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
@@ -34,6 +138,50 @@ function useDebouncedValue(value, delay = 200) {
|
|
|
34
138
|
]);
|
|
35
139
|
return debouncedValue;
|
|
36
140
|
}
|
|
141
|
+
function useDeferredPresence(isPresent, { delayMs, exitMs, minimumVisibleMs }) {
|
|
142
|
+
const [state, setState] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)({
|
|
143
|
+
phase: "hidden"
|
|
144
|
+
});
|
|
145
|
+
const timerRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(void 0);
|
|
146
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
147
|
+
clearTimeout(timerRef.current);
|
|
148
|
+
if (isPresent) {
|
|
149
|
+
if ("visible" === state.phase) return;
|
|
150
|
+
if ("exiting" === state.phase) {
|
|
151
|
+
setState({
|
|
152
|
+
phase: "visible",
|
|
153
|
+
shownAt: state.shownAt
|
|
154
|
+
});
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
timerRef.current = window.setTimeout(()=>{
|
|
158
|
+
setState({
|
|
159
|
+
phase: "visible",
|
|
160
|
+
shownAt: Date.now()
|
|
161
|
+
});
|
|
162
|
+
}, delayMs);
|
|
163
|
+
} else if ("visible" === state.phase) {
|
|
164
|
+
const visibleMs = Date.now() - state.shownAt;
|
|
165
|
+
const delay = Math.max(0, minimumVisibleMs - visibleMs);
|
|
166
|
+
timerRef.current = window.setTimeout(()=>{
|
|
167
|
+
setState({
|
|
168
|
+
phase: "exiting",
|
|
169
|
+
shownAt: state.shownAt
|
|
170
|
+
});
|
|
171
|
+
}, delay);
|
|
172
|
+
} else if ("exiting" === state.phase) timerRef.current = window.setTimeout(()=>setState({
|
|
173
|
+
phase: "hidden"
|
|
174
|
+
}), exitMs);
|
|
175
|
+
return ()=>clearTimeout(timerRef.current);
|
|
176
|
+
}, [
|
|
177
|
+
delayMs,
|
|
178
|
+
exitMs,
|
|
179
|
+
isPresent,
|
|
180
|
+
minimumVisibleMs,
|
|
181
|
+
state
|
|
182
|
+
]);
|
|
183
|
+
return state.phase;
|
|
184
|
+
}
|
|
37
185
|
function useDisclosure(initialOpen = false) {
|
|
38
186
|
const [isOpen, setIsOpen] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(initialOpen);
|
|
39
187
|
const onClose = (0, __WEBPACK_EXTERNAL_MODULE_react__.useCallback)(()=>{
|
|
@@ -52,24 +200,376 @@ function useDisclosure(initialOpen = false) {
|
|
|
52
200
|
onToggle
|
|
53
201
|
};
|
|
54
202
|
}
|
|
55
|
-
function
|
|
56
|
-
const
|
|
57
|
-
if ("undefined" == typeof window) return initialValue;
|
|
58
|
-
const storedValue = window.localStorage.getItem(key);
|
|
59
|
-
return storedValue ? JSON.parse(storedValue) : initialValue;
|
|
60
|
-
});
|
|
203
|
+
function useEventListener(type, listener, target) {
|
|
204
|
+
const listenerRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(listener);
|
|
61
205
|
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
62
|
-
|
|
63
|
-
|
|
206
|
+
listenerRef.current = listener;
|
|
207
|
+
}, [
|
|
208
|
+
listener
|
|
209
|
+
]);
|
|
210
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
211
|
+
const el = void 0 === target ? window : target && "current" in target ? target.current : target;
|
|
212
|
+
if (!el) return;
|
|
213
|
+
const handler = (e)=>listenerRef.current(e);
|
|
214
|
+
el.addEventListener(type, handler);
|
|
215
|
+
return ()=>el.removeEventListener(type, handler);
|
|
216
|
+
}, [
|
|
217
|
+
type,
|
|
218
|
+
target
|
|
219
|
+
]);
|
|
220
|
+
}
|
|
221
|
+
function useHover() {
|
|
222
|
+
const ref = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(null);
|
|
223
|
+
const [hovered, setHovered] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(false);
|
|
224
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
225
|
+
const el = ref.current;
|
|
226
|
+
if (!el) return;
|
|
227
|
+
const enter = ()=>setHovered(true);
|
|
228
|
+
const leave = ()=>setHovered(false);
|
|
229
|
+
el.addEventListener("pointerenter", enter);
|
|
230
|
+
el.addEventListener("pointerleave", leave);
|
|
231
|
+
return ()=>{
|
|
232
|
+
el.removeEventListener("pointerenter", enter);
|
|
233
|
+
el.removeEventListener("pointerleave", leave);
|
|
234
|
+
};
|
|
235
|
+
}, []);
|
|
236
|
+
return [
|
|
237
|
+
ref,
|
|
238
|
+
hovered
|
|
239
|
+
];
|
|
240
|
+
}
|
|
241
|
+
function useInterval(callback, delay) {
|
|
242
|
+
const callbackRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(callback);
|
|
243
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
244
|
+
callbackRef.current = callback;
|
|
64
245
|
}, [
|
|
246
|
+
callback
|
|
247
|
+
]);
|
|
248
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
249
|
+
if (null === delay) return;
|
|
250
|
+
const id = window.setInterval(()=>callbackRef.current(), delay);
|
|
251
|
+
return ()=>window.clearInterval(id);
|
|
252
|
+
}, [
|
|
253
|
+
delay
|
|
254
|
+
]);
|
|
255
|
+
}
|
|
256
|
+
function useKeyDown(key, callback, { ctrl = false, meta = false, shift = false, alt = false, enabled = true } = {}) {
|
|
257
|
+
const callbackRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(callback);
|
|
258
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
259
|
+
callbackRef.current = callback;
|
|
260
|
+
}, [
|
|
261
|
+
callback
|
|
262
|
+
]);
|
|
263
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
264
|
+
if (!enabled) return;
|
|
265
|
+
const handler = (e)=>{
|
|
266
|
+
if (e.key !== key) return;
|
|
267
|
+
if (ctrl && !e.ctrlKey) return;
|
|
268
|
+
if (meta && !e.metaKey) return;
|
|
269
|
+
if (shift && !e.shiftKey) return;
|
|
270
|
+
if (alt && !e.altKey) return;
|
|
271
|
+
callbackRef.current(e);
|
|
272
|
+
};
|
|
273
|
+
window.addEventListener("keydown", handler);
|
|
274
|
+
return ()=>window.removeEventListener("keydown", handler);
|
|
275
|
+
}, [
|
|
276
|
+
key,
|
|
277
|
+
ctrl,
|
|
278
|
+
meta,
|
|
279
|
+
shift,
|
|
280
|
+
alt,
|
|
281
|
+
enabled
|
|
282
|
+
]);
|
|
283
|
+
}
|
|
284
|
+
const instanceId = `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
285
|
+
const tabSubscribers = new Map();
|
|
286
|
+
function tabSubscribe(key, fn) {
|
|
287
|
+
let tabSet = tabSubscribers.get(key);
|
|
288
|
+
if (!tabSet) {
|
|
289
|
+
tabSet = new Set();
|
|
290
|
+
tabSubscribers.set(key, tabSet);
|
|
291
|
+
}
|
|
292
|
+
tabSet.add(fn);
|
|
293
|
+
return ()=>{
|
|
294
|
+
const set = tabSubscribers.get(key);
|
|
295
|
+
set?.delete(fn);
|
|
296
|
+
if (set?.size === 0) tabSubscribers.delete(key);
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
function tabNotify(key, value) {
|
|
300
|
+
tabSubscribers.get(key)?.forEach((fn)=>fn(value));
|
|
301
|
+
}
|
|
302
|
+
const crossTabSubscribers = new Map();
|
|
303
|
+
let broadcastChannel = null;
|
|
304
|
+
function getChannel() {
|
|
305
|
+
if ("undefined" == typeof window || "undefined" == typeof BroadcastChannel) return null;
|
|
306
|
+
if (!broadcastChannel) {
|
|
307
|
+
broadcastChannel = new BroadcastChannel("ox0:storage");
|
|
308
|
+
broadcastChannel.addEventListener("message", (e)=>{
|
|
309
|
+
crossTabSubscribers.get(e.data.key)?.forEach((fn)=>fn(e.data));
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
return broadcastChannel;
|
|
313
|
+
}
|
|
314
|
+
function crossTabSubscribe(key, fn) {
|
|
315
|
+
let crossTabSet = crossTabSubscribers.get(key);
|
|
316
|
+
if (!crossTabSet) {
|
|
317
|
+
crossTabSet = new Set();
|
|
318
|
+
crossTabSubscribers.set(key, crossTabSet);
|
|
319
|
+
}
|
|
320
|
+
crossTabSet.add(fn);
|
|
321
|
+
getChannel();
|
|
322
|
+
return ()=>{
|
|
323
|
+
const set = crossTabSubscribers.get(key);
|
|
324
|
+
set?.delete(fn);
|
|
325
|
+
if (set?.size === 0) crossTabSubscribers.delete(key);
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function getTabId() {
|
|
329
|
+
if ("undefined" == typeof sessionStorage) return instanceId;
|
|
330
|
+
const existing = sessionStorage.getItem("ox0:tab-id");
|
|
331
|
+
if (existing) return existing;
|
|
332
|
+
const next = `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
333
|
+
sessionStorage.setItem("ox0:tab-id", next);
|
|
334
|
+
return next;
|
|
335
|
+
}
|
|
336
|
+
function getStorage(kind) {
|
|
337
|
+
if ("undefined" == typeof window) return null;
|
|
338
|
+
return "persistent" === kind ? window.localStorage : window.sessionStorage;
|
|
339
|
+
}
|
|
340
|
+
function makeStorageKey(key, kind, shared, scope) {
|
|
341
|
+
const scoped = null !== scope ? `${scope}:${key}` : key;
|
|
342
|
+
const base = "session" === kind ? `session:${scoped}` : scoped;
|
|
343
|
+
return shared ? base : `${base}::${getTabId()}`;
|
|
344
|
+
}
|
|
345
|
+
function readSafe(raw, parser, defaultValue, version, migrate) {
|
|
346
|
+
if (null === raw) return {
|
|
347
|
+
value: defaultValue,
|
|
348
|
+
migrated: false
|
|
349
|
+
};
|
|
350
|
+
try {
|
|
351
|
+
const parsed = JSON.parse(raw);
|
|
352
|
+
if (!parsed || "object" != typeof parsed || !("v" in parsed) || !("value" in parsed)) return {
|
|
353
|
+
value: defaultValue,
|
|
354
|
+
migrated: false
|
|
355
|
+
};
|
|
356
|
+
if (parsed.v !== version) return migrate ? {
|
|
357
|
+
value: migrate(parsed.value, parsed.v),
|
|
358
|
+
migrated: true
|
|
359
|
+
} : {
|
|
360
|
+
value: defaultValue,
|
|
361
|
+
migrated: false
|
|
362
|
+
};
|
|
363
|
+
return {
|
|
364
|
+
value: parser.parse(parsed.value),
|
|
365
|
+
migrated: false
|
|
366
|
+
};
|
|
367
|
+
} catch {
|
|
368
|
+
return {
|
|
369
|
+
value: defaultValue,
|
|
370
|
+
migrated: false
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
function writeStorage(storage, key, value, version) {
|
|
375
|
+
const payload = {
|
|
376
|
+
v: version,
|
|
377
|
+
value
|
|
378
|
+
};
|
|
379
|
+
const raw = JSON.stringify(payload);
|
|
380
|
+
try {
|
|
381
|
+
storage?.setItem(key, raw);
|
|
382
|
+
} catch {}
|
|
383
|
+
return raw;
|
|
384
|
+
}
|
|
385
|
+
const StorageScopeContext = (0, __WEBPACK_EXTERNAL_MODULE_react__.createContext)(void 0);
|
|
386
|
+
function StorageProvider({ scope, children }) {
|
|
387
|
+
return (0, __WEBPACK_EXTERNAL_MODULE_react__.createElement)(StorageScopeContext.Provider, {
|
|
388
|
+
value: scope
|
|
389
|
+
}, children);
|
|
390
|
+
}
|
|
391
|
+
function useStorageScope() {
|
|
392
|
+
const scope = (0, __WEBPACK_EXTERNAL_MODULE_react__.useContext)(StorageScopeContext);
|
|
393
|
+
if (void 0 === scope) throw new Error("useStoredState: no StorageProvider found. Wrap your app with <StorageProvider scope={userId ?? null}>.");
|
|
394
|
+
return scope;
|
|
395
|
+
}
|
|
396
|
+
function useStoredState(kind, key, parser, { defaultValue, version = 1, migrate }, shared) {
|
|
397
|
+
const scope = useStorageScope();
|
|
398
|
+
const storage = getStorage(kind);
|
|
399
|
+
const storageKey = (0, __WEBPACK_EXTERNAL_MODULE_react__.useMemo)(()=>makeStorageKey(key, kind, shared, scope), [
|
|
65
400
|
key,
|
|
401
|
+
kind,
|
|
402
|
+
shared,
|
|
403
|
+
scope
|
|
404
|
+
]);
|
|
405
|
+
const parserRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(parser);
|
|
406
|
+
const defaultValueRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(defaultValue);
|
|
407
|
+
const versionRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(version);
|
|
408
|
+
const migrateRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(migrate);
|
|
409
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
410
|
+
parserRef.current = parser;
|
|
411
|
+
defaultValueRef.current = defaultValue;
|
|
412
|
+
versionRef.current = version;
|
|
413
|
+
migrateRef.current = migrate;
|
|
414
|
+
});
|
|
415
|
+
const [value, setValueState] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(()=>{
|
|
416
|
+
const raw = storage?.getItem(storageKey) ?? null;
|
|
417
|
+
const result = readSafe(raw, parser, defaultValue, version, migrate);
|
|
418
|
+
if (result.migrated) writeStorage(storage, storageKey, result.value, version);
|
|
419
|
+
return result.value;
|
|
420
|
+
});
|
|
421
|
+
const valueRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(value);
|
|
422
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
423
|
+
valueRef.current = value;
|
|
424
|
+
}, [
|
|
66
425
|
value
|
|
67
426
|
]);
|
|
427
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
428
|
+
const raw = storage?.getItem(storageKey) ?? null;
|
|
429
|
+
const result = readSafe(raw, parserRef.current, defaultValueRef.current, versionRef.current, migrateRef.current);
|
|
430
|
+
setValueState((prev)=>Object.is(prev, result.value) ? prev : result.value);
|
|
431
|
+
if (result.migrated) writeStorage(storage, storageKey, result.value, versionRef.current);
|
|
432
|
+
}, [
|
|
433
|
+
storage,
|
|
434
|
+
storageKey
|
|
435
|
+
]);
|
|
436
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>tabSubscribe(storageKey, (next)=>{
|
|
437
|
+
setValueState((prev)=>Object.is(prev, next) ? prev : next);
|
|
438
|
+
}), [
|
|
439
|
+
storageKey
|
|
440
|
+
]);
|
|
441
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
442
|
+
if (!shared) return;
|
|
443
|
+
return crossTabSubscribe(storageKey, (msg)=>{
|
|
444
|
+
if (msg.storage !== kind || msg.sourceId === instanceId) return;
|
|
445
|
+
const result = readSafe(msg.payload, parserRef.current, defaultValueRef.current, versionRef.current, migrateRef.current);
|
|
446
|
+
setValueState((prev)=>Object.is(prev, result.value) ? prev : result.value);
|
|
447
|
+
tabNotify(storageKey, result.value);
|
|
448
|
+
if (result.migrated) writeStorage(storage, storageKey, result.value, versionRef.current);
|
|
449
|
+
});
|
|
450
|
+
}, [
|
|
451
|
+
kind,
|
|
452
|
+
shared,
|
|
453
|
+
storage,
|
|
454
|
+
storageKey
|
|
455
|
+
]);
|
|
456
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
457
|
+
if (!shared || "persistent" !== kind || "undefined" == typeof window) return;
|
|
458
|
+
const handler = (event)=>{
|
|
459
|
+
if (event.key !== storageKey) return;
|
|
460
|
+
const result = readSafe(event.newValue, parserRef.current, defaultValueRef.current, versionRef.current, migrateRef.current);
|
|
461
|
+
setValueState((prev)=>Object.is(prev, result.value) ? prev : result.value);
|
|
462
|
+
tabNotify(storageKey, result.value);
|
|
463
|
+
if (result.migrated) writeStorage(storage, storageKey, result.value, versionRef.current);
|
|
464
|
+
};
|
|
465
|
+
window.addEventListener("storage", handler);
|
|
466
|
+
return ()=>window.removeEventListener("storage", handler);
|
|
467
|
+
}, [
|
|
468
|
+
kind,
|
|
469
|
+
shared,
|
|
470
|
+
storage,
|
|
471
|
+
storageKey
|
|
472
|
+
]);
|
|
473
|
+
const setValue = (0, __WEBPACK_EXTERNAL_MODULE_react__.useCallback)((next)=>{
|
|
474
|
+
const resolved = "function" == typeof next ? next(valueRef.current) : next;
|
|
475
|
+
if (Object.is(valueRef.current, resolved)) return;
|
|
476
|
+
valueRef.current = resolved;
|
|
477
|
+
setValueState(resolved);
|
|
478
|
+
const raw = writeStorage(storage, storageKey, resolved, versionRef.current);
|
|
479
|
+
tabNotify(storageKey, resolved);
|
|
480
|
+
if (shared) getChannel()?.postMessage({
|
|
481
|
+
key: storageKey,
|
|
482
|
+
payload: raw,
|
|
483
|
+
storage: kind,
|
|
484
|
+
sourceId: instanceId
|
|
485
|
+
});
|
|
486
|
+
}, [
|
|
487
|
+
kind,
|
|
488
|
+
shared,
|
|
489
|
+
storage,
|
|
490
|
+
storageKey
|
|
491
|
+
]);
|
|
68
492
|
return [
|
|
69
493
|
value,
|
|
70
494
|
setValue
|
|
71
495
|
];
|
|
72
496
|
}
|
|
497
|
+
function usePersistentState(key, parser, options) {
|
|
498
|
+
return useStoredState("persistent", key, parser, options, false);
|
|
499
|
+
}
|
|
500
|
+
function usePersistentSharedState(key, parser, options) {
|
|
501
|
+
return useStoredState("persistent", key, parser, options, true);
|
|
502
|
+
}
|
|
503
|
+
function useSessionState(key, parser, options) {
|
|
504
|
+
return useStoredState("session", key, parser, options, false);
|
|
505
|
+
}
|
|
506
|
+
function useSessionSharedState(key, parser, options) {
|
|
507
|
+
return useStoredState("session", key, parser, options, true);
|
|
508
|
+
}
|
|
509
|
+
function useLongPress({ delayMs = 500, moveThresholdPx = 8, disabled = false, onLongPress }) {
|
|
510
|
+
const timerRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(null);
|
|
511
|
+
const pointerIdRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(null);
|
|
512
|
+
const startRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(null);
|
|
513
|
+
const triggeredRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(false);
|
|
514
|
+
const clearTimer = ()=>{
|
|
515
|
+
if (null == timerRef.current) return;
|
|
516
|
+
window.clearTimeout(timerRef.current);
|
|
517
|
+
timerRef.current = null;
|
|
518
|
+
};
|
|
519
|
+
const reset = ()=>{
|
|
520
|
+
clearTimer();
|
|
521
|
+
pointerIdRef.current = null;
|
|
522
|
+
startRef.current = null;
|
|
523
|
+
};
|
|
524
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
525
|
+
if (disabled) {
|
|
526
|
+
triggeredRef.current = false;
|
|
527
|
+
reset();
|
|
528
|
+
}
|
|
529
|
+
}, [
|
|
530
|
+
disabled
|
|
531
|
+
]);
|
|
532
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>()=>clearTimer(), []);
|
|
533
|
+
return {
|
|
534
|
+
onPointerDown (event) {
|
|
535
|
+
if (disabled || 0 !== event.button) return;
|
|
536
|
+
const target = event.target instanceof HTMLElement ? event.target : null;
|
|
537
|
+
if (target?.closest("button,a,input,select,textarea")) return;
|
|
538
|
+
triggeredRef.current = false;
|
|
539
|
+
pointerIdRef.current = event.pointerId;
|
|
540
|
+
startRef.current = {
|
|
541
|
+
x: event.clientX,
|
|
542
|
+
y: event.clientY
|
|
543
|
+
};
|
|
544
|
+
clearTimer();
|
|
545
|
+
timerRef.current = window.setTimeout(()=>{
|
|
546
|
+
triggeredRef.current = true;
|
|
547
|
+
onLongPress();
|
|
548
|
+
}, delayMs);
|
|
549
|
+
},
|
|
550
|
+
onPointerMove (event) {
|
|
551
|
+
if (pointerIdRef.current !== event.pointerId || !startRef.current) return;
|
|
552
|
+
const dx = event.clientX - startRef.current.x;
|
|
553
|
+
const dy = event.clientY - startRef.current.y;
|
|
554
|
+
if (Math.hypot(dx, dy) > moveThresholdPx) reset();
|
|
555
|
+
},
|
|
556
|
+
onPointerUp (event) {
|
|
557
|
+
if (pointerIdRef.current !== event.pointerId) return;
|
|
558
|
+
clearTimer();
|
|
559
|
+
},
|
|
560
|
+
onPointerCancel (event) {
|
|
561
|
+
if (pointerIdRef.current !== event.pointerId) return;
|
|
562
|
+
reset();
|
|
563
|
+
},
|
|
564
|
+
onClickCapture (event) {
|
|
565
|
+
if (!triggeredRef.current) return;
|
|
566
|
+
event.preventDefault();
|
|
567
|
+
event.stopPropagation();
|
|
568
|
+
triggeredRef.current = false;
|
|
569
|
+
reset();
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
}
|
|
73
573
|
function useMediaQuery(query) {
|
|
74
574
|
const getMatches = ()=>"undefined" != typeof window && window.matchMedia(query).matches;
|
|
75
575
|
const [matches, setMatches] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(getMatches);
|
|
@@ -89,4 +589,137 @@ function useMediaQuery(query) {
|
|
|
89
589
|
]);
|
|
90
590
|
return matches;
|
|
91
591
|
}
|
|
92
|
-
|
|
592
|
+
function useNavigatorOnline() {
|
|
593
|
+
const [isOnline, setIsOnline] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(()=>"undefined" == typeof navigator ? true : navigator.onLine);
|
|
594
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
595
|
+
if ("undefined" == typeof window) return;
|
|
596
|
+
const sync = ()=>setIsOnline(navigator.onLine);
|
|
597
|
+
window.addEventListener("online", sync);
|
|
598
|
+
window.addEventListener("offline", sync);
|
|
599
|
+
return ()=>{
|
|
600
|
+
window.removeEventListener("online", sync);
|
|
601
|
+
window.removeEventListener("offline", sync);
|
|
602
|
+
};
|
|
603
|
+
}, []);
|
|
604
|
+
return isOnline;
|
|
605
|
+
}
|
|
606
|
+
function useNow({ update = 1000 } = {}) {
|
|
607
|
+
const [now, setNow] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(()=>Date.now());
|
|
608
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
609
|
+
if (false === update) return;
|
|
610
|
+
const id = window.setInterval(()=>setNow(Date.now()), update);
|
|
611
|
+
return ()=>window.clearInterval(id);
|
|
612
|
+
}, [
|
|
613
|
+
update
|
|
614
|
+
]);
|
|
615
|
+
return now;
|
|
616
|
+
}
|
|
617
|
+
function detectOS() {
|
|
618
|
+
if ("undefined" == typeof navigator) return "windows";
|
|
619
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
620
|
+
const platform = (navigator.platform ?? "").toLowerCase();
|
|
621
|
+
const combined = `${ua} ${platform}`;
|
|
622
|
+
if (/iphone|ipad|ipod|android|mobile/.test(combined)) return "mobile";
|
|
623
|
+
if (/mac|macintosh|mac os x/.test(combined)) return "mac";
|
|
624
|
+
if (/win|windows/.test(combined)) return "windows";
|
|
625
|
+
if (/linux|x11/.test(combined)) return "linux";
|
|
626
|
+
return "windows";
|
|
627
|
+
}
|
|
628
|
+
function useOS(override) {
|
|
629
|
+
return (0, __WEBPACK_EXTERNAL_MODULE_react__.useMemo)(()=>override ?? detectOS(), [
|
|
630
|
+
override
|
|
631
|
+
]);
|
|
632
|
+
}
|
|
633
|
+
function usePointerCoarse() {
|
|
634
|
+
return useMediaQuery("(pointer: coarse)");
|
|
635
|
+
}
|
|
636
|
+
function usePrefersReducedMotion() {
|
|
637
|
+
return useMediaQuery("(prefers-reduced-motion: reduce)");
|
|
638
|
+
}
|
|
639
|
+
function usePrevious(value) {
|
|
640
|
+
const ref = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(void 0);
|
|
641
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
642
|
+
ref.current = value;
|
|
643
|
+
}, [
|
|
644
|
+
value
|
|
645
|
+
]);
|
|
646
|
+
return ref.current;
|
|
647
|
+
}
|
|
648
|
+
function useTimeout(callback, delay) {
|
|
649
|
+
const callbackRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(callback);
|
|
650
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
651
|
+
callbackRef.current = callback;
|
|
652
|
+
}, [
|
|
653
|
+
callback
|
|
654
|
+
]);
|
|
655
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
656
|
+
if (null === delay) return;
|
|
657
|
+
const id = window.setTimeout(()=>callbackRef.current(), delay);
|
|
658
|
+
return ()=>window.clearTimeout(id);
|
|
659
|
+
}, [
|
|
660
|
+
delay
|
|
661
|
+
]);
|
|
662
|
+
}
|
|
663
|
+
const KEYBOARD_OPEN_DELTA = 150;
|
|
664
|
+
function getViewportState() {
|
|
665
|
+
if ("undefined" == typeof window) return {
|
|
666
|
+
visualViewportHeight: 0,
|
|
667
|
+
keyboardOpen: false
|
|
668
|
+
};
|
|
669
|
+
const visual = window.visualViewport?.height ?? window.innerHeight;
|
|
670
|
+
const layout = window.innerHeight;
|
|
671
|
+
return {
|
|
672
|
+
visualViewportHeight: visual,
|
|
673
|
+
keyboardOpen: layout - visual > KEYBOARD_OPEN_DELTA
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
function useViewport() {
|
|
677
|
+
const [state, setState] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(()=>getViewportState());
|
|
678
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
679
|
+
if ("undefined" == typeof window) return;
|
|
680
|
+
const target = window.visualViewport ?? window;
|
|
681
|
+
const handleChange = ()=>{
|
|
682
|
+
setState((prev)=>{
|
|
683
|
+
const next = getViewportState();
|
|
684
|
+
return prev.visualViewportHeight === next.visualViewportHeight && prev.keyboardOpen === next.keyboardOpen ? prev : next;
|
|
685
|
+
});
|
|
686
|
+
};
|
|
687
|
+
handleChange();
|
|
688
|
+
target.addEventListener("resize", handleChange);
|
|
689
|
+
window.addEventListener("resize", handleChange);
|
|
690
|
+
return ()=>{
|
|
691
|
+
target.removeEventListener("resize", handleChange);
|
|
692
|
+
window.removeEventListener("resize", handleChange);
|
|
693
|
+
};
|
|
694
|
+
}, []);
|
|
695
|
+
return state;
|
|
696
|
+
}
|
|
697
|
+
function getWindowSize() {
|
|
698
|
+
if ("undefined" == typeof window) return {
|
|
699
|
+
width: 0,
|
|
700
|
+
height: 0
|
|
701
|
+
};
|
|
702
|
+
return {
|
|
703
|
+
width: window.innerWidth,
|
|
704
|
+
height: window.innerHeight
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
function useWindowSize() {
|
|
708
|
+
const [size, setSize] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(getWindowSize);
|
|
709
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
710
|
+
if ("undefined" == typeof window) return;
|
|
711
|
+
const handleResize = ()=>{
|
|
712
|
+
setSize((prev)=>{
|
|
713
|
+
const next = getWindowSize();
|
|
714
|
+
return prev.width === next.width && prev.height === next.height ? prev : next;
|
|
715
|
+
});
|
|
716
|
+
};
|
|
717
|
+
handleResize();
|
|
718
|
+
window.addEventListener("resize", handleResize);
|
|
719
|
+
return ()=>window.removeEventListener("resize", handleResize);
|
|
720
|
+
}, []);
|
|
721
|
+
return size;
|
|
722
|
+
}
|
|
723
|
+
var __webpack_exports__isFocusVisible = __WEBPACK_EXTERNAL_MODULE__react_aria_interactions_8422cce9__.isFocusVisible;
|
|
724
|
+
var __webpack_exports__usePress = __WEBPACK_EXTERNAL_MODULE__react_aria_interactions_8422cce9__.usePress;
|
|
725
|
+
export { StorageProvider, useBeforeUnloadWarning, useBreakpoint, useContainerSize, useControllableState, useCopyToClipboard, useDebouncedValue, useDeferredPresence, useDisclosure, useEventListener, useHover, useInterval, useKeyDown, useLongPress, useMediaQuery, useNavigatorOnline, useNow, useOS, usePersistentSharedState, usePersistentState, usePointerCoarse, usePrefersReducedMotion, usePrevious, useSessionSharedState, useSessionState, useTimeout, useViewport, useWindowSize, __webpack_exports__isFocusVisible as isFocusVisible, __webpack_exports__usePress as usePress };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-before-unload-warning.d.ts","sourceRoot":"","sources":["../src/use-before-unload-warning.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAU7D"}
|