@develemit/web-hooks 0.0.0-stage → 0.2.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.
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +249 -2
- package/dist/auto-grow.cjs +60 -0
- package/dist/auto-grow.d.cts +14 -0
- package/dist/auto-grow.d.ts +14 -0
- package/dist/auto-grow.js +9 -0
- package/dist/chunk-3CACI4OQ.js +68 -0
- package/dist/chunk-3UGRXQIA.js +39 -0
- package/dist/chunk-5CA5RIMH.js +34 -0
- package/dist/chunk-5KIH2XLV.js +136 -0
- package/dist/chunk-6KCRVSLS.js +80 -0
- package/dist/chunk-DNU57XEJ.js +82 -0
- package/dist/chunk-IWQDAJEP.js +69 -0
- package/dist/chunk-LZKAGDER.js +22 -0
- package/dist/chunk-NKLEB5TR.js +98 -0
- package/dist/chunk-OZ4PU4E3.js +115 -0
- package/dist/chunk-S4YKMGQE.js +23 -0
- package/dist/chunk-UPVNSGIK.js +72 -0
- package/dist/chunk-UZADAINO.js +61 -0
- package/dist/clipboard.cjs +94 -0
- package/dist/clipboard.d.cts +17 -0
- package/dist/clipboard.d.ts +17 -0
- package/dist/clipboard.js +9 -0
- package/dist/debounce.cjs +96 -0
- package/dist/debounce.d.cts +21 -0
- package/dist/debounce.d.ts +21 -0
- package/dist/debounce.js +11 -0
- package/dist/drawer-swipe.cjs +149 -0
- package/dist/drawer-swipe.d.cts +26 -0
- package/dist/drawer-swipe.d.ts +26 -0
- package/dist/drawer-swipe.js +25 -0
- package/dist/escape.cjs +48 -0
- package/dist/escape.d.cts +3 -0
- package/dist/escape.d.ts +3 -0
- package/dist/escape.js +7 -0
- package/dist/focus-trap.cjs +110 -0
- package/dist/focus-trap.d.cts +17 -0
- package/dist/focus-trap.d.ts +17 -0
- package/dist/focus-trap.js +13 -0
- package/dist/hotkey.cjs +127 -0
- package/dist/hotkey.d.cts +31 -0
- package/dist/hotkey.d.ts +31 -0
- package/dist/hotkey.js +15 -0
- package/dist/index.cjs +918 -0
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +115 -0
- package/dist/media-query.cjs +90 -0
- package/dist/media-query.d.cts +12 -0
- package/dist/media-query.d.ts +12 -0
- package/dist/media-query.js +15 -0
- package/dist/outside-press.cjs +66 -0
- package/dist/outside-press.d.cts +15 -0
- package/dist/outside-press.d.ts +15 -0
- package/dist/outside-press.js +11 -0
- package/dist/scroll-lock.cjs +107 -0
- package/dist/scroll-lock.d.cts +8 -0
- package/dist/scroll-lock.d.ts +8 -0
- package/dist/scroll-lock.js +11 -0
- package/dist/storage-state.cjs +161 -0
- package/dist/storage-state.d.cts +14 -0
- package/dist/storage-state.d.ts +14 -0
- package/dist/storage-state.js +7 -0
- package/dist/unsaved-guard.cjs +48 -0
- package/dist/unsaved-guard.d.cts +5 -0
- package/dist/unsaved-guard.d.ts +5 -0
- package/dist/unsaved-guard.js +9 -0
- package/dist/visibility-polling.cjs +98 -0
- package/dist/visibility-polling.d.cts +14 -0
- package/dist/visibility-polling.d.ts +14 -0
- package/dist/visibility-polling.js +9 -0
- package/package.json +126 -3
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/media-query/use-media-query.ts
|
|
4
|
+
import { useCallback, useSyncExternalStore } from "react";
|
|
5
|
+
|
|
6
|
+
// src/media-query/media-query.ts
|
|
7
|
+
var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
8
|
+
var COARSE_POINTER_QUERY = "(pointer: coarse)";
|
|
9
|
+
var lists = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
function getList(query) {
|
|
11
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return null;
|
|
12
|
+
const owner = window.matchMedia;
|
|
13
|
+
let byQuery = lists.get(owner);
|
|
14
|
+
if (!byQuery) {
|
|
15
|
+
byQuery = /* @__PURE__ */ new Map();
|
|
16
|
+
lists.set(owner, byQuery);
|
|
17
|
+
}
|
|
18
|
+
let list = byQuery.get(query);
|
|
19
|
+
if (!list) {
|
|
20
|
+
list = owner.call(window, query);
|
|
21
|
+
byQuery.set(query, list);
|
|
22
|
+
}
|
|
23
|
+
return list;
|
|
24
|
+
}
|
|
25
|
+
function getMatches(query) {
|
|
26
|
+
return getList(query)?.matches ?? null;
|
|
27
|
+
}
|
|
28
|
+
function subscribe(query, onChange) {
|
|
29
|
+
const list = getList(query);
|
|
30
|
+
if (!list) return () => {
|
|
31
|
+
};
|
|
32
|
+
if (typeof list.addEventListener === "function") {
|
|
33
|
+
list.addEventListener("change", onChange);
|
|
34
|
+
return () => list.removeEventListener("change", onChange);
|
|
35
|
+
}
|
|
36
|
+
list.addListener(onChange);
|
|
37
|
+
return () => list.removeListener(onChange);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/media-query/use-media-query.ts
|
|
41
|
+
function useMediaQuery(query, options = {}) {
|
|
42
|
+
const serverDefault = options.serverDefault ?? false;
|
|
43
|
+
const subscribeToQuery = useCallback((onChange) => subscribe(query, onChange), [query]);
|
|
44
|
+
const getSnapshot = useCallback(() => getMatches(query) ?? serverDefault, [query, serverDefault]);
|
|
45
|
+
const getServerSnapshot = useCallback(() => serverDefault, [serverDefault]);
|
|
46
|
+
return useSyncExternalStore(subscribeToQuery, getSnapshot, getServerSnapshot);
|
|
47
|
+
}
|
|
48
|
+
function useReducedMotion(options) {
|
|
49
|
+
return useMediaQuery(REDUCED_MOTION_QUERY, options);
|
|
50
|
+
}
|
|
51
|
+
function useCoarsePointer(options) {
|
|
52
|
+
return useMediaQuery(COARSE_POINTER_QUERY, options);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export {
|
|
56
|
+
REDUCED_MOTION_QUERY,
|
|
57
|
+
COARSE_POINTER_QUERY,
|
|
58
|
+
useMediaQuery,
|
|
59
|
+
useReducedMotion,
|
|
60
|
+
useCoarsePointer
|
|
61
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/clipboard/index.ts
|
|
22
|
+
var clipboard_exports = {};
|
|
23
|
+
__export(clipboard_exports, {
|
|
24
|
+
copyText: () => copyText,
|
|
25
|
+
useCopyFeedback: () => useCopyFeedback
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(clipboard_exports);
|
|
28
|
+
|
|
29
|
+
// src/clipboard/copy-text.ts
|
|
30
|
+
async function copyText(text) {
|
|
31
|
+
const hasClipboardApi = typeof navigator !== "undefined" && !!navigator.clipboard?.writeText && typeof window !== "undefined" && window.isSecureContext;
|
|
32
|
+
if (hasClipboardApi) {
|
|
33
|
+
try {
|
|
34
|
+
await navigator.clipboard.writeText(text);
|
|
35
|
+
return { ok: true };
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (execCommandCopy(text)) return { ok: true };
|
|
40
|
+
return { ok: false, reason: hasClipboardApi ? "denied" : "unavailable" };
|
|
41
|
+
}
|
|
42
|
+
function execCommandCopy(text) {
|
|
43
|
+
if (typeof document === "undefined") return false;
|
|
44
|
+
const textarea = document.createElement("textarea");
|
|
45
|
+
textarea.value = text;
|
|
46
|
+
textarea.readOnly = true;
|
|
47
|
+
textarea.style.position = "fixed";
|
|
48
|
+
textarea.style.top = "-1000px";
|
|
49
|
+
textarea.style.left = "-1000px";
|
|
50
|
+
textarea.style.fontSize = "16px";
|
|
51
|
+
const previouslyFocused = document.activeElement;
|
|
52
|
+
document.body.appendChild(textarea);
|
|
53
|
+
try {
|
|
54
|
+
textarea.focus({ preventScroll: true });
|
|
55
|
+
textarea.select();
|
|
56
|
+
textarea.setSelectionRange(0, text.length);
|
|
57
|
+
return document.execCommand("copy");
|
|
58
|
+
} catch {
|
|
59
|
+
return false;
|
|
60
|
+
} finally {
|
|
61
|
+
document.body.removeChild(textarea);
|
|
62
|
+
if (previouslyFocused instanceof HTMLElement && previouslyFocused !== document.body) {
|
|
63
|
+
previouslyFocused.focus({ preventScroll: true });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/clipboard/use-copy-feedback.ts
|
|
69
|
+
var import_react = require("react");
|
|
70
|
+
function useCopyFeedback({ resetMs = 1500 } = {}) {
|
|
71
|
+
const [status, setStatus] = (0, import_react.useState)("idle");
|
|
72
|
+
const timerRef = (0, import_react.useRef)(void 0);
|
|
73
|
+
const clearTimer = (0, import_react.useCallback)(() => {
|
|
74
|
+
if (timerRef.current !== void 0) clearTimeout(timerRef.current);
|
|
75
|
+
timerRef.current = void 0;
|
|
76
|
+
}, []);
|
|
77
|
+
(0, import_react.useEffect)(() => clearTimer, [clearTimer]);
|
|
78
|
+
const copy = (0, import_react.useCallback)(
|
|
79
|
+
async (text) => {
|
|
80
|
+
const result = await copyText(text);
|
|
81
|
+
clearTimer();
|
|
82
|
+
setStatus(result.ok ? "copied" : "failed");
|
|
83
|
+
timerRef.current = setTimeout(() => setStatus("idle"), resetMs);
|
|
84
|
+
return result;
|
|
85
|
+
},
|
|
86
|
+
[clearTimer, resetMs]
|
|
87
|
+
);
|
|
88
|
+
return { copy, status };
|
|
89
|
+
}
|
|
90
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
91
|
+
0 && (module.exports = {
|
|
92
|
+
copyText,
|
|
93
|
+
useCopyFeedback
|
|
94
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type CopyResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
} | {
|
|
4
|
+
ok: false;
|
|
5
|
+
reason: 'unavailable' | 'denied';
|
|
6
|
+
};
|
|
7
|
+
declare function copyText(text: string): Promise<CopyResult>;
|
|
8
|
+
|
|
9
|
+
type CopyStatus = 'idle' | 'copied' | 'failed';
|
|
10
|
+
declare function useCopyFeedback({ resetMs }?: {
|
|
11
|
+
resetMs?: number;
|
|
12
|
+
}): {
|
|
13
|
+
copy: (text: string) => Promise<CopyResult>;
|
|
14
|
+
status: CopyStatus;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { type CopyResult, type CopyStatus, copyText, useCopyFeedback };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type CopyResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
} | {
|
|
4
|
+
ok: false;
|
|
5
|
+
reason: 'unavailable' | 'denied';
|
|
6
|
+
};
|
|
7
|
+
declare function copyText(text: string): Promise<CopyResult>;
|
|
8
|
+
|
|
9
|
+
type CopyStatus = 'idle' | 'copied' | 'failed';
|
|
10
|
+
declare function useCopyFeedback({ resetMs }?: {
|
|
11
|
+
resetMs?: number;
|
|
12
|
+
}): {
|
|
13
|
+
copy: (text: string) => Promise<CopyResult>;
|
|
14
|
+
status: CopyStatus;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { type CopyResult, type CopyStatus, copyText, useCopyFeedback };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/debounce/index.ts
|
|
22
|
+
var debounce_exports = {};
|
|
23
|
+
__export(debounce_exports, {
|
|
24
|
+
createDebouncer: () => createDebouncer,
|
|
25
|
+
useDebouncedCallback: () => useDebouncedCallback,
|
|
26
|
+
useDebouncedValue: () => useDebouncedValue
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(debounce_exports);
|
|
29
|
+
|
|
30
|
+
// src/debounce/debouncer.ts
|
|
31
|
+
function createDebouncer(getFn, getMs) {
|
|
32
|
+
let timer;
|
|
33
|
+
let pending;
|
|
34
|
+
function clear() {
|
|
35
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
36
|
+
timer = void 0;
|
|
37
|
+
pending = void 0;
|
|
38
|
+
}
|
|
39
|
+
function run() {
|
|
40
|
+
const args = pending;
|
|
41
|
+
clear();
|
|
42
|
+
if (args) getFn()(...args);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
call(...args) {
|
|
46
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
47
|
+
pending = args;
|
|
48
|
+
timer = setTimeout(run, getMs());
|
|
49
|
+
},
|
|
50
|
+
cancel: clear,
|
|
51
|
+
flush() {
|
|
52
|
+
if (pending) run();
|
|
53
|
+
},
|
|
54
|
+
isPending: () => pending !== void 0
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/debounce/use-debounced-value.ts
|
|
59
|
+
var import_react = require("react");
|
|
60
|
+
function useDebouncedValue(value, ms) {
|
|
61
|
+
const [debounced, setDebounced] = (0, import_react.useState)(value);
|
|
62
|
+
(0, import_react.useEffect)(() => {
|
|
63
|
+
const timer = setTimeout(() => setDebounced(value), ms);
|
|
64
|
+
return () => clearTimeout(timer);
|
|
65
|
+
}, [value, ms]);
|
|
66
|
+
return debounced;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/debounce/use-debounced-callback.ts
|
|
70
|
+
var import_react2 = require("react");
|
|
71
|
+
function useDebouncedCallback(fn, ms) {
|
|
72
|
+
const fnRef = (0, import_react2.useRef)(fn);
|
|
73
|
+
const msRef = (0, import_react2.useRef)(ms);
|
|
74
|
+
(0, import_react2.useEffect)(() => {
|
|
75
|
+
fnRef.current = fn;
|
|
76
|
+
msRef.current = ms;
|
|
77
|
+
});
|
|
78
|
+
const [debounced] = (0, import_react2.useState)(() => {
|
|
79
|
+
const debouncer = createDebouncer(
|
|
80
|
+
() => fnRef.current,
|
|
81
|
+
() => msRef.current
|
|
82
|
+
);
|
|
83
|
+
return Object.assign((...args) => debouncer.call(...args), {
|
|
84
|
+
cancel: debouncer.cancel,
|
|
85
|
+
flush: debouncer.flush
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
(0, import_react2.useEffect)(() => () => debounced.cancel(), [debounced]);
|
|
89
|
+
return debounced;
|
|
90
|
+
}
|
|
91
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
92
|
+
0 && (module.exports = {
|
|
93
|
+
createDebouncer,
|
|
94
|
+
useDebouncedCallback,
|
|
95
|
+
useDebouncedValue
|
|
96
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface Debouncer<Args extends unknown[]> {
|
|
2
|
+
call(...args: Args): void;
|
|
3
|
+
cancel(): void;
|
|
4
|
+
/** Runs the pending call right now; does nothing when none is pending. */
|
|
5
|
+
flush(): void;
|
|
6
|
+
isPending(): boolean;
|
|
7
|
+
}
|
|
8
|
+
/** `getFn` and `getMs` are read at call time, so the latest values always win. */
|
|
9
|
+
declare function createDebouncer<Args extends unknown[]>(getFn: () => (...args: Args) => void, getMs: () => number): Debouncer<Args>;
|
|
10
|
+
|
|
11
|
+
declare function useDebouncedValue<T>(value: T, ms: number): T;
|
|
12
|
+
|
|
13
|
+
interface DebouncedCallback<Args extends unknown[]> {
|
|
14
|
+
(...args: Args): void;
|
|
15
|
+
cancel(): void;
|
|
16
|
+
flush(): void;
|
|
17
|
+
}
|
|
18
|
+
/** The returned function keeps one identity for the life of the component. */
|
|
19
|
+
declare function useDebouncedCallback<Args extends unknown[]>(fn: (...args: Args) => void, ms: number): DebouncedCallback<Args>;
|
|
20
|
+
|
|
21
|
+
export { type DebouncedCallback, type Debouncer, createDebouncer, useDebouncedCallback, useDebouncedValue };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface Debouncer<Args extends unknown[]> {
|
|
2
|
+
call(...args: Args): void;
|
|
3
|
+
cancel(): void;
|
|
4
|
+
/** Runs the pending call right now; does nothing when none is pending. */
|
|
5
|
+
flush(): void;
|
|
6
|
+
isPending(): boolean;
|
|
7
|
+
}
|
|
8
|
+
/** `getFn` and `getMs` are read at call time, so the latest values always win. */
|
|
9
|
+
declare function createDebouncer<Args extends unknown[]>(getFn: () => (...args: Args) => void, getMs: () => number): Debouncer<Args>;
|
|
10
|
+
|
|
11
|
+
declare function useDebouncedValue<T>(value: T, ms: number): T;
|
|
12
|
+
|
|
13
|
+
interface DebouncedCallback<Args extends unknown[]> {
|
|
14
|
+
(...args: Args): void;
|
|
15
|
+
cancel(): void;
|
|
16
|
+
flush(): void;
|
|
17
|
+
}
|
|
18
|
+
/** The returned function keeps one identity for the life of the component. */
|
|
19
|
+
declare function useDebouncedCallback<Args extends unknown[]>(fn: (...args: Args) => void, ms: number): DebouncedCallback<Args>;
|
|
20
|
+
|
|
21
|
+
export { type DebouncedCallback, type Debouncer, createDebouncer, useDebouncedCallback, useDebouncedValue };
|
package/dist/debounce.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/drawer-swipe/index.ts
|
|
22
|
+
var drawer_swipe_exports = {};
|
|
23
|
+
__export(drawer_swipe_exports, {
|
|
24
|
+
BACK_ZONE_PX: () => BACK_ZONE_PX,
|
|
25
|
+
CLOSE_DISTANCE_PX: () => CLOSE_DISTANCE_PX,
|
|
26
|
+
FORWARD_ZONE_PX: () => FORWARD_ZONE_PX,
|
|
27
|
+
MAX_SWIPE_DURATION_MS: () => MAX_SWIPE_DURATION_MS,
|
|
28
|
+
OPEN_DISTANCE_PX: () => OPEN_DISTANCE_PX,
|
|
29
|
+
VERTICAL_CANCEL_PX: () => VERTICAL_CANCEL_PX,
|
|
30
|
+
isInOpenZone: () => isInOpenZone,
|
|
31
|
+
isInsideHorizontalScroller: () => isInsideHorizontalScroller,
|
|
32
|
+
resolveSwipeIntent: () => resolveSwipeIntent,
|
|
33
|
+
useDrawerSwipe: () => useDrawerSwipe
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(drawer_swipe_exports);
|
|
36
|
+
|
|
37
|
+
// src/drawer-swipe/swipe-intent.ts
|
|
38
|
+
var BACK_ZONE_PX = 60;
|
|
39
|
+
var FORWARD_ZONE_PX = 30;
|
|
40
|
+
var OPEN_DISTANCE_PX = 80;
|
|
41
|
+
var CLOSE_DISTANCE_PX = 60;
|
|
42
|
+
var VERTICAL_CANCEL_PX = 40;
|
|
43
|
+
var MAX_SWIPE_DURATION_MS = 450;
|
|
44
|
+
var HORIZONTAL_DOMINANCE = 1.5;
|
|
45
|
+
function isInOpenZone(x, viewportWidth) {
|
|
46
|
+
return x > BACK_ZONE_PX && x < viewportWidth - FORWARD_ZONE_PX;
|
|
47
|
+
}
|
|
48
|
+
function resolveSwipeIntent(start, end, drawerOpen, viewportWidth) {
|
|
49
|
+
const dx = end.x - start.x;
|
|
50
|
+
const dy = end.y - start.y;
|
|
51
|
+
if (end.time - start.time > MAX_SWIPE_DURATION_MS) return null;
|
|
52
|
+
if (Math.abs(dx) < Math.abs(dy) * HORIZONTAL_DOMINANCE) return null;
|
|
53
|
+
if (drawerOpen) {
|
|
54
|
+
return dx <= -CLOSE_DISTANCE_PX ? "close" : null;
|
|
55
|
+
}
|
|
56
|
+
if (dx < OPEN_DISTANCE_PX) return null;
|
|
57
|
+
return isInOpenZone(start.x, viewportWidth) ? "open" : null;
|
|
58
|
+
}
|
|
59
|
+
function isInsideHorizontalScroller(target) {
|
|
60
|
+
let node = target instanceof Element ? target : null;
|
|
61
|
+
while (node && node !== document.body) {
|
|
62
|
+
const { overflowX } = window.getComputedStyle(node);
|
|
63
|
+
if ((overflowX === "auto" || overflowX === "scroll") && node.scrollWidth > node.clientWidth) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
node = node.parentElement;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/drawer-swipe/use-drawer-swipe.ts
|
|
72
|
+
var import_react = require("react");
|
|
73
|
+
function isWideViewport(maxViewportWidth) {
|
|
74
|
+
return window.matchMedia(`(min-width: ${maxViewportWidth}px)`).matches;
|
|
75
|
+
}
|
|
76
|
+
function useDrawerSwipe({
|
|
77
|
+
drawerOpen,
|
|
78
|
+
onOpen,
|
|
79
|
+
onClose,
|
|
80
|
+
enabled = true,
|
|
81
|
+
maxViewportWidth = 768
|
|
82
|
+
}) {
|
|
83
|
+
const start = (0, import_react.useRef)(null);
|
|
84
|
+
const handlers = (0, import_react.useRef)({ drawerOpen, onOpen, onClose, maxViewportWidth });
|
|
85
|
+
handlers.current = { drawerOpen, onOpen, onClose, maxViewportWidth };
|
|
86
|
+
(0, import_react.useEffect)(() => {
|
|
87
|
+
if (!enabled) return;
|
|
88
|
+
function handleStart(event) {
|
|
89
|
+
start.current = null;
|
|
90
|
+
if (event.touches.length !== 1) return;
|
|
91
|
+
if (isWideViewport(handlers.current.maxViewportWidth)) return;
|
|
92
|
+
if (!handlers.current.drawerOpen && isInsideHorizontalScroller(event.target)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const touch = event.touches[0];
|
|
96
|
+
if (!touch) return;
|
|
97
|
+
start.current = { x: touch.clientX, y: touch.clientY, time: Date.now() };
|
|
98
|
+
}
|
|
99
|
+
function handleMove(event) {
|
|
100
|
+
const origin = start.current;
|
|
101
|
+
const touch = event.touches[0];
|
|
102
|
+
if (!origin || !touch) return;
|
|
103
|
+
if (Math.abs(touch.clientY - origin.y) > VERTICAL_CANCEL_PX) {
|
|
104
|
+
start.current = null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function handleEnd(event) {
|
|
108
|
+
const origin = start.current;
|
|
109
|
+
start.current = null;
|
|
110
|
+
const touch = event.changedTouches[0];
|
|
111
|
+
if (!origin || !touch) return;
|
|
112
|
+
const { drawerOpen: drawerOpen2, onOpen: onOpen2, onClose: onClose2 } = handlers.current;
|
|
113
|
+
const intent = resolveSwipeIntent(
|
|
114
|
+
origin,
|
|
115
|
+
{ x: touch.clientX, y: touch.clientY, time: Date.now() },
|
|
116
|
+
drawerOpen2,
|
|
117
|
+
window.innerWidth
|
|
118
|
+
);
|
|
119
|
+
if (intent === "open") onOpen2();
|
|
120
|
+
if (intent === "close") onClose2();
|
|
121
|
+
}
|
|
122
|
+
function handleCancel() {
|
|
123
|
+
start.current = null;
|
|
124
|
+
}
|
|
125
|
+
document.addEventListener("touchstart", handleStart, { passive: true });
|
|
126
|
+
document.addEventListener("touchmove", handleMove, { passive: true });
|
|
127
|
+
document.addEventListener("touchend", handleEnd, { passive: true });
|
|
128
|
+
document.addEventListener("touchcancel", handleCancel, { passive: true });
|
|
129
|
+
return () => {
|
|
130
|
+
document.removeEventListener("touchstart", handleStart);
|
|
131
|
+
document.removeEventListener("touchmove", handleMove);
|
|
132
|
+
document.removeEventListener("touchend", handleEnd);
|
|
133
|
+
document.removeEventListener("touchcancel", handleCancel);
|
|
134
|
+
};
|
|
135
|
+
}, [enabled]);
|
|
136
|
+
}
|
|
137
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
138
|
+
0 && (module.exports = {
|
|
139
|
+
BACK_ZONE_PX,
|
|
140
|
+
CLOSE_DISTANCE_PX,
|
|
141
|
+
FORWARD_ZONE_PX,
|
|
142
|
+
MAX_SWIPE_DURATION_MS,
|
|
143
|
+
OPEN_DISTANCE_PX,
|
|
144
|
+
VERTICAL_CANCEL_PX,
|
|
145
|
+
isInOpenZone,
|
|
146
|
+
isInsideHorizontalScroller,
|
|
147
|
+
resolveSwipeIntent,
|
|
148
|
+
useDrawerSwipe
|
|
149
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type SwipePoint = {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
time: number;
|
|
5
|
+
};
|
|
6
|
+
declare const BACK_ZONE_PX = 60;
|
|
7
|
+
declare const FORWARD_ZONE_PX = 30;
|
|
8
|
+
declare const OPEN_DISTANCE_PX = 80;
|
|
9
|
+
declare const CLOSE_DISTANCE_PX = 60;
|
|
10
|
+
declare const VERTICAL_CANCEL_PX = 40;
|
|
11
|
+
declare const MAX_SWIPE_DURATION_MS = 450;
|
|
12
|
+
type SwipeIntent = 'open' | 'close' | null;
|
|
13
|
+
declare function isInOpenZone(x: number, viewportWidth: number): boolean;
|
|
14
|
+
declare function resolveSwipeIntent(start: SwipePoint, end: SwipePoint, drawerOpen: boolean, viewportWidth: number): SwipeIntent;
|
|
15
|
+
declare function isInsideHorizontalScroller(target: EventTarget | null): boolean;
|
|
16
|
+
|
|
17
|
+
type UseDrawerSwipeOptions = {
|
|
18
|
+
drawerOpen: boolean;
|
|
19
|
+
onOpen: () => void;
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
maxViewportWidth?: number;
|
|
23
|
+
};
|
|
24
|
+
declare function useDrawerSwipe({ drawerOpen, onOpen, onClose, enabled, maxViewportWidth, }: UseDrawerSwipeOptions): void;
|
|
25
|
+
|
|
26
|
+
export { BACK_ZONE_PX, CLOSE_DISTANCE_PX, FORWARD_ZONE_PX, MAX_SWIPE_DURATION_MS, OPEN_DISTANCE_PX, type SwipeIntent, type SwipePoint, type UseDrawerSwipeOptions, VERTICAL_CANCEL_PX, isInOpenZone, isInsideHorizontalScroller, resolveSwipeIntent, useDrawerSwipe };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type SwipePoint = {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
time: number;
|
|
5
|
+
};
|
|
6
|
+
declare const BACK_ZONE_PX = 60;
|
|
7
|
+
declare const FORWARD_ZONE_PX = 30;
|
|
8
|
+
declare const OPEN_DISTANCE_PX = 80;
|
|
9
|
+
declare const CLOSE_DISTANCE_PX = 60;
|
|
10
|
+
declare const VERTICAL_CANCEL_PX = 40;
|
|
11
|
+
declare const MAX_SWIPE_DURATION_MS = 450;
|
|
12
|
+
type SwipeIntent = 'open' | 'close' | null;
|
|
13
|
+
declare function isInOpenZone(x: number, viewportWidth: number): boolean;
|
|
14
|
+
declare function resolveSwipeIntent(start: SwipePoint, end: SwipePoint, drawerOpen: boolean, viewportWidth: number): SwipeIntent;
|
|
15
|
+
declare function isInsideHorizontalScroller(target: EventTarget | null): boolean;
|
|
16
|
+
|
|
17
|
+
type UseDrawerSwipeOptions = {
|
|
18
|
+
drawerOpen: boolean;
|
|
19
|
+
onOpen: () => void;
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
maxViewportWidth?: number;
|
|
23
|
+
};
|
|
24
|
+
declare function useDrawerSwipe({ drawerOpen, onOpen, onClose, enabled, maxViewportWidth, }: UseDrawerSwipeOptions): void;
|
|
25
|
+
|
|
26
|
+
export { BACK_ZONE_PX, CLOSE_DISTANCE_PX, FORWARD_ZONE_PX, MAX_SWIPE_DURATION_MS, OPEN_DISTANCE_PX, type SwipeIntent, type SwipePoint, type UseDrawerSwipeOptions, VERTICAL_CANCEL_PX, isInOpenZone, isInsideHorizontalScroller, resolveSwipeIntent, useDrawerSwipe };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
BACK_ZONE_PX,
|
|
4
|
+
CLOSE_DISTANCE_PX,
|
|
5
|
+
FORWARD_ZONE_PX,
|
|
6
|
+
MAX_SWIPE_DURATION_MS,
|
|
7
|
+
OPEN_DISTANCE_PX,
|
|
8
|
+
VERTICAL_CANCEL_PX,
|
|
9
|
+
isInOpenZone,
|
|
10
|
+
isInsideHorizontalScroller,
|
|
11
|
+
resolveSwipeIntent,
|
|
12
|
+
useDrawerSwipe
|
|
13
|
+
} from "./chunk-OZ4PU4E3.js";
|
|
14
|
+
export {
|
|
15
|
+
BACK_ZONE_PX,
|
|
16
|
+
CLOSE_DISTANCE_PX,
|
|
17
|
+
FORWARD_ZONE_PX,
|
|
18
|
+
MAX_SWIPE_DURATION_MS,
|
|
19
|
+
OPEN_DISTANCE_PX,
|
|
20
|
+
VERTICAL_CANCEL_PX,
|
|
21
|
+
isInOpenZone,
|
|
22
|
+
isInsideHorizontalScroller,
|
|
23
|
+
resolveSwipeIntent,
|
|
24
|
+
useDrawerSwipe
|
|
25
|
+
};
|
package/dist/escape.cjs
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/escape/index.ts
|
|
22
|
+
var escape_exports = {};
|
|
23
|
+
__export(escape_exports, {
|
|
24
|
+
useEscape: () => useEscape
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(escape_exports);
|
|
27
|
+
|
|
28
|
+
// src/escape/use-escape.ts
|
|
29
|
+
var import_react = require("react");
|
|
30
|
+
function useEscape(onEscape, active = true) {
|
|
31
|
+
const handlerRef = (0, import_react.useRef)(onEscape);
|
|
32
|
+
(0, import_react.useEffect)(() => {
|
|
33
|
+
handlerRef.current = onEscape;
|
|
34
|
+
});
|
|
35
|
+
(0, import_react.useEffect)(() => {
|
|
36
|
+
if (!active) return;
|
|
37
|
+
function onKeyDown(event) {
|
|
38
|
+
if (event.isComposing || event.keyCode === 229) return;
|
|
39
|
+
if (event.key === "Escape") handlerRef.current();
|
|
40
|
+
}
|
|
41
|
+
document.addEventListener("keydown", onKeyDown);
|
|
42
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
43
|
+
}, [active]);
|
|
44
|
+
}
|
|
45
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
46
|
+
0 && (module.exports = {
|
|
47
|
+
useEscape
|
|
48
|
+
});
|
package/dist/escape.d.ts
ADDED