react-hook-toolkit 3.0.2 → 3.0.4
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/dist/chunk1213/chunk158261.js +22 -22
- package/dist/chunk1415/chunk143.js +21 -25
- package/dist/chunk1516/chunk0021.d.ts +23 -3
- package/dist/chunk1516/chunk0021.js +386 -352
- package/dist/chunk1516/chunk0022.js +159 -277
- package/dist/chunk1516/chunk3312.d.ts +63 -0
- package/dist/chunk1516/chunk3312.js +462 -0
- package/dist/chunk1516/chunk726433.js +172 -206
- package/dist/chunk1516/chunk940514.js +284 -415
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/utils.js +42 -68
- package/package.json +1 -1
|
@@ -1,70 +1,25 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
12
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
-
function step(op) {
|
|
15
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
-
switch (op[0]) {
|
|
20
|
-
case 0: case 1: t = op; break;
|
|
21
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
-
default:
|
|
25
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
-
if (t[2]) _.ops.pop();
|
|
30
|
-
_.trys.pop(); continue;
|
|
31
|
-
}
|
|
32
|
-
op = body.call(thisArg, _);
|
|
33
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
38
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
39
|
-
if (ar || !(i in from)) {
|
|
40
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
41
|
-
ar[i] = from[i];
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
45
|
-
};
|
|
46
1
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
47
2
|
import { flattenArrayByKey, navigateTo } from "../utils";
|
|
48
|
-
export
|
|
3
|
+
export const useBrowser = () => {
|
|
49
4
|
var _a, _b;
|
|
50
|
-
|
|
51
|
-
|
|
5
|
+
const [currentUrl, setCurrentUrl] = useState(new URL(window.location.href));
|
|
6
|
+
const [historyState, setHistoryState] = useState({
|
|
52
7
|
canGoBack: ((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.idx) > 0,
|
|
53
8
|
canGoForward: ((_b = window.history.state) === null || _b === void 0 ? void 0 : _b.idx) < window.history.length - 1,
|
|
54
9
|
historyLength: window.history.length,
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
10
|
+
});
|
|
11
|
+
const [isOnline, setIsOnline] = useState(navigator.onLine);
|
|
12
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
13
|
+
const [viewportSize, setViewportSize] = useState({
|
|
59
14
|
width: window.innerWidth,
|
|
60
15
|
height: window.innerHeight,
|
|
61
|
-
})
|
|
62
|
-
|
|
16
|
+
});
|
|
17
|
+
const [screenSize, setScreenSize] = useState({
|
|
63
18
|
width: window.screen.width,
|
|
64
19
|
height: window.screen.height,
|
|
65
|
-
})
|
|
20
|
+
});
|
|
66
21
|
// Update URL and history state when changes occur
|
|
67
|
-
|
|
22
|
+
const updateState = useCallback(() => {
|
|
68
23
|
var _a, _b;
|
|
69
24
|
setCurrentUrl(new URL(window.location.href));
|
|
70
25
|
setHistoryState({
|
|
@@ -74,11 +29,11 @@ export var useBrowser = function () {
|
|
|
74
29
|
});
|
|
75
30
|
}, []);
|
|
76
31
|
// Event listeners setup
|
|
77
|
-
useEffect(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const handlePopState = () => updateState();
|
|
34
|
+
const handleOnline = () => setIsOnline(true);
|
|
35
|
+
const handleOffline = () => setIsOnline(false);
|
|
36
|
+
const handleResize = () => {
|
|
82
37
|
setViewportSize({
|
|
83
38
|
width: window.innerWidth,
|
|
84
39
|
height: window.innerHeight,
|
|
@@ -88,7 +43,7 @@ export var useBrowser = function () {
|
|
|
88
43
|
height: window.screen.height,
|
|
89
44
|
});
|
|
90
45
|
};
|
|
91
|
-
|
|
46
|
+
const handleFullscreenChange = () => {
|
|
92
47
|
setIsFullscreen(!!document.fullscreenElement);
|
|
93
48
|
};
|
|
94
49
|
window.addEventListener('popstate', handlePopState);
|
|
@@ -96,7 +51,7 @@ export var useBrowser = function () {
|
|
|
96
51
|
window.addEventListener('offline', handleOffline);
|
|
97
52
|
window.addEventListener('resize', handleResize);
|
|
98
53
|
document.addEventListener('fullscreenchange', handleFullscreenChange);
|
|
99
|
-
return
|
|
54
|
+
return () => {
|
|
100
55
|
window.removeEventListener('popstate', handlePopState);
|
|
101
56
|
window.removeEventListener('online', handleOnline);
|
|
102
57
|
window.removeEventListener('offline', handleOffline);
|
|
@@ -104,7 +59,7 @@ export var useBrowser = function () {
|
|
|
104
59
|
document.removeEventListener('fullscreenchange', handleFullscreenChange);
|
|
105
60
|
};
|
|
106
61
|
}, [updateState]);
|
|
107
|
-
|
|
62
|
+
const goBack = useCallback(() => {
|
|
108
63
|
try {
|
|
109
64
|
if (historyState.canGoBack) {
|
|
110
65
|
window.history.back();
|
|
@@ -118,7 +73,7 @@ export var useBrowser = function () {
|
|
|
118
73
|
window.location.href = '/';
|
|
119
74
|
}
|
|
120
75
|
}, [historyState.canGoBack]);
|
|
121
|
-
|
|
76
|
+
const goForward = useCallback(() => {
|
|
122
77
|
try {
|
|
123
78
|
if (historyState.canGoForward) {
|
|
124
79
|
window.history.forward();
|
|
@@ -131,9 +86,7 @@ export var useBrowser = function () {
|
|
|
131
86
|
console.error('Error going forward:', error);
|
|
132
87
|
}
|
|
133
88
|
}, [historyState.canGoForward]);
|
|
134
|
-
|
|
135
|
-
if (hardReload === void 0) { hardReload = false; }
|
|
136
|
-
if (scrollToTop === void 0) { scrollToTop = false; }
|
|
89
|
+
const reload = useCallback((hardReload = false, scrollToTop = false) => {
|
|
137
90
|
try {
|
|
138
91
|
if (scrollToTop) {
|
|
139
92
|
window.scrollTo(0, 0);
|
|
@@ -149,10 +102,9 @@ export var useBrowser = function () {
|
|
|
149
102
|
console.error('Error reloading page:', error);
|
|
150
103
|
}
|
|
151
104
|
}, []);
|
|
152
|
-
|
|
153
|
-
if (replace === void 0) { replace = false; }
|
|
105
|
+
const navigateTo = useCallback((url, replace = false) => {
|
|
154
106
|
try {
|
|
155
|
-
|
|
107
|
+
const urlObj = typeof url === 'string' ? new URL(url, window.location.origin) : url;
|
|
156
108
|
if (replace) {
|
|
157
109
|
window.location.replace(urlObj.href);
|
|
158
110
|
}
|
|
@@ -161,79 +113,50 @@ export var useBrowser = function () {
|
|
|
161
113
|
}
|
|
162
114
|
}
|
|
163
115
|
catch (error) {
|
|
164
|
-
console.error(
|
|
116
|
+
console.error(`Error navigating to ${url}:`, error);
|
|
165
117
|
}
|
|
166
118
|
}, []);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
119
|
+
const clearBrowserData = useCallback(async (settings = {}) => {
|
|
120
|
+
const { clearCache = false, clearCookies = false, clearLocalStorage = false, clearSessionStorage = false, } = settings;
|
|
121
|
+
try {
|
|
122
|
+
if (clearLocalStorage) {
|
|
123
|
+
localStorage.clear();
|
|
124
|
+
}
|
|
125
|
+
if (clearSessionStorage) {
|
|
126
|
+
sessionStorage.clear();
|
|
127
|
+
}
|
|
128
|
+
if (clearCookies) {
|
|
129
|
+
document.cookie.split(';').forEach((cookie) => {
|
|
130
|
+
const [name] = cookie.split('=');
|
|
131
|
+
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
if (clearCache && 'caches' in window) {
|
|
135
|
+
const cacheKeys = await caches.keys();
|
|
136
|
+
await Promise.all(cacheKeys.map((key) => caches.delete(key)));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error('Error clearing browser data:', error);
|
|
141
|
+
throw error;
|
|
171
142
|
}
|
|
172
|
-
return __awaiter(void 0, __spreadArray([], args_1, true), void 0, function (settings) {
|
|
173
|
-
var _a, clearCache, _b, clearCookies, _c, clearLocalStorage, _d, clearSessionStorage, cacheKeys, error_1;
|
|
174
|
-
if (settings === void 0) { settings = {}; }
|
|
175
|
-
return __generator(this, function (_e) {
|
|
176
|
-
switch (_e.label) {
|
|
177
|
-
case 0:
|
|
178
|
-
_a = settings.clearCache, clearCache = _a === void 0 ? false : _a, _b = settings.clearCookies, clearCookies = _b === void 0 ? false : _b, _c = settings.clearLocalStorage, clearLocalStorage = _c === void 0 ? false : _c, _d = settings.clearSessionStorage, clearSessionStorage = _d === void 0 ? false : _d;
|
|
179
|
-
_e.label = 1;
|
|
180
|
-
case 1:
|
|
181
|
-
_e.trys.push([1, 5, , 6]);
|
|
182
|
-
if (clearLocalStorage) {
|
|
183
|
-
localStorage.clear();
|
|
184
|
-
}
|
|
185
|
-
if (clearSessionStorage) {
|
|
186
|
-
sessionStorage.clear();
|
|
187
|
-
}
|
|
188
|
-
if (clearCookies) {
|
|
189
|
-
document.cookie.split(';').forEach(function (cookie) {
|
|
190
|
-
var name = cookie.split('=')[0];
|
|
191
|
-
document.cookie = "".concat(name, "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/");
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
if (!(clearCache && 'caches' in window)) return [3 /*break*/, 4];
|
|
195
|
-
return [4 /*yield*/, caches.keys()];
|
|
196
|
-
case 2:
|
|
197
|
-
cacheKeys = _e.sent();
|
|
198
|
-
return [4 /*yield*/, Promise.all(cacheKeys.map(function (key) { return caches.delete(key); }))];
|
|
199
|
-
case 3:
|
|
200
|
-
_e.sent();
|
|
201
|
-
_e.label = 4;
|
|
202
|
-
case 4: return [3 /*break*/, 6];
|
|
203
|
-
case 5:
|
|
204
|
-
error_1 = _e.sent();
|
|
205
|
-
console.error('Error clearing browser data:', error_1);
|
|
206
|
-
throw error_1;
|
|
207
|
-
case 6: return [2 /*return*/];
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
143
|
}, []);
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
textArea.select();
|
|
229
|
-
document.execCommand('copy');
|
|
230
|
-
document.body.removeChild(textArea);
|
|
231
|
-
return [3 /*break*/, 3];
|
|
232
|
-
case 3: return [2 /*return*/];
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
}); }, []);
|
|
236
|
-
var openNewTab = useCallback(function (url) {
|
|
144
|
+
const copyCurrentUrl = useCallback(async () => {
|
|
145
|
+
try {
|
|
146
|
+
await navigator.clipboard.writeText(window.location.href);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
console.error('Error copying URL to clipboard:', error);
|
|
150
|
+
// Fallback for browsers that don't support clipboard API
|
|
151
|
+
const textArea = document.createElement('textarea');
|
|
152
|
+
textArea.value = window.location.href;
|
|
153
|
+
document.body.appendChild(textArea);
|
|
154
|
+
textArea.select();
|
|
155
|
+
document.execCommand('copy');
|
|
156
|
+
document.body.removeChild(textArea);
|
|
157
|
+
}
|
|
158
|
+
}, []);
|
|
159
|
+
const openNewTab = useCallback((url) => {
|
|
237
160
|
try {
|
|
238
161
|
window.open(url || window.location.href, '_blank', 'noopener,noreferrer');
|
|
239
162
|
}
|
|
@@ -241,104 +164,65 @@ export var useBrowser = function () {
|
|
|
241
164
|
console.error('Error opening new tab:', error);
|
|
242
165
|
}
|
|
243
166
|
}, []);
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
var url = new URL(window.location.origin);
|
|
167
|
+
const getFaviconUrl = useCallback((size = 32) => {
|
|
168
|
+
const url = new URL(window.location.origin);
|
|
247
169
|
url.pathname = '/favicon.ico';
|
|
248
170
|
url.searchParams.set('size', size.toString());
|
|
249
171
|
return url.href;
|
|
250
172
|
}, []);
|
|
251
|
-
|
|
173
|
+
const getPageTitle = useCallback(() => {
|
|
252
174
|
return document.title;
|
|
253
175
|
}, []);
|
|
254
|
-
|
|
176
|
+
const setPageTitle = useCallback((title) => {
|
|
255
177
|
document.title = title;
|
|
256
178
|
}, []);
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
case 0:
|
|
262
|
-
_a.trys.push([0, 7, , 8]);
|
|
263
|
-
if (!document.documentElement.requestFullscreen) return [3 /*break*/, 2];
|
|
264
|
-
return [4 /*yield*/, document.documentElement.requestFullscreen()];
|
|
265
|
-
case 1:
|
|
266
|
-
_a.sent();
|
|
267
|
-
return [3 /*break*/, 6];
|
|
268
|
-
case 2:
|
|
269
|
-
if (!document.documentElement.webkitRequestFullscreen) return [3 /*break*/, 4];
|
|
270
|
-
return [4 /*yield*/, document.documentElement.webkitRequestFullscreen()];
|
|
271
|
-
case 3:
|
|
272
|
-
_a.sent();
|
|
273
|
-
return [3 /*break*/, 6];
|
|
274
|
-
case 4:
|
|
275
|
-
if (!document.documentElement.msRequestFullscreen) return [3 /*break*/, 6];
|
|
276
|
-
return [4 /*yield*/, document.documentElement.msRequestFullscreen()];
|
|
277
|
-
case 5:
|
|
278
|
-
_a.sent();
|
|
279
|
-
_a.label = 6;
|
|
280
|
-
case 6: return [3 /*break*/, 8];
|
|
281
|
-
case 7:
|
|
282
|
-
error_3 = _a.sent();
|
|
283
|
-
console.error('Error enabling fullscreen:', error_3);
|
|
284
|
-
throw error_3;
|
|
285
|
-
case 8: return [2 /*return*/];
|
|
179
|
+
const enableFullscreen = useCallback(async () => {
|
|
180
|
+
try {
|
|
181
|
+
if (document.documentElement.requestFullscreen) {
|
|
182
|
+
await document.documentElement.requestFullscreen();
|
|
286
183
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
var disableFullscreen = useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
290
|
-
var error_4;
|
|
291
|
-
return __generator(this, function (_a) {
|
|
292
|
-
switch (_a.label) {
|
|
293
|
-
case 0:
|
|
294
|
-
_a.trys.push([0, 7, , 8]);
|
|
295
|
-
if (!document.exitFullscreen) return [3 /*break*/, 2];
|
|
296
|
-
return [4 /*yield*/, document.exitFullscreen()];
|
|
297
|
-
case 1:
|
|
298
|
-
_a.sent();
|
|
299
|
-
return [3 /*break*/, 6];
|
|
300
|
-
case 2:
|
|
301
|
-
if (!document.webkitExitFullscreen) return [3 /*break*/, 4];
|
|
302
|
-
return [4 /*yield*/, document.webkitExitFullscreen()];
|
|
303
|
-
case 3:
|
|
304
|
-
_a.sent();
|
|
305
|
-
return [3 /*break*/, 6];
|
|
306
|
-
case 4:
|
|
307
|
-
if (!document.msExitFullscreen) return [3 /*break*/, 6];
|
|
308
|
-
return [4 /*yield*/, document.msExitFullscreen()];
|
|
309
|
-
case 5:
|
|
310
|
-
_a.sent();
|
|
311
|
-
_a.label = 6;
|
|
312
|
-
case 6: return [3 /*break*/, 8];
|
|
313
|
-
case 7:
|
|
314
|
-
error_4 = _a.sent();
|
|
315
|
-
console.error('Error disabling fullscreen:', error_4);
|
|
316
|
-
throw error_4;
|
|
317
|
-
case 8: return [2 /*return*/];
|
|
184
|
+
else if (document.documentElement.webkitRequestFullscreen) {
|
|
185
|
+
await document.documentElement.webkitRequestFullscreen();
|
|
318
186
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
187
|
+
else if (document.documentElement.msRequestFullscreen) {
|
|
188
|
+
await document.documentElement.msRequestFullscreen();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
console.error('Error enabling fullscreen:', error);
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
}, []);
|
|
196
|
+
const disableFullscreen = useCallback(async () => {
|
|
197
|
+
try {
|
|
198
|
+
if (document.exitFullscreen) {
|
|
199
|
+
await document.exitFullscreen();
|
|
200
|
+
}
|
|
201
|
+
else if (document.webkitExitFullscreen) {
|
|
202
|
+
await document.webkitExitFullscreen();
|
|
203
|
+
}
|
|
204
|
+
else if (document.msExitFullscreen) {
|
|
205
|
+
await document.msExitFullscreen();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
console.error('Error disabling fullscreen:', error);
|
|
210
|
+
throw error;
|
|
211
|
+
}
|
|
212
|
+
}, []);
|
|
213
|
+
const printPage = useCallback(() => {
|
|
322
214
|
window.print();
|
|
323
215
|
}, []);
|
|
324
|
-
|
|
216
|
+
const getUserAgent = useCallback(() => {
|
|
325
217
|
return navigator.userAgent;
|
|
326
218
|
}, []);
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
return [4 /*yield*/, navigator.share(data)];
|
|
335
|
-
case 1:
|
|
336
|
-
_a.sent();
|
|
337
|
-
return [2 /*return*/];
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
}); }, []);
|
|
341
|
-
var closeCurrentTab = useCallback(function () {
|
|
219
|
+
const shareContent = useCallback(async (data) => {
|
|
220
|
+
if (!navigator.share) {
|
|
221
|
+
throw new Error('Web Share API not supported');
|
|
222
|
+
}
|
|
223
|
+
await navigator.share(data);
|
|
224
|
+
}, []);
|
|
225
|
+
const closeCurrentTab = useCallback(() => {
|
|
342
226
|
try {
|
|
343
227
|
// Note: This will only work if the tab was opened by JavaScript
|
|
344
228
|
// Browsers typically prevent closing windows/tabs not opened by script
|
|
@@ -351,70 +235,69 @@ export var useBrowser = function () {
|
|
|
351
235
|
}
|
|
352
236
|
}, []);
|
|
353
237
|
return {
|
|
354
|
-
currentUrl
|
|
238
|
+
currentUrl,
|
|
355
239
|
currentPath: currentUrl.pathname,
|
|
356
240
|
currentHash: currentUrl.hash,
|
|
357
241
|
currentSearchParams: currentUrl.searchParams,
|
|
358
|
-
goBack
|
|
359
|
-
goForward
|
|
360
|
-
reload
|
|
361
|
-
navigateTo
|
|
362
|
-
clearBrowserData
|
|
363
|
-
historyState
|
|
364
|
-
isOnline
|
|
365
|
-
copyCurrentUrl
|
|
366
|
-
openNewTab
|
|
367
|
-
getFaviconUrl
|
|
368
|
-
getPageTitle
|
|
369
|
-
setPageTitle
|
|
242
|
+
goBack,
|
|
243
|
+
goForward,
|
|
244
|
+
reload,
|
|
245
|
+
navigateTo,
|
|
246
|
+
clearBrowserData,
|
|
247
|
+
historyState,
|
|
248
|
+
isOnline,
|
|
249
|
+
copyCurrentUrl,
|
|
250
|
+
openNewTab,
|
|
251
|
+
getFaviconUrl,
|
|
252
|
+
getPageTitle,
|
|
253
|
+
setPageTitle,
|
|
370
254
|
isSecureContext: window.isSecureContext,
|
|
371
|
-
viewportSize
|
|
372
|
-
screenSize
|
|
373
|
-
enableFullscreen
|
|
374
|
-
disableFullscreen
|
|
375
|
-
isFullscreen
|
|
376
|
-
printPage
|
|
377
|
-
getUserAgent
|
|
378
|
-
shareContent
|
|
255
|
+
viewportSize,
|
|
256
|
+
screenSize,
|
|
257
|
+
enableFullscreen,
|
|
258
|
+
disableFullscreen,
|
|
259
|
+
isFullscreen,
|
|
260
|
+
printPage,
|
|
261
|
+
getUserAgent,
|
|
262
|
+
shareContent,
|
|
379
263
|
isShareSupported: 'share' in navigator,
|
|
380
|
-
closeCurrentTab
|
|
264
|
+
closeCurrentTab,
|
|
381
265
|
};
|
|
382
266
|
};
|
|
383
|
-
export function useRouter(initialPath) {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
var _a = path.split('?'), basePath = _a[0], queryString = _a[1];
|
|
267
|
+
export function useRouter(initialPath = window.location.pathname + window.location.search) {
|
|
268
|
+
const [path, setPath] = useState(initialPath);
|
|
269
|
+
const { pathname, searchParams } = useMemo(() => {
|
|
270
|
+
const [basePath, queryString] = path.split('?');
|
|
388
271
|
return {
|
|
389
272
|
pathname: basePath,
|
|
390
273
|
searchParams: new URLSearchParams(queryString || ''),
|
|
391
274
|
};
|
|
392
|
-
}, [path])
|
|
393
|
-
|
|
394
|
-
|
|
275
|
+
}, [path]);
|
|
276
|
+
const navigate = useCallback((newPath) => {
|
|
277
|
+
const newPathStr = String(newPath);
|
|
395
278
|
setPath(newPathStr);
|
|
396
279
|
window.history.pushState({}, '', newPathStr);
|
|
397
280
|
}, []);
|
|
398
|
-
useEffect(
|
|
399
|
-
|
|
281
|
+
useEffect(() => {
|
|
282
|
+
const handlePopState = () => {
|
|
400
283
|
setPath(window.location.pathname + window.location.search);
|
|
401
284
|
};
|
|
402
285
|
window.addEventListener('popstate', handlePopState);
|
|
403
|
-
return
|
|
286
|
+
return () => window.removeEventListener('popstate', handlePopState);
|
|
404
287
|
}, []);
|
|
405
288
|
return {
|
|
406
|
-
pathname
|
|
407
|
-
searchParams
|
|
408
|
-
navigate
|
|
289
|
+
pathname,
|
|
290
|
+
searchParams,
|
|
291
|
+
navigate,
|
|
409
292
|
};
|
|
410
293
|
}
|
|
411
294
|
export function useNavigationState() {
|
|
412
|
-
|
|
295
|
+
const [location, setLocation] = useState({
|
|
413
296
|
pathname: window.location.pathname,
|
|
414
297
|
search: window.location.search,
|
|
415
298
|
state: window.history.state,
|
|
416
|
-
})
|
|
417
|
-
|
|
299
|
+
});
|
|
300
|
+
const navigate = useCallback((newPath, options) => {
|
|
418
301
|
window.history.pushState((options === null || options === void 0 ? void 0 : options.state) || {}, "", newPath);
|
|
419
302
|
setLocation({
|
|
420
303
|
pathname: window.location.pathname,
|
|
@@ -423,8 +306,8 @@ export function useNavigationState() {
|
|
|
423
306
|
});
|
|
424
307
|
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
425
308
|
}, []);
|
|
426
|
-
useEffect(
|
|
427
|
-
|
|
309
|
+
useEffect(() => {
|
|
310
|
+
const handlePopState = () => {
|
|
428
311
|
setLocation({
|
|
429
312
|
pathname: window.location.pathname,
|
|
430
313
|
search: window.location.search,
|
|
@@ -432,31 +315,30 @@ export function useNavigationState() {
|
|
|
432
315
|
});
|
|
433
316
|
};
|
|
434
317
|
window.addEventListener("popstate", handlePopState);
|
|
435
|
-
return
|
|
318
|
+
return () => window.removeEventListener("popstate", handlePopState);
|
|
436
319
|
}, []);
|
|
437
|
-
|
|
320
|
+
const searchParams = useMemo(() => new URLSearchParams(location.search), [location.search]);
|
|
438
321
|
return {
|
|
439
322
|
pathname: location.pathname,
|
|
440
323
|
search: location.search,
|
|
441
|
-
searchParams
|
|
324
|
+
searchParams,
|
|
442
325
|
state: location.state,
|
|
443
|
-
navigate
|
|
326
|
+
navigate,
|
|
444
327
|
};
|
|
445
328
|
}
|
|
446
|
-
export function useMenuNavigation(menuData, key) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
useEffect(function () {
|
|
329
|
+
export function useMenuNavigation(menuData, key = 'children') {
|
|
330
|
+
const [menuList, setMenuList] = useState([]);
|
|
331
|
+
useEffect(() => {
|
|
450
332
|
if (menuData.length > 0) {
|
|
451
|
-
|
|
333
|
+
const data = flattenArrayByKey(menuData, key);
|
|
452
334
|
setMenuList(data);
|
|
453
335
|
}
|
|
454
|
-
return
|
|
336
|
+
return () => setMenuList([]);
|
|
455
337
|
}, [menuData, key]);
|
|
456
|
-
|
|
338
|
+
const handleSelect = (path) => {
|
|
457
339
|
if (path) {
|
|
458
340
|
navigateTo(path);
|
|
459
341
|
}
|
|
460
342
|
};
|
|
461
|
-
return { menuList
|
|
343
|
+
return { menuList, handleSelect };
|
|
462
344
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export type VoiceStatus = 'idle' | 'listening' | 'processing' | 'confirming' | 'error' | 'unsupported';
|
|
2
|
+
export interface VoiceCommand {
|
|
3
|
+
keywords: string[];
|
|
4
|
+
label: string;
|
|
5
|
+
path?: string;
|
|
6
|
+
requiresConfirmation?: boolean;
|
|
7
|
+
action?: () => void;
|
|
8
|
+
}
|
|
9
|
+
export interface HistoryEntry {
|
|
10
|
+
text: string;
|
|
11
|
+
matched: boolean;
|
|
12
|
+
label?: string;
|
|
13
|
+
time: string;
|
|
14
|
+
}
|
|
15
|
+
export type NavigateFn = (path: string) => void;
|
|
16
|
+
export interface UseVoiceOptions {
|
|
17
|
+
commands?: VoiceCommand[];
|
|
18
|
+
language?: string;
|
|
19
|
+
continuous?: boolean;
|
|
20
|
+
interimResults?: boolean;
|
|
21
|
+
autoNavigate?: boolean;
|
|
22
|
+
historySize?: number;
|
|
23
|
+
minConfidence?: number;
|
|
24
|
+
idleTimeoutMs?: number;
|
|
25
|
+
wakeWord?: string;
|
|
26
|
+
shortcut?: string;
|
|
27
|
+
navigate?: NavigateFn;
|
|
28
|
+
onMatch?: (command: VoiceCommand, text: string) => void;
|
|
29
|
+
onNoMatch?: (text: string, closest: VoiceCommand | null) => void;
|
|
30
|
+
onError?: (error: string) => void;
|
|
31
|
+
onStart?: () => void;
|
|
32
|
+
onEnd?: () => void;
|
|
33
|
+
onToast?: (type: 'success' | 'error' | 'warn', message: string) => void;
|
|
34
|
+
}
|
|
35
|
+
export interface UseVoiceResult {
|
|
36
|
+
status: VoiceStatus;
|
|
37
|
+
transcript: string;
|
|
38
|
+
audioLevel: number;
|
|
39
|
+
history: HistoryEntry[];
|
|
40
|
+
lastMatch: VoiceCommand | null;
|
|
41
|
+
pendingConfirm: VoiceCommand | null;
|
|
42
|
+
isSupported: boolean;
|
|
43
|
+
isContinuousSupported: boolean;
|
|
44
|
+
isListening: boolean;
|
|
45
|
+
isProcessing: boolean;
|
|
46
|
+
start: () => Promise<void>;
|
|
47
|
+
stop: () => void;
|
|
48
|
+
toggle: () => Promise<void>;
|
|
49
|
+
reset: () => void;
|
|
50
|
+
executeCommand: (text: string) => void;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Word-boundary match — avoids "home" firing on "homework".
|
|
54
|
+
* Splits both transcript and keyword on whitespace and checks for an
|
|
55
|
+
* exact word (or multi-word phrase) match.
|
|
56
|
+
*/
|
|
57
|
+
export declare function matchVoiceCommand(transcript: string, commands: VoiceCommand[]): VoiceCommand | null;
|
|
58
|
+
/**
|
|
59
|
+
* Returns the command whose keywords share the most words with the transcript.
|
|
60
|
+
* Used for "did you mean?" hints on no-match.
|
|
61
|
+
*/
|
|
62
|
+
export declare function closestVoiceCommand(transcript: string, commands: VoiceCommand[]): VoiceCommand | null;
|
|
63
|
+
export declare function useVoice(options?: UseVoiceOptions): UseVoiceResult;
|