@reactuses/core 1.0.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 +24 -0
- package/README.md +73 -0
- package/index.cjs +2215 -0
- package/index.d.ts +588 -0
- package/index.mjs +2147 -0
- package/package.json +42 -0
package/index.mjs
ADDED
|
@@ -0,0 +1,2147 @@
|
|
|
1
|
+
import { useRef, useEffect, useState, useLayoutEffect, useCallback, useReducer, useMemo } from 'react';
|
|
2
|
+
import { throttle, debounce, isEqual } from 'lodash';
|
|
3
|
+
|
|
4
|
+
function usePrevious(state) {
|
|
5
|
+
const ref = useRef();
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
ref.current = state;
|
|
8
|
+
});
|
|
9
|
+
return ref.current;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
var __async$1 = (__this, __arguments, generator) => {
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
var fulfilled = (value) => {
|
|
15
|
+
try {
|
|
16
|
+
step(generator.next(value));
|
|
17
|
+
} catch (e) {
|
|
18
|
+
reject(e);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var rejected = (value) => {
|
|
22
|
+
try {
|
|
23
|
+
step(generator.throw(value));
|
|
24
|
+
} catch (e) {
|
|
25
|
+
reject(e);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
29
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
function useMarkdown(filepath) {
|
|
33
|
+
const [content, setContent] = useState("");
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const getContent = () => __async$1(this, null, function* () {
|
|
36
|
+
const data = yield (yield fetch(filepath)).text();
|
|
37
|
+
setContent(data);
|
|
38
|
+
});
|
|
39
|
+
getContent();
|
|
40
|
+
}, [filepath]);
|
|
41
|
+
return content;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function useLatest(value) {
|
|
45
|
+
const ref = useRef(value);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
ref.current = value;
|
|
48
|
+
}, [value]);
|
|
49
|
+
return ref;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function useFirstMountState() {
|
|
53
|
+
const isFirst = useRef(true);
|
|
54
|
+
if (isFirst.current) {
|
|
55
|
+
isFirst.current = false;
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return isFirst.current;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const createUpdateEffect = (hook) => (effect, deps) => {
|
|
62
|
+
const isFirstMount = useFirstMountState();
|
|
63
|
+
hook(() => {
|
|
64
|
+
if (!isFirstMount) {
|
|
65
|
+
return effect();
|
|
66
|
+
}
|
|
67
|
+
}, deps);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
var useUpdateEffect = createUpdateEffect(useEffect);
|
|
71
|
+
|
|
72
|
+
var useUpdateLayoutEffect = createUpdateEffect(useLayoutEffect);
|
|
73
|
+
|
|
74
|
+
var _a;
|
|
75
|
+
const isFunction = (val) => typeof val === "function";
|
|
76
|
+
const isDev = process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test";
|
|
77
|
+
const isBrowser = typeof window !== "undefined";
|
|
78
|
+
const isNavigator = typeof navigator !== "undefined";
|
|
79
|
+
const noop = () => {
|
|
80
|
+
};
|
|
81
|
+
const isIOS = isBrowser && ((_a = window == null ? void 0 : window.navigator) == null ? void 0 : _a.userAgent) && /iP(ad|hone|od)/.test(window.navigator.userAgent);
|
|
82
|
+
|
|
83
|
+
function guessSerializerType(rawInit) {
|
|
84
|
+
return rawInit == null ? "any" : rawInit instanceof Set ? "set" : rawInit instanceof Map ? "map" : rawInit instanceof Date ? "date" : typeof rawInit === "boolean" ? "boolean" : typeof rawInit === "string" ? "string" : typeof rawInit === "object" ? "object" : Array.isArray(rawInit) ? "object" : !Number.isNaN(rawInit) ? "number" : "any";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;
|
|
88
|
+
|
|
89
|
+
function useEvent(fn) {
|
|
90
|
+
if (isDev) {
|
|
91
|
+
if (!isFunction(fn)) {
|
|
92
|
+
console.error(
|
|
93
|
+
`useEvent expected parameter is a function, got ${typeof fn}`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const handlerRef = useRef(fn);
|
|
98
|
+
useIsomorphicLayoutEffect(() => {
|
|
99
|
+
handlerRef.current = fn;
|
|
100
|
+
}, [fn]);
|
|
101
|
+
return useCallback((...args) => {
|
|
102
|
+
const fn2 = handlerRef.current;
|
|
103
|
+
return fn2(...args);
|
|
104
|
+
}, []);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const StorageSerializers = {
|
|
108
|
+
boolean: {
|
|
109
|
+
read: (v) => v === "true",
|
|
110
|
+
write: (v) => String(v)
|
|
111
|
+
},
|
|
112
|
+
object: {
|
|
113
|
+
read: (v) => JSON.parse(v),
|
|
114
|
+
write: (v) => JSON.stringify(v)
|
|
115
|
+
},
|
|
116
|
+
number: {
|
|
117
|
+
read: (v) => Number.parseFloat(v),
|
|
118
|
+
write: (v) => String(v)
|
|
119
|
+
},
|
|
120
|
+
any: {
|
|
121
|
+
read: (v) => v,
|
|
122
|
+
write: (v) => String(v)
|
|
123
|
+
},
|
|
124
|
+
string: {
|
|
125
|
+
read: (v) => v,
|
|
126
|
+
write: (v) => String(v)
|
|
127
|
+
},
|
|
128
|
+
map: {
|
|
129
|
+
read: (v) => new Map(JSON.parse(v)),
|
|
130
|
+
write: (v) => JSON.stringify(Array.from(v.entries()))
|
|
131
|
+
},
|
|
132
|
+
set: {
|
|
133
|
+
read: (v) => new Set(JSON.parse(v)),
|
|
134
|
+
write: (v) => JSON.stringify(Array.from(v))
|
|
135
|
+
},
|
|
136
|
+
date: {
|
|
137
|
+
read: (v) => new Date(v),
|
|
138
|
+
write: (v) => v.toISOString()
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
function useStorage(key, defaults, getStorage, options = {}) {
|
|
142
|
+
var _a;
|
|
143
|
+
let storage;
|
|
144
|
+
const {
|
|
145
|
+
onError = (e) => {
|
|
146
|
+
console.error(e);
|
|
147
|
+
}
|
|
148
|
+
} = options;
|
|
149
|
+
const data = defaults;
|
|
150
|
+
try {
|
|
151
|
+
storage = getStorage();
|
|
152
|
+
} catch (err) {
|
|
153
|
+
console.error(err);
|
|
154
|
+
}
|
|
155
|
+
const type = guessSerializerType(defaults);
|
|
156
|
+
const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];
|
|
157
|
+
const getStoredValue = () => {
|
|
158
|
+
try {
|
|
159
|
+
const raw = storage == null ? void 0 : storage.getItem(key);
|
|
160
|
+
if (raw) {
|
|
161
|
+
return serializer.read(raw);
|
|
162
|
+
} else {
|
|
163
|
+
storage == null ? void 0 : storage.setItem(key, serializer.write(data));
|
|
164
|
+
return data;
|
|
165
|
+
}
|
|
166
|
+
} catch (e) {
|
|
167
|
+
onError(e);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
const [state, setState] = useState(() => getStoredValue());
|
|
171
|
+
useUpdateEffect(() => {
|
|
172
|
+
setState(getStoredValue());
|
|
173
|
+
}, [key]);
|
|
174
|
+
const updateState = useEvent(
|
|
175
|
+
(valOrFunc) => {
|
|
176
|
+
const currentState = isFunction(valOrFunc) ? valOrFunc(state) : valOrFunc;
|
|
177
|
+
setState(currentState);
|
|
178
|
+
if (currentState === null) {
|
|
179
|
+
storage == null ? void 0 : storage.removeItem(key);
|
|
180
|
+
} else {
|
|
181
|
+
try {
|
|
182
|
+
storage == null ? void 0 : storage.setItem(key, serializer.write(currentState));
|
|
183
|
+
} catch (e) {
|
|
184
|
+
onError(e);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
return [state, updateState];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function useLocalStorage(key, defaults, options = {}) {
|
|
193
|
+
return useStorage(
|
|
194
|
+
key,
|
|
195
|
+
defaults,
|
|
196
|
+
() => isBrowser ? localStorage : void 0,
|
|
197
|
+
options
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function useSessionStorage(key, defaults, options = {}) {
|
|
202
|
+
return useStorage(
|
|
203
|
+
key,
|
|
204
|
+
defaults,
|
|
205
|
+
() => isBrowser ? sessionStorage : void 0,
|
|
206
|
+
options
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const toggleReducer = (state, nextValue) => typeof nextValue === "boolean" ? nextValue : !state;
|
|
211
|
+
function useToggle(initialValue) {
|
|
212
|
+
return useReducer(toggleReducer, initialValue);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function useInterval(callback, delay, options) {
|
|
216
|
+
const immediate = options == null ? void 0 : options.immediate;
|
|
217
|
+
const savedCallback = useLatest(callback);
|
|
218
|
+
useEffect(() => {
|
|
219
|
+
if (immediate) {
|
|
220
|
+
savedCallback.current();
|
|
221
|
+
}
|
|
222
|
+
if (delay !== null) {
|
|
223
|
+
const interval = setInterval(() => savedCallback.current(), delay || 0);
|
|
224
|
+
return () => clearInterval(interval);
|
|
225
|
+
}
|
|
226
|
+
return void 0;
|
|
227
|
+
}, [delay, immediate]);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const getInitialState = (query, defaultState) => {
|
|
231
|
+
if (isBrowser) {
|
|
232
|
+
return window.matchMedia(query).matches;
|
|
233
|
+
}
|
|
234
|
+
if (defaultState !== void 0) {
|
|
235
|
+
return defaultState;
|
|
236
|
+
}
|
|
237
|
+
if (process.env.NODE_ENV !== "production") {
|
|
238
|
+
console.warn(
|
|
239
|
+
"`useMedia` When server side rendering, defaultState should be defined to prevent a hydration mismatches."
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
return false;
|
|
243
|
+
};
|
|
244
|
+
function useMediaQuery(query, defaultState) {
|
|
245
|
+
const [state, setState] = useState(getInitialState(query, defaultState));
|
|
246
|
+
useEffect(() => {
|
|
247
|
+
let mounted = true;
|
|
248
|
+
const mql = window.matchMedia(query);
|
|
249
|
+
const onChange = () => {
|
|
250
|
+
if (!mounted) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
setState(!!mql.matches);
|
|
254
|
+
};
|
|
255
|
+
if ("addEventListener" in mql) {
|
|
256
|
+
mql.addEventListener("change", onChange);
|
|
257
|
+
} else {
|
|
258
|
+
mql.addListener(onChange);
|
|
259
|
+
}
|
|
260
|
+
setState(mql.matches);
|
|
261
|
+
return () => {
|
|
262
|
+
mounted = false;
|
|
263
|
+
if ("removeEventListener" in mql) {
|
|
264
|
+
mql.removeEventListener("change", onChange);
|
|
265
|
+
} else {
|
|
266
|
+
mql.removeListener(onChange);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}, [query]);
|
|
270
|
+
return state;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function usePreferredDark(defaultState) {
|
|
274
|
+
return useMediaQuery("(prefers-color-scheme: dark)", defaultState);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function useDarkMode(options = {}) {
|
|
278
|
+
const {
|
|
279
|
+
selector = "html",
|
|
280
|
+
attribute = "class",
|
|
281
|
+
initialValue,
|
|
282
|
+
storageKey = "reactuses-color-scheme",
|
|
283
|
+
storage = () => isBrowser ? localStorage : void 0
|
|
284
|
+
} = options;
|
|
285
|
+
const prefersDarkMode = usePreferredDark();
|
|
286
|
+
const value = initialValue ? initialValue : prefersDarkMode ? "dark" : "light";
|
|
287
|
+
const [dark, setDark] = useStorage(storageKey, value, storage);
|
|
288
|
+
useEffect(() => {
|
|
289
|
+
const element = window == null ? void 0 : window.document.querySelector(selector);
|
|
290
|
+
if (!element) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (attribute === "class") {
|
|
294
|
+
dark && element.classList.add(dark);
|
|
295
|
+
} else {
|
|
296
|
+
dark && element.setAttribute(attribute, dark);
|
|
297
|
+
}
|
|
298
|
+
return () => {
|
|
299
|
+
dark && (element == null ? void 0 : element.classList.remove(dark));
|
|
300
|
+
};
|
|
301
|
+
}, [attribute, dark, selector]);
|
|
302
|
+
return [dark, setDark];
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function useMount(fn) {
|
|
306
|
+
if (isDev) {
|
|
307
|
+
if (!isFunction(fn)) {
|
|
308
|
+
console.error(
|
|
309
|
+
`useMount: parameter \`fn\` expected to be a function, but got "${typeof fn}".`
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
useEffect(() => {
|
|
314
|
+
fn == null ? void 0 : fn();
|
|
315
|
+
}, []);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function useUnmount(fn) {
|
|
319
|
+
if (isDev) {
|
|
320
|
+
if (!isFunction(fn)) {
|
|
321
|
+
console.error(
|
|
322
|
+
`useUnmount expected parameter is a function, got ${typeof fn}`
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
const fnRef = useLatest(fn);
|
|
327
|
+
useEffect(
|
|
328
|
+
() => () => {
|
|
329
|
+
fnRef.current();
|
|
330
|
+
},
|
|
331
|
+
[fnRef]
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function useThrottleFn(fn, wait, options) {
|
|
336
|
+
if (isDev) {
|
|
337
|
+
if (!isFunction(fn)) {
|
|
338
|
+
console.error(
|
|
339
|
+
`useThrottleFn expected parameter is a function, got ${typeof fn}`
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
const fnRef = useLatest(fn);
|
|
344
|
+
const throttled = useMemo(
|
|
345
|
+
() => throttle(
|
|
346
|
+
(...args) => {
|
|
347
|
+
return fnRef.current(...args);
|
|
348
|
+
},
|
|
349
|
+
wait,
|
|
350
|
+
options
|
|
351
|
+
),
|
|
352
|
+
[]
|
|
353
|
+
);
|
|
354
|
+
useUnmount(() => {
|
|
355
|
+
throttled.cancel();
|
|
356
|
+
});
|
|
357
|
+
return {
|
|
358
|
+
run: throttled,
|
|
359
|
+
cancel: throttled.cancel,
|
|
360
|
+
flush: throttled.flush
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function useThrottle(value, wait, options) {
|
|
365
|
+
const [throttled, setThrottled] = useState(value);
|
|
366
|
+
const { run } = useThrottleFn(
|
|
367
|
+
() => {
|
|
368
|
+
setThrottled(value);
|
|
369
|
+
},
|
|
370
|
+
wait,
|
|
371
|
+
options
|
|
372
|
+
);
|
|
373
|
+
useEffect(() => {
|
|
374
|
+
run();
|
|
375
|
+
}, [run, value]);
|
|
376
|
+
return throttled;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function useDebounceFn(fn, wait, options) {
|
|
380
|
+
if (isDev) {
|
|
381
|
+
if (!isFunction(fn)) {
|
|
382
|
+
console.error(
|
|
383
|
+
`useDebounceFn expected parameter is a function, got ${typeof fn}`
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const fnRef = useLatest(fn);
|
|
388
|
+
const debounced = useMemo(
|
|
389
|
+
() => debounce(
|
|
390
|
+
(...args) => {
|
|
391
|
+
return fnRef.current(...args);
|
|
392
|
+
},
|
|
393
|
+
wait,
|
|
394
|
+
options
|
|
395
|
+
),
|
|
396
|
+
[]
|
|
397
|
+
);
|
|
398
|
+
useUnmount(() => {
|
|
399
|
+
debounced.cancel();
|
|
400
|
+
});
|
|
401
|
+
return {
|
|
402
|
+
run: debounced,
|
|
403
|
+
cancel: debounced.cancel,
|
|
404
|
+
flush: debounced.flush
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function useDebounce(value, wait, options) {
|
|
409
|
+
const [debounced, setDebounced] = useState(value);
|
|
410
|
+
const { run } = useDebounceFn(
|
|
411
|
+
() => {
|
|
412
|
+
setDebounced(value);
|
|
413
|
+
},
|
|
414
|
+
wait,
|
|
415
|
+
options
|
|
416
|
+
);
|
|
417
|
+
useEffect(() => {
|
|
418
|
+
run();
|
|
419
|
+
}, [run, value]);
|
|
420
|
+
return debounced;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function useRafState(initialState) {
|
|
424
|
+
const frame = useRef(0);
|
|
425
|
+
const [state, setState] = useState(initialState);
|
|
426
|
+
const setRafState = useCallback((value) => {
|
|
427
|
+
cancelAnimationFrame(frame.current);
|
|
428
|
+
frame.current = requestAnimationFrame(() => {
|
|
429
|
+
setState(value);
|
|
430
|
+
});
|
|
431
|
+
}, []);
|
|
432
|
+
useUnmount(() => {
|
|
433
|
+
cancelAnimationFrame(frame.current);
|
|
434
|
+
});
|
|
435
|
+
return [state, setRafState];
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const updateReducer = (num) => (num + 1) % 1e6;
|
|
439
|
+
function useUpdate() {
|
|
440
|
+
const [, update] = useReducer(updateReducer, 0);
|
|
441
|
+
return update;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function useTimeoutFn(cb, interval, options = {}) {
|
|
445
|
+
const { immediate = true } = options;
|
|
446
|
+
const [pending, setPending] = useState(false);
|
|
447
|
+
const savedCallback = useLatest(cb);
|
|
448
|
+
const timer = useRef();
|
|
449
|
+
const stop = useEvent(() => {
|
|
450
|
+
setPending(false);
|
|
451
|
+
if (timer.current) {
|
|
452
|
+
clearTimeout(timer.current);
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
const start = useEvent((...args) => {
|
|
456
|
+
if (timer) {
|
|
457
|
+
clearTimeout(timer.current);
|
|
458
|
+
}
|
|
459
|
+
timer.current = setTimeout(() => {
|
|
460
|
+
setPending(false);
|
|
461
|
+
savedCallback.current(...args);
|
|
462
|
+
}, interval);
|
|
463
|
+
setPending(true);
|
|
464
|
+
});
|
|
465
|
+
useEffect(() => {
|
|
466
|
+
if (immediate) {
|
|
467
|
+
start();
|
|
468
|
+
}
|
|
469
|
+
return stop;
|
|
470
|
+
}, [stop, immediate, interval, start]);
|
|
471
|
+
return [pending, start, stop];
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function useTimeout(ms = 0, options = {}) {
|
|
475
|
+
const update = useUpdate();
|
|
476
|
+
return useTimeoutFn(update, ms, options);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function useMountedState() {
|
|
480
|
+
const mountedRef = useRef(false);
|
|
481
|
+
const get = useCallback(() => mountedRef.current, []);
|
|
482
|
+
useEffect(() => {
|
|
483
|
+
mountedRef.current = true;
|
|
484
|
+
return () => {
|
|
485
|
+
mountedRef.current = false;
|
|
486
|
+
};
|
|
487
|
+
}, []);
|
|
488
|
+
return get;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function on(obj, ...args) {
|
|
492
|
+
if (obj && obj.addEventListener) {
|
|
493
|
+
obj.addEventListener(
|
|
494
|
+
...args
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
function off(obj, ...args) {
|
|
499
|
+
if (obj && obj.removeEventListener) {
|
|
500
|
+
obj.removeEventListener(
|
|
501
|
+
...args
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function getTargetElement(target, defaultElement) {
|
|
507
|
+
if (!isBrowser) {
|
|
508
|
+
return void 0;
|
|
509
|
+
}
|
|
510
|
+
if (!target) {
|
|
511
|
+
return defaultElement;
|
|
512
|
+
}
|
|
513
|
+
let targetElement;
|
|
514
|
+
if (isFunction(target)) {
|
|
515
|
+
targetElement = target();
|
|
516
|
+
} else if ("current" in target) {
|
|
517
|
+
targetElement = target.current;
|
|
518
|
+
} else {
|
|
519
|
+
targetElement = target;
|
|
520
|
+
}
|
|
521
|
+
return targetElement;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
const isPrimitive$1 = (val) => val !== Object(val);
|
|
525
|
+
function useCustomCompareEffect(effect, deps, depsEqual) {
|
|
526
|
+
if (process.env.NODE_ENV !== "production") {
|
|
527
|
+
if (!(deps instanceof Array) || !deps.length) {
|
|
528
|
+
console.warn(
|
|
529
|
+
"`useCustomCompareEffect` should not be used with no dependencies. Use React.useEffect instead."
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
if (deps.every(isPrimitive$1)) {
|
|
533
|
+
console.warn(
|
|
534
|
+
"`useCustomCompareEffect` should not be used with dependencies that are all primitive values. Use React.useEffect instead."
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
if (typeof depsEqual !== "function") {
|
|
538
|
+
console.warn(
|
|
539
|
+
"`useCustomCompareEffect` should be used with depsEqual callback for comparing deps list"
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const ref = useRef(void 0);
|
|
544
|
+
if (!ref.current || !depsEqual(deps, ref.current)) {
|
|
545
|
+
ref.current = deps;
|
|
546
|
+
}
|
|
547
|
+
useEffect(effect, ref.current);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const isPrimitive = (val) => val !== Object(val);
|
|
551
|
+
function useDeepCompareEffect(effect, deps) {
|
|
552
|
+
if (process.env.NODE_ENV !== "production") {
|
|
553
|
+
if (!(deps instanceof Array) || !deps.length) {
|
|
554
|
+
console.warn(
|
|
555
|
+
"`useDeepCompareEffect` should not be used with no dependencies. Use React.useEffect instead."
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
if (deps.every(isPrimitive)) {
|
|
559
|
+
console.warn(
|
|
560
|
+
"`useDeepCompareEffect` should not be used with dependencies that are all primitive values. Use React.useEffect instead."
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
useCustomCompareEffect(effect, deps, isEqual);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function useEventListener(eventName, handler, element, options) {
|
|
568
|
+
const savedHandler = useLatest(handler);
|
|
569
|
+
useDeepCompareEffect(() => {
|
|
570
|
+
const targetElement = getTargetElement(element, window);
|
|
571
|
+
if (!(targetElement && targetElement.addEventListener)) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
const eventListener = (event) => savedHandler.current(event);
|
|
575
|
+
on(targetElement, eventName, eventListener, options);
|
|
576
|
+
return () => {
|
|
577
|
+
off(targetElement, eventName, eventListener);
|
|
578
|
+
};
|
|
579
|
+
}, [eventName, element, options, savedHandler]);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function useCounter(initialValue = 0, max = null, min = null) {
|
|
583
|
+
const initFunc = () => {
|
|
584
|
+
let init = typeof initialValue === "function" ? initialValue() : initialValue;
|
|
585
|
+
typeof init !== "number" && console.error(
|
|
586
|
+
"initialValue has to be a number, got " + typeof initialValue
|
|
587
|
+
);
|
|
588
|
+
if (typeof min === "number") {
|
|
589
|
+
init = Math.max(init, min);
|
|
590
|
+
} else if (min !== null) {
|
|
591
|
+
console.error("min has to be a number, got " + typeof min);
|
|
592
|
+
}
|
|
593
|
+
if (typeof max === "number") {
|
|
594
|
+
init = Math.min(init, max);
|
|
595
|
+
} else if (max !== null) {
|
|
596
|
+
console.error("max has to be a number, got " + typeof max);
|
|
597
|
+
}
|
|
598
|
+
return init;
|
|
599
|
+
};
|
|
600
|
+
const [value, setValue] = useState(initFunc);
|
|
601
|
+
const set = useEvent(
|
|
602
|
+
(newState) => {
|
|
603
|
+
setValue((v) => {
|
|
604
|
+
let nextValue = typeof newState === "function" ? newState(v) : newState;
|
|
605
|
+
if (typeof min === "number") {
|
|
606
|
+
nextValue = Math.max(nextValue, min);
|
|
607
|
+
}
|
|
608
|
+
if (typeof max === "number") {
|
|
609
|
+
nextValue = Math.min(nextValue, max);
|
|
610
|
+
}
|
|
611
|
+
return nextValue;
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
);
|
|
615
|
+
const inc = (delta = 1) => {
|
|
616
|
+
set((value2) => value2 + delta);
|
|
617
|
+
};
|
|
618
|
+
const dec = (delta = 1) => {
|
|
619
|
+
set((value2) => value2 - delta);
|
|
620
|
+
};
|
|
621
|
+
const reset = () => {
|
|
622
|
+
set(initFunc);
|
|
623
|
+
};
|
|
624
|
+
return [value, set, inc, dec, reset];
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
function useRafFn(callback, initiallyActive = true) {
|
|
628
|
+
const raf = useRef(null);
|
|
629
|
+
const rafActivity = useRef(false);
|
|
630
|
+
const rafCallback = useLatest(callback);
|
|
631
|
+
const step = useCallback(
|
|
632
|
+
(time) => {
|
|
633
|
+
if (rafActivity.current) {
|
|
634
|
+
rafCallback.current(time);
|
|
635
|
+
raf.current = requestAnimationFrame(step);
|
|
636
|
+
}
|
|
637
|
+
},
|
|
638
|
+
[rafCallback]
|
|
639
|
+
);
|
|
640
|
+
const result = useMemo(
|
|
641
|
+
() => [
|
|
642
|
+
() => {
|
|
643
|
+
if (rafActivity.current) {
|
|
644
|
+
rafActivity.current = false;
|
|
645
|
+
raf.current && cancelAnimationFrame(raf.current);
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
() => {
|
|
649
|
+
if (!rafActivity.current) {
|
|
650
|
+
rafActivity.current = true;
|
|
651
|
+
raf.current = requestAnimationFrame(step);
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
() => rafActivity.current
|
|
655
|
+
],
|
|
656
|
+
[step]
|
|
657
|
+
);
|
|
658
|
+
useEffect(() => {
|
|
659
|
+
if (initiallyActive) {
|
|
660
|
+
result[1]();
|
|
661
|
+
}
|
|
662
|
+
return result[0];
|
|
663
|
+
}, [initiallyActive, result]);
|
|
664
|
+
return result;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
function useEventEmitter() {
|
|
668
|
+
const listeners = useRef([]);
|
|
669
|
+
const _event = useRef((listener) => {
|
|
670
|
+
listeners.current.push(listener);
|
|
671
|
+
const disposable = {
|
|
672
|
+
dispose: () => {
|
|
673
|
+
if (!_disposed.current) {
|
|
674
|
+
for (let i = 0; i < listeners.current.length; i++) {
|
|
675
|
+
if (listeners.current[i] === listener) {
|
|
676
|
+
listeners.current.splice(i, 1);
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
return disposable;
|
|
684
|
+
});
|
|
685
|
+
const _disposed = useRef(false);
|
|
686
|
+
const fire = (arg1, arg2) => {
|
|
687
|
+
const queue = [];
|
|
688
|
+
for (let i = 0; i < listeners.current.length; i++) {
|
|
689
|
+
queue.push(listeners.current[i]);
|
|
690
|
+
}
|
|
691
|
+
for (let i = 0; i < queue.length; i++) {
|
|
692
|
+
queue[i].call(void 0, arg1, arg2);
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
const dispose = () => {
|
|
696
|
+
if (listeners.current.length !== 0) {
|
|
697
|
+
listeners.current.length = 0;
|
|
698
|
+
}
|
|
699
|
+
_disposed.current = true;
|
|
700
|
+
};
|
|
701
|
+
return [_event.current, fire, dispose];
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function useFavicon(href, baseUrl = "", rel = "icon") {
|
|
705
|
+
useEffect(() => {
|
|
706
|
+
const url = `${baseUrl}${href}`;
|
|
707
|
+
const element = document.head.querySelectorAll(
|
|
708
|
+
`link[rel*="${rel}"]`
|
|
709
|
+
);
|
|
710
|
+
element.forEach((el) => el.href = url);
|
|
711
|
+
if (element.length === 0) {
|
|
712
|
+
const link = document.createElement("link");
|
|
713
|
+
link.rel = rel;
|
|
714
|
+
link.href = url;
|
|
715
|
+
document.getElementsByTagName("head")[0].appendChild(link);
|
|
716
|
+
}
|
|
717
|
+
}, [baseUrl, href, rel]);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
function useMutationObserver(callback, target, options = {}) {
|
|
721
|
+
const callbackRef = useLatest(callback);
|
|
722
|
+
const observerRef = useRef();
|
|
723
|
+
const stop = useCallback(() => {
|
|
724
|
+
if (observerRef.current) {
|
|
725
|
+
observerRef.current.disconnect();
|
|
726
|
+
}
|
|
727
|
+
}, []);
|
|
728
|
+
useDeepCompareEffect(() => {
|
|
729
|
+
const element = getTargetElement(target);
|
|
730
|
+
if (!element) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
observerRef.current = new MutationObserver(callbackRef.current);
|
|
734
|
+
observerRef.current.observe(element, options);
|
|
735
|
+
return stop;
|
|
736
|
+
}, [options]);
|
|
737
|
+
return stop;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
function useTitle(title) {
|
|
741
|
+
useEffect(() => {
|
|
742
|
+
document.title = title;
|
|
743
|
+
}, [title]);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
function useScriptTag(src, onLoaded = noop, options = {}) {
|
|
747
|
+
const {
|
|
748
|
+
immediate = true,
|
|
749
|
+
manual = false,
|
|
750
|
+
type = "text/javascript",
|
|
751
|
+
async = true,
|
|
752
|
+
crossOrigin,
|
|
753
|
+
referrerPolicy,
|
|
754
|
+
noModule,
|
|
755
|
+
defer,
|
|
756
|
+
attrs = {}
|
|
757
|
+
} = options;
|
|
758
|
+
const scriptTag = useRef(null);
|
|
759
|
+
const _promise = useRef(null);
|
|
760
|
+
const [status, setStatus] = useState(src ? "loading" : "idle");
|
|
761
|
+
const loadScript = (waitForScriptLoad) => new Promise((resolve, reject) => {
|
|
762
|
+
const resolveWithElement = (el2) => {
|
|
763
|
+
scriptTag.current = el2;
|
|
764
|
+
resolve(el2);
|
|
765
|
+
return el2;
|
|
766
|
+
};
|
|
767
|
+
if (!document) {
|
|
768
|
+
resolve(false);
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
if (!src) {
|
|
772
|
+
setStatus("idle");
|
|
773
|
+
resolve(false);
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
let shouldAppend = false;
|
|
777
|
+
let el = document.querySelector(
|
|
778
|
+
`script[src="${src}"]`
|
|
779
|
+
);
|
|
780
|
+
if (!el) {
|
|
781
|
+
el = document.createElement("script");
|
|
782
|
+
el.type = type;
|
|
783
|
+
el.async = async;
|
|
784
|
+
el.src = src;
|
|
785
|
+
if (defer) {
|
|
786
|
+
el.defer = defer;
|
|
787
|
+
}
|
|
788
|
+
if (crossOrigin) {
|
|
789
|
+
el.crossOrigin = crossOrigin;
|
|
790
|
+
}
|
|
791
|
+
if (noModule) {
|
|
792
|
+
el.noModule = noModule;
|
|
793
|
+
}
|
|
794
|
+
if (referrerPolicy) {
|
|
795
|
+
el.referrerPolicy = referrerPolicy;
|
|
796
|
+
}
|
|
797
|
+
Object.entries(attrs).forEach(
|
|
798
|
+
([name, value]) => el == null ? void 0 : el.setAttribute(name, value)
|
|
799
|
+
);
|
|
800
|
+
shouldAppend = true;
|
|
801
|
+
} else if (el.hasAttribute("data-loaded")) {
|
|
802
|
+
setStatus(el.getAttribute("data-status"));
|
|
803
|
+
resolveWithElement(el);
|
|
804
|
+
}
|
|
805
|
+
el.addEventListener("error", (event) => {
|
|
806
|
+
setStatus(event.type === "load" ? "ready" : "error");
|
|
807
|
+
return reject(event);
|
|
808
|
+
});
|
|
809
|
+
el.addEventListener("abort", (event) => {
|
|
810
|
+
setStatus(event.type === "load" ? "ready" : "error");
|
|
811
|
+
return reject(event);
|
|
812
|
+
});
|
|
813
|
+
el.addEventListener("load", (event) => {
|
|
814
|
+
setStatus(event.type === "load" ? "ready" : "error");
|
|
815
|
+
el.setAttribute("data-loaded", "true");
|
|
816
|
+
onLoaded(el);
|
|
817
|
+
resolveWithElement(el);
|
|
818
|
+
});
|
|
819
|
+
if (shouldAppend) {
|
|
820
|
+
el = document.head.appendChild(el);
|
|
821
|
+
}
|
|
822
|
+
if (!waitForScriptLoad) {
|
|
823
|
+
resolveWithElement(el);
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
const load = (waitForScriptLoad = true) => {
|
|
827
|
+
if (!_promise.current) {
|
|
828
|
+
_promise.current = loadScript(waitForScriptLoad);
|
|
829
|
+
}
|
|
830
|
+
return _promise.current;
|
|
831
|
+
};
|
|
832
|
+
const unload = () => {
|
|
833
|
+
if (!document) {
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
_promise.current = null;
|
|
837
|
+
if (scriptTag.current) {
|
|
838
|
+
scriptTag.current = null;
|
|
839
|
+
}
|
|
840
|
+
const el = document.querySelector(
|
|
841
|
+
`script[src="${src}"]`
|
|
842
|
+
);
|
|
843
|
+
if (el) {
|
|
844
|
+
document.head.removeChild(el);
|
|
845
|
+
}
|
|
846
|
+
};
|
|
847
|
+
useMount(() => {
|
|
848
|
+
if (immediate && !manual) {
|
|
849
|
+
load();
|
|
850
|
+
}
|
|
851
|
+
});
|
|
852
|
+
useUnmount(() => {
|
|
853
|
+
if (!manual) {
|
|
854
|
+
unload();
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
return [scriptTag.current, status, load, unload];
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
function usePermission(permissionDesc) {
|
|
861
|
+
const [state, setState] = useState("");
|
|
862
|
+
useEffect(() => {
|
|
863
|
+
const desc = typeof permissionDesc === "string" ? { name: permissionDesc } : permissionDesc;
|
|
864
|
+
let mounted = true;
|
|
865
|
+
let permissionStatus = null;
|
|
866
|
+
const onChange = () => {
|
|
867
|
+
if (!mounted) {
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
setState(() => {
|
|
871
|
+
var _a;
|
|
872
|
+
return (_a = permissionStatus == null ? void 0 : permissionStatus.state) != null ? _a : "";
|
|
873
|
+
});
|
|
874
|
+
};
|
|
875
|
+
navigator.permissions.query(desc).then((status) => {
|
|
876
|
+
permissionStatus = status;
|
|
877
|
+
on(permissionStatus, "change", onChange);
|
|
878
|
+
onChange();
|
|
879
|
+
}).catch(noop);
|
|
880
|
+
return () => {
|
|
881
|
+
permissionStatus && off(permissionStatus, "change", onChange);
|
|
882
|
+
mounted = false;
|
|
883
|
+
permissionStatus = null;
|
|
884
|
+
};
|
|
885
|
+
}, [permissionDesc]);
|
|
886
|
+
return state;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
const isTouchEvent = (ev) => {
|
|
890
|
+
return "touches" in ev;
|
|
891
|
+
};
|
|
892
|
+
const preventDefault$1 = (ev) => {
|
|
893
|
+
if (!isTouchEvent(ev)) {
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
if (ev.touches.length < 2 && ev.preventDefault) {
|
|
897
|
+
ev.preventDefault();
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
function useLongPress(callback, { isPreventDefault = true, delay = 300 } = {}) {
|
|
901
|
+
const timeout = useRef();
|
|
902
|
+
const target = useRef();
|
|
903
|
+
const start = useCallback(
|
|
904
|
+
(event) => {
|
|
905
|
+
if (isPreventDefault && event.target) {
|
|
906
|
+
on(event.target, "touchend", preventDefault$1, { passive: false });
|
|
907
|
+
target.current = event.target;
|
|
908
|
+
}
|
|
909
|
+
timeout.current = setTimeout(() => callback(event), delay);
|
|
910
|
+
},
|
|
911
|
+
[callback, delay, isPreventDefault]
|
|
912
|
+
);
|
|
913
|
+
const clear = useCallback(() => {
|
|
914
|
+
timeout.current && clearTimeout(timeout.current);
|
|
915
|
+
if (isPreventDefault && target.current) {
|
|
916
|
+
off(target.current, "touchend", preventDefault$1);
|
|
917
|
+
}
|
|
918
|
+
}, [isPreventDefault]);
|
|
919
|
+
return {
|
|
920
|
+
onMouseDown: (e) => start(e),
|
|
921
|
+
onTouchStart: (e) => start(e),
|
|
922
|
+
onMouseUp: clear,
|
|
923
|
+
onMouseLeave: clear,
|
|
924
|
+
onTouchEnd: clear
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
function useObjectUrl(object) {
|
|
929
|
+
const [url, setUrl] = useState();
|
|
930
|
+
useEffect(() => {
|
|
931
|
+
if (object) {
|
|
932
|
+
setUrl(URL.createObjectURL(object));
|
|
933
|
+
}
|
|
934
|
+
return () => {
|
|
935
|
+
if (url) {
|
|
936
|
+
URL.revokeObjectURL(url);
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
}, [object]);
|
|
940
|
+
return url;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
const defaultEvents$1 = [
|
|
944
|
+
"mousemove",
|
|
945
|
+
"mousedown",
|
|
946
|
+
"resize",
|
|
947
|
+
"keydown",
|
|
948
|
+
"touchstart",
|
|
949
|
+
"wheel"
|
|
950
|
+
];
|
|
951
|
+
const oneMinute = 6e4;
|
|
952
|
+
function useIdle(ms = oneMinute, initialState = false, events = defaultEvents$1) {
|
|
953
|
+
const [state, setState] = useState(initialState);
|
|
954
|
+
useEffect(() => {
|
|
955
|
+
let mounted = true;
|
|
956
|
+
let timeout;
|
|
957
|
+
let localState = state;
|
|
958
|
+
const set = (newState) => {
|
|
959
|
+
if (mounted) {
|
|
960
|
+
localState = newState;
|
|
961
|
+
setState(newState);
|
|
962
|
+
}
|
|
963
|
+
};
|
|
964
|
+
const onEvent = throttle(() => {
|
|
965
|
+
if (localState) {
|
|
966
|
+
set(false);
|
|
967
|
+
}
|
|
968
|
+
clearTimeout(timeout);
|
|
969
|
+
timeout = setTimeout(() => set(true), ms);
|
|
970
|
+
}, 50);
|
|
971
|
+
const onVisibility = () => {
|
|
972
|
+
if (!document.hidden) {
|
|
973
|
+
onEvent();
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
for (let i = 0; i < events.length; i++) {
|
|
977
|
+
on(window, events[i], onEvent);
|
|
978
|
+
}
|
|
979
|
+
on(document, "visibilitychange", onVisibility);
|
|
980
|
+
timeout = setTimeout(() => set(true), ms);
|
|
981
|
+
return () => {
|
|
982
|
+
mounted = false;
|
|
983
|
+
for (let i = 0; i < events.length; i++) {
|
|
984
|
+
off(window, events[i], onEvent);
|
|
985
|
+
}
|
|
986
|
+
off(document, "visibilitychange", onVisibility);
|
|
987
|
+
};
|
|
988
|
+
}, [ms, events]);
|
|
989
|
+
return state;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
function useMediaDevices() {
|
|
993
|
+
const [state, setState] = useState({ devices: [] });
|
|
994
|
+
useEffect(() => {
|
|
995
|
+
let mounted = true;
|
|
996
|
+
const onChange = () => {
|
|
997
|
+
navigator.mediaDevices.enumerateDevices().then((devices) => {
|
|
998
|
+
if (mounted) {
|
|
999
|
+
setState({
|
|
1000
|
+
devices: devices.map(({ deviceId, groupId, kind, label }) => ({
|
|
1001
|
+
deviceId,
|
|
1002
|
+
groupId,
|
|
1003
|
+
kind,
|
|
1004
|
+
label
|
|
1005
|
+
}))
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
1008
|
+
}).catch(noop);
|
|
1009
|
+
};
|
|
1010
|
+
on(navigator.mediaDevices, "devicechange", onChange);
|
|
1011
|
+
onChange();
|
|
1012
|
+
return () => {
|
|
1013
|
+
mounted = false;
|
|
1014
|
+
off(navigator.mediaDevices, "devicechange", onChange);
|
|
1015
|
+
};
|
|
1016
|
+
}, []);
|
|
1017
|
+
return state;
|
|
1018
|
+
}
|
|
1019
|
+
const useMediaDevicesMock = () => ({});
|
|
1020
|
+
var useMediaDevices$1 = isNavigator && !!navigator.mediaDevices ? useMediaDevices : useMediaDevicesMock;
|
|
1021
|
+
|
|
1022
|
+
function useTextDirection(options = {}) {
|
|
1023
|
+
const { selector = "html", initialValue = "ltr" } = options;
|
|
1024
|
+
const getValue = () => {
|
|
1025
|
+
var _a, _b;
|
|
1026
|
+
if (isBrowser) {
|
|
1027
|
+
return (_b = (_a = document == null ? void 0 : document.querySelector(selector)) == null ? void 0 : _a.getAttribute("dir")) != null ? _b : initialValue;
|
|
1028
|
+
} else {
|
|
1029
|
+
return initialValue;
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
const [value, setValue] = useState(getValue());
|
|
1033
|
+
const set = (value2) => {
|
|
1034
|
+
var _a, _b;
|
|
1035
|
+
if (!isBrowser) {
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
if (value2 !== null) {
|
|
1039
|
+
(_a = document.querySelector(selector)) == null ? void 0 : _a.setAttribute("dir", value2);
|
|
1040
|
+
} else {
|
|
1041
|
+
(_b = document.querySelector(selector)) == null ? void 0 : _b.removeAttribute("dir");
|
|
1042
|
+
}
|
|
1043
|
+
setValue(value2);
|
|
1044
|
+
};
|
|
1045
|
+
return [value, set];
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
const initState = {
|
|
1049
|
+
screenX: NaN,
|
|
1050
|
+
screenY: NaN,
|
|
1051
|
+
clientX: NaN,
|
|
1052
|
+
clientY: NaN,
|
|
1053
|
+
pageX: NaN,
|
|
1054
|
+
pageY: NaN,
|
|
1055
|
+
elementX: NaN,
|
|
1056
|
+
elementY: NaN,
|
|
1057
|
+
elementH: NaN,
|
|
1058
|
+
elementW: NaN,
|
|
1059
|
+
elementPosX: NaN,
|
|
1060
|
+
elementPosY: NaN
|
|
1061
|
+
};
|
|
1062
|
+
function useMouse(target) {
|
|
1063
|
+
const [state, setState] = useRafState(initState);
|
|
1064
|
+
useEventListener(
|
|
1065
|
+
"mousemove",
|
|
1066
|
+
(event) => {
|
|
1067
|
+
const { screenX, screenY, clientX, clientY, pageX, pageY } = event;
|
|
1068
|
+
const newState = {
|
|
1069
|
+
screenX,
|
|
1070
|
+
screenY,
|
|
1071
|
+
clientX,
|
|
1072
|
+
clientY,
|
|
1073
|
+
pageX,
|
|
1074
|
+
pageY,
|
|
1075
|
+
elementX: NaN,
|
|
1076
|
+
elementY: NaN,
|
|
1077
|
+
elementH: NaN,
|
|
1078
|
+
elementW: NaN,
|
|
1079
|
+
elementPosX: NaN,
|
|
1080
|
+
elementPosY: NaN
|
|
1081
|
+
};
|
|
1082
|
+
const targetElement = getTargetElement(target);
|
|
1083
|
+
if (targetElement) {
|
|
1084
|
+
const { left, top, width, height } = targetElement.getBoundingClientRect();
|
|
1085
|
+
newState.elementPosX = left + window.pageXOffset;
|
|
1086
|
+
newState.elementPosY = top + window.pageYOffset;
|
|
1087
|
+
newState.elementX = pageX - newState.elementPosX;
|
|
1088
|
+
newState.elementY = pageY - newState.elementPosY;
|
|
1089
|
+
newState.elementW = width;
|
|
1090
|
+
newState.elementH = height;
|
|
1091
|
+
}
|
|
1092
|
+
setState(newState);
|
|
1093
|
+
},
|
|
1094
|
+
() => document
|
|
1095
|
+
);
|
|
1096
|
+
return state;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
function useFps(options) {
|
|
1100
|
+
var _a;
|
|
1101
|
+
const [fps, setFps] = useState(0);
|
|
1102
|
+
const every = (_a = options == null ? void 0 : options.every) != null ? _a : 10;
|
|
1103
|
+
const last = useRef(performance.now());
|
|
1104
|
+
const ticks = useRef(0);
|
|
1105
|
+
useRafFn(() => {
|
|
1106
|
+
ticks.current += 1;
|
|
1107
|
+
if (ticks.current >= every) {
|
|
1108
|
+
const now = performance.now();
|
|
1109
|
+
const diff = now - last.current;
|
|
1110
|
+
setFps(Math.round(1e3 / (diff / ticks.current)));
|
|
1111
|
+
last.current = now;
|
|
1112
|
+
ticks.current = 0;
|
|
1113
|
+
}
|
|
1114
|
+
});
|
|
1115
|
+
return fps;
|
|
1116
|
+
}
|
|
1117
|
+
const useFpsMock = (options) => 0;
|
|
1118
|
+
var useFps$1 = typeof performance === "undefined" ? useFpsMock : useFps;
|
|
1119
|
+
|
|
1120
|
+
const initCoord = {
|
|
1121
|
+
accuracy: 0,
|
|
1122
|
+
latitude: Infinity,
|
|
1123
|
+
longitude: Infinity,
|
|
1124
|
+
altitude: null,
|
|
1125
|
+
altitudeAccuracy: null,
|
|
1126
|
+
heading: null,
|
|
1127
|
+
speed: null
|
|
1128
|
+
};
|
|
1129
|
+
function useGeolocation(options = {}) {
|
|
1130
|
+
const {
|
|
1131
|
+
enableHighAccuracy = true,
|
|
1132
|
+
maximumAge = 3e4,
|
|
1133
|
+
timeout = 27e3
|
|
1134
|
+
} = options;
|
|
1135
|
+
const [coordinates, setCoordinates] = useState(initCoord);
|
|
1136
|
+
const [locatedAt, setLocatedAt] = useState(null);
|
|
1137
|
+
const [error, setError] = useState(null);
|
|
1138
|
+
const updatePosition = useCallback((position) => {
|
|
1139
|
+
setCoordinates(position.coords);
|
|
1140
|
+
setLocatedAt(position.timestamp);
|
|
1141
|
+
setError(null);
|
|
1142
|
+
}, []);
|
|
1143
|
+
const updateError = useCallback((err) => {
|
|
1144
|
+
setCoordinates(initCoord);
|
|
1145
|
+
setLocatedAt(null);
|
|
1146
|
+
setError(err);
|
|
1147
|
+
}, []);
|
|
1148
|
+
useEffect(() => {
|
|
1149
|
+
navigator.geolocation.getCurrentPosition(updatePosition, updateError);
|
|
1150
|
+
const watchId = navigator.geolocation.watchPosition(
|
|
1151
|
+
updatePosition,
|
|
1152
|
+
updateError,
|
|
1153
|
+
{
|
|
1154
|
+
enableHighAccuracy,
|
|
1155
|
+
maximumAge,
|
|
1156
|
+
timeout
|
|
1157
|
+
}
|
|
1158
|
+
);
|
|
1159
|
+
return () => {
|
|
1160
|
+
if (watchId) {
|
|
1161
|
+
navigator.geolocation.clearWatch(watchId);
|
|
1162
|
+
}
|
|
1163
|
+
};
|
|
1164
|
+
}, [enableHighAccuracy, maximumAge, timeout, updateError, updatePosition]);
|
|
1165
|
+
return {
|
|
1166
|
+
coordinates,
|
|
1167
|
+
locatedAt,
|
|
1168
|
+
error
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
var screenfull$1 = {exports: {}};
|
|
1173
|
+
|
|
1174
|
+
/*!
|
|
1175
|
+
* screenfull
|
|
1176
|
+
* v5.2.0 - 2021-11-03
|
|
1177
|
+
* (c) Sindre Sorhus; MIT License
|
|
1178
|
+
*/
|
|
1179
|
+
|
|
1180
|
+
(function (module) {
|
|
1181
|
+
(function () {
|
|
1182
|
+
|
|
1183
|
+
var document = typeof window !== 'undefined' && typeof window.document !== 'undefined' ? window.document : {};
|
|
1184
|
+
var isCommonjs = module.exports;
|
|
1185
|
+
|
|
1186
|
+
var fn = (function () {
|
|
1187
|
+
var val;
|
|
1188
|
+
|
|
1189
|
+
var fnMap = [
|
|
1190
|
+
[
|
|
1191
|
+
'requestFullscreen',
|
|
1192
|
+
'exitFullscreen',
|
|
1193
|
+
'fullscreenElement',
|
|
1194
|
+
'fullscreenEnabled',
|
|
1195
|
+
'fullscreenchange',
|
|
1196
|
+
'fullscreenerror'
|
|
1197
|
+
],
|
|
1198
|
+
// New WebKit
|
|
1199
|
+
[
|
|
1200
|
+
'webkitRequestFullscreen',
|
|
1201
|
+
'webkitExitFullscreen',
|
|
1202
|
+
'webkitFullscreenElement',
|
|
1203
|
+
'webkitFullscreenEnabled',
|
|
1204
|
+
'webkitfullscreenchange',
|
|
1205
|
+
'webkitfullscreenerror'
|
|
1206
|
+
|
|
1207
|
+
],
|
|
1208
|
+
// Old WebKit
|
|
1209
|
+
[
|
|
1210
|
+
'webkitRequestFullScreen',
|
|
1211
|
+
'webkitCancelFullScreen',
|
|
1212
|
+
'webkitCurrentFullScreenElement',
|
|
1213
|
+
'webkitCancelFullScreen',
|
|
1214
|
+
'webkitfullscreenchange',
|
|
1215
|
+
'webkitfullscreenerror'
|
|
1216
|
+
|
|
1217
|
+
],
|
|
1218
|
+
[
|
|
1219
|
+
'mozRequestFullScreen',
|
|
1220
|
+
'mozCancelFullScreen',
|
|
1221
|
+
'mozFullScreenElement',
|
|
1222
|
+
'mozFullScreenEnabled',
|
|
1223
|
+
'mozfullscreenchange',
|
|
1224
|
+
'mozfullscreenerror'
|
|
1225
|
+
],
|
|
1226
|
+
[
|
|
1227
|
+
'msRequestFullscreen',
|
|
1228
|
+
'msExitFullscreen',
|
|
1229
|
+
'msFullscreenElement',
|
|
1230
|
+
'msFullscreenEnabled',
|
|
1231
|
+
'MSFullscreenChange',
|
|
1232
|
+
'MSFullscreenError'
|
|
1233
|
+
]
|
|
1234
|
+
];
|
|
1235
|
+
|
|
1236
|
+
var i = 0;
|
|
1237
|
+
var l = fnMap.length;
|
|
1238
|
+
var ret = {};
|
|
1239
|
+
|
|
1240
|
+
for (; i < l; i++) {
|
|
1241
|
+
val = fnMap[i];
|
|
1242
|
+
if (val && val[1] in document) {
|
|
1243
|
+
for (i = 0; i < val.length; i++) {
|
|
1244
|
+
ret[fnMap[0][i]] = val[i];
|
|
1245
|
+
}
|
|
1246
|
+
return ret;
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
return false;
|
|
1251
|
+
})();
|
|
1252
|
+
|
|
1253
|
+
var eventNameMap = {
|
|
1254
|
+
change: fn.fullscreenchange,
|
|
1255
|
+
error: fn.fullscreenerror
|
|
1256
|
+
};
|
|
1257
|
+
|
|
1258
|
+
var screenfull = {
|
|
1259
|
+
request: function (element, options) {
|
|
1260
|
+
return new Promise(function (resolve, reject) {
|
|
1261
|
+
var onFullScreenEntered = function () {
|
|
1262
|
+
this.off('change', onFullScreenEntered);
|
|
1263
|
+
resolve();
|
|
1264
|
+
}.bind(this);
|
|
1265
|
+
|
|
1266
|
+
this.on('change', onFullScreenEntered);
|
|
1267
|
+
|
|
1268
|
+
element = element || document.documentElement;
|
|
1269
|
+
|
|
1270
|
+
var returnPromise = element[fn.requestFullscreen](options);
|
|
1271
|
+
|
|
1272
|
+
if (returnPromise instanceof Promise) {
|
|
1273
|
+
returnPromise.then(onFullScreenEntered).catch(reject);
|
|
1274
|
+
}
|
|
1275
|
+
}.bind(this));
|
|
1276
|
+
},
|
|
1277
|
+
exit: function () {
|
|
1278
|
+
return new Promise(function (resolve, reject) {
|
|
1279
|
+
if (!this.isFullscreen) {
|
|
1280
|
+
resolve();
|
|
1281
|
+
return;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
var onFullScreenExit = function () {
|
|
1285
|
+
this.off('change', onFullScreenExit);
|
|
1286
|
+
resolve();
|
|
1287
|
+
}.bind(this);
|
|
1288
|
+
|
|
1289
|
+
this.on('change', onFullScreenExit);
|
|
1290
|
+
|
|
1291
|
+
var returnPromise = document[fn.exitFullscreen]();
|
|
1292
|
+
|
|
1293
|
+
if (returnPromise instanceof Promise) {
|
|
1294
|
+
returnPromise.then(onFullScreenExit).catch(reject);
|
|
1295
|
+
}
|
|
1296
|
+
}.bind(this));
|
|
1297
|
+
},
|
|
1298
|
+
toggle: function (element, options) {
|
|
1299
|
+
return this.isFullscreen ? this.exit() : this.request(element, options);
|
|
1300
|
+
},
|
|
1301
|
+
onchange: function (callback) {
|
|
1302
|
+
this.on('change', callback);
|
|
1303
|
+
},
|
|
1304
|
+
onerror: function (callback) {
|
|
1305
|
+
this.on('error', callback);
|
|
1306
|
+
},
|
|
1307
|
+
on: function (event, callback) {
|
|
1308
|
+
var eventName = eventNameMap[event];
|
|
1309
|
+
if (eventName) {
|
|
1310
|
+
document.addEventListener(eventName, callback, false);
|
|
1311
|
+
}
|
|
1312
|
+
},
|
|
1313
|
+
off: function (event, callback) {
|
|
1314
|
+
var eventName = eventNameMap[event];
|
|
1315
|
+
if (eventName) {
|
|
1316
|
+
document.removeEventListener(eventName, callback, false);
|
|
1317
|
+
}
|
|
1318
|
+
},
|
|
1319
|
+
raw: fn
|
|
1320
|
+
};
|
|
1321
|
+
|
|
1322
|
+
if (!fn) {
|
|
1323
|
+
if (isCommonjs) {
|
|
1324
|
+
module.exports = {isEnabled: false};
|
|
1325
|
+
} else {
|
|
1326
|
+
window.screenfull = {isEnabled: false};
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
Object.defineProperties(screenfull, {
|
|
1333
|
+
isFullscreen: {
|
|
1334
|
+
get: function () {
|
|
1335
|
+
return Boolean(document[fn.fullscreenElement]);
|
|
1336
|
+
}
|
|
1337
|
+
},
|
|
1338
|
+
element: {
|
|
1339
|
+
enumerable: true,
|
|
1340
|
+
get: function () {
|
|
1341
|
+
return document[fn.fullscreenElement];
|
|
1342
|
+
}
|
|
1343
|
+
},
|
|
1344
|
+
isEnabled: {
|
|
1345
|
+
enumerable: true,
|
|
1346
|
+
get: function () {
|
|
1347
|
+
// Coerce to boolean in case of old WebKit
|
|
1348
|
+
return Boolean(document[fn.fullscreenEnabled]);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
});
|
|
1352
|
+
|
|
1353
|
+
if (isCommonjs) {
|
|
1354
|
+
module.exports = screenfull;
|
|
1355
|
+
} else {
|
|
1356
|
+
window.screenfull = screenfull;
|
|
1357
|
+
}
|
|
1358
|
+
})();
|
|
1359
|
+
} (screenfull$1));
|
|
1360
|
+
|
|
1361
|
+
var screenfull = screenfull$1.exports;
|
|
1362
|
+
|
|
1363
|
+
function useFullscreen(target, options) {
|
|
1364
|
+
const { onExit, onEnter } = options || {};
|
|
1365
|
+
const onExitRef = useLatest(onExit);
|
|
1366
|
+
const onEnterRef = useLatest(onEnter);
|
|
1367
|
+
const [state, setState] = useState(false);
|
|
1368
|
+
const onChange = () => {
|
|
1369
|
+
var _a, _b;
|
|
1370
|
+
if (screenfull.isEnabled) {
|
|
1371
|
+
const { isFullscreen } = screenfull;
|
|
1372
|
+
if (isFullscreen) {
|
|
1373
|
+
(_a = onEnterRef.current) == null ? void 0 : _a.call(onEnterRef);
|
|
1374
|
+
} else {
|
|
1375
|
+
screenfull.off("change", onChange);
|
|
1376
|
+
(_b = onExitRef.current) == null ? void 0 : _b.call(onExitRef);
|
|
1377
|
+
}
|
|
1378
|
+
setState(isFullscreen);
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
const enterFullscreen = () => {
|
|
1382
|
+
const el = getTargetElement(target);
|
|
1383
|
+
if (!el) {
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
if (screenfull.isEnabled) {
|
|
1387
|
+
try {
|
|
1388
|
+
screenfull.request(el);
|
|
1389
|
+
screenfull.on("change", onChange);
|
|
1390
|
+
} catch (error) {
|
|
1391
|
+
console.error(error);
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
const exitFullscreen = () => {
|
|
1396
|
+
if (screenfull.isEnabled) {
|
|
1397
|
+
screenfull.exit();
|
|
1398
|
+
}
|
|
1399
|
+
};
|
|
1400
|
+
const toggleFullscreen = () => {
|
|
1401
|
+
if (state) {
|
|
1402
|
+
exitFullscreen();
|
|
1403
|
+
} else {
|
|
1404
|
+
enterFullscreen();
|
|
1405
|
+
}
|
|
1406
|
+
};
|
|
1407
|
+
useUnmount(() => {
|
|
1408
|
+
if (screenfull.isEnabled) {
|
|
1409
|
+
screenfull.off("change", onChange);
|
|
1410
|
+
}
|
|
1411
|
+
});
|
|
1412
|
+
return [
|
|
1413
|
+
state,
|
|
1414
|
+
{
|
|
1415
|
+
enterFullscreen: useEvent(enterFullscreen),
|
|
1416
|
+
exitFullscreen: useEvent(exitFullscreen),
|
|
1417
|
+
toggleFullscreen: useEvent(toggleFullscreen),
|
|
1418
|
+
isEnabled: screenfull.isEnabled
|
|
1419
|
+
}
|
|
1420
|
+
];
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
const nav = isNavigator ? navigator : void 0;
|
|
1424
|
+
const conn = nav && (nav.connection || nav.mozConnection || nav.webkitConnection);
|
|
1425
|
+
function getConnectionState(previousState) {
|
|
1426
|
+
const online = nav == null ? void 0 : nav.onLine;
|
|
1427
|
+
const previousOnline = previousState == null ? void 0 : previousState.online;
|
|
1428
|
+
return {
|
|
1429
|
+
online,
|
|
1430
|
+
previous: previousOnline,
|
|
1431
|
+
since: online !== previousOnline ? new Date() : previousState == null ? void 0 : previousState.since,
|
|
1432
|
+
downlink: conn == null ? void 0 : conn.downlink,
|
|
1433
|
+
downlinkMax: conn == null ? void 0 : conn.downlinkMax,
|
|
1434
|
+
effectiveType: conn == null ? void 0 : conn.effectiveType,
|
|
1435
|
+
rtt: conn == null ? void 0 : conn.rtt,
|
|
1436
|
+
saveData: conn == null ? void 0 : conn.saveData,
|
|
1437
|
+
type: conn == null ? void 0 : conn.type
|
|
1438
|
+
};
|
|
1439
|
+
}
|
|
1440
|
+
function useNetwork() {
|
|
1441
|
+
const [state, setState] = useState(getConnectionState);
|
|
1442
|
+
useEffect(() => {
|
|
1443
|
+
const handleStateChange = () => {
|
|
1444
|
+
setState(getConnectionState);
|
|
1445
|
+
};
|
|
1446
|
+
on(window, "online", handleStateChange, { passive: true });
|
|
1447
|
+
on(window, "offline", handleStateChange, { passive: true });
|
|
1448
|
+
if (conn) {
|
|
1449
|
+
on(conn, "change", handleStateChange, { passive: true });
|
|
1450
|
+
}
|
|
1451
|
+
return () => {
|
|
1452
|
+
off(window, "online", handleStateChange);
|
|
1453
|
+
off(window, "offline", handleStateChange);
|
|
1454
|
+
if (conn) {
|
|
1455
|
+
off(conn, "change", handleStateChange);
|
|
1456
|
+
}
|
|
1457
|
+
};
|
|
1458
|
+
}, []);
|
|
1459
|
+
return state;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
function useOnline() {
|
|
1463
|
+
const { online } = useNetwork();
|
|
1464
|
+
return online;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
const defaultState = {
|
|
1468
|
+
angle: 0,
|
|
1469
|
+
type: "landscape-primary"
|
|
1470
|
+
};
|
|
1471
|
+
function useOrientation(initialState = defaultState) {
|
|
1472
|
+
const [state, setState] = useState(initialState);
|
|
1473
|
+
useEffect(() => {
|
|
1474
|
+
const screen = window.screen;
|
|
1475
|
+
let mounted = true;
|
|
1476
|
+
const onChange = () => {
|
|
1477
|
+
if (mounted) {
|
|
1478
|
+
const { orientation } = screen;
|
|
1479
|
+
if (orientation) {
|
|
1480
|
+
const { angle, type } = orientation;
|
|
1481
|
+
setState({ angle, type });
|
|
1482
|
+
} else if (window.orientation !== void 0) {
|
|
1483
|
+
setState({
|
|
1484
|
+
angle: typeof window.orientation === "number" ? window.orientation : 0,
|
|
1485
|
+
type: ""
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
on(window, "orientationchange", onChange);
|
|
1491
|
+
onChange();
|
|
1492
|
+
return () => {
|
|
1493
|
+
mounted = false;
|
|
1494
|
+
off(window, "orientationchange", onChange);
|
|
1495
|
+
};
|
|
1496
|
+
}, []);
|
|
1497
|
+
const lockOrientation = (type) => {
|
|
1498
|
+
if (isBrowser) {
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
if (!(window && "screen" in window && "orientation" in window.screen)) {
|
|
1502
|
+
return Promise.reject(new Error("Not supported"));
|
|
1503
|
+
}
|
|
1504
|
+
return window.screen.orientation.lock(type);
|
|
1505
|
+
};
|
|
1506
|
+
const unlockOrientation = () => {
|
|
1507
|
+
if (isBrowser) {
|
|
1508
|
+
return;
|
|
1509
|
+
}
|
|
1510
|
+
if (!(window && "screen" in window && "orientation" in window.screen)) {
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
return window.screen.orientation.unlock();
|
|
1514
|
+
};
|
|
1515
|
+
return [state, lockOrientation, unlockOrientation];
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
function useIntersectionObserver(target, callback, options = {}) {
|
|
1519
|
+
const savedCallback = useLatest(callback);
|
|
1520
|
+
const observerRef = useRef();
|
|
1521
|
+
const stop = useCallback(() => {
|
|
1522
|
+
if (observerRef.current) {
|
|
1523
|
+
observerRef.current.disconnect();
|
|
1524
|
+
}
|
|
1525
|
+
}, []);
|
|
1526
|
+
useDeepCompareEffect(() => {
|
|
1527
|
+
const element = getTargetElement(target);
|
|
1528
|
+
if (!element) {
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
observerRef.current = new IntersectionObserver(
|
|
1532
|
+
savedCallback.current,
|
|
1533
|
+
options
|
|
1534
|
+
);
|
|
1535
|
+
observerRef.current.observe(element);
|
|
1536
|
+
return stop;
|
|
1537
|
+
}, [options]);
|
|
1538
|
+
return stop;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
function usePageLeave() {
|
|
1542
|
+
const [isLeft, setIsLeft] = useState(false);
|
|
1543
|
+
const handler = (event) => {
|
|
1544
|
+
if (!window)
|
|
1545
|
+
return;
|
|
1546
|
+
event = event || window.event;
|
|
1547
|
+
const from = event.relatedTarget || event.toElement;
|
|
1548
|
+
setIsLeft(!from);
|
|
1549
|
+
};
|
|
1550
|
+
useEventListener("mouseout", handler, window, { passive: true });
|
|
1551
|
+
useEventListener("mouseleave", handler, document, { passive: true });
|
|
1552
|
+
useEventListener("mouseenter", handler, document, { passive: true });
|
|
1553
|
+
return isLeft;
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
function useDocumentVisibility() {
|
|
1557
|
+
const [visible, setVisible] = useState(() => {
|
|
1558
|
+
if (!document) {
|
|
1559
|
+
return "visible";
|
|
1560
|
+
} else {
|
|
1561
|
+
return document.visibilityState;
|
|
1562
|
+
}
|
|
1563
|
+
});
|
|
1564
|
+
useEventListener(
|
|
1565
|
+
"visibilitychange",
|
|
1566
|
+
() => {
|
|
1567
|
+
setVisible(document.visibilityState);
|
|
1568
|
+
},
|
|
1569
|
+
document
|
|
1570
|
+
);
|
|
1571
|
+
return visible;
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
function useResizeObserver(target, callback, options = {}) {
|
|
1575
|
+
const savedCallback = useLatest(callback);
|
|
1576
|
+
const observerRef = useRef();
|
|
1577
|
+
const stop = useCallback(() => {
|
|
1578
|
+
if (observerRef.current) {
|
|
1579
|
+
observerRef.current.disconnect();
|
|
1580
|
+
}
|
|
1581
|
+
}, []);
|
|
1582
|
+
useDeepCompareEffect(() => {
|
|
1583
|
+
const element = getTargetElement(target);
|
|
1584
|
+
if (!element) {
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
observerRef.current = new ResizeObserver(savedCallback.current);
|
|
1588
|
+
observerRef.current.observe(element, options);
|
|
1589
|
+
return stop;
|
|
1590
|
+
}, [options]);
|
|
1591
|
+
return stop;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
function useDropZone(target, onDrop) {
|
|
1595
|
+
const [over, setOver] = useState(false);
|
|
1596
|
+
const counter = useRef(0);
|
|
1597
|
+
const element = getTargetElement(target);
|
|
1598
|
+
useEventListener(
|
|
1599
|
+
"dragenter",
|
|
1600
|
+
(event) => {
|
|
1601
|
+
event.preventDefault();
|
|
1602
|
+
counter.current += 1;
|
|
1603
|
+
setOver(true);
|
|
1604
|
+
},
|
|
1605
|
+
element
|
|
1606
|
+
);
|
|
1607
|
+
useEventListener(
|
|
1608
|
+
"dragover",
|
|
1609
|
+
(event) => {
|
|
1610
|
+
event.preventDefault();
|
|
1611
|
+
},
|
|
1612
|
+
element
|
|
1613
|
+
);
|
|
1614
|
+
useEventListener(
|
|
1615
|
+
"dragleave",
|
|
1616
|
+
(event) => {
|
|
1617
|
+
event.preventDefault();
|
|
1618
|
+
counter.current -= 1;
|
|
1619
|
+
if (counter.current === 0) {
|
|
1620
|
+
setOver(false);
|
|
1621
|
+
}
|
|
1622
|
+
},
|
|
1623
|
+
element
|
|
1624
|
+
);
|
|
1625
|
+
useEventListener(
|
|
1626
|
+
"drop",
|
|
1627
|
+
(event) => {
|
|
1628
|
+
var _a, _b;
|
|
1629
|
+
event.preventDefault();
|
|
1630
|
+
counter.current = 0;
|
|
1631
|
+
setOver(false);
|
|
1632
|
+
const files = Array.from((_b = (_a = event.dataTransfer) == null ? void 0 : _a.files) != null ? _b : []);
|
|
1633
|
+
onDrop == null ? void 0 : onDrop(files.length === 0 ? null : files);
|
|
1634
|
+
},
|
|
1635
|
+
element
|
|
1636
|
+
);
|
|
1637
|
+
return over;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
var __defProp$1 = Object.defineProperty;
|
|
1641
|
+
var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
|
|
1642
|
+
var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
|
|
1643
|
+
var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
|
|
1644
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1645
|
+
var __spreadValues$1 = (a, b) => {
|
|
1646
|
+
for (var prop in b || (b = {}))
|
|
1647
|
+
if (__hasOwnProp$1.call(b, prop))
|
|
1648
|
+
__defNormalProp$1(a, prop, b[prop]);
|
|
1649
|
+
if (__getOwnPropSymbols$1)
|
|
1650
|
+
for (var prop of __getOwnPropSymbols$1(b)) {
|
|
1651
|
+
if (__propIsEnum$1.call(b, prop))
|
|
1652
|
+
__defNormalProp$1(a, prop, b[prop]);
|
|
1653
|
+
}
|
|
1654
|
+
return a;
|
|
1655
|
+
};
|
|
1656
|
+
const DEFAULT_OPTIONS = {
|
|
1657
|
+
multiple: true,
|
|
1658
|
+
accept: "*"
|
|
1659
|
+
};
|
|
1660
|
+
function useFileDialog(options = {}) {
|
|
1661
|
+
const [files, setFiles] = useState(null);
|
|
1662
|
+
const inputRef = useRef();
|
|
1663
|
+
const initFn = useCallback(() => {
|
|
1664
|
+
if (!document) {
|
|
1665
|
+
return void 0;
|
|
1666
|
+
}
|
|
1667
|
+
const input = document.createElement("input");
|
|
1668
|
+
input.type = "file";
|
|
1669
|
+
input.onchange = (event) => {
|
|
1670
|
+
const result = event.target;
|
|
1671
|
+
setFiles(result.files);
|
|
1672
|
+
};
|
|
1673
|
+
return input;
|
|
1674
|
+
}, []);
|
|
1675
|
+
inputRef.current = initFn();
|
|
1676
|
+
const open = (localOptions) => {
|
|
1677
|
+
if (!inputRef.current) {
|
|
1678
|
+
return;
|
|
1679
|
+
}
|
|
1680
|
+
const _options = __spreadValues$1(__spreadValues$1(__spreadValues$1({}, DEFAULT_OPTIONS), options), localOptions);
|
|
1681
|
+
inputRef.current.multiple = _options.multiple;
|
|
1682
|
+
inputRef.current.accept = _options.accept;
|
|
1683
|
+
inputRef.current.capture = _options.capture;
|
|
1684
|
+
inputRef.current.click();
|
|
1685
|
+
};
|
|
1686
|
+
const reset = () => {
|
|
1687
|
+
setFiles(null);
|
|
1688
|
+
if (inputRef.current) {
|
|
1689
|
+
inputRef.current.value = "";
|
|
1690
|
+
}
|
|
1691
|
+
};
|
|
1692
|
+
return [files, open, reset];
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
const ARRIVED_STATE_THRESHOLD_PIXELS = 1;
|
|
1696
|
+
function useScroll(target, options = {}) {
|
|
1697
|
+
const {
|
|
1698
|
+
throttle = 0,
|
|
1699
|
+
idle = 200,
|
|
1700
|
+
onStop = noop,
|
|
1701
|
+
onScroll = noop,
|
|
1702
|
+
offset = {
|
|
1703
|
+
left: 0,
|
|
1704
|
+
right: 0,
|
|
1705
|
+
top: 0,
|
|
1706
|
+
bottom: 0
|
|
1707
|
+
},
|
|
1708
|
+
eventListenerOptions = {
|
|
1709
|
+
capture: false,
|
|
1710
|
+
passive: true
|
|
1711
|
+
}
|
|
1712
|
+
} = options;
|
|
1713
|
+
const [x, setX] = useState(0);
|
|
1714
|
+
const [y, setY] = useState(0);
|
|
1715
|
+
const [isScrolling, setIsScrolling] = useState(false);
|
|
1716
|
+
const [arrivedState, setArrivedState] = useState({
|
|
1717
|
+
left: true,
|
|
1718
|
+
right: false,
|
|
1719
|
+
top: true,
|
|
1720
|
+
bottom: false
|
|
1721
|
+
});
|
|
1722
|
+
const [directions, setDirections] = useState({
|
|
1723
|
+
left: false,
|
|
1724
|
+
right: false,
|
|
1725
|
+
top: false,
|
|
1726
|
+
bottom: false
|
|
1727
|
+
});
|
|
1728
|
+
const { run: onScrollEnd } = useDebounceFn((e) => {
|
|
1729
|
+
setIsScrolling(false);
|
|
1730
|
+
setDirections({ left: false, right: false, top: false, bottom: false });
|
|
1731
|
+
onStop(e);
|
|
1732
|
+
}, throttle + idle);
|
|
1733
|
+
const onScrollHandler = useEvent((e) => {
|
|
1734
|
+
const eventTarget = e.target === document ? e.target.documentElement : e.target;
|
|
1735
|
+
const scrollLeft = eventTarget.scrollLeft;
|
|
1736
|
+
let scrollTop = eventTarget.scrollTop;
|
|
1737
|
+
if (e.target === document && !scrollTop)
|
|
1738
|
+
scrollTop = document.body.scrollTop;
|
|
1739
|
+
setX(scrollLeft);
|
|
1740
|
+
setY(scrollTop);
|
|
1741
|
+
setDirections({
|
|
1742
|
+
left: scrollLeft < x,
|
|
1743
|
+
right: scrollLeft > x,
|
|
1744
|
+
top: scrollTop < y,
|
|
1745
|
+
bottom: scrollTop > y
|
|
1746
|
+
});
|
|
1747
|
+
setArrivedState({
|
|
1748
|
+
left: scrollLeft <= 0 + (offset.left || 0),
|
|
1749
|
+
right: scrollLeft + eventTarget.clientWidth >= eventTarget.scrollWidth - (offset.right || 0) - ARRIVED_STATE_THRESHOLD_PIXELS,
|
|
1750
|
+
top: scrollTop <= 0 + (offset.top || 0),
|
|
1751
|
+
bottom: scrollTop + eventTarget.clientHeight >= eventTarget.scrollHeight - (offset.bottom || 0) - ARRIVED_STATE_THRESHOLD_PIXELS
|
|
1752
|
+
});
|
|
1753
|
+
setIsScrolling(true);
|
|
1754
|
+
onScrollEnd(e);
|
|
1755
|
+
onScroll(e);
|
|
1756
|
+
});
|
|
1757
|
+
const { run: throttleOnScroll } = useThrottleFn(onScrollHandler, throttle);
|
|
1758
|
+
useEventListener(
|
|
1759
|
+
"scroll",
|
|
1760
|
+
throttle ? throttleOnScroll : onScrollHandler,
|
|
1761
|
+
target,
|
|
1762
|
+
eventListenerOptions
|
|
1763
|
+
);
|
|
1764
|
+
return [x, y, isScrolling, arrivedState, directions];
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
var __defProp = Object.defineProperty;
|
|
1768
|
+
var __defProps = Object.defineProperties;
|
|
1769
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
1770
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
1771
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
1772
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
1773
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1774
|
+
var __spreadValues = (a, b) => {
|
|
1775
|
+
for (var prop in b || (b = {}))
|
|
1776
|
+
if (__hasOwnProp.call(b, prop))
|
|
1777
|
+
__defNormalProp(a, prop, b[prop]);
|
|
1778
|
+
if (__getOwnPropSymbols)
|
|
1779
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
1780
|
+
if (__propIsEnum.call(b, prop))
|
|
1781
|
+
__defNormalProp(a, prop, b[prop]);
|
|
1782
|
+
}
|
|
1783
|
+
return a;
|
|
1784
|
+
};
|
|
1785
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
1786
|
+
var __async = (__this, __arguments, generator) => {
|
|
1787
|
+
return new Promise((resolve, reject) => {
|
|
1788
|
+
var fulfilled = (value) => {
|
|
1789
|
+
try {
|
|
1790
|
+
step(generator.next(value));
|
|
1791
|
+
} catch (e) {
|
|
1792
|
+
reject(e);
|
|
1793
|
+
}
|
|
1794
|
+
};
|
|
1795
|
+
var rejected = (value) => {
|
|
1796
|
+
try {
|
|
1797
|
+
step(generator.throw(value));
|
|
1798
|
+
} catch (e) {
|
|
1799
|
+
reject(e);
|
|
1800
|
+
}
|
|
1801
|
+
};
|
|
1802
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
1803
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
1804
|
+
});
|
|
1805
|
+
};
|
|
1806
|
+
function useInfiniteScroll(target, onLoadMore, options = {}) {
|
|
1807
|
+
var _a, _b;
|
|
1808
|
+
const savedLoadMore = useLatest(onLoadMore);
|
|
1809
|
+
const direction = (_a = options.direction) != null ? _a : "bottom";
|
|
1810
|
+
const state = useScroll(target, __spreadProps(__spreadValues({}, options), {
|
|
1811
|
+
offset: __spreadValues({
|
|
1812
|
+
[direction]: (_b = options.distance) != null ? _b : 0
|
|
1813
|
+
}, options.offset)
|
|
1814
|
+
}));
|
|
1815
|
+
const di = state[3][direction];
|
|
1816
|
+
useUpdateEffect(() => {
|
|
1817
|
+
const fn = () => __async(this, null, function* () {
|
|
1818
|
+
var _a2, _b2;
|
|
1819
|
+
const element = getTargetElement(target);
|
|
1820
|
+
const previous = {
|
|
1821
|
+
height: (_a2 = element == null ? void 0 : element.scrollHeight) != null ? _a2 : 0,
|
|
1822
|
+
width: (_b2 = element == null ? void 0 : element.scrollWidth) != null ? _b2 : 0
|
|
1823
|
+
};
|
|
1824
|
+
yield savedLoadMore.current(state);
|
|
1825
|
+
if (options.preserveScrollPosition && element) {
|
|
1826
|
+
element.scrollTo({
|
|
1827
|
+
top: element.scrollHeight - previous.height,
|
|
1828
|
+
left: element.scrollWidth - previous.width
|
|
1829
|
+
});
|
|
1830
|
+
}
|
|
1831
|
+
});
|
|
1832
|
+
fn();
|
|
1833
|
+
}, [di, options.preserveScrollPosition]);
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
const defaultEvents = [
|
|
1837
|
+
"mousedown",
|
|
1838
|
+
"mouseup",
|
|
1839
|
+
"keydown",
|
|
1840
|
+
"keyup"
|
|
1841
|
+
];
|
|
1842
|
+
function useKeyModifier(modifier, options = {}) {
|
|
1843
|
+
const { events = defaultEvents, initial = false } = options;
|
|
1844
|
+
const [state, setState] = useState(initial);
|
|
1845
|
+
useMount(() => {
|
|
1846
|
+
events.forEach((listenEvent) => {
|
|
1847
|
+
on(document, listenEvent, (evt) => {
|
|
1848
|
+
if (typeof evt.getModifierState === "function") {
|
|
1849
|
+
setState(evt.getModifierState(modifier));
|
|
1850
|
+
}
|
|
1851
|
+
});
|
|
1852
|
+
});
|
|
1853
|
+
return () => {
|
|
1854
|
+
events.forEach((listenerEvent) => {
|
|
1855
|
+
off(document, listenerEvent, (evt) => {
|
|
1856
|
+
if (typeof evt.getModifierState === "function") {
|
|
1857
|
+
setState(evt.getModifierState(modifier));
|
|
1858
|
+
}
|
|
1859
|
+
});
|
|
1860
|
+
});
|
|
1861
|
+
};
|
|
1862
|
+
});
|
|
1863
|
+
return state;
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
function useMousePressed(target, options = {}) {
|
|
1867
|
+
const { touch = true, drag = true, initialValue = false } = options;
|
|
1868
|
+
const [pressed, setPressed] = useState(initialValue);
|
|
1869
|
+
const [sourceType, setSourceType] = useState(null);
|
|
1870
|
+
const onPressed = useCallback(
|
|
1871
|
+
(srcType) => () => {
|
|
1872
|
+
setPressed(true);
|
|
1873
|
+
setSourceType(srcType);
|
|
1874
|
+
},
|
|
1875
|
+
[]
|
|
1876
|
+
);
|
|
1877
|
+
const onReleased = useCallback(() => {
|
|
1878
|
+
setPressed(false);
|
|
1879
|
+
setSourceType(null);
|
|
1880
|
+
}, []);
|
|
1881
|
+
useEventListener("mousedown", onPressed("mouse"), target, { passive: true });
|
|
1882
|
+
useEventListener("mouseleave", onReleased, window, { passive: true });
|
|
1883
|
+
useEventListener("mouseup", onReleased, window, { passive: true });
|
|
1884
|
+
useMount(() => {
|
|
1885
|
+
const element = getTargetElement(target);
|
|
1886
|
+
if (drag) {
|
|
1887
|
+
element == null ? void 0 : element.addEventListener("dragstart", onPressed("mouse"), {
|
|
1888
|
+
passive: true
|
|
1889
|
+
});
|
|
1890
|
+
element == null ? void 0 : element.addEventListener("drop", onReleased, {
|
|
1891
|
+
passive: true
|
|
1892
|
+
});
|
|
1893
|
+
element == null ? void 0 : element.addEventListener("dragend", onReleased, {
|
|
1894
|
+
passive: true
|
|
1895
|
+
});
|
|
1896
|
+
}
|
|
1897
|
+
if (touch) {
|
|
1898
|
+
element == null ? void 0 : element.addEventListener("touchstart", onPressed("touch"), {
|
|
1899
|
+
passive: true
|
|
1900
|
+
});
|
|
1901
|
+
element == null ? void 0 : element.addEventListener("touchend", onReleased, {
|
|
1902
|
+
passive: true
|
|
1903
|
+
});
|
|
1904
|
+
element == null ? void 0 : element.addEventListener("touchcancel", onReleased, {
|
|
1905
|
+
passive: true
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
return () => {
|
|
1909
|
+
if (drag) {
|
|
1910
|
+
element == null ? void 0 : element.removeEventListener("dragstart", onPressed("mouse"));
|
|
1911
|
+
element == null ? void 0 : element.removeEventListener("drop", onReleased);
|
|
1912
|
+
element == null ? void 0 : element.removeEventListener("dragend", onReleased);
|
|
1913
|
+
}
|
|
1914
|
+
if (touch) {
|
|
1915
|
+
element == null ? void 0 : element.removeEventListener("touchstart", onPressed("touch"));
|
|
1916
|
+
element == null ? void 0 : element.removeEventListener("touchend", onReleased);
|
|
1917
|
+
element == null ? void 0 : element.removeEventListener("touchcancel", onReleased);
|
|
1918
|
+
}
|
|
1919
|
+
};
|
|
1920
|
+
});
|
|
1921
|
+
return [pressed, sourceType];
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
function preventDefault(rawEvent) {
|
|
1925
|
+
const e = rawEvent || window.event;
|
|
1926
|
+
if (e.touches.length > 1) {
|
|
1927
|
+
return true;
|
|
1928
|
+
}
|
|
1929
|
+
if (e.preventDefault) {
|
|
1930
|
+
e.preventDefault();
|
|
1931
|
+
}
|
|
1932
|
+
return false;
|
|
1933
|
+
}
|
|
1934
|
+
function useScrollLock(target, initialState = false) {
|
|
1935
|
+
const [locked, setLocked] = useState(initialState);
|
|
1936
|
+
const initialOverflowRef = useRef("scroll");
|
|
1937
|
+
useMount(() => {
|
|
1938
|
+
const element = getTargetElement(target);
|
|
1939
|
+
if (element) {
|
|
1940
|
+
initialOverflowRef.current = element.style.overflow;
|
|
1941
|
+
if (locked) {
|
|
1942
|
+
element.style.overflow = "hidden";
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
});
|
|
1946
|
+
const lock = useEvent(() => {
|
|
1947
|
+
const element = getTargetElement(target);
|
|
1948
|
+
if (!element || locked) {
|
|
1949
|
+
return;
|
|
1950
|
+
}
|
|
1951
|
+
if (isIOS) {
|
|
1952
|
+
element.addEventListener("touchmove", preventDefault, { passive: false });
|
|
1953
|
+
}
|
|
1954
|
+
element.style.overflow = "hidden";
|
|
1955
|
+
setLocked(true);
|
|
1956
|
+
});
|
|
1957
|
+
const unlock = useEvent(() => {
|
|
1958
|
+
const element = getTargetElement(target);
|
|
1959
|
+
if (!element || !locked) {
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1962
|
+
if (isIOS) {
|
|
1963
|
+
element.removeEventListener("touchmove", preventDefault);
|
|
1964
|
+
}
|
|
1965
|
+
element.style.overflow = initialOverflowRef.current;
|
|
1966
|
+
setLocked(false);
|
|
1967
|
+
});
|
|
1968
|
+
const set = useEvent((flag) => {
|
|
1969
|
+
if (flag) {
|
|
1970
|
+
lock();
|
|
1971
|
+
} else {
|
|
1972
|
+
unlock();
|
|
1973
|
+
}
|
|
1974
|
+
});
|
|
1975
|
+
return [locked, set];
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
function useElementSize(target, options = {}) {
|
|
1979
|
+
const { box = "content-box" } = options;
|
|
1980
|
+
const [width, setWidth] = useState(0);
|
|
1981
|
+
const [height, setHeight] = useState(0);
|
|
1982
|
+
useResizeObserver(
|
|
1983
|
+
target,
|
|
1984
|
+
([entry]) => {
|
|
1985
|
+
const boxSize = box === "border-box" ? entry.borderBoxSize : box === "content-box" ? entry.contentBoxSize : entry.devicePixelContentBoxSize;
|
|
1986
|
+
if (boxSize) {
|
|
1987
|
+
setWidth(boxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0));
|
|
1988
|
+
setHeight(boxSize.reduce((acc, { blockSize }) => acc + blockSize, 0));
|
|
1989
|
+
} else {
|
|
1990
|
+
setWidth(entry.contentRect.width);
|
|
1991
|
+
setHeight(entry.contentRect.height);
|
|
1992
|
+
}
|
|
1993
|
+
},
|
|
1994
|
+
options
|
|
1995
|
+
);
|
|
1996
|
+
return [width, height];
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
function useVirtualList(list = [], options) {
|
|
2000
|
+
const containerRef = useRef(null);
|
|
2001
|
+
const [width, height] = useElementSize(containerRef);
|
|
2002
|
+
const [currentList, setCurrentList] = useState([]);
|
|
2003
|
+
const { itemHeight, overscan = 5, containerHeight = 300 } = options;
|
|
2004
|
+
const state = useRef({ start: 0, end: 10 });
|
|
2005
|
+
const getViewCapacity = useCallback(
|
|
2006
|
+
(containerHeight2) => {
|
|
2007
|
+
if (typeof itemHeight === "number") {
|
|
2008
|
+
return Math.ceil(containerHeight2 / itemHeight);
|
|
2009
|
+
}
|
|
2010
|
+
const { start = 0 } = state.current;
|
|
2011
|
+
let sum = 0;
|
|
2012
|
+
let capacity = 0;
|
|
2013
|
+
for (let i = start; i < list.length; i++) {
|
|
2014
|
+
const height2 = itemHeight(i);
|
|
2015
|
+
sum += height2;
|
|
2016
|
+
if (sum >= containerHeight2) {
|
|
2017
|
+
capacity = i;
|
|
2018
|
+
break;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
return capacity - start;
|
|
2022
|
+
},
|
|
2023
|
+
[itemHeight, list]
|
|
2024
|
+
);
|
|
2025
|
+
const getOffset = useCallback(
|
|
2026
|
+
(scrollTop) => {
|
|
2027
|
+
if (typeof itemHeight === "number")
|
|
2028
|
+
return Math.floor(scrollTop / itemHeight) + 1;
|
|
2029
|
+
let sum = 0;
|
|
2030
|
+
let offset = 0;
|
|
2031
|
+
for (let i = 0; i < list.length; i++) {
|
|
2032
|
+
const height2 = itemHeight(i);
|
|
2033
|
+
sum += height2;
|
|
2034
|
+
if (sum >= scrollTop) {
|
|
2035
|
+
offset = i;
|
|
2036
|
+
break;
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
return offset + 1;
|
|
2040
|
+
},
|
|
2041
|
+
[itemHeight, list]
|
|
2042
|
+
);
|
|
2043
|
+
const calculateRange = useEvent(() => {
|
|
2044
|
+
const element = containerRef.current;
|
|
2045
|
+
if (element != null) {
|
|
2046
|
+
const offset = getOffset(element.scrollTop);
|
|
2047
|
+
const viewCapacity = getViewCapacity(element.clientHeight);
|
|
2048
|
+
const from = offset - overscan;
|
|
2049
|
+
const to = offset + viewCapacity + overscan;
|
|
2050
|
+
state.current = {
|
|
2051
|
+
start: from < 0 ? 0 : from,
|
|
2052
|
+
end: to > list.length ? list.length : to
|
|
2053
|
+
};
|
|
2054
|
+
setCurrentList(
|
|
2055
|
+
list.slice(state.current.start, state.current.end).map((ele, index) => ({
|
|
2056
|
+
data: ele,
|
|
2057
|
+
index: index + state.current.start
|
|
2058
|
+
}))
|
|
2059
|
+
);
|
|
2060
|
+
}
|
|
2061
|
+
});
|
|
2062
|
+
useEffect(() => {
|
|
2063
|
+
calculateRange();
|
|
2064
|
+
}, [width, height, list, calculateRange]);
|
|
2065
|
+
const totalHeight = useMemo(() => {
|
|
2066
|
+
if (typeof itemHeight === "number") {
|
|
2067
|
+
return list.length * itemHeight;
|
|
2068
|
+
}
|
|
2069
|
+
return list.reduce((sum, _, index) => sum + itemHeight(index), 0);
|
|
2070
|
+
}, [itemHeight, list]);
|
|
2071
|
+
const getDistanceTop = useCallback(
|
|
2072
|
+
(index) => {
|
|
2073
|
+
if (typeof itemHeight === "number") {
|
|
2074
|
+
const height3 = index * itemHeight;
|
|
2075
|
+
return height3;
|
|
2076
|
+
}
|
|
2077
|
+
const height2 = list.slice(0, index).reduce((sum, _, i) => sum + itemHeight(i), 0);
|
|
2078
|
+
return height2;
|
|
2079
|
+
},
|
|
2080
|
+
[itemHeight, list]
|
|
2081
|
+
);
|
|
2082
|
+
const scrollTo = useEvent((index) => {
|
|
2083
|
+
if (containerRef.current) {
|
|
2084
|
+
containerRef.current.scrollTop = getDistanceTop(index);
|
|
2085
|
+
calculateRange();
|
|
2086
|
+
}
|
|
2087
|
+
});
|
|
2088
|
+
const offsetTop = useMemo(
|
|
2089
|
+
() => getDistanceTop(state.current.start),
|
|
2090
|
+
[getDistanceTop]
|
|
2091
|
+
);
|
|
2092
|
+
const wrapperProps = useMemo(() => {
|
|
2093
|
+
return {
|
|
2094
|
+
style: {
|
|
2095
|
+
width: "100%",
|
|
2096
|
+
height: `${totalHeight - offsetTop}px`,
|
|
2097
|
+
marginTop: `${offsetTop}px`
|
|
2098
|
+
}
|
|
2099
|
+
};
|
|
2100
|
+
}, [offsetTop, totalHeight]);
|
|
2101
|
+
const containerStyle = useMemo(() => {
|
|
2102
|
+
return { overflowY: "auto", height: containerHeight };
|
|
2103
|
+
}, [containerHeight]);
|
|
2104
|
+
return {
|
|
2105
|
+
list: currentList,
|
|
2106
|
+
scrollTo,
|
|
2107
|
+
containerProps: {
|
|
2108
|
+
ref: containerRef,
|
|
2109
|
+
onScroll: () => {
|
|
2110
|
+
calculateRange();
|
|
2111
|
+
},
|
|
2112
|
+
style: containerStyle
|
|
2113
|
+
},
|
|
2114
|
+
wrapperProps
|
|
2115
|
+
};
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
function usePreferredColorScheme(defaultState) {
|
|
2119
|
+
const isLight = useMediaQuery("(prefers-color-scheme: light)");
|
|
2120
|
+
const isDark = useMediaQuery("(prefers-color-scheme: dark)");
|
|
2121
|
+
if (!isBrowser && defaultState) {
|
|
2122
|
+
return defaultState;
|
|
2123
|
+
}
|
|
2124
|
+
return isDark ? "dark" : isLight ? "light" : "no-preference";
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
function usePreferredContrast(defaultState) {
|
|
2128
|
+
const isMore = useMediaQuery("(prefers-contrast: more)");
|
|
2129
|
+
const isLess = useMediaQuery("(prefers-contrast: less)");
|
|
2130
|
+
const isCustom = useMediaQuery("(prefers-contrast: custom)");
|
|
2131
|
+
if (!isBrowser && defaultState) {
|
|
2132
|
+
return defaultState;
|
|
2133
|
+
}
|
|
2134
|
+
return isMore ? "more" : isLess ? "less" : isCustom ? "custom" : "no-preference";
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
function useActiveElement() {
|
|
2138
|
+
const [active, setActive] = useState(null);
|
|
2139
|
+
const listener = useCallback(() => {
|
|
2140
|
+
setActive(window == null ? void 0 : window.document.activeElement);
|
|
2141
|
+
}, []);
|
|
2142
|
+
useEventListener("blur", listener, window, true);
|
|
2143
|
+
useEventListener("focus", listener, window, true);
|
|
2144
|
+
return active;
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
export { useActiveElement, useCounter, useCustomCompareEffect, useDarkMode, useDebounce, useDebounceFn, useDeepCompareEffect, useDocumentVisibility, useDropZone, useElementSize, useEvent, useEventEmitter, useEventListener, useFavicon, useFileDialog, useFirstMountState, useFps$1 as useFps, useFullscreen, useGeolocation, useIdle, useInfiniteScroll, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyModifier, useLatest, useLocalStorage, useLongPress, useMarkdown, useMediaDevices$1 as useMediaDevices, useMediaQuery, useMount, useMountedState, useMouse, useMousePressed, useMutationObserver, useNetwork, useObjectUrl, useOnline, useOrientation, usePageLeave, usePermission, usePreferredColorScheme, usePreferredContrast, usePreferredDark, usePrevious, useRafFn, useRafState, useResizeObserver, useScriptTag, useScroll, useScrollLock, useSessionStorage, useTextDirection, useThrottle, useThrottleFn, useTimeout, useTimeoutFn, useTitle, useToggle, useUnmount, useUpdate, useUpdateEffect, useUpdateLayoutEffect, useVirtualList };
|