@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.
- package/CHANGELOG.md +28 -0
- package/README.md +311 -0
- 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-4PVVTQ5V.js +74 -0
- package/dist/chunk-5CA5RIMH.js +34 -0
- package/dist/chunk-5KIH2XLV.js +136 -0
- package/dist/chunk-5XRVPZHD.js +125 -0
- package/dist/chunk-6KCRVSLS.js +80 -0
- package/dist/chunk-DNU57XEJ.js +82 -0
- package/dist/chunk-DQBKU7HI.js +46 -0
- package/dist/chunk-EXEJI4FK.js +43 -0
- package/dist/chunk-FE3BQD2I.js +44 -0
- package/dist/chunk-HTVNN2NM.js +29 -0
- package/dist/chunk-IWQDAJEP.js +69 -0
- package/dist/chunk-JG3GPTMY.js +101 -0
- package/dist/chunk-LZKAGDER.js +22 -0
- package/dist/chunk-NKLEB5TR.js +98 -0
- package/dist/chunk-S4YKMGQE.js +23 -0
- package/dist/chunk-TNEJ34T5.js +86 -0
- package/dist/chunk-UJ366T3Y.js +146 -0
- package/dist/chunk-UPVNSGIK.js +72 -0
- package/dist/chunk-WVM2LTWQ.js +42 -0
- package/dist/chunk-WXL22EWK.js +21 -0
- package/dist/chunk-YFMMSLMB.js +41 -0
- package/dist/chunk-Z3X27PCA.js +108 -0
- package/dist/clipboard.cjs +18 -0
- package/dist/clipboard.d.cts +10 -1
- package/dist/clipboard.d.ts +10 -1
- package/dist/clipboard.js +8 -57
- 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 +16 -4
- package/dist/drawer-swipe.d.cts +7 -3
- package/dist/drawer-swipe.d.ts +7 -3
- package/dist/drawer-swipe.js +16 -101
- package/dist/escape.cjs +1 -0
- package/dist/escape.js +3 -17
- package/dist/focus-trap.cjs +3 -1
- package/dist/focus-trap.js +6 -72
- 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 +1207 -7
- package/dist/index.d.cts +20 -60
- package/dist/index.d.ts +20 -60
- package/dist/index.js +167 -247
- package/dist/keyboard-inset.cjs +113 -0
- package/dist/keyboard-inset.d.cts +25 -0
- package/dist/keyboard-inset.d.ts +25 -0
- package/dist/keyboard-inset.js +11 -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 +17 -0
- package/dist/online-status.cjs +46 -0
- package/dist/online-status.d.cts +3 -0
- package/dist/online-status.d.ts +3 -0
- package/dist/online-status.js +7 -0
- package/dist/outside-press.cjs +73 -0
- package/dist/outside-press.d.cts +17 -0
- package/dist/outside-press.d.ts +17 -0
- package/dist/outside-press.js +11 -0
- package/dist/push.cjs +201 -0
- package/dist/push.d.cts +37 -0
- package/dist/push.d.ts +37 -0
- package/dist/push.js +14 -0
- package/dist/pwa.cjs +198 -0
- package/dist/pwa.d.cts +35 -0
- package/dist/pwa.d.ts +35 -0
- package/dist/pwa.js +22 -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/service-worker.cjs +128 -0
- package/dist/service-worker.d.cts +23 -0
- package/dist/service-worker.d.ts +23 -0
- package/dist/service-worker.js +11 -0
- package/dist/share.cjs +139 -0
- package/dist/share.d.cts +23 -0
- package/dist/share.d.ts +23 -0
- package/dist/share.js +16 -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 +85 -2
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare function useScrollLock(active?: boolean): void;
|
|
2
|
+
|
|
3
|
+
/** Locks page scroll. Locks are counted; the returned release is safe to call twice. */
|
|
4
|
+
declare function lockScroll(): () => void;
|
|
5
|
+
/** Releases one lock taken with `lockScroll()` that was not released through its own function. */
|
|
6
|
+
declare function unlockScroll(): void;
|
|
7
|
+
|
|
8
|
+
export { lockScroll, unlockScroll, useScrollLock };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare function useScrollLock(active?: boolean): void;
|
|
2
|
+
|
|
3
|
+
/** Locks page scroll. Locks are counted; the returned release is safe to call twice. */
|
|
4
|
+
declare function lockScroll(): () => void;
|
|
5
|
+
/** Releases one lock taken with `lockScroll()` that was not released through its own function. */
|
|
6
|
+
declare function unlockScroll(): void;
|
|
7
|
+
|
|
8
|
+
export { lockScroll, unlockScroll, useScrollLock };
|
|
@@ -0,0 +1,128 @@
|
|
|
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/service-worker/index.ts
|
|
22
|
+
var service_worker_exports = {};
|
|
23
|
+
__export(service_worker_exports, {
|
|
24
|
+
deriveUpdateState: () => deriveUpdateState,
|
|
25
|
+
unregisterAll: () => unregisterAll,
|
|
26
|
+
useServiceWorker: () => useServiceWorker
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(service_worker_exports);
|
|
29
|
+
|
|
30
|
+
// src/service-worker/use-service-worker.ts
|
|
31
|
+
var import_react = require("react");
|
|
32
|
+
|
|
33
|
+
// src/service-worker/update-state.ts
|
|
34
|
+
function deriveUpdateState({ hasController: hasController2, waiting, installingState }) {
|
|
35
|
+
if (!hasController2) return false;
|
|
36
|
+
return waiting || installingState === "installed";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/service-worker/register.ts
|
|
40
|
+
var reloaded = false;
|
|
41
|
+
function isServiceWorkerSupported() {
|
|
42
|
+
return typeof navigator !== "undefined" && "serviceWorker" in navigator;
|
|
43
|
+
}
|
|
44
|
+
var hasController = () => Boolean(navigator.serviceWorker.controller);
|
|
45
|
+
async function unregisterAll() {
|
|
46
|
+
if (!isServiceWorkerSupported()) return;
|
|
47
|
+
try {
|
|
48
|
+
const registrations = await navigator.serviceWorker.getRegistrations();
|
|
49
|
+
await Promise.all(registrations.map((r) => r.unregister()));
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function registerServiceWorker({ url, scope, onUpdateAvailable }, { reload = () => window.location.reload() } = {}) {
|
|
54
|
+
let registration;
|
|
55
|
+
let disposed = false;
|
|
56
|
+
let applying = false;
|
|
57
|
+
const cleanups = [];
|
|
58
|
+
const controlledAtStart = hasController();
|
|
59
|
+
const onControllerChange = () => {
|
|
60
|
+
if (!(applying || controlledAtStart) || reloaded) return;
|
|
61
|
+
reloaded = true;
|
|
62
|
+
reload();
|
|
63
|
+
};
|
|
64
|
+
navigator.serviceWorker.addEventListener("controllerchange", onControllerChange);
|
|
65
|
+
cleanups.push(() => navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange));
|
|
66
|
+
const watchInstalling = (reg) => {
|
|
67
|
+
const worker = reg.installing;
|
|
68
|
+
if (!worker) return;
|
|
69
|
+
const onState = () => {
|
|
70
|
+
if (deriveUpdateState({ hasController: hasController(), waiting: false, installingState: worker.state })) {
|
|
71
|
+
onUpdateAvailable();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
worker.addEventListener("statechange", onState);
|
|
75
|
+
cleanups.push(() => worker.removeEventListener("statechange", onState));
|
|
76
|
+
};
|
|
77
|
+
navigator.serviceWorker.register(url, scope === void 0 ? void 0 : { scope }).then((reg) => {
|
|
78
|
+
if (disposed) return;
|
|
79
|
+
registration = reg;
|
|
80
|
+
if (deriveUpdateState({ hasController: hasController(), waiting: Boolean(reg.waiting) })) {
|
|
81
|
+
onUpdateAvailable();
|
|
82
|
+
}
|
|
83
|
+
const onUpdateFound = () => watchInstalling(reg);
|
|
84
|
+
reg.addEventListener("updatefound", onUpdateFound);
|
|
85
|
+
cleanups.push(() => reg.removeEventListener("updatefound", onUpdateFound));
|
|
86
|
+
}).catch(() => {
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
applyUpdate() {
|
|
90
|
+
const waiting = registration?.waiting;
|
|
91
|
+
if (!waiting) return;
|
|
92
|
+
applying = true;
|
|
93
|
+
waiting.postMessage({ type: "SKIP_WAITING" });
|
|
94
|
+
},
|
|
95
|
+
dispose() {
|
|
96
|
+
disposed = true;
|
|
97
|
+
cleanups.splice(0).forEach((fn) => fn());
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/service-worker/use-service-worker.ts
|
|
103
|
+
function useServiceWorker({ url, scope, enabled = true }) {
|
|
104
|
+
const [supported, setSupported] = (0, import_react.useState)(true);
|
|
105
|
+
const [updateAvailable, setUpdateAvailable] = (0, import_react.useState)(false);
|
|
106
|
+
const handle = (0, import_react.useRef)(void 0);
|
|
107
|
+
(0, import_react.useEffect)(() => {
|
|
108
|
+
if (!enabled) return;
|
|
109
|
+
if (!isServiceWorkerSupported()) {
|
|
110
|
+
setSupported(false);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const registered = registerServiceWorker({ url, scope, onUpdateAvailable: () => setUpdateAvailable(true) });
|
|
114
|
+
handle.current = registered;
|
|
115
|
+
return () => {
|
|
116
|
+
registered.dispose();
|
|
117
|
+
handle.current = void 0;
|
|
118
|
+
};
|
|
119
|
+
}, [url, scope, enabled]);
|
|
120
|
+
const applyUpdate = (0, import_react.useCallback)(() => handle.current?.applyUpdate(), []);
|
|
121
|
+
return { supported, updateAvailable, applyUpdate };
|
|
122
|
+
}
|
|
123
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
124
|
+
0 && (module.exports = {
|
|
125
|
+
deriveUpdateState,
|
|
126
|
+
unregisterAll,
|
|
127
|
+
useServiceWorker
|
|
128
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface UseServiceWorkerOptions {
|
|
2
|
+
url: string;
|
|
3
|
+
scope?: string;
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
}
|
|
6
|
+
interface ServiceWorkerState$1 {
|
|
7
|
+
supported: boolean;
|
|
8
|
+
updateAvailable: boolean;
|
|
9
|
+
applyUpdate: () => void;
|
|
10
|
+
}
|
|
11
|
+
declare function useServiceWorker({ url, scope, enabled }: UseServiceWorkerOptions): ServiceWorkerState$1;
|
|
12
|
+
|
|
13
|
+
declare function unregisterAll(): Promise<void>;
|
|
14
|
+
|
|
15
|
+
interface UpdateStateInput {
|
|
16
|
+
hasController: boolean;
|
|
17
|
+
waiting: boolean;
|
|
18
|
+
installingState?: ServiceWorkerState | null;
|
|
19
|
+
}
|
|
20
|
+
/** A first install (no controller yet) is never an "update". */
|
|
21
|
+
declare function deriveUpdateState({ hasController, waiting, installingState }: UpdateStateInput): boolean;
|
|
22
|
+
|
|
23
|
+
export { type ServiceWorkerState$1 as ServiceWorkerState, type UpdateStateInput, type UseServiceWorkerOptions, deriveUpdateState, unregisterAll, useServiceWorker };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface UseServiceWorkerOptions {
|
|
2
|
+
url: string;
|
|
3
|
+
scope?: string;
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
}
|
|
6
|
+
interface ServiceWorkerState$1 {
|
|
7
|
+
supported: boolean;
|
|
8
|
+
updateAvailable: boolean;
|
|
9
|
+
applyUpdate: () => void;
|
|
10
|
+
}
|
|
11
|
+
declare function useServiceWorker({ url, scope, enabled }: UseServiceWorkerOptions): ServiceWorkerState$1;
|
|
12
|
+
|
|
13
|
+
declare function unregisterAll(): Promise<void>;
|
|
14
|
+
|
|
15
|
+
interface UpdateStateInput {
|
|
16
|
+
hasController: boolean;
|
|
17
|
+
waiting: boolean;
|
|
18
|
+
installingState?: ServiceWorkerState | null;
|
|
19
|
+
}
|
|
20
|
+
/** A first install (no controller yet) is never an "update". */
|
|
21
|
+
declare function deriveUpdateState({ hasController, waiting, installingState }: UpdateStateInput): boolean;
|
|
22
|
+
|
|
23
|
+
export { type ServiceWorkerState$1 as ServiceWorkerState, type UpdateStateInput, type UseServiceWorkerOptions, deriveUpdateState, unregisterAll, useServiceWorker };
|
package/dist/share.cjs
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
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/share/index.ts
|
|
22
|
+
var share_exports = {};
|
|
23
|
+
__export(share_exports, {
|
|
24
|
+
canShareFiles: () => canShareFiles,
|
|
25
|
+
isShareCancel: () => isShareCancel,
|
|
26
|
+
shareOrCopy: () => shareOrCopy,
|
|
27
|
+
shareTextFor: () => shareTextFor,
|
|
28
|
+
useShareFeedback: () => useShareFeedback
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(share_exports);
|
|
31
|
+
|
|
32
|
+
// src/share/share-text.ts
|
|
33
|
+
function shareTextFor({ text, url }) {
|
|
34
|
+
return [text, url].filter((part) => !!part).join("\n");
|
|
35
|
+
}
|
|
36
|
+
function isShareCancel(error) {
|
|
37
|
+
return typeof error === "object" && error !== null && error.name === "AbortError";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/clipboard/copy-text.ts
|
|
41
|
+
async function copyText(text) {
|
|
42
|
+
const hasClipboardApi = typeof navigator !== "undefined" && !!navigator.clipboard?.writeText && typeof window !== "undefined" && window.isSecureContext;
|
|
43
|
+
if (hasClipboardApi) {
|
|
44
|
+
try {
|
|
45
|
+
await navigator.clipboard.writeText(text);
|
|
46
|
+
return { ok: true };
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (execCommandCopy(text)) return { ok: true };
|
|
51
|
+
return { ok: false, reason: hasClipboardApi ? "denied" : "unavailable" };
|
|
52
|
+
}
|
|
53
|
+
function execCommandCopy(text) {
|
|
54
|
+
if (typeof document === "undefined") return false;
|
|
55
|
+
const textarea = document.createElement("textarea");
|
|
56
|
+
textarea.value = text;
|
|
57
|
+
textarea.readOnly = true;
|
|
58
|
+
textarea.style.position = "fixed";
|
|
59
|
+
textarea.style.top = "-1000px";
|
|
60
|
+
textarea.style.left = "-1000px";
|
|
61
|
+
textarea.style.fontSize = "16px";
|
|
62
|
+
const previouslyFocused = document.activeElement;
|
|
63
|
+
document.body.appendChild(textarea);
|
|
64
|
+
try {
|
|
65
|
+
textarea.focus({ preventScroll: true });
|
|
66
|
+
textarea.select();
|
|
67
|
+
textarea.setSelectionRange(0, text.length);
|
|
68
|
+
return document.execCommand("copy");
|
|
69
|
+
} catch {
|
|
70
|
+
return false;
|
|
71
|
+
} finally {
|
|
72
|
+
document.body.removeChild(textarea);
|
|
73
|
+
if (previouslyFocused instanceof HTMLElement && previouslyFocused !== document.body) {
|
|
74
|
+
previouslyFocused.focus({ preventScroll: true });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/share/share-or-copy.ts
|
|
80
|
+
async function shareOrCopy(data) {
|
|
81
|
+
if (canShareNatively(data)) {
|
|
82
|
+
try {
|
|
83
|
+
await navigator.share(data);
|
|
84
|
+
return { status: "shared" };
|
|
85
|
+
} catch (error) {
|
|
86
|
+
if (isShareCancel(error)) return { status: "cancelled" };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const result = await copyText(shareTextFor(data));
|
|
90
|
+
return { status: result.ok ? "copied" : "failed" };
|
|
91
|
+
}
|
|
92
|
+
function canShareFiles(files) {
|
|
93
|
+
if (typeof navigator === "undefined" || typeof navigator.canShare !== "function") return false;
|
|
94
|
+
try {
|
|
95
|
+
return navigator.canShare({ files });
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function canShareNatively(data) {
|
|
101
|
+
if (typeof navigator === "undefined" || typeof navigator.share !== "function") return false;
|
|
102
|
+
if (typeof navigator.canShare !== "function") return true;
|
|
103
|
+
try {
|
|
104
|
+
return navigator.canShare(data);
|
|
105
|
+
} catch {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/share/use-share-feedback.ts
|
|
111
|
+
var import_react = require("react");
|
|
112
|
+
function useShareFeedback({ resetMs = 1500 } = {}) {
|
|
113
|
+
const [status, setStatus] = (0, import_react.useState)("idle");
|
|
114
|
+
const timerRef = (0, import_react.useRef)(void 0);
|
|
115
|
+
const clearTimer = (0, import_react.useCallback)(() => {
|
|
116
|
+
if (timerRef.current !== void 0) clearTimeout(timerRef.current);
|
|
117
|
+
timerRef.current = void 0;
|
|
118
|
+
}, []);
|
|
119
|
+
(0, import_react.useEffect)(() => clearTimer, [clearTimer]);
|
|
120
|
+
const share = (0, import_react.useCallback)(
|
|
121
|
+
async (data) => {
|
|
122
|
+
const result = await shareOrCopy(data);
|
|
123
|
+
clearTimer();
|
|
124
|
+
setStatus(result.status);
|
|
125
|
+
timerRef.current = setTimeout(() => setStatus("idle"), resetMs);
|
|
126
|
+
return result;
|
|
127
|
+
},
|
|
128
|
+
[clearTimer, resetMs]
|
|
129
|
+
);
|
|
130
|
+
return { share, status };
|
|
131
|
+
}
|
|
132
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
133
|
+
0 && (module.exports = {
|
|
134
|
+
canShareFiles,
|
|
135
|
+
isShareCancel,
|
|
136
|
+
shareOrCopy,
|
|
137
|
+
shareTextFor,
|
|
138
|
+
useShareFeedback
|
|
139
|
+
});
|
package/dist/share.d.cts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface ShareInput {
|
|
2
|
+
title?: string;
|
|
3
|
+
text?: string;
|
|
4
|
+
url?: string;
|
|
5
|
+
}
|
|
6
|
+
declare function shareTextFor({ text, url }: ShareInput): string;
|
|
7
|
+
declare function isShareCancel(error: unknown): boolean;
|
|
8
|
+
|
|
9
|
+
type ShareResult = {
|
|
10
|
+
status: 'shared' | 'copied' | 'cancelled' | 'failed';
|
|
11
|
+
};
|
|
12
|
+
declare function shareOrCopy(data: ShareInput): Promise<ShareResult>;
|
|
13
|
+
declare function canShareFiles(files: File[]): boolean;
|
|
14
|
+
|
|
15
|
+
type ShareStatus = 'idle' | ShareResult['status'];
|
|
16
|
+
declare function useShareFeedback({ resetMs }?: {
|
|
17
|
+
resetMs?: number;
|
|
18
|
+
}): {
|
|
19
|
+
share: (data: ShareInput) => Promise<ShareResult>;
|
|
20
|
+
status: ShareStatus;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { type ShareInput, type ShareResult, type ShareStatus, canShareFiles, isShareCancel, shareOrCopy, shareTextFor, useShareFeedback };
|
package/dist/share.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface ShareInput {
|
|
2
|
+
title?: string;
|
|
3
|
+
text?: string;
|
|
4
|
+
url?: string;
|
|
5
|
+
}
|
|
6
|
+
declare function shareTextFor({ text, url }: ShareInput): string;
|
|
7
|
+
declare function isShareCancel(error: unknown): boolean;
|
|
8
|
+
|
|
9
|
+
type ShareResult = {
|
|
10
|
+
status: 'shared' | 'copied' | 'cancelled' | 'failed';
|
|
11
|
+
};
|
|
12
|
+
declare function shareOrCopy(data: ShareInput): Promise<ShareResult>;
|
|
13
|
+
declare function canShareFiles(files: File[]): boolean;
|
|
14
|
+
|
|
15
|
+
type ShareStatus = 'idle' | ShareResult['status'];
|
|
16
|
+
declare function useShareFeedback({ resetMs }?: {
|
|
17
|
+
resetMs?: number;
|
|
18
|
+
}): {
|
|
19
|
+
share: (data: ShareInput) => Promise<ShareResult>;
|
|
20
|
+
status: ShareStatus;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { type ShareInput, type ShareResult, type ShareStatus, canShareFiles, isShareCancel, shareOrCopy, shareTextFor, useShareFeedback };
|
package/dist/share.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
canShareFiles,
|
|
4
|
+
isShareCancel,
|
|
5
|
+
shareOrCopy,
|
|
6
|
+
shareTextFor,
|
|
7
|
+
useShareFeedback
|
|
8
|
+
} from "./chunk-4PVVTQ5V.js";
|
|
9
|
+
import "./chunk-FE3BQD2I.js";
|
|
10
|
+
export {
|
|
11
|
+
canShareFiles,
|
|
12
|
+
isShareCancel,
|
|
13
|
+
shareOrCopy,
|
|
14
|
+
shareTextFor,
|
|
15
|
+
useShareFeedback
|
|
16
|
+
};
|
|
@@ -0,0 +1,161 @@
|
|
|
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/storage-state/index.ts
|
|
22
|
+
var storage_state_exports = {};
|
|
23
|
+
__export(storage_state_exports, {
|
|
24
|
+
useStorageState: () => useStorageState
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(storage_state_exports);
|
|
27
|
+
|
|
28
|
+
// src/storage-state/use-storage-state.ts
|
|
29
|
+
var import_react = require("react");
|
|
30
|
+
|
|
31
|
+
// src/storage-state/storage-store.ts
|
|
32
|
+
function getStorage(kind) {
|
|
33
|
+
try {
|
|
34
|
+
if (typeof window === "undefined") return null;
|
|
35
|
+
return kind === "session" ? window.sessionStorage : window.localStorage;
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function readRaw(storage, key) {
|
|
41
|
+
try {
|
|
42
|
+
return storage ? storage.getItem(key) : null;
|
|
43
|
+
} catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function writeRaw(storage, key, value) {
|
|
48
|
+
try {
|
|
49
|
+
if (!storage) return false;
|
|
50
|
+
storage.setItem(key, value);
|
|
51
|
+
return true;
|
|
52
|
+
} catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function removeRaw(storage, key) {
|
|
57
|
+
try {
|
|
58
|
+
if (!storage) return false;
|
|
59
|
+
storage.removeItem(key);
|
|
60
|
+
return true;
|
|
61
|
+
} catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function parseOr(raw, parse, fallback) {
|
|
66
|
+
if (raw === null) return fallback;
|
|
67
|
+
try {
|
|
68
|
+
return parse(raw);
|
|
69
|
+
} catch {
|
|
70
|
+
return fallback;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
var slot = (kind, key) => `${kind}\0${key}`;
|
|
74
|
+
var memory = /* @__PURE__ */ new Map();
|
|
75
|
+
var listeners = /* @__PURE__ */ new Map();
|
|
76
|
+
function readCurrent(kind, key) {
|
|
77
|
+
const held = memory.get(slot(kind, key));
|
|
78
|
+
if (held !== void 0) return held;
|
|
79
|
+
return readRaw(getStorage(kind), key);
|
|
80
|
+
}
|
|
81
|
+
function notify(id) {
|
|
82
|
+
for (const listener of [...listeners.get(id) ?? []]) listener();
|
|
83
|
+
}
|
|
84
|
+
function writeCurrent(kind, key, raw) {
|
|
85
|
+
const id = slot(kind, key);
|
|
86
|
+
if (writeRaw(getStorage(kind), key, raw)) memory.delete(id);
|
|
87
|
+
else memory.set(id, raw);
|
|
88
|
+
notify(id);
|
|
89
|
+
}
|
|
90
|
+
function removeCurrent(kind, key) {
|
|
91
|
+
const id = slot(kind, key);
|
|
92
|
+
if (removeRaw(getStorage(kind), key)) memory.delete(id);
|
|
93
|
+
else memory.set(id, null);
|
|
94
|
+
notify(id);
|
|
95
|
+
}
|
|
96
|
+
function onStorageEvent(event) {
|
|
97
|
+
const kinds = [];
|
|
98
|
+
if (!event.storageArea || event.storageArea === getStorage("local")) kinds.push("local");
|
|
99
|
+
if (!event.storageArea || event.storageArea === getStorage("session")) kinds.push("session");
|
|
100
|
+
for (const id of [...listeners.keys()]) {
|
|
101
|
+
const [kind, key] = id.split("\0");
|
|
102
|
+
if (!kinds.includes(kind)) continue;
|
|
103
|
+
if (event.key !== null && event.key !== key) continue;
|
|
104
|
+
memory.delete(id);
|
|
105
|
+
notify(id);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function subscribeToKey(kind, key, listener) {
|
|
109
|
+
const id = slot(kind, key);
|
|
110
|
+
const wasEmpty = listeners.size === 0;
|
|
111
|
+
let set = listeners.get(id);
|
|
112
|
+
if (!set) listeners.set(id, set = /* @__PURE__ */ new Set());
|
|
113
|
+
set.add(listener);
|
|
114
|
+
if (wasEmpty) window.addEventListener("storage", onStorageEvent);
|
|
115
|
+
return () => {
|
|
116
|
+
const current = listeners.get(id);
|
|
117
|
+
current?.delete(listener);
|
|
118
|
+
if (current?.size === 0) listeners.delete(id);
|
|
119
|
+
if (listeners.size === 0) window.removeEventListener("storage", onStorageEvent);
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/storage-state/use-storage-state.ts
|
|
124
|
+
function useStorageState(key, defaultValue, options = {}) {
|
|
125
|
+
const kind = options.storage ?? "local";
|
|
126
|
+
const serialize = options.serialize ?? JSON.stringify;
|
|
127
|
+
const parse = options.parse ?? JSON.parse;
|
|
128
|
+
const latest = (0, import_react.useRef)({ serialize, parse, defaultValue });
|
|
129
|
+
(0, import_react.useEffect)(() => {
|
|
130
|
+
latest.current = { serialize, parse, defaultValue };
|
|
131
|
+
});
|
|
132
|
+
const cache = (0, import_react.useRef)(null);
|
|
133
|
+
const subscribe = (0, import_react.useCallback)((onChange) => subscribeToKey(kind, key, onChange), [kind, key]);
|
|
134
|
+
const getSnapshot = (0, import_react.useCallback)(() => {
|
|
135
|
+
const raw = readCurrent(kind, key);
|
|
136
|
+
const hit = cache.current;
|
|
137
|
+
if (hit && hit.kind === kind && hit.key === key && hit.raw === raw && hit.parse === parse) return hit.value;
|
|
138
|
+
const value2 = parseOr(raw, parse, defaultValue);
|
|
139
|
+
cache.current = { kind, key, raw, parse, value: value2 };
|
|
140
|
+
return value2;
|
|
141
|
+
}, [kind, key, parse, defaultValue]);
|
|
142
|
+
const getServerSnapshot = (0, import_react.useCallback)(() => defaultValue, [defaultValue]);
|
|
143
|
+
const value = (0, import_react.useSyncExternalStore)(subscribe, getSnapshot, getServerSnapshot);
|
|
144
|
+
const set = (0, import_react.useCallback)(
|
|
145
|
+
(next) => {
|
|
146
|
+
const { serialize: encode, parse: decode, defaultValue: fallback } = latest.current;
|
|
147
|
+
try {
|
|
148
|
+
const resolved = typeof next === "function" ? next(parseOr(readCurrent(kind, key), decode, fallback)) : next;
|
|
149
|
+
writeCurrent(kind, key, encode(resolved));
|
|
150
|
+
} catch {
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
[kind, key]
|
|
154
|
+
);
|
|
155
|
+
const remove = (0, import_react.useCallback)(() => removeCurrent(kind, key), [kind, key]);
|
|
156
|
+
return [value, set, remove];
|
|
157
|
+
}
|
|
158
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
159
|
+
0 && (module.exports = {
|
|
160
|
+
useStorageState
|
|
161
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type StorageKind = 'local' | 'session';
|
|
2
|
+
|
|
3
|
+
interface UseStorageStateOptions<T> {
|
|
4
|
+
/** `'local'` (default) or `'session'`. */
|
|
5
|
+
storage?: StorageKind;
|
|
6
|
+
/** Default `JSON.stringify`. */
|
|
7
|
+
serialize?: (value: T) => string;
|
|
8
|
+
/** Default `JSON.parse`. A throw returns `defaultValue`. */
|
|
9
|
+
parse?: (raw: string) => T;
|
|
10
|
+
}
|
|
11
|
+
type StorageStateSetter<T> = (next: T | ((prev: T) => T)) => void;
|
|
12
|
+
declare function useStorageState<T>(key: string, defaultValue: T, options?: UseStorageStateOptions<T>): readonly [T, StorageStateSetter<T>, () => void];
|
|
13
|
+
|
|
14
|
+
export { type StorageKind, type StorageStateSetter, type UseStorageStateOptions, useStorageState };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type StorageKind = 'local' | 'session';
|
|
2
|
+
|
|
3
|
+
interface UseStorageStateOptions<T> {
|
|
4
|
+
/** `'local'` (default) or `'session'`. */
|
|
5
|
+
storage?: StorageKind;
|
|
6
|
+
/** Default `JSON.stringify`. */
|
|
7
|
+
serialize?: (value: T) => string;
|
|
8
|
+
/** Default `JSON.parse`. A throw returns `defaultValue`. */
|
|
9
|
+
parse?: (raw: string) => T;
|
|
10
|
+
}
|
|
11
|
+
type StorageStateSetter<T> = (next: T | ((prev: T) => T)) => void;
|
|
12
|
+
declare function useStorageState<T>(key: string, defaultValue: T, options?: UseStorageStateOptions<T>): readonly [T, StorageStateSetter<T>, () => void];
|
|
13
|
+
|
|
14
|
+
export { type StorageKind, type StorageStateSetter, type UseStorageStateOptions, useStorageState };
|
|
@@ -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/unsaved-guard/index.ts
|
|
22
|
+
var unsaved_guard_exports = {};
|
|
23
|
+
__export(unsaved_guard_exports, {
|
|
24
|
+
handleBeforeUnload: () => handleBeforeUnload,
|
|
25
|
+
useUnsavedChangesGuard: () => useUnsavedChangesGuard
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(unsaved_guard_exports);
|
|
28
|
+
|
|
29
|
+
// src/unsaved-guard/handle-before-unload.ts
|
|
30
|
+
function handleBeforeUnload(event) {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
event.returnValue = "";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/unsaved-guard/use-unsaved-changes-guard.ts
|
|
36
|
+
var import_react = require("react");
|
|
37
|
+
function useUnsavedChangesGuard(dirty) {
|
|
38
|
+
(0, import_react.useEffect)(() => {
|
|
39
|
+
if (!dirty) return;
|
|
40
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
41
|
+
return () => window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
42
|
+
}, [dirty]);
|
|
43
|
+
}
|
|
44
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
45
|
+
0 && (module.exports = {
|
|
46
|
+
handleBeforeUnload,
|
|
47
|
+
useUnsavedChangesGuard
|
|
48
|
+
});
|