@reause/shared 0.1.2

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.
@@ -0,0 +1,3381 @@
1
+ (function(exports, react) {
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ //#region \0rolldown/runtime.js
4
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
5
+ //#endregion
6
+ //#region createEventHook/index.tsx
7
+ /**
8
+ * Utility for creating event hooks
9
+ *
10
+ * @see https://vueuse.org/createEventHook
11
+ *
12
+ * @__NO_SIDE_EFFECTS__
13
+ */
14
+ function createEventHook() {
15
+ const fns = /* @__PURE__ */ new Set();
16
+ const off = (fn) => {
17
+ fns.delete(fn);
18
+ };
19
+ const clear = () => {
20
+ fns.clear();
21
+ };
22
+ const on = (fn) => {
23
+ fns.add(fn);
24
+ const offFn = () => off(fn);
25
+ return { off: offFn };
26
+ };
27
+ const trigger = (...args) => {
28
+ return Promise.all(Array.from(fns).map((fn) => fn(...args)));
29
+ };
30
+ return {
31
+ on,
32
+ off,
33
+ trigger,
34
+ clear
35
+ };
36
+ }
37
+ //#endregion
38
+ //#region createGlobalState/index.tsx
39
+ /* @__NO_SIDE_EFFECTS__ */
40
+ function createGlobalState(initialState) {
41
+ let state = typeof initialState === "function" ? initialState() : initialState;
42
+ const listeners = /* @__PURE__ */ new Set();
43
+ const subscribe = (listener) => {
44
+ listeners.add(listener);
45
+ return () => {
46
+ listeners.delete(listener);
47
+ };
48
+ };
49
+ const getSnapshot = () => state;
50
+ const setState = (update) => {
51
+ state = typeof update === "function" ? update(state) : update;
52
+ for (const listener of listeners) listener();
53
+ };
54
+ return function useGlobalState() {
55
+ const snapshot = (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
56
+ return (0, react.useMemo)(() => [snapshot, setState], [snapshot, setState]);
57
+ };
58
+ }
59
+ //#endregion
60
+ //#region ../../node_modules/.pnpm/react@19.2.8/node_modules/react/cjs/react-jsx-runtime.development.js
61
+ /**
62
+ * @license React
63
+ * react-jsx-runtime.development.js
64
+ *
65
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
66
+ *
67
+ * This source code is licensed under the MIT license found in the
68
+ * LICENSE file in the root directory of this source tree.
69
+ */
70
+ var require_react_jsx_runtime_development = /* @__PURE__ */ __commonJSMin(((exports) => {
71
+ (function() {
72
+ function getComponentNameFromType(type) {
73
+ if (null == type) return null;
74
+ if ("function" === typeof type) return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
75
+ if ("string" === typeof type) return type;
76
+ switch (type) {
77
+ case REACT_FRAGMENT_TYPE: return "Fragment";
78
+ case REACT_PROFILER_TYPE: return "Profiler";
79
+ case REACT_STRICT_MODE_TYPE: return "StrictMode";
80
+ case REACT_SUSPENSE_TYPE: return "Suspense";
81
+ case REACT_SUSPENSE_LIST_TYPE: return "SuspenseList";
82
+ case REACT_ACTIVITY_TYPE: return "Activity";
83
+ }
84
+ if ("object" === typeof type) switch ("number" === typeof type.tag && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), type.$$typeof) {
85
+ case REACT_PORTAL_TYPE: return "Portal";
86
+ case REACT_CONTEXT_TYPE: return type.displayName || "Context";
87
+ case REACT_CONSUMER_TYPE: return (type._context.displayName || "Context") + ".Consumer";
88
+ case REACT_FORWARD_REF_TYPE:
89
+ var innerType = type.render;
90
+ type = type.displayName;
91
+ type || (type = innerType.displayName || innerType.name || "", type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef");
92
+ return type;
93
+ case REACT_MEMO_TYPE: return innerType = type.displayName || null, null !== innerType ? innerType : getComponentNameFromType(type.type) || "Memo";
94
+ case REACT_LAZY_TYPE:
95
+ innerType = type._payload;
96
+ type = type._init;
97
+ try {
98
+ return getComponentNameFromType(type(innerType));
99
+ } catch (x) {}
100
+ }
101
+ return null;
102
+ }
103
+ function testStringCoercion(value) {
104
+ return "" + value;
105
+ }
106
+ function checkKeyStringCoercion(value) {
107
+ try {
108
+ testStringCoercion(value);
109
+ var JSCompiler_inline_result = !1;
110
+ } catch (e) {
111
+ JSCompiler_inline_result = !0;
112
+ }
113
+ if (JSCompiler_inline_result) {
114
+ JSCompiler_inline_result = console;
115
+ var JSCompiler_temp_const = JSCompiler_inline_result.error;
116
+ var JSCompiler_inline_result$jscomp$0 = "function" === typeof Symbol && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
117
+ JSCompiler_temp_const.call(JSCompiler_inline_result, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", JSCompiler_inline_result$jscomp$0);
118
+ return testStringCoercion(value);
119
+ }
120
+ }
121
+ function getTaskName(type) {
122
+ if (type === REACT_FRAGMENT_TYPE) return "<>";
123
+ if ("object" === typeof type && null !== type && type.$$typeof === REACT_LAZY_TYPE) return "<...>";
124
+ try {
125
+ var name = getComponentNameFromType(type);
126
+ return name ? "<" + name + ">" : "<...>";
127
+ } catch (x) {
128
+ return "<...>";
129
+ }
130
+ }
131
+ function getOwner() {
132
+ var dispatcher = ReactSharedInternals.A;
133
+ return null === dispatcher ? null : dispatcher.getOwner();
134
+ }
135
+ function UnknownOwner() {
136
+ return Error("react-stack-top-frame");
137
+ }
138
+ function hasValidKey(config) {
139
+ if (hasOwnProperty.call(config, "key")) {
140
+ var getter = Object.getOwnPropertyDescriptor(config, "key").get;
141
+ if (getter && getter.isReactWarning) return !1;
142
+ }
143
+ return void 0 !== config.key;
144
+ }
145
+ function defineKeyPropWarningGetter(props, displayName) {
146
+ function warnAboutAccessingKey() {
147
+ specialPropKeyWarningShown || (specialPropKeyWarningShown = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", displayName));
148
+ }
149
+ warnAboutAccessingKey.isReactWarning = !0;
150
+ Object.defineProperty(props, "key", {
151
+ get: warnAboutAccessingKey,
152
+ configurable: !0
153
+ });
154
+ }
155
+ function elementRefGetterWithDeprecationWarning() {
156
+ var componentName = getComponentNameFromType(this.type);
157
+ didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."));
158
+ componentName = this.props.ref;
159
+ return void 0 !== componentName ? componentName : null;
160
+ }
161
+ function ReactElement(type, key, props, owner, debugStack, debugTask) {
162
+ var refProp = props.ref;
163
+ type = {
164
+ $$typeof: REACT_ELEMENT_TYPE,
165
+ type,
166
+ key,
167
+ props,
168
+ _owner: owner
169
+ };
170
+ null !== (void 0 !== refProp ? refProp : null) ? Object.defineProperty(type, "ref", {
171
+ enumerable: !1,
172
+ get: elementRefGetterWithDeprecationWarning
173
+ }) : Object.defineProperty(type, "ref", {
174
+ enumerable: !1,
175
+ value: null
176
+ });
177
+ type._store = {};
178
+ Object.defineProperty(type._store, "validated", {
179
+ configurable: !1,
180
+ enumerable: !1,
181
+ writable: !0,
182
+ value: 0
183
+ });
184
+ Object.defineProperty(type, "_debugInfo", {
185
+ configurable: !1,
186
+ enumerable: !1,
187
+ writable: !0,
188
+ value: null
189
+ });
190
+ Object.defineProperty(type, "_debugStack", {
191
+ configurable: !1,
192
+ enumerable: !1,
193
+ writable: !0,
194
+ value: debugStack
195
+ });
196
+ Object.defineProperty(type, "_debugTask", {
197
+ configurable: !1,
198
+ enumerable: !1,
199
+ writable: !0,
200
+ value: debugTask
201
+ });
202
+ Object.freeze && (Object.freeze(type.props), Object.freeze(type));
203
+ return type;
204
+ }
205
+ function jsxDEVImpl(type, config, maybeKey, isStaticChildren, debugStack, debugTask) {
206
+ var children = config.children;
207
+ if (void 0 !== children) if (isStaticChildren) if (isArrayImpl(children)) {
208
+ for (isStaticChildren = 0; isStaticChildren < children.length; isStaticChildren++) validateChildKeys(children[isStaticChildren]);
209
+ Object.freeze && Object.freeze(children);
210
+ } else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
211
+ else validateChildKeys(children);
212
+ if (hasOwnProperty.call(config, "key")) {
213
+ children = getComponentNameFromType(type);
214
+ var keys = Object.keys(config).filter(function(k) {
215
+ return "key" !== k;
216
+ });
217
+ isStaticChildren = 0 < keys.length ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" : "{key: someKey}";
218
+ didWarnAboutKeySpread[children + isStaticChildren] || (keys = 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}", console.error("A props object containing a \"key\" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />", isStaticChildren, children, keys, children), didWarnAboutKeySpread[children + isStaticChildren] = !0);
219
+ }
220
+ children = null;
221
+ void 0 !== maybeKey && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
222
+ hasValidKey(config) && (checkKeyStringCoercion(config.key), children = "" + config.key);
223
+ if ("key" in config) {
224
+ maybeKey = {};
225
+ for (var propName in config) "key" !== propName && (maybeKey[propName] = config[propName]);
226
+ } else maybeKey = config;
227
+ children && defineKeyPropWarningGetter(maybeKey, "function" === typeof type ? type.displayName || type.name || "Unknown" : type);
228
+ return ReactElement(type, children, maybeKey, getOwner(), debugStack, debugTask);
229
+ }
230
+ function validateChildKeys(node) {
231
+ isValidElement(node) ? node._store && (node._store.validated = 1) : "object" === typeof node && null !== node && node.$$typeof === REACT_LAZY_TYPE && ("fulfilled" === node._payload.status ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
232
+ }
233
+ function isValidElement(object) {
234
+ return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
235
+ }
236
+ var React = require("react"), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
237
+ return null;
238
+ };
239
+ React = { react_stack_bottom_frame: function(callStackForError) {
240
+ return callStackForError();
241
+ } };
242
+ var specialPropKeyWarningShown;
243
+ var didWarnAboutElementRef = {};
244
+ var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(React, UnknownOwner)();
245
+ var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
246
+ var didWarnAboutKeySpread = {};
247
+ exports.Fragment = REACT_FRAGMENT_TYPE;
248
+ exports.jsx = function(type, config, maybeKey) {
249
+ var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
250
+ return jsxDEVImpl(type, config, maybeKey, !1, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
251
+ };
252
+ exports.jsxs = function(type, config, maybeKey) {
253
+ var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
254
+ return jsxDEVImpl(type, config, maybeKey, !0, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
255
+ };
256
+ })();
257
+ }));
258
+ //#endregion
259
+ //#region createInjectionState/index.tsx
260
+ var import_jsx_runtime = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
261
+ module.exports = require_react_jsx_runtime_development();
262
+ })))();
263
+ function createInjectionState(composable, options) {
264
+ var _options$injectionKey;
265
+ const InjectionContext = (_options$injectionKey = options === null || options === void 0 ? void 0 : options.injectionKey) !== null && _options$injectionKey !== void 0 ? _options$injectionKey : (0, react.createContext)(options === null || options === void 0 ? void 0 : options.defaultValue);
266
+ function Provider(props) {
267
+ const { children, ...rest } = props;
268
+ const state = composable(rest);
269
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InjectionContext.Provider, {
270
+ value: state,
271
+ children
272
+ });
273
+ }
274
+ Provider.displayName = composable.name ? `${composable.name}Provider` : "InjectionStateProvider";
275
+ const useInjectedState = () => (0, react.useContext)(InjectionContext);
276
+ return [Provider, useInjectedState];
277
+ }
278
+ //#endregion
279
+ //#region createSharedHook/index.tsx
280
+ /**
281
+ * Make a composable function usable with multiple React components.
282
+ *
283
+ * Map from @vueuse/shared `createSharedComposable`
284
+ * Mapping: upstream runs the composable once inside a detached
285
+ * `effectScope(true)`, counts the subscribers and stops the scope when the
286
+ * last consumer leaves. React has no `effectScope`, so the same lifetime is
287
+ * expressed by an external store held in the closure of one
288
+ * `createSharedHook` call — the `state` snapshot, a `Set` of `listeners`, the
289
+ * `refCount` and the optional `cleanup` — which every consumer reads through
290
+ * `useSyncExternalStore`.
291
+ *
292
+ * The shared instance is created by the **first consumer to render** (the
293
+ * "creator"): it runs the wrapped hook on every one of its renders — the
294
+ * wrapped hook is therefore free to use React hooks internally — assigning
295
+ * the result to `state`, and `useLayoutEffect` publishes the latest value to
296
+ * every other consumer after commit. Every later consumer never calls the
297
+ * wrapped hook (both call patterns are stable per consumer, so the hook order
298
+ * never changes across renders); it just reads the published snapshot. The
299
+ * creator assigns `state` *before* `useSyncExternalStore` reads its snapshot
300
+ * in the same render, so every consumer — creator included — receives the
301
+ * shared value on its very first render, never `undefined`.
302
+ *
303
+ * The creator deliberately **does not register a store listener**: it already
304
+ * re-renders on its own state changes (the wrapped hook's setters belong to
305
+ * its component) and re-publishes afterwards, so a notification would only
306
+ * re-render it from its own publish. `useSyncExternalStore` requires the
307
+ * snapshot to stay reference-stable between real changes ("the result of
308
+ * getSnapshot should be cached"): every creator render assigns a fresh
309
+ * reference, so a subscribed creator would see "the store changed" forever and
310
+ * loop. The creator still counts toward `refCount`, so teardown timing is
311
+ * exact — it just never receives notifications.
312
+ *
313
+ * Deviations from upstream:
314
+ * - upstream runs the composable exactly once, with the first caller's
315
+ * arguments; here the creator re-runs the wrapped hook on every one of its
316
+ * renders (React hooks cannot be called outside a render), so while the
317
+ * creator stays mounted the shared value keeps tracking its latest render.
318
+ * - **frozen after the creator unmounts**: the wrapped hook's setters belong
319
+ * to the creator's component, so if the creator unmounts while other
320
+ * consumers remain mounted, the shared value stops updating — it freezes at
321
+ * the last published value. The instance itself lives on until the last
322
+ * consumer unmounts (upstream lifetime parity).
323
+ * - `getServerSnapshot` returns the same snapshot as the client: server
324
+ * rendering yields the uninitialized value, the client fills it in after
325
+ * hydration, and `useSyncExternalStore` handles the mismatch.
326
+ * - Teardown has no `tryOnScopeDispose` to hook into, so the optional
327
+ * `cleanup` argument is called — and the state dropped — when the last
328
+ * consumer unmounts; a later mount starts a fresh instance, exactly like
329
+ * upstream's `scope.stop()` followed by `state = undefined`.
330
+ *
331
+ * ```tsx
332
+ * const useSharedMouse = createSharedHook(useMouse)
333
+ *
334
+ * // CompA — const { x, y } = useSharedMouse()
335
+ * // CompB — const { x, y } = useSharedMouse() // same state, no new listeners
336
+ * ```
337
+ *
338
+ * @see https://vueuse.org/createSharedComposable
339
+ * @param hook The composable to share across every consumer of the returned
340
+ * hook. It runs on every render of the first consumer (the creator).
341
+ * @param cleanup Called when the last consumer unmounts, before the shared
342
+ * state is dropped — the place to undo whatever `hook` set up outside React.
343
+ */
344
+ /* @__NO_SIDE_EFFECTS__ */
345
+ function createSharedHook(hook, cleanup) {
346
+ let state;
347
+ const listeners = /* @__PURE__ */ new Set();
348
+ let refCount = 0;
349
+ let teardown = cleanup;
350
+ let creatorId;
351
+ const notify = () => {
352
+ for (const listener of listeners) listener();
353
+ };
354
+ const subscribe = (listener) => {
355
+ listeners.add(listener);
356
+ refCount += 1;
357
+ return () => {
358
+ listeners.delete(listener);
359
+ refCount -= 1;
360
+ if (refCount <= 0) {
361
+ state = void 0;
362
+ refCount = 0;
363
+ creatorId = void 0;
364
+ teardown === null || teardown === void 0 || teardown();
365
+ teardown = void 0;
366
+ }
367
+ };
368
+ };
369
+ const creatorSubscribe = (_listener) => {
370
+ refCount += 1;
371
+ return () => {
372
+ refCount -= 1;
373
+ if (refCount <= 0) {
374
+ state = void 0;
375
+ refCount = 0;
376
+ creatorId = void 0;
377
+ teardown === null || teardown === void 0 || teardown();
378
+ teardown = void 0;
379
+ }
380
+ };
381
+ };
382
+ const getSnapshot = () => state;
383
+ const getServerSnapshot = getSnapshot;
384
+ return function useSharedHook(...args) {
385
+ const id = (0, react.useRef)(Symbol("createSharedHook")).current;
386
+ if (creatorId === void 0) creatorId = id;
387
+ const isCreator = creatorId === id;
388
+ if (isCreator) state = hook(...args);
389
+ (0, react.useLayoutEffect)(() => {
390
+ if (isCreator) notify();
391
+ });
392
+ return (0, react.useSyncExternalStore)(isCreator ? creatorSubscribe : subscribe, getSnapshot, getServerSnapshot);
393
+ };
394
+ }
395
+ //#endregion
396
+ //#region utils/index.tsx
397
+ function promiseTimeout(ms, throwOnTimeout = false, reason = "Timeout") {
398
+ return new Promise((resolve, reject) => {
399
+ if (throwOnTimeout) setTimeout(reject, ms, reason);
400
+ else setTimeout(resolve, ms);
401
+ });
402
+ }
403
+ /**
404
+ * Create singleton promise function
405
+ *
406
+ * @example
407
+ * ```
408
+ * const promise = createSingletonPromise(async () => { ... })
409
+ *
410
+ * await promise()
411
+ * await promise() // all of them will be bind to a single promise instance
412
+ * await promise() // and be resolved together
413
+ * ```
414
+ */
415
+ function createSingletonPromise(fn) {
416
+ let _promise;
417
+ function wrapper() {
418
+ if (!_promise) _promise = fn();
419
+ return _promise;
420
+ }
421
+ wrapper.reset = async () => {
422
+ const _prev = _promise;
423
+ _promise = void 0;
424
+ if (_prev) await _prev;
425
+ };
426
+ return wrapper;
427
+ }
428
+ function increaseWithUnit(target, delta) {
429
+ var _target$match;
430
+ if (typeof target === "number") return target + delta;
431
+ const value = ((_target$match = target.match(/^-?\d+\.?\d*/)) === null || _target$match === void 0 ? void 0 : _target$match[0]) || "";
432
+ const unit = target.slice(value.length);
433
+ const result = Number.parseFloat(value) + delta;
434
+ if (Number.isNaN(result)) return target;
435
+ return result + unit;
436
+ }
437
+ /**
438
+ * Get a px value for SSR use, do not rely on this method outside of SSR as REM
439
+ * unit is assumed at 16px, which might not be the case on the client
440
+ *
441
+ * @example pxValue('37rem') // 592
442
+ * @example pxValue('500px') // 500
443
+ */
444
+ function pxValue(px) {
445
+ return px.endsWith("rem") ? Number.parseFloat(px) * 16 : Number.parseFloat(px);
446
+ }
447
+ /**
448
+ * Create a new subset object by giving keys
449
+ */
450
+ function objectPick(obj, keys, omitUndefined = false) {
451
+ return keys.reduce((n, k) => {
452
+ if (k in obj) {
453
+ if (!omitUndefined || obj[k] !== void 0) n[k] = obj[k];
454
+ }
455
+ return n;
456
+ }, {});
457
+ }
458
+ /**
459
+ * Create a new subset object by omit giving keys
460
+ */
461
+ function objectOmit(obj, keys, omitUndefined = false) {
462
+ return Object.fromEntries(Object.entries(obj).filter(([key, value]) => {
463
+ return (!omitUndefined || value !== void 0) && !keys.includes(key);
464
+ }));
465
+ }
466
+ function toArray(value) {
467
+ return Array.isArray(value) ? value : [value];
468
+ }
469
+ const isClient$1 = typeof window !== "undefined" && typeof document !== "undefined";
470
+ const isDef = (val) => typeof val !== "undefined";
471
+ const assert = (condition, ...infos) => {
472
+ if (!condition) console.warn(...infos);
473
+ };
474
+ const toString$1 = Object.prototype.toString;
475
+ const isObject = (val) => toString$1.call(val) === "[object Object]";
476
+ const now = () => Date.now();
477
+ const timestamp = () => +Date.now();
478
+ const clamp = (n, min, max) => Math.min(max, Math.max(min, n));
479
+ const rand = (min, max) => {
480
+ min = Math.ceil(min);
481
+ max = Math.floor(max);
482
+ return Math.floor(Math.random() * (max - min + 1)) + min;
483
+ };
484
+ const hasOwn = (val, key) => Object.hasOwn(val, key);
485
+ const isIOS = /* #__PURE__ */ getIsIOS();
486
+ function getIsIOS() {
487
+ var _window, _window2, _window3;
488
+ return isClient$1 && !!((_window = window) === null || _window === void 0 || (_window = _window.navigator) === null || _window === void 0 ? void 0 : _window.userAgent) && (/iP(?:ad|hone|od)/.test(window.navigator.userAgent) || ((_window2 = window) === null || _window2 === void 0 || (_window2 = _window2.navigator) === null || _window2 === void 0 ? void 0 : _window2.maxTouchPoints) > 2 && /iPad|Macintosh/.test((_window3 = window) === null || _window3 === void 0 ? void 0 : _window3.navigator.userAgent));
489
+ }
490
+ function cacheStringFunction(fn) {
491
+ const cache = Object.create(null);
492
+ return ((str) => {
493
+ return cache[str] || (cache[str] = fn(str));
494
+ });
495
+ }
496
+ const hyphenateRE = /\B([A-Z])/g;
497
+ const hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, "-$1").toLowerCase());
498
+ /**
499
+ * Type guard for React ref objects (`RefObject` — `{ current }` holders).
500
+ * Callback refs are functions and cannot be read synchronously, so they are
501
+ * not ref-like.
502
+ */
503
+ function isRefLike(value) {
504
+ return value !== null && value !== void 0 && typeof value === "object" && "current" in value;
505
+ }
506
+ function toValue(value) {
507
+ if (Array.isArray(value) && value.length === 2 && typeof value[1] === "function") return value[0];
508
+ if (value !== null && value !== void 0 && typeof value === "object" && "value" in value && !("addEventListener" in value)) return value.value;
509
+ if (typeof value === "function") return value();
510
+ if (isRefLike(value)) return value.current;
511
+ return value;
512
+ }
513
+ /**
514
+ * Write a value back through a writable `State<T>` source — a ref-like
515
+ * `.current`, a `[value, setter]` tuple or a `{ value, onChange }` pair.
516
+ * Plain values and getters have no write path and are skipped. This is the
517
+ * write-side counterpart of `toValue`; hooks that push values into a
518
+ * `State<T>` import it from here rather than re-implementing the branches.
519
+ */
520
+ function writeState(source, value) {
521
+ if (source === null || source === void 0) return;
522
+ if (Array.isArray(source) && source.length === 2 && typeof source[1] === "function") {
523
+ source[1](value);
524
+ return;
525
+ }
526
+ if (isRefLike(source)) {
527
+ source.current = value;
528
+ return;
529
+ }
530
+ if (typeof source === "object" && !Array.isArray(source) && "value" in source && !("addEventListener" in source)) {
531
+ var _onChange;
532
+ (_onChange = source.onChange) === null || _onChange === void 0 || _onChange.call(source, value);
533
+ }
534
+ }
535
+ //#endregion
536
+ //#region isDefined/index.tsx
537
+ function isDefined(v) {
538
+ return (isRefLike(v) ? v.current : v) != null;
539
+ }
540
+ //#endregion
541
+ //#region makeDestructurable/index.tsx
542
+ /**
543
+ * Make isomorphic destructurable for object and array at the same time —
544
+ * React port of VueUse's `makeDestructurable` (a pure utility function, so it
545
+ * maps 1:1 with no React adaptation). See this blog for the underlying idea:
546
+ * https://antfu.me/posts/destructuring-with-object-or-array/
547
+ *
548
+ * Map from @vueuse/shared `makeDestructurable`
549
+ * Upstream semantics are kept verbatim: given `(obj, arr)` the returned value
550
+ * can be destructured as an object (`const { foo, bar } = obj`) or as an array
551
+ * (`const [foo, bar] = obj`) — the array mode is backed by a non-enumerable
552
+ * `Symbol.iterator` defined on a shallow clone of `obj` (spread
553
+ * `{ ...obj }`); `Object.assign` appears only in the no-Symbol SSR fallback.
554
+ *
555
+ * @example
556
+ * const foo = { name: 'foo' }
557
+ * const bar = 1024
558
+ * const obj = makeDestructurable({ foo, bar } as const, [foo, bar] as const)
559
+ * const { foo: f1, bar: b1 } = obj // object destructuring
560
+ * const [f2, b2] = obj // array destructuring
561
+ */
562
+ /* @__NO_SIDE_EFFECTS__ */
563
+ function makeDestructurable(obj, arr) {
564
+ if (typeof Symbol !== "undefined") {
565
+ const clone = { ...obj };
566
+ Object.defineProperty(clone, Symbol.iterator, {
567
+ enumerable: false,
568
+ value() {
569
+ let index = 0;
570
+ return { next: () => ({
571
+ value: arr[index++],
572
+ done: index > arr.length
573
+ }) };
574
+ }
575
+ });
576
+ return clone;
577
+ } else return Object.assign([...arr], obj);
578
+ }
579
+ //#endregion
580
+ //#region syncState/index.tsx
581
+ const neverObserved$1 = Symbol("reause.syncState.neverObserved");
582
+ function classifyWritable(source) {
583
+ if (source === null || source === void 0) return "readonly";
584
+ if (isRefLike(source)) return "sync";
585
+ if (Array.isArray(source) && source.length === 2 && typeof source[1] === "function") return "async";
586
+ if (typeof source === "object" && !Array.isArray(source) && "value" in source && !("addEventListener" in source)) return "async";
587
+ return "readonly";
588
+ }
589
+ /**
590
+ * Two-way state synchronization — keeps two writable `State<T>` sources in
591
+ * sync, with optional direction and value transforms.
592
+ *
593
+ * Map from @vueuse/shared `syncRef`
594
+ * (`source/vueuse/packages/shared/syncRef/`), renamed `syncState` for the
595
+ * React port: the two sides are `State<T>` sources — a `[value, setter]`
596
+ * tuple, a `{ value, onChange }` pair, a ref-like `{ current }`, a getter or
597
+ * a plain value — instead of Vue refs. Each side is read with `toValue` and
598
+ * written back through its writable form (tuple setter / `onChange` /
599
+ * `.current`); plain values and getters have no write path, so that side is
600
+ * treated as read-only (the sync becomes one-way for it).
601
+ *
602
+ * React Hook adaptation: upstream drives both sides through Vue's reactive
603
+ * `watchPausable`, pausing all watchers while writing so a side never echoes
604
+ * its own write back. React has no reactive system, so `syncState` is
605
+ * implemented as a hook (call it unconditionally at the top of a component).
606
+ * A `useEffect` that runs after every commit compares each side's resolved
607
+ * value with the last observed one via `Object.is` and mirrors the changed
608
+ * side into the other — through the optional `transform` convertors when
609
+ * given — recording the value it just wrote as already observed on the
610
+ * receiving side (the React analogue of upstream's pause/resume). Ref-like
611
+ * `.current` writes are synchronous and need no absorption; writes through a
612
+ * setter / `onChange` are asynchronous, so until the target's value reflects
613
+ * the write the stale pre-write value is absorbed and never mistaken for an
614
+ * external change. Read-only sides (plain values / getters) are never marked
615
+ * as written, so a changing source keeps propagating. The initial sync
616
+ * (upstream default `immediate: true`) runs in the mount effect and cascades
617
+ * ltr before rtl,
618
+ * matching upstream's watcher creation order. Because the observation happens
619
+ * post-commit, an external mutation is only adopted on the render that
620
+ * follows it — the mutation itself never schedules a render, so a bare
621
+ * `.current` write outside of React is not observed (see the maintainer
622
+ * notes on reause #40 / #41). The returned `stop` function tears the
623
+ * synchronization down; the effect also stops doing any work once the owning
624
+ * component unmounts.
625
+ *
626
+ * @example
627
+ * const [a, setA] = useState('a')
628
+ * const [b, setB] = useState('b')
629
+ *
630
+ * const stop = syncState([a, setA], [b, setB])
631
+ *
632
+ * console.log(a) // a
633
+ *
634
+ * setB('foo') // then the component re-renders
635
+ * console.log(a) // foo
636
+ *
637
+ * setA('bar') // then the component re-renders
638
+ * console.log(b) // bar
639
+ *
640
+ * stop()
641
+ */
642
+ function syncState(left, right, options = {}) {
643
+ var _transform$ltr, _transform$rtl;
644
+ const { immediate = true, direction = "both", transform = {} } = options;
645
+ const leftRef = (0, react.useRef)(left);
646
+ leftRef.current = left;
647
+ const rightRef = (0, react.useRef)(right);
648
+ rightRef.current = right;
649
+ const transformLTR = (_transform$ltr = transform.ltr) !== null && _transform$ltr !== void 0 ? _transform$ltr : ((v) => v);
650
+ const transformRTL = (_transform$rtl = transform.rtl) !== null && _transform$rtl !== void 0 ? _transform$rtl : ((v) => v);
651
+ const lastLeftRef = (0, react.useRef)(neverObserved$1);
652
+ const lastRightRef = (0, react.useRef)(neverObserved$1);
653
+ const pendingLeftRef = (0, react.useRef)(null);
654
+ const pendingRightRef = (0, react.useRef)(null);
655
+ const stoppedRef = (0, react.useRef)(false);
656
+ (0, react.useEffect)(() => {
657
+ if (stoppedRef.current) return;
658
+ const leftState = leftRef.current;
659
+ const rightState = rightRef.current;
660
+ const l = toValue(leftState);
661
+ const r = toValue(rightState);
662
+ const ltrActive = direction === "both" || direction === "ltr";
663
+ const rtlActive = direction === "both" || direction === "rtl";
664
+ if (lastLeftRef.current === neverObserved$1 && lastRightRef.current === neverObserved$1) {
665
+ let lastLeft = l;
666
+ let lastRight = r;
667
+ if (immediate) {
668
+ if (ltrActive) {
669
+ const newRight = transformLTR(l);
670
+ if (!Object.is(r, newRight)) {
671
+ const rightKind = classifyWritable(rightState);
672
+ if (rightKind !== "readonly") {
673
+ writeState(rightState, newRight);
674
+ lastRight = newRight;
675
+ if (rightKind === "async") pendingRightRef.current = {
676
+ before: r,
677
+ after: newRight
678
+ };
679
+ }
680
+ }
681
+ if (rtlActive) {
682
+ const newLeft = transformRTL(newRight);
683
+ if (!Object.is(l, newLeft)) {
684
+ const leftKind = classifyWritable(leftState);
685
+ if (leftKind !== "readonly") {
686
+ writeState(leftState, newLeft);
687
+ lastLeft = newLeft;
688
+ if (leftKind === "async") pendingLeftRef.current = {
689
+ before: l,
690
+ after: newLeft
691
+ };
692
+ }
693
+ }
694
+ }
695
+ } else {
696
+ const newLeft = transformRTL(r);
697
+ if (!Object.is(l, newLeft)) {
698
+ const leftKind = classifyWritable(leftState);
699
+ if (leftKind !== "readonly") {
700
+ writeState(leftState, newLeft);
701
+ lastLeft = newLeft;
702
+ if (leftKind === "async") pendingLeftRef.current = {
703
+ before: l,
704
+ after: newLeft
705
+ };
706
+ }
707
+ }
708
+ }
709
+ }
710
+ lastLeftRef.current = lastLeft;
711
+ lastRightRef.current = lastRight;
712
+ return;
713
+ }
714
+ const leftPending = pendingLeftRef.current;
715
+ const rightPending = pendingRightRef.current;
716
+ const leftChanged = !Object.is(lastLeftRef.current, l) && !(leftPending && Object.is(leftPending.before, l));
717
+ const rightChanged = !Object.is(lastRightRef.current, r) && !(rightPending && Object.is(rightPending.before, r));
718
+ if (leftPending && !Object.is(leftPending.before, l)) pendingLeftRef.current = null;
719
+ if (rightPending && !Object.is(rightPending.before, r)) pendingRightRef.current = null;
720
+ if (ltrActive && leftChanged) {
721
+ lastLeftRef.current = l;
722
+ const converted = transformLTR(l);
723
+ if (!Object.is(r, converted)) {
724
+ const rightKind = classifyWritable(rightState);
725
+ if (rightKind !== "readonly") {
726
+ writeState(rightState, converted);
727
+ lastRightRef.current = converted;
728
+ if (rightKind === "async") pendingRightRef.current = {
729
+ before: r,
730
+ after: converted
731
+ };
732
+ }
733
+ }
734
+ }
735
+ if (rtlActive && rightChanged) {
736
+ lastRightRef.current = r;
737
+ const converted = transformRTL(r);
738
+ if (!Object.is(l, converted)) {
739
+ const leftKind = classifyWritable(leftState);
740
+ if (leftKind !== "readonly") {
741
+ writeState(leftState, converted);
742
+ lastLeftRef.current = converted;
743
+ if (leftKind === "async") pendingLeftRef.current = {
744
+ before: l,
745
+ after: converted
746
+ };
747
+ }
748
+ }
749
+ }
750
+ });
751
+ return () => {
752
+ stoppedRef.current = true;
753
+ };
754
+ }
755
+ //#endregion
756
+ //#region syncStates/index.tsx
757
+ const neverObserved = Symbol("reause.syncStates.neverObserved");
758
+ /**
759
+ * Keep target state(s) in sync with a source value — React port of VueUse's
760
+ * `syncRefs`.
761
+ *
762
+ * Map from @vueuse/shared `syncRefs`
763
+ * (`source/vueuse/packages/shared/syncRefs/`), renamed `syncStates` for the
764
+ * React port: the source is a `State<T>` — a plain value, getter, ref-like,
765
+ * `[value, setter]` tuple or `{ value, onChange }` pair (upstream:
766
+ * `WatchSource`) — resolved with `toValue`; the targets are writable
767
+ * `State<T>` sources written back through their writable form (tuple setter /
768
+ * `onChange` / `.current`); upstream's `flush` / `deep` / `immediate` options
769
+ * are kept for signature compatibility.
770
+ *
771
+ * React Hook adaptation: upstream syncs through Vue's reactive `watch`, and
772
+ * React has no reactive system — so `syncStates` is implemented as a hook
773
+ * (call it unconditionally at the top of a component). Internally a
774
+ * `useEffect` that runs after every commit compares the resolved source value
775
+ * with the last observed one via `Object.is`; a change is written through to
776
+ * all targets. Because the observation happens post-commit, the caller must
777
+ * re-render (e.g. `setState`) for a new source value to reach the targets —
778
+ * a bare mutation outside of React is never observed (see the maintainer
779
+ * notes on reause #40 / #41). The returned `stop` function tears the
780
+ * synchronization down; the effect also stops doing any work once the owning
781
+ * component unmounts.
782
+ *
783
+ * @example
784
+ * function Form() {
785
+ * const [source, setSource] = useState('hello')
786
+ * const [target, setTarget] = useState('target')
787
+ *
788
+ * const stop = syncStates(source, [target, setTarget])
789
+ *
790
+ * // during the first render `target` is still 'target' — the sync effect
791
+ * // runs after the commit, so the source reaches the target only once the
792
+ * // component has mounted (target === 'hello' afterwards).
793
+ * // Calling `setSource('foo')` re-renders and the effect then copies 'foo'
794
+ * // into the target state on the following commit.
795
+ *
796
+ * stop()
797
+ * }
798
+ */
799
+ function syncStates(source, targets, options = {}) {
800
+ const { immediate = true } = options;
801
+ const sourceRef = (0, react.useRef)(source);
802
+ sourceRef.current = source;
803
+ const isTupleTarget = Array.isArray(targets) && targets.length === 2 && typeof targets[1] === "function";
804
+ const targetsArray = Array.isArray(targets) && !isTupleTarget ? targets : [targets];
805
+ const targetsRef = (0, react.useRef)(targetsArray);
806
+ targetsRef.current = targetsArray;
807
+ const lastValueRef = (0, react.useRef)(neverObserved);
808
+ const stoppedRef = (0, react.useRef)(false);
809
+ (0, react.useEffect)(() => {
810
+ if (stoppedRef.current) return;
811
+ const value = toValue(sourceRef.current);
812
+ const last = lastValueRef.current;
813
+ lastValueRef.current = value;
814
+ if (last === neverObserved) {
815
+ if (!immediate) return;
816
+ } else if (Object.is(last, value)) return;
817
+ targetsRef.current.forEach((target) => {
818
+ if (!Object.is(toValue(target), value)) writeState(target, value);
819
+ });
820
+ });
821
+ return (0, react.useCallback)(() => {
822
+ stoppedRef.current = true;
823
+ }, []);
824
+ }
825
+ //#endregion
826
+ //#region until/index.tsx
827
+ /**
828
+ * Polling interval (ms) used to resolve `until` promises. React has no
829
+ * reactive watch, so the port re-reads the source at this fixed interval —
830
+ * the same polling approach `useFetch` uses for its `refetch` watch.
831
+ */
832
+ const UNTIL_POLL_INTERVAL = 50;
833
+ /**
834
+ * Minimal structural equality — `Object.is` for primitives (so `NaN` equals
835
+ * `NaN`), arrays compared by length and element, plain objects by own-key
836
+ * count and value. Used by `changedTimes` when `deep: true`.
837
+ */
838
+ function deepEquals(a, b) {
839
+ if (Object.is(a, b)) return true;
840
+ if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
841
+ const aIsArray = Array.isArray(a);
842
+ const bIsArray = Array.isArray(b);
843
+ if (aIsArray !== bIsArray) return false;
844
+ if (aIsArray && bIsArray) {
845
+ const arrA = a;
846
+ const arrB = b;
847
+ if (arrA.length !== arrB.length) return false;
848
+ return arrA.every((item, index) => deepEquals(item, arrB[index]));
849
+ }
850
+ const keysA = Object.keys(a);
851
+ const keysB = Object.keys(b);
852
+ if (keysA.length !== keysB.length) return false;
853
+ return keysA.every((key) => deepEquals(a[key], b[key]));
854
+ }
855
+ /**
856
+ * Clone used to snapshot the source between polls when `changedTimes` runs
857
+ * with `deep: true` — the poller re-reads the same reference, so a reference
858
+ * copy could never see an in-place mutation.
859
+ */
860
+ function cloneDeep(value) {
861
+ if (value === null || typeof value !== "object") return value;
862
+ if (Array.isArray(value)) return value.map((item) => cloneDeep(item));
863
+ const result = {};
864
+ for (const key of Object.keys(value)) result[key] = cloneDeep(value[key]);
865
+ return result;
866
+ }
867
+ /**
868
+ * Resolve the accepted `until` source — a plain value or a zero-argument
869
+ * getter (the React-idiomatic live source; a `Ref` / `{ current }` object is
870
+ * not accepted — pass `() => ref.current`).
871
+ *
872
+ * NOTE: a source value that *is* a function is treated as a getter and
873
+ * invoked (the same ambiguity `toValue` has).
874
+ */
875
+ function resolveSource(source) {
876
+ return typeof source === "function" ? source() : source;
877
+ }
878
+ function createUntil(r, isNot = false) {
879
+ function toMatch(condition, { timeout, throwOnTimeout } = {}) {
880
+ let stop = null;
881
+ const promises = [new Promise((resolve) => {
882
+ let settled = false;
883
+ const check = () => {
884
+ if (settled) return;
885
+ const value = resolveSource(r);
886
+ if (condition(value) !== isNot) {
887
+ settled = true;
888
+ stop === null || stop === void 0 || stop();
889
+ resolve(value);
890
+ }
891
+ };
892
+ check();
893
+ if (!settled) {
894
+ const timer = setInterval(check, UNTIL_POLL_INTERVAL);
895
+ stop = () => clearInterval(timer);
896
+ }
897
+ })];
898
+ if (timeout != null) promises.push(promiseTimeout(timeout, throwOnTimeout).then(() => resolveSource(r)).finally(() => stop === null || stop === void 0 ? void 0 : stop()));
899
+ return Promise.race(promises);
900
+ }
901
+ function toBe(value, options) {
902
+ return toMatch((v) => v === value, options);
903
+ }
904
+ function toBeTruthy(options) {
905
+ return toMatch((v) => Boolean(v), options);
906
+ }
907
+ function toBeNull(options) {
908
+ return toBe(null, options);
909
+ }
910
+ function toBeUndefined(options) {
911
+ return toBe(void 0, options);
912
+ }
913
+ function toBeNaN(options) {
914
+ return toMatch(Number.isNaN, options);
915
+ }
916
+ function toContains(value, options) {
917
+ return toMatch((v) => {
918
+ return Array.from(v).includes(value);
919
+ }, options);
920
+ }
921
+ function changed(options) {
922
+ return changedTimes(1, options);
923
+ }
924
+ function changedTimes(n = 1, options) {
925
+ var _options$deep;
926
+ let count = 0;
927
+ let hasBaseline = false;
928
+ let lastValue;
929
+ const deep = (_options$deep = options === null || options === void 0 ? void 0 : options.deep) !== null && _options$deep !== void 0 ? _options$deep : false;
930
+ const snapshot = (value) => deep ? cloneDeep(value) : value;
931
+ return toMatch((v) => {
932
+ if (!hasBaseline) {
933
+ hasBaseline = true;
934
+ lastValue = snapshot(v);
935
+ return count >= n;
936
+ }
937
+ if (deep ? !deepEquals(lastValue, v) : !Object.is(lastValue, v)) {
938
+ count += 1;
939
+ lastValue = snapshot(v);
940
+ }
941
+ return count >= n;
942
+ }, options);
943
+ }
944
+ if (Array.isArray(resolveSource(r))) return {
945
+ toMatch,
946
+ toContains,
947
+ changed,
948
+ changedTimes,
949
+ get not() {
950
+ return createUntil(r, !isNot);
951
+ }
952
+ };
953
+ else return {
954
+ toMatch,
955
+ toBe,
956
+ toBeTruthy,
957
+ toBeNull,
958
+ toBeNaN,
959
+ toBeUndefined,
960
+ changed,
961
+ changedTimes,
962
+ get not() {
963
+ return createUntil(r, !isNot);
964
+ }
965
+ };
966
+ }
967
+ function until(r) {
968
+ return createUntil(r);
969
+ }
970
+ //#endregion
971
+ //#region useArrayDifference/index.tsx
972
+ function defaultComparator(value, othVal) {
973
+ return value === othVal;
974
+ }
975
+ /**
976
+ * React port of VueUse's `useArrayDifference`.
977
+ *
978
+ * Map from @vueuse/shared `useArrayDifference`
979
+ * Mapping: upstream wraps the diff passes in `computed(...)` and returns a
980
+ * `ComputedRef`; React has no reactive value tracking, so this is a plain
981
+ * function recomputed on every render over the plain `list` / `values` arrays
982
+ * the caller passes — pass state arrays and the difference is re-diffed on the
983
+ * next render, no `.value` on the result. The same three call shapes as
984
+ * upstream are supported: plain diff, diff by `key`, and diff by `compareFn`,
985
+ * plus the `{ symmetric }` option.
986
+ *
987
+ * @see https://vueuse.org/shared/useArrayDifference/
988
+ *
989
+ * @example
990
+ * const list = [{ id: 1 }, { id: 2 }, { id: 3 }]
991
+ * useArrayDifference(list, [{ id: 3 }]) // [{ id: 1 }, { id: 2 }]
992
+ * useArrayDifference(list, [{ id: 3 }], 'id') // diff by key
993
+ * useArrayDifference(list, [{ id: 3 }], (a, b) => a.id === b.id, { symmetric: true })
994
+ */
995
+ function useArrayDifference(...args) {
996
+ var _args$, _args$2;
997
+ const list = args[0];
998
+ const values = args[1];
999
+ let compareFn = (_args$ = args[2]) !== null && _args$ !== void 0 ? _args$ : defaultComparator;
1000
+ const { symmetric = false } = (_args$2 = args[3]) !== null && _args$2 !== void 0 ? _args$2 : {};
1001
+ if (typeof compareFn === "string") {
1002
+ const key = compareFn;
1003
+ compareFn = (value, othVal) => value[key] === othVal[key];
1004
+ }
1005
+ const diff1 = list.filter((x) => values.findIndex((y) => compareFn(x, y)) === -1);
1006
+ if (symmetric) {
1007
+ const diff2 = values.filter((x) => list.findIndex((y) => compareFn(x, y)) === -1);
1008
+ return [...diff1, ...diff2];
1009
+ } else return diff1;
1010
+ }
1011
+ //#endregion
1012
+ //#region useArrayEvery/index.tsx
1013
+ /**
1014
+ * React port of VueUse's `useArrayEvery`.
1015
+ *
1016
+ * Map from @vueuse/shared `useArrayEvery`
1017
+ * Mapping: upstream wraps `toValue(list).every(...)` in `computed(() => ...)`
1018
+ * and returns a `ComputedRef`; React has no reactive value tracking, so this
1019
+ * is a plain function recomputed on every render over the plain `list` array
1020
+ * the caller passes. Hold the array in `useState` (or any render-scoped value)
1021
+ * and pass a new array to observe a change — the result recomputes on the next
1022
+ * render. The predicate may return any value (coerced by truthiness, like
1023
+ * `Array.prototype.every`).
1024
+ *
1025
+ * @see https://vueuse.org/shared/useArrayEvery/
1026
+ *
1027
+ * @example
1028
+ * const [list, setList] = useState([0, 2, 4])
1029
+ * useArrayEvery(list, val => val % 2 === 0) // true
1030
+ * setList([0, 2, 5]) // false on the next render
1031
+ *
1032
+ * @param list - the array was called upon.
1033
+ * @param fn - a function to test each element.
1034
+ *
1035
+ * @returns **true** if the `fn` function returns a **truthy** value for every element from the array. Otherwise, **false**.
1036
+ */
1037
+ function useArrayEvery(list, fn) {
1038
+ return list.every(fn);
1039
+ }
1040
+ //#endregion
1041
+ //#region useArrayFilter/index.tsx
1042
+ function useArrayFilter(list, fn) {
1043
+ return list.filter(fn);
1044
+ }
1045
+ //#endregion
1046
+ //#region useArrayFind/index.tsx
1047
+ /**
1048
+ * React port of VueUse's `useArrayFind`.
1049
+ *
1050
+ * Map from @vueuse/shared `useArrayFind`
1051
+ * Mapping: upstream wraps `toValue(list).find(...)` in `computed(() => ...)`
1052
+ * and returns a `ComputedRef`; React has no reactive value tracking, so this
1053
+ * is a plain function recomputed on every render over the plain `list` array
1054
+ * the caller passes. Hold the array in `useState` and pass a new array to
1055
+ * observe a change — the first match is returned on the next render.
1056
+ *
1057
+ * @see https://vueuse.org/shared/useArrayFind/
1058
+ *
1059
+ * @example
1060
+ * const [list, setList] = useState([1, -1, 2])
1061
+ * useArrayFind(list, val => val > 0) // 1
1062
+ * setList([3, -1, 2]) // 3 on the next render
1063
+ */
1064
+ function useArrayFind(list, fn) {
1065
+ return list.find(fn);
1066
+ }
1067
+ //#endregion
1068
+ //#region useArrayFindIndex/index.tsx
1069
+ /**
1070
+ * React port of VueUse's `useArrayFindIndex`.
1071
+ *
1072
+ * Map from @vueuse/shared `useArrayFindIndex`
1073
+ * Mapping: upstream wraps `toValue(list).findIndex(...)` in `computed(...)`
1074
+ * and accepts a `RefOrValue`; React has no reactive value tracking, so
1075
+ * this is a plain function that recomputes the index on every render — pass
1076
+ * a state array (upstream: reactive array) and re-render with new state to
1077
+ * see the updated result. The return is a plain number, no `.value`.
1078
+ *
1079
+ * @example
1080
+ * const [list, setList] = useState([0, 2, 4, 6, 8])
1081
+ * useArrayFindIndex(list, i => i % 2 === 0) // 0
1082
+ *
1083
+ * setList([1, 3, 5, 7, 9]) // result === -1 on the next render
1084
+ *
1085
+ * @param list - the array was called upon.
1086
+ * @param fn - a function to test each element.
1087
+ *
1088
+ * @returns the index of the first element in the array that passes the test. Otherwise, "-1".
1089
+ */
1090
+ function useArrayFindIndex(list, fn) {
1091
+ return list.findIndex(fn);
1092
+ }
1093
+ //#endregion
1094
+ //#region useArrayFindLast/index.tsx
1095
+ /**
1096
+ * Loop equivalent of `Array.prototype.findLast` — upstream ships the same
1097
+ * fallback for runtimes without the native method (e.g. node < 18); the repo
1098
+ * targets lib ES2022, where the native method is not available.
1099
+ */
1100
+ function findLast(array, fn) {
1101
+ for (let index = array.length - 1; index >= 0; index--) if (fn(array[index], index, array)) return array[index];
1102
+ }
1103
+ /**
1104
+ * React port of VueUse's `useArrayFindLast`.
1105
+ *
1106
+ * Map from @vueuse/shared `useArrayFindLast`
1107
+ * Mapping: upstream wraps native `Array.prototype.findLast` (with a loop
1108
+ * fallback for runtimes without it) in `computed(() => ...)` and returns a
1109
+ * `ComputedRef`; React has no reactive value tracking, so this is a plain
1110
+ * function recomputed on every render over the plain `list` array the caller
1111
+ * passes — the loop helper stands in for the native method since the repo
1112
+ * targets lib ES2022. Hold the array in `useState` and pass a new array to
1113
+ * observe a change — the last match is returned on the next render.
1114
+ *
1115
+ * @see https://vueuse.org/shared/useArrayFindLast/
1116
+ *
1117
+ * @example
1118
+ * const [list, setList] = useState([1, -1, 2])
1119
+ * useArrayFindLast(list, val => val > 0) // 2
1120
+ * setList([1, -1, -2]) // 1 on the next render
1121
+ */
1122
+ function useArrayFindLast(list, fn) {
1123
+ return findLast(list, fn);
1124
+ }
1125
+ //#endregion
1126
+ //#region useArrayIncludes/index.tsx
1127
+ const toString = Object.prototype.toString;
1128
+ function isObject$1(val) {
1129
+ return toString.call(val) === "[object Object]";
1130
+ }
1131
+ function containsProp(obj, ...props) {
1132
+ return props.some((k) => k in obj);
1133
+ }
1134
+ function isArrayIncludesOptions(obj) {
1135
+ return isObject$1(obj) && containsProp(obj, "formIndex", "comparator");
1136
+ }
1137
+ function useArrayIncludes(...args) {
1138
+ var _comparator;
1139
+ const list = args[0];
1140
+ const value = args[1];
1141
+ let comparator = args[2];
1142
+ let formIndex = 0;
1143
+ if (isArrayIncludesOptions(comparator)) {
1144
+ var _comparator$fromIndex;
1145
+ formIndex = (_comparator$fromIndex = comparator.fromIndex) !== null && _comparator$fromIndex !== void 0 ? _comparator$fromIndex : 0;
1146
+ comparator = comparator.comparator;
1147
+ }
1148
+ if (typeof comparator === "string") {
1149
+ const key = comparator;
1150
+ comparator = (element, value) => element[key] === value;
1151
+ }
1152
+ comparator = (_comparator = comparator) !== null && _comparator !== void 0 ? _comparator : ((element, value) => element === value);
1153
+ return list.slice(formIndex).some((element, index, arr) => comparator(element, value, index, arr));
1154
+ }
1155
+ //#endregion
1156
+ //#region useArrayJoin/index.tsx
1157
+ /**
1158
+ * React port of VueUse's `useArrayJoin`.
1159
+ *
1160
+ * Map from @vueuse/shared `useArrayJoin`
1161
+ * Mapping: upstream wraps `toValue(list).map(i => toValue(i)).join(toValue(separator))`
1162
+ * in `computed(...)` and accepts a `RefOrValue`; React has no reactive
1163
+ * value tracking, so this is a plain function that recomputes the join on
1164
+ * every render — pass a state array (upstream: reactive array) and re-render
1165
+ * with new state to see the updated result. The return is a plain string,
1166
+ * no `.value`.
1167
+ *
1168
+ * `list` holds plain values only: the elements are joined with
1169
+ * `Array.prototype.join`, so no per-element unwrap happens (upstream
1170
+ * `toValue`s each element). A function element would be stringified to its
1171
+ * source instead of invoked.
1172
+ *
1173
+ * @example
1174
+ * const [list, setList] = useState(['foo', 0, { prop: 'val' }])
1175
+ * useArrayJoin(list) // 'foo,0,[object Object]'
1176
+ * useArrayJoin(list, '--') // 'foo--0--[object Object]'
1177
+ *
1178
+ * setList([...list, 'bar']) // result === 'foo--0--[object Object]--bar' on the next render
1179
+ *
1180
+ * @param list - the array was called upon.
1181
+ * @param separator - a string to separate each pair of adjacent elements of the array. If omitted, the array elements are separated with a comma (",").
1182
+ *
1183
+ * @returns a string with all array elements joined. If `list.length` is 0, the empty string is returned.
1184
+ */
1185
+ function useArrayJoin(list, separator) {
1186
+ return list.join(separator);
1187
+ }
1188
+ //#endregion
1189
+ //#region useArrayMap/index.tsx
1190
+ /**
1191
+ * Reactive `Array.map`
1192
+ *
1193
+ * Map from @vueuse/shared `useArrayMap`
1194
+ * React port of VueUse's `useArrayMap`.
1195
+ *
1196
+ * Mapping: Vue's `computed` → recompute per render and return a plain array
1197
+ * (no `.value`) over the plain `list` array the caller passes.
1198
+ * Pass a `useState` array directly — the result updates on the next render.
1199
+ *
1200
+ * @example
1201
+ * const [list, setList] = useState([0, 1, 2, 3, 4])
1202
+ * const result = useArrayMap(list, i => i * 2) // [0, 2, 4, 6, 8]
1203
+ * setList(list.slice(0, -1)) // result: [0, 2, 4, 6] on the next render
1204
+ */
1205
+ function useArrayMap(list, fn) {
1206
+ return list.map(fn);
1207
+ }
1208
+ //#endregion
1209
+ //#region useArrayReduce/index.tsx
1210
+ function useArrayReduce(list, reducer, ...args) {
1211
+ const reduceCallback = (sum, value, index) => reducer(sum, value, index);
1212
+ const initial = typeof args[0] === "function" ? args[0]() : args[0];
1213
+ return args.length ? list.reduce(reduceCallback, initial) : list.reduce(reduceCallback);
1214
+ }
1215
+ //#endregion
1216
+ //#region useArraySome/index.tsx
1217
+ /**
1218
+ * React port of VueUse's `useArraySome`.
1219
+ *
1220
+ * Map from @vueuse/shared `useArraySome`
1221
+ * Mapping: `computed(() => ...)` → recompute on every render — the result is a
1222
+ * plain `boolean` (no `.value`, no caching) computed from the plain `list`
1223
+ * array the caller passes. Hold the array in `useState` and pass a new array
1224
+ * to observe a change; the result recomputes on the next render.
1225
+ *
1226
+ * @see https://vueuse.org/shared/useArraySome/
1227
+ * @param list - the array was called upon.
1228
+ * @param fn - a function to test each element.
1229
+ *
1230
+ * @returns **true** if the `fn` function returns a **truthy** value for any element from the array. Otherwise, **false**.
1231
+ *
1232
+ * @example
1233
+ * const [list, setList] = useState([0, 2, 4, 6, 8])
1234
+ * const result = useArraySome(list, i => i > 10) // false
1235
+ * setList([...list, 11]) // result === true on the next render
1236
+ */
1237
+ function useArraySome(list, fn) {
1238
+ return list.some(fn);
1239
+ }
1240
+ //#endregion
1241
+ //#region useArrayUnique/index.tsx
1242
+ /**
1243
+ * Reactive `Array.unique`
1244
+ *
1245
+ * Map from @vueuse/shared `useArrayUnique`
1246
+ * React port of VueUse's `useArrayUnique`.
1247
+ *
1248
+ * Mapping: upstream wraps `toValue(list)` in `computed(() => ...)` and returns
1249
+ * a `ComputedRef`; React has no reactive value tracking, so this is a plain
1250
+ * function recomputed on every render over the plain `list` array the caller
1251
+ * passes — the result is a deduped plain array (no `.value`, no caching).
1252
+ * Duplicate detection uses a `Set` of the values (reference identity for
1253
+ * objects) unless a custom `compareFn` is given — same as upstream. Hold the
1254
+ * array in `useState` and pass a new array to observe a change.
1255
+ *
1256
+ * @see https://vueuse.org/shared/useArrayUnique/
1257
+ *
1258
+ * @example
1259
+ * const [list, setList] = useState([0, 2, 2, 4, 4, 4])
1260
+ * const result = useArrayUnique(list) // [0, 2, 4]
1261
+ *
1262
+ * setList([0, 2, 4, 6, 6]) // result === [0, 2, 4, 6] on the next render
1263
+ */
1264
+ function useArrayUnique(list, compareFn) {
1265
+ return compareFn ? uniqueElementsBy(list, compareFn) : uniq(list);
1266
+ }
1267
+ function uniq(array) {
1268
+ return Array.from(new Set(array));
1269
+ }
1270
+ function uniqueElementsBy(array, fn) {
1271
+ return array.reduce((acc, v) => {
1272
+ if (!acc.some((x) => fn(v, x, array))) acc.push(v);
1273
+ return acc;
1274
+ }, []);
1275
+ }
1276
+ //#endregion
1277
+ //#region useControllableState/index.tsx
1278
+ function isTuple(state) {
1279
+ return Array.isArray(state) && state.length === 2 && typeof state[1] === "function";
1280
+ }
1281
+ function isObjectState$1(state) {
1282
+ return typeof state === "object" && state !== null && !Array.isArray(state) && "value" in state;
1283
+ }
1284
+ /**
1285
+ * Combine controlled and uncontrolled state sources.
1286
+ *
1287
+ * `state` is resolved with `toValue` on every render. A tuple
1288
+ * `[value, setter]` or a `{ value, onChange }` pair is always controlled: the
1289
+ * current value is the resolved source and `setValue` writes through to the
1290
+ * tuple setter / `onChange`. With `passive: true` a plain value, getter, or
1291
+ * ref source is uncontrolled — the hook initializes from the source and local
1292
+ * updates persist, and external source changes are synced back (honoring
1293
+ * `shouldUpdate`). With the default `passive: false` such a source is
1294
+ * controlled (the external value wins on every render); `setValue` then has
1295
+ * no channel back to the caller, so it warns instead of silently discarding
1296
+ * the update — pass a tuple, a `{ value, onChange }` pair, or use
1297
+ * `passive: true` to write. `defaultValue` (value or lazy initializer) seeds
1298
+ * the internal state of uncontrolled sources; `shouldUpdate(prev, next)`
1299
+ * guards every commit, including the passive sync.
1300
+ */
1301
+ function useControllableState(state, options = {}) {
1302
+ const { defaultValue, shouldUpdate = (prev, next) => !Object.is(prev, next), passive = false } = options;
1303
+ const controlled = isTuple(state) || isObjectState$1(state) || !passive;
1304
+ const externalValue = toValue(state);
1305
+ const initial = defaultValue === void 0 ? externalValue : typeof defaultValue === "function" ? defaultValue() : defaultValue;
1306
+ const [internal, setInternal] = (0, react.useState)(initial);
1307
+ const value = controlled ? externalValue : internal;
1308
+ const valueRef = (0, react.useRef)(value);
1309
+ const previousExternalRef = (0, react.useRef)(externalValue);
1310
+ valueRef.current = value;
1311
+ const stateRef = (0, react.useRef)(state);
1312
+ stateRef.current = state;
1313
+ (0, react.useEffect)(() => {
1314
+ const canSync = typeof state === "function" || isRefLike(state) || externalValue === null || typeof externalValue !== "object";
1315
+ if (passive && canSync && !isTuple(state) && !isObjectState$1(state) && !Object.is(previousExternalRef.current, externalValue) && shouldUpdate(valueRef.current, externalValue)) setInternal(externalValue);
1316
+ previousExternalRef.current = externalValue;
1317
+ }, [
1318
+ externalValue,
1319
+ passive,
1320
+ shouldUpdate
1321
+ ]);
1322
+ return [value, (0, react.useCallback)((action) => {
1323
+ var _currentState$onChang;
1324
+ const prev = valueRef.current;
1325
+ const next = typeof action === "function" ? action(prev) : action;
1326
+ if (!shouldUpdate(prev, next)) return;
1327
+ const currentState = stateRef.current;
1328
+ if (isTuple(currentState)) currentState[1](next);
1329
+ else if (isObjectState$1(currentState)) (_currentState$onChang = currentState.onChange) === null || _currentState$onChang === void 0 || _currentState$onChang.call(currentState, next);
1330
+ else if (!controlled) setInternal(next);
1331
+ else assert(false, "useControllableState: `setValue` on a controlled source without a write channel (a plain value, getter, or ref with `passive: false`) is ignored. Pass a [value, setter] tuple, a { value, onChange } pair, or use `passive: true`.");
1332
+ }, [controlled, shouldUpdate])];
1333
+ }
1334
+ //#endregion
1335
+ //#region useCounter/index.tsx
1336
+ /**
1337
+ * React port of VueUse's `useCounter`.
1338
+ *
1339
+ * Map from @vueuse/shared `useCounter`
1340
+ * Mapping: `ref(initialValue)` → `useState`, mutation functions become
1341
+ * stable `useCallback`s; options are kept in refs so callbacks stay stable.
1342
+ *
1343
+ * @example
1344
+ * const { count, inc, dec, set, reset } = useCounter(10, { min: 0, max: 100 })
1345
+ */
1346
+ function useCounter(initialValue = 0, options = {}) {
1347
+ const { min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY } = options;
1348
+ const minRef = (0, react.useRef)(min);
1349
+ const maxRef = (0, react.useRef)(max);
1350
+ const initialRef = (0, react.useRef)(toValue(initialValue));
1351
+ const [count, setCount] = useControllableState(initialValue, { passive: true });
1352
+ const set = (0, react.useCallback)((value) => {
1353
+ setCount((current) => {
1354
+ const next = clamp(value, minRef.current, maxRef.current);
1355
+ return current === next ? current : next;
1356
+ });
1357
+ }, []);
1358
+ const get = (0, react.useCallback)(() => count, [count]);
1359
+ return {
1360
+ count,
1361
+ inc: (0, react.useCallback)((delta = 1) => {
1362
+ setCount((current) => {
1363
+ const next = clamp(current + delta, minRef.current, maxRef.current);
1364
+ return current === next ? current : next;
1365
+ });
1366
+ }, []),
1367
+ dec: (0, react.useCallback)((delta = 1) => {
1368
+ setCount((current) => {
1369
+ const next = clamp(current - delta, minRef.current, maxRef.current);
1370
+ return current === next ? current : next;
1371
+ });
1372
+ }, []),
1373
+ get,
1374
+ set,
1375
+ reset: (0, react.useCallback)((val) => {
1376
+ const target = val === void 0 ? initialRef.current : val;
1377
+ initialRef.current = target;
1378
+ const next = clamp(target, minRef.current, maxRef.current);
1379
+ setCount((current) => current === next ? current : next);
1380
+ return next;
1381
+ }, [])
1382
+ };
1383
+ }
1384
+ //#endregion
1385
+ //#region useDateFormat/index.tsx
1386
+ const REGEX_PARSE = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[T\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/i;
1387
+ const REGEX_FORMAT = /[YMDHhms]o|\[([^\]]+)\]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a{1,2}|A{1,2}|m{1,2}|s{1,2}|Z{1,2}|z{1,4}|SSS/g;
1388
+ function defaultMeridiem(hours, minutes, isLowercase, hasPeriod) {
1389
+ let m = hours < 12 ? "AM" : "PM";
1390
+ if (hasPeriod) m = m.split("").reduce((acc, curr) => acc += `${curr}.`, "");
1391
+ return isLowercase ? m.toLowerCase() : m;
1392
+ }
1393
+ function formatOrdinal(num) {
1394
+ const suffixes = [
1395
+ "th",
1396
+ "st",
1397
+ "nd",
1398
+ "rd"
1399
+ ];
1400
+ const v = num % 100;
1401
+ return num + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);
1402
+ }
1403
+ /**
1404
+ * Unwrap the house input convention — a plain value, a ref-like `{ current }`
1405
+ * or a getter function (house replacement for Vue's `toValue` /
1406
+ * `RefOrValue<T>`).
1407
+ */
1408
+ function formatDate(date, formatStr, options = {}) {
1409
+ var _options$customMeridi;
1410
+ const years = date.getFullYear();
1411
+ const month = date.getMonth();
1412
+ const days = date.getDate();
1413
+ const hours = date.getHours();
1414
+ const minutes = date.getMinutes();
1415
+ const seconds = date.getSeconds();
1416
+ const milliseconds = date.getMilliseconds();
1417
+ const day = date.getDay();
1418
+ const meridiem = (_options$customMeridi = options.customMeridiem) !== null && _options$customMeridi !== void 0 ? _options$customMeridi : defaultMeridiem;
1419
+ const stripTimeZone = (dateString) => {
1420
+ var _dateString$split$;
1421
+ return (_dateString$split$ = dateString.split(" ")[1]) !== null && _dateString$split$ !== void 0 ? _dateString$split$ : "";
1422
+ };
1423
+ const matches = {
1424
+ Yo: () => formatOrdinal(years),
1425
+ YY: () => String(years).slice(-2),
1426
+ YYYY: () => years,
1427
+ M: () => month + 1,
1428
+ Mo: () => formatOrdinal(month + 1),
1429
+ MM: () => `${month + 1}`.padStart(2, "0"),
1430
+ MMM: () => date.toLocaleDateString(options.locales, { month: "short" }),
1431
+ MMMM: () => date.toLocaleDateString(options.locales, { month: "long" }),
1432
+ D: () => String(days),
1433
+ Do: () => formatOrdinal(days),
1434
+ DD: () => `${days}`.padStart(2, "0"),
1435
+ H: () => String(hours),
1436
+ Ho: () => formatOrdinal(hours),
1437
+ HH: () => `${hours}`.padStart(2, "0"),
1438
+ h: () => `${hours % 12 || 12}`.padStart(1, "0"),
1439
+ ho: () => formatOrdinal(hours % 12 || 12),
1440
+ hh: () => `${hours % 12 || 12}`.padStart(2, "0"),
1441
+ m: () => String(minutes),
1442
+ mo: () => formatOrdinal(minutes),
1443
+ mm: () => `${minutes}`.padStart(2, "0"),
1444
+ s: () => String(seconds),
1445
+ so: () => formatOrdinal(seconds),
1446
+ ss: () => `${seconds}`.padStart(2, "0"),
1447
+ SSS: () => `${milliseconds}`.padStart(3, "0"),
1448
+ d: () => day,
1449
+ dd: () => date.toLocaleDateString(options.locales, { weekday: "narrow" }),
1450
+ ddd: () => date.toLocaleDateString(options.locales, { weekday: "short" }),
1451
+ dddd: () => date.toLocaleDateString(options.locales, { weekday: "long" }),
1452
+ A: () => meridiem(hours, minutes),
1453
+ AA: () => meridiem(hours, minutes, false, true),
1454
+ a: () => meridiem(hours, minutes, true),
1455
+ aa: () => meridiem(hours, minutes, true, true),
1456
+ z: () => stripTimeZone(date.toLocaleDateString(options.locales, { timeZoneName: "shortOffset" })),
1457
+ zz: () => stripTimeZone(date.toLocaleDateString(options.locales, { timeZoneName: "shortOffset" })),
1458
+ zzz: () => stripTimeZone(date.toLocaleDateString(options.locales, { timeZoneName: "shortOffset" })),
1459
+ zzzz: () => stripTimeZone(date.toLocaleDateString(options.locales, { timeZoneName: "longOffset" }))
1460
+ };
1461
+ return formatStr.replace(REGEX_FORMAT, (match, $1) => {
1462
+ var _ref, _matches$match;
1463
+ return (_ref = $1 !== null && $1 !== void 0 ? $1 : (_matches$match = matches[match]) === null || _matches$match === void 0 ? void 0 : _matches$match.call(matches)) !== null && _ref !== void 0 ? _ref : match;
1464
+ });
1465
+ }
1466
+ function normalizeDate(date) {
1467
+ if (date === null) return /* @__PURE__ */ new Date(NaN);
1468
+ if (date === void 0) return /* @__PURE__ */ new Date();
1469
+ if (date instanceof Date) return new Date(date);
1470
+ if (typeof date === "string" && !/Z$/i.test(date)) {
1471
+ const d = date.match(REGEX_PARSE);
1472
+ if (d) {
1473
+ const m = Number(d[2]) - 1 || 0;
1474
+ const ms = Number((d[7] || "0").substring(0, 3));
1475
+ return new Date(Number(d[1]), m, Number(d[3]) || 1, Number(d[4]) || 0, Number(d[5]) || 0, Number(d[6]) || 0, ms);
1476
+ }
1477
+ }
1478
+ return new Date(date);
1479
+ }
1480
+ /**
1481
+ * Get the formatted date according to the string of tokens passed in.
1482
+ *
1483
+ * Map from @vueuse/shared `useDateFormat`.
1484
+ *
1485
+ * React divergence: upstream wraps the result in a Vue `computed` and returns
1486
+ * `ComputedRef<string>` — this port returns a PLAIN STRING. Call it during
1487
+ * render and pass plain values (e.g. your `useState` date); the string is
1488
+ * recomputed on every render with fresh inputs. Do not read `.value` from it.
1489
+ *
1490
+ * Inputs (`date`, `formatStr`, `options.locales`) are plain read-only values
1491
+ * — pass `ref.current` or the state value; a `MaybeRefOrGetter` source must be
1492
+ * resolved by the caller (upstream types them `MaybeRefOrGetter`).
1493
+ *
1494
+ * Supported tokens (mirroring upstream 1:1, default format `HH:mm:ss`):
1495
+ * `Yo YY YYYY` — year · `M Mo MM MMM MMMM` — month (locale-aware short/long
1496
+ * names via `Intl`) · `D Do DD` — day of month · `H Ho HH` — 24-hour clock ·
1497
+ * `h ho hh` — 12-hour clock · `m mo mm` — minutes · `s so ss` — seconds ·
1498
+ * `SSS` — milliseconds (3 digits) · `d dd ddd dddd` — weekday (locale-aware
1499
+ * via `Intl`) · `A AA a aa` — meridiem, customizable via
1500
+ * `options.customMeridiem` · `z zz zzz zzzz` — timezone offset names
1501
+ * (`shortOffset` / `longOffset` via `toLocaleString`). Text wrapped in
1502
+ * brackets (`[...]`) is output literally as an escape sequence.
1503
+ *
1504
+ * @see https://vueuse.org/useDateFormat
1505
+ * @param date - The date to format, can either be a `Date` object, a timestamp, or a string
1506
+ * @param formatStr - The combination of tokens to format the date
1507
+ * @param options - UseDateFormatOptions
1508
+ *
1509
+ * @__NO_SIDE_EFFECTS__
1510
+ */
1511
+ function useDateFormat(date, formatStr = "HH:mm:ss", options = {}) {
1512
+ return formatDate(normalizeDate(date), formatStr, options);
1513
+ }
1514
+ //#endregion
1515
+ //#region useDebounceFn/index.tsx
1516
+ /**
1517
+ * Debounce execution of a function — React port of VueUse's `useDebounceFn`.
1518
+ *
1519
+ * Map from @vueuse/shared `useDebounceFn`
1520
+ * Mapping: upstream builds `createFilterWrapper(debounceFilter(ms, options), fn)`
1521
+ * so every call returns a promise and the wrapper carries `cancel` / `flush` /
1522
+ * `isPending`. This port builds the same wrapper once (`useMemo`) so its
1523
+ * identity is stable across renders; the latest `fn` / `ms` / `options` are
1524
+ * mirrored into refs so every call sees fresh values. `ms` accepts a number or
1525
+ * a ref-like `{ current }` (upstream: `RefOrValue<number>`) and is re-read on
1526
+ * every call. `isPending` becomes a non-reactive getter (React has no reactive
1527
+ * refs); promise settlement mirrors upstream — a regular debounce resolves
1528
+ * with the result, a superseded/canceled call settles with `undefined` (or
1529
+ * rejects with `rejectOnCancel`), and the `maxWait` trailing edge runs the
1530
+ * latest invocation but settles the pending promise without its result.
1531
+ * Pending timers are cleared when the component unmounts (upstream leaves
1532
+ * disposal to the effect scope).
1533
+ *
1534
+ * @example
1535
+ * const debouncedFn = useDebounceFn(() => { ... }, 1000)
1536
+ * debouncedFn()
1537
+ * debouncedFn.cancel()
1538
+ * debouncedFn.flush()
1539
+ */
1540
+ function useDebounceFn(fn, ms = 200, options = {}) {
1541
+ const fnRef = (0, react.useRef)(fn);
1542
+ fnRef.current = fn;
1543
+ const msRef = (0, react.useRef)(ms);
1544
+ msRef.current = ms;
1545
+ const optionsRef = (0, react.useRef)(options);
1546
+ optionsRef.current = options;
1547
+ const timerRef = (0, react.useRef)(null);
1548
+ const maxTimerRef = (0, react.useRef)(null);
1549
+ const pendingRef = (0, react.useRef)(false);
1550
+ const onCancelRef = (0, react.useRef)(noop);
1551
+ const onFlushRef = (0, react.useRef)(noop);
1552
+ const lastInvokeRef = (0, react.useRef)(noop);
1553
+ const debounced = (0, react.useMemo)(() => {
1554
+ const clearTimers = () => {
1555
+ if (timerRef.current !== null) {
1556
+ clearTimeout(timerRef.current);
1557
+ timerRef.current = null;
1558
+ }
1559
+ if (maxTimerRef.current !== null) {
1560
+ clearTimeout(maxTimerRef.current);
1561
+ maxTimerRef.current = null;
1562
+ }
1563
+ };
1564
+ const settleCurrent = (settleRef) => {
1565
+ const callback = settleRef.current;
1566
+ onCancelRef.current = noop;
1567
+ onFlushRef.current = noop;
1568
+ pendingRef.current = false;
1569
+ callback();
1570
+ };
1571
+ const handler = (invoke) => {
1572
+ const duration = toValue(msRef.current);
1573
+ const maxDuration = toValue(optionsRef.current.maxWait);
1574
+ if (timerRef.current !== null) {
1575
+ clearTimeout(timerRef.current);
1576
+ timerRef.current = null;
1577
+ settleCurrent(onCancelRef);
1578
+ }
1579
+ if (duration === void 0 || duration <= 0 || maxDuration !== void 0 && maxDuration <= 0) {
1580
+ clearTimers();
1581
+ pendingRef.current = false;
1582
+ try {
1583
+ return Promise.resolve(invoke());
1584
+ } catch (error) {
1585
+ return Promise.reject(error);
1586
+ }
1587
+ }
1588
+ pendingRef.current = true;
1589
+ return new Promise((resolve, reject) => {
1590
+ onCancelRef.current = optionsRef.current.rejectOnCancel ? reject : () => resolve(void 0);
1591
+ onFlushRef.current = () => resolve(invoke());
1592
+ lastInvokeRef.current = invoke;
1593
+ if (maxDuration !== void 0 && maxTimerRef.current === null) maxTimerRef.current = setTimeout(() => {
1594
+ maxTimerRef.current = null;
1595
+ if (timerRef.current !== null) {
1596
+ clearTimeout(timerRef.current);
1597
+ timerRef.current = null;
1598
+ }
1599
+ const invoke = lastInvokeRef.current;
1600
+ settleCurrent(onCancelRef);
1601
+ invoke();
1602
+ }, maxDuration);
1603
+ timerRef.current = setTimeout(() => {
1604
+ timerRef.current = null;
1605
+ if (maxTimerRef.current !== null) {
1606
+ clearTimeout(maxTimerRef.current);
1607
+ maxTimerRef.current = null;
1608
+ }
1609
+ settleCurrent(onFlushRef);
1610
+ }, duration);
1611
+ });
1612
+ };
1613
+ const cancel = () => {
1614
+ clearTimers();
1615
+ settleCurrent(onCancelRef);
1616
+ };
1617
+ const flush = () => {
1618
+ if (!pendingRef.current) return;
1619
+ clearTimers();
1620
+ settleCurrent(onFlushRef);
1621
+ };
1622
+ const wrapped = ((...args) => {
1623
+ return handler(() => fnRef.current(...args));
1624
+ });
1625
+ wrapped.cancel = cancel;
1626
+ wrapped.flush = flush;
1627
+ Object.defineProperty(wrapped, "isPending", {
1628
+ enumerable: true,
1629
+ get: () => pendingRef.current
1630
+ });
1631
+ return wrapped;
1632
+ }, []);
1633
+ (0, react.useEffect)(() => debounced.cancel, [debounced]);
1634
+ return debounced;
1635
+ }
1636
+ //#endregion
1637
+ //#region useInterval/index.tsx
1638
+ function useInterval(interval = 1e3, options = {}) {
1639
+ const { controls: exposeControls = false, immediate = true, callback, immediateCallback = false } = options;
1640
+ const intervalRef = (0, react.useRef)(interval);
1641
+ intervalRef.current = interval;
1642
+ const callbackRef = (0, react.useRef)(callback);
1643
+ callbackRef.current = callback;
1644
+ const immediateCallbackRef = (0, react.useRef)(immediateCallback);
1645
+ immediateCallbackRef.current = immediateCallback;
1646
+ const [counter, setCounter] = (0, react.useState)(0);
1647
+ const counterRef = (0, react.useRef)(0);
1648
+ const [isActive, setIsActive] = (0, react.useState)(() => immediate && toValue(interval) > 0);
1649
+ const isActiveRef = (0, react.useRef)(false);
1650
+ const timerRef = (0, react.useRef)(null);
1651
+ const tick = (0, react.useCallback)(() => {
1652
+ var _callbackRef$current;
1653
+ counterRef.current += 1;
1654
+ setCounter(counterRef.current);
1655
+ (_callbackRef$current = callbackRef.current) === null || _callbackRef$current === void 0 || _callbackRef$current.call(callbackRef, counterRef.current);
1656
+ }, []);
1657
+ const reset = (0, react.useCallback)(() => {
1658
+ counterRef.current = 0;
1659
+ setCounter(0);
1660
+ }, []);
1661
+ const pause = (0, react.useCallback)(() => {
1662
+ isActiveRef.current = false;
1663
+ setIsActive(false);
1664
+ if (timerRef.current !== null) {
1665
+ clearInterval(timerRef.current);
1666
+ timerRef.current = null;
1667
+ }
1668
+ }, []);
1669
+ const resume = (0, react.useCallback)(() => {
1670
+ const ms = toValue(intervalRef.current);
1671
+ if (ms <= 0) return;
1672
+ isActiveRef.current = true;
1673
+ setIsActive(true);
1674
+ if (immediateCallbackRef.current) tick();
1675
+ if (timerRef.current !== null) {
1676
+ clearInterval(timerRef.current);
1677
+ timerRef.current = null;
1678
+ }
1679
+ timerRef.current = setInterval(tick, ms);
1680
+ }, [tick]);
1681
+ const startedRef = (0, react.useRef)(false);
1682
+ (0, react.useEffect)(() => {
1683
+ if (immediate && !startedRef.current) {
1684
+ startedRef.current = true;
1685
+ resume();
1686
+ }
1687
+ return pause;
1688
+ }, [immediate, resume]);
1689
+ const mountedRef = (0, react.useRef)(false);
1690
+ const intervalMs = toValue(interval);
1691
+ (0, react.useEffect)(() => {
1692
+ if (!mountedRef.current) {
1693
+ mountedRef.current = true;
1694
+ return;
1695
+ }
1696
+ if (isActiveRef.current) resume();
1697
+ }, [intervalMs, resume]);
1698
+ if (exposeControls) return {
1699
+ counter,
1700
+ reset,
1701
+ isActive,
1702
+ pause,
1703
+ resume
1704
+ };
1705
+ return counter;
1706
+ }
1707
+ //#endregion
1708
+ //#region useIntervalFn/index.tsx
1709
+ /**
1710
+ * React port of VueUse's `useIntervalFn` — wrapper for `setInterval` with
1711
+ * controls.
1712
+ *
1713
+ * Map from @vueuse/shared `useIntervalFn`
1714
+ * Mapping: upstream accepts `RefOrValue<number>` for the interval — this
1715
+ * port accepts a plain `number`. `isActive` is a boolean state (upstream: a
1716
+ * readonly shallow ref), also mirrored in a ref so `resume()` can check it
1717
+ * synchronously right after `immediateCallback` fires the callback — the
1718
+ * callback may `pause()` itself ("pause in callback"). The timer is scheduled
1719
+ * in a mount effect (upstream starts synchronously during setup) and cleared
1720
+ * on unmount via effect cleanup; changing the interval while active restarts
1721
+ * the timer (upstream: a `watch` on the interval calls `resume()`). The
1722
+ * callback, interval and options are kept in refs so every tick and restart
1723
+ * uses the newest ones.
1724
+ *
1725
+ * @example
1726
+ * const { isActive, pause, resume } = useIntervalFn(() => { ... }, 1000)
1727
+ */
1728
+ function useIntervalFn(cb, interval = 1e3, options = {}) {
1729
+ const { immediate = true, immediateCallback = false } = options;
1730
+ const [isActive, setIsActive] = (0, react.useState)(false);
1731
+ const isActiveRef = (0, react.useRef)(false);
1732
+ const cbRef = (0, react.useRef)(cb);
1733
+ const intervalRef = (0, react.useRef)(interval);
1734
+ const immediateCallbackRef = (0, react.useRef)(immediateCallback);
1735
+ const timerRef = (0, react.useRef)(null);
1736
+ cbRef.current = cb;
1737
+ intervalRef.current = interval;
1738
+ immediateCallbackRef.current = immediateCallback;
1739
+ const immediateRef = (0, react.useRef)(immediate);
1740
+ function clean() {
1741
+ if (timerRef.current) {
1742
+ clearInterval(timerRef.current);
1743
+ timerRef.current = null;
1744
+ }
1745
+ }
1746
+ function setActive(active) {
1747
+ isActiveRef.current = active;
1748
+ setIsActive(active);
1749
+ }
1750
+ const pause = (0, react.useCallback)(() => {
1751
+ setActive(false);
1752
+ clean();
1753
+ }, []);
1754
+ const resume = (0, react.useCallback)(() => {
1755
+ const intervalValue = intervalRef.current;
1756
+ if (intervalValue <= 0) return;
1757
+ setActive(true);
1758
+ if (immediateCallbackRef.current) cbRef.current();
1759
+ clean();
1760
+ if (isActiveRef.current) timerRef.current = setInterval(() => cbRef.current(), intervalValue);
1761
+ }, []);
1762
+ (0, react.useEffect)(() => {
1763
+ if (immediateRef.current) resume();
1764
+ return () => {
1765
+ clean();
1766
+ };
1767
+ }, [resume]);
1768
+ const mountedRef = (0, react.useRef)(false);
1769
+ (0, react.useEffect)(() => {
1770
+ if (!mountedRef.current) {
1771
+ mountedRef.current = true;
1772
+ return;
1773
+ }
1774
+ if (isActiveRef.current) resume();
1775
+ }, [interval, resume]);
1776
+ return {
1777
+ isActive,
1778
+ pause,
1779
+ resume
1780
+ };
1781
+ }
1782
+ //#endregion
1783
+ //#region useLastChanged/index.tsx
1784
+ function useLastChanged(value, options = {}) {
1785
+ const [lastChanged, setLastChanged] = (0, react.useState)(() => {
1786
+ var _options$initialValue;
1787
+ return (_options$initialValue = options.initialValue) !== null && _options$initialValue !== void 0 ? _options$initialValue : null;
1788
+ });
1789
+ const prevValue = (0, react.useRef)(value);
1790
+ (0, react.useEffect)(() => {
1791
+ if (!Object.is(prevValue.current, value)) {
1792
+ prevValue.current = value;
1793
+ setLastChanged(timestamp());
1794
+ }
1795
+ });
1796
+ return lastChanged;
1797
+ }
1798
+ //#endregion
1799
+ //#region useListener/index.tsx
1800
+ /**
1801
+ * React port of the `useListener` protocol — bind a callback to an event
1802
+ * registration function returned by a reause hook, with automatic cleanup
1803
+ * on unmount.
1804
+ *
1805
+ * Map from @reause/shared `useListener` (protocol: #129)
1806
+ * Motivation: hooks like `useFileDialog` return `onChange` / `onCancel`
1807
+ * registration functions (upstream `EventHookOn`). In Vue those auto-clean
1808
+ * via the effect scope; in React we need a hook to own that lifecycle.
1809
+ * `useListener` registers `cb` with `on` on mount and, when `on` returns an
1810
+ * `off` function, calls it on unmount, so listeners are cleaned up and
1811
+ * callbacks never fire after the component is gone. (An `on` that returns
1812
+ * nothing provides no cleanup — nothing can be released.) The callback is
1813
+ * kept in a ref, so changing `cb` across renders does not re-register — the
1814
+ * latest callback is used by the already-registered listener. If `on` itself
1815
+ * changes (a new hook instance), the effect re-runs and re-registers.
1816
+ *
1817
+ * @example
1818
+ * const { files, open, onChange } = useFileDialog()
1819
+ * useListener(onChange, (files) => { console.log(files) })
1820
+ */
1821
+ function useListener(on, cb) {
1822
+ const cbRef = (0, react.useRef)(cb);
1823
+ cbRef.current = cb;
1824
+ (0, react.useEffect)(() => {
1825
+ if (typeof on !== "function") return;
1826
+ const result = on(((...args) => cbRef.current(...args)));
1827
+ return () => {
1828
+ var _result$off;
1829
+ result === null || result === void 0 || (_result$off = result.off) === null || _result$off === void 0 || _result$off.call(result);
1830
+ };
1831
+ }, [on]);
1832
+ }
1833
+ //#endregion
1834
+ //#region useMount/index.tsx
1835
+ /**
1836
+ * React port of react-use's `useMount`.
1837
+ *
1838
+ * Map from react-use `useMount`.
1839
+ * Runs `fn` exactly once after the component mounts.
1840
+ *
1841
+ * @example
1842
+ * useMount(() => {
1843
+ * trackPageView()
1844
+ * })
1845
+ */
1846
+ function useMount(fn) {
1847
+ (0, react.useEffect)(() => {
1848
+ fn();
1849
+ }, []);
1850
+ }
1851
+ //#endregion
1852
+ //#region useStateAutoReset/index.tsx
1853
+ /**
1854
+ * A state which will be reset to the default value after some time.
1855
+ *
1856
+ * Map from @vueuse/shared `refAutoReset`
1857
+ * (`source/vueuse/packages/shared/refAutoReset/`). Upstream returns a single
1858
+ * writable Vue ref; per this repo's `useState*` family convention the return
1859
+ * is the React `[value, setValue]` tuple — `value` is the state, `setValue`
1860
+ * is a `useState`-style setter (value or updater form, `Dispatch<SetStateAction>`)
1861
+ * that also (re)schedules a timer to restore `defaultValue` after `afterMs`
1862
+ * milliseconds. `defaultValue` accepts the shared `State<T>` form (plain value,
1863
+ * lazy getter, ref-like object, state tuple, or controlled `{ value, onChange }` pair).
1864
+ * `afterMs` accepts the shared `RefOrValue<number>` form and is resolved with `toValue` at fire time
1865
+ * (upstream: `toValue`); the pending timer is cleared on unmount (upstream:
1866
+ * `tryOnScopeDispose`, timers in the effect scope). The deprecated `autoResetRef`
1867
+ * alias is not ported.
1868
+ *
1869
+ * @param defaultValue The value which will be set.
1870
+ * @param afterMs A zero-or-greater delay in milliseconds.
1871
+ * @example
1872
+ * const [message, setMessage] = useStateAutoReset('default message', 1000)
1873
+ *
1874
+ * function handleMessage() {
1875
+ * setMessage('message has set') // resets to 'default message' after 1000ms
1876
+ * }
1877
+ */
1878
+ function useStateAutoReset(defaultValue, afterMs = 1e4) {
1879
+ const [value, setValue] = useControllableState(defaultValue, { passive: true });
1880
+ const defaultValueRef = (0, react.useRef)(defaultValue);
1881
+ const afterMsRef = (0, react.useRef)(afterMs);
1882
+ const timerRef = (0, react.useRef)(null);
1883
+ defaultValueRef.current = defaultValue;
1884
+ afterMsRef.current = afterMs;
1885
+ const scheduleReset = (0, react.useCallback)(() => {
1886
+ if (timerRef.current) clearTimeout(timerRef.current);
1887
+ timerRef.current = setTimeout(() => {
1888
+ timerRef.current = null;
1889
+ setValue(toValue(defaultValueRef.current));
1890
+ }, toValue(afterMsRef.current));
1891
+ }, []);
1892
+ const setValueWithReset = (0, react.useCallback)((next) => {
1893
+ setValue(next);
1894
+ scheduleReset();
1895
+ }, [scheduleReset]);
1896
+ (0, react.useEffect)(() => () => {
1897
+ if (timerRef.current) clearTimeout(timerRef.current);
1898
+ }, []);
1899
+ return [value, setValueWithReset];
1900
+ }
1901
+ //#endregion
1902
+ //#region useStateDebounced/index.tsx
1903
+ /**
1904
+ * Debounce updates of a state value — React port of VueUse's `refDebounced`.
1905
+ *
1906
+ * Map from @vueuse/shared `refDebounced`
1907
+ * Mapping: upstream takes a Vue `Ref<T>` and returns a readonly ref that only
1908
+ * flips to the latest source value once it stops changing for `ms` (a watcher
1909
+ * hands every change to `useDebounceFn`). The naming follows this repo's
1910
+ * `ref* → useState*` rule (`refDebounced` → `useStateDebounced`), the Vue
1911
+ * `Ref<T>` input becomes a plain initial value, and the readonly ref becomes
1912
+ * an extra state slot — so the hook returns the tuple
1913
+ * `[value, setValue, debounced]`:
1914
+ *
1915
+ * ```ts
1916
+ * const [input, setInput, debounced] = useStateDebounced('foo', 1000)
1917
+ *
1918
+ * setInput('bar')
1919
+ * console.log(debounced) // 'foo' — flips to 'bar' once the debounce elapses
1920
+ * ```
1921
+ *
1922
+ * `value` is the source state, `setValue` its setter, and `debounced` lags
1923
+ * behind it by `ms`. Writes settle through a `useDebounceFn` updater, so a
1924
+ * burst of writes collapses into a single trailing update carrying the last
1925
+ * written value. `ms` (and `options.maxWait`) accept a plain number or a
1926
+ * ref-like `{ current }` (upstream: `RefOrValue<number>`) and are re-read on
1927
+ * every write; pending timers are cleared when the component unmounts
1928
+ * (upstream disposes with the effect scope). Note: a write only schedules the
1929
+ * debounce when the value actually changes — writing the same value is
1930
+ * skipped by `useControllableState`'s `Object.is` guard, so the pending timer
1931
+ * is not re-delayed (upstream's `watch` re-delays on every source write, even
1932
+ * unchanged ones).
1933
+ *
1934
+ * @example
1935
+ * ```ts
1936
+ * const [value, setValue, debounced] = useStateDebounced('foo', 1000)
1937
+ * ```
1938
+ */
1939
+ function useStateDebounced(value, ms = 200, options = {}) {
1940
+ const [state, setState] = useControllableState(value, { passive: true });
1941
+ const [debounced, setDebounced] = (0, react.useState)(state);
1942
+ const stateRef = (0, react.useRef)(state);
1943
+ stateRef.current = state;
1944
+ const updater = useDebounceFn(() => {
1945
+ setDebounced(stateRef.current);
1946
+ }, ms, options);
1947
+ const isFirstRunRef = (0, react.useRef)(true);
1948
+ (0, react.useEffect)(() => {
1949
+ if (isFirstRunRef.current) {
1950
+ isFirstRunRef.current = false;
1951
+ return;
1952
+ }
1953
+ updater();
1954
+ }, [state, updater]);
1955
+ return [
1956
+ state,
1957
+ setState,
1958
+ debounced
1959
+ ];
1960
+ }
1961
+ //#endregion
1962
+ //#region useStateDefault/index.tsx
1963
+ /**
1964
+ * A state tuple (`[value, setter]`) — mirrors `toValue`'s tuple branch.
1965
+ */
1966
+ function isStateTuple(source) {
1967
+ return Array.isArray(source) && source.length === 2 && typeof source[1] === "function";
1968
+ }
1969
+ /**
1970
+ * A `{ value, onChange }` source — mirrors `toValue`'s object branch (the
1971
+ * `addEventListener` guard keeps DOM-ish objects out, like `toValue`).
1972
+ */
1973
+ function isObjectState(source) {
1974
+ return typeof source === "object" && source !== null && !Array.isArray(source) && "value" in source && !("addEventListener" in source);
1975
+ }
1976
+ /**
1977
+ * A ref-like `{ current }` source.
1978
+ */
1979
+ function isRefState(source) {
1980
+ return source !== null && source !== void 0 && typeof source === "object" && "current" in source;
1981
+ }
1982
+ /**
1983
+ * Apply default value to a ref-like source — React port of VueUse's
1984
+ * `refDefault` renamed to `useStateDefault` (this repo's naming for the
1985
+ * `ref*` family; upstream's single writable computed ref becomes a tuple).
1986
+ *
1987
+ * Map from @vueuse/shared `refDefault`
1988
+ * Mapping: upstream derives a writable `computed` from a source
1989
+ * `Ref<T | undefined | null>` — it reads `source.value ?? defaultValue` and
1990
+ * writes back to `source.value`. This port accepts a `State<T | undefined |
1991
+ * null>` — a plain value, a ref-like object (`{ current }`, e.g. the first
1992
+ * tuple element of `useStorage`), a getter, a `[value, setter]` tuple or a
1993
+ * `{ value, onChange }` pair — and returns the React tuple
1994
+ * `const [value, setValue] = useStateDefault(raw, 'default')`. `value` is
1995
+ * derived on every render from the source through `toValue` (`source.current
1996
+ * ?? defaultValue`), so it always reflects the source's current value —
1997
+ * including writes made from outside the component; `setValue` resolves the
1998
+ * next value (value or updater form), writes it through to the source (its
1999
+ * `current`, its setter or its `onChange`) and bumps a local version counter
2000
+ * so the derived `value` re-renders. SSR-safe: nothing touches the DOM and the
2001
+ * first server render already shows the default.
2002
+ *
2003
+ * @param source The `State<T | undefined | null>` source holding the
2004
+ * value — read through `toValue` on every render and
2005
+ * written back to `current` / the tuple setter /
2006
+ * `onChange` on `setValue`.
2007
+ * @param defaultValue The value displayed while the source is `null` or
2008
+ * `undefined`.
2009
+ * @return A tuple `[value, setValue]` — the current value (source value or
2010
+ * `defaultValue`) and its setter.
2011
+ *
2012
+ * @example
2013
+ * const raw = { current: undefined as string | undefined }
2014
+ * const [value, setValue] = useStateDefault(raw, 'default')
2015
+ *
2016
+ * setValue('hello')
2017
+ * console.log(value) // 'hello' after the next render (React derives at render)
2018
+ *
2019
+ * setValue(undefined)
2020
+ * console.log(value) // 'default' after the next render
2021
+ */
2022
+ function useStateDefault(source, defaultValue) {
2023
+ var _toValue;
2024
+ const sourceRef = (0, react.useRef)(source);
2025
+ sourceRef.current = source;
2026
+ const [, setVersion] = (0, react.useState)(0);
2027
+ const bump = () => {
2028
+ setVersion((current) => current + 1);
2029
+ };
2030
+ const setValue = (0, react.useCallback)((next) => {
2031
+ const current = toValue(sourceRef.current);
2032
+ const resolved = typeof next === "function" ? next(current) : next;
2033
+ const currentSource = sourceRef.current;
2034
+ if (isStateTuple(currentSource)) {
2035
+ currentSource[1](resolved);
2036
+ bump();
2037
+ } else if (isObjectState(currentSource)) {
2038
+ var _currentSource$onChan;
2039
+ (_currentSource$onChan = currentSource.onChange) === null || _currentSource$onChan === void 0 || _currentSource$onChan.call(currentSource, resolved);
2040
+ bump();
2041
+ } else if (isRefState(currentSource)) {
2042
+ currentSource.current = resolved;
2043
+ bump();
2044
+ }
2045
+ }, []);
2046
+ return [(_toValue = toValue(source)) !== null && _toValue !== void 0 ? _toValue : defaultValue, setValue];
2047
+ }
2048
+ //#endregion
2049
+ //#region useStateManualReset/index.tsx
2050
+ /**
2051
+ * A controlled source — a `[value, setter]` tuple or a `{ value, onChange }`
2052
+ * object. These have no stored default of their own: `toValue` returns the
2053
+ * live value, so resetting to it would be a no-op. Reset therefore restores
2054
+ * the initial argument value instead.
2055
+ */
2056
+ function isControlledSource$1(state) {
2057
+ return Array.isArray(state) && state.length === 2 && typeof state[1] === "function" || typeof state === "object" && state !== null && !Array.isArray(state) && "value" in state;
2058
+ }
2059
+ /**
2060
+ * React port of VueUse's `refManualReset`.
2061
+ *
2062
+ * Map from @vueuse/shared `refManualReset`
2063
+ * (`source/vueuse/packages/shared/refManualReset/`). Create a state with
2064
+ * manual reset functionality — any update can be reverted back to the initial
2065
+ * value with the returned `reset` function.
2066
+ *
2067
+ * Upstream returns a writable Vue `Ref<T>` extended with a `reset` method
2068
+ * (built on `customRef`). Per this repo's naming rules the port is renamed to
2069
+ * `useStateManualReset` and the ref becomes a `[value, setValue, reset]`
2070
+ * tuple: the second element is the plain `useState` setter (value or updater
2071
+ * form), and `reset` restores the default value.
2072
+ *
2073
+ * The state input accepts the shared `State<T>` form: a value, getter, ref-like
2074
+ * object, state tuple, or controlled `{ value, onChange }` object. `reset`
2075
+ * re-reads the input on every call, so plain, getter and ref-like sources
2076
+ * reset to the latest source value (matching upstream's
2077
+ * `value = toValue(defaultValue)`); tuple / `{ value, onChange }` (controlled)
2078
+ * sources have no stored default, so they restore the initial argument value.
2079
+ *
2080
+ * @example
2081
+ * const [message, setMessage, resetMessage] = useStateManualReset('default message')
2082
+ * setMessage('message has set')
2083
+ * resetMessage()
2084
+ * console.log(message) // 'default message'
2085
+ */
2086
+ function useStateManualReset(value) {
2087
+ const valueRef = (0, react.useRef)(value);
2088
+ valueRef.current = value;
2089
+ const initialDefaultRef = (0, react.useRef)(toValue(value));
2090
+ const [state, setState] = useControllableState(value, { passive: true });
2091
+ return [
2092
+ state,
2093
+ setState,
2094
+ (0, react.useCallback)(() => {
2095
+ const current = valueRef.current;
2096
+ setState(isControlledSource$1(current) ? initialDefaultRef.current : toValue(current));
2097
+ }, [])
2098
+ ];
2099
+ }
2100
+ //#endregion
2101
+ //#region useThrottleFn/index.tsx
2102
+ /**
2103
+ * Throttle execution of a function — React port of VueUse's `useThrottleFn`.
2104
+ * Especially useful for rate limiting execution of handlers on events like
2105
+ * resize and scroll.
2106
+ *
2107
+ * Map from @vueuse/shared `useThrottleFn`
2108
+ * Mapping: upstream builds `createFilterWrapper(throttleFilter(ms, trailing,
2109
+ * leading, rejectOnCancel), fn)` and returns a plain `PromisifyFn<T>` — the
2110
+ * throttled wrapper carries no `cancel` / `flush` / `isPending` (unlike the
2111
+ * debounce filter, upstream's `throttleFilter` is not cancelable), so this
2112
+ * port mirrors that: the return value is the wrapped function and nothing
2113
+ * more. The wrapper is built once (`useMemo`) so its identity is stable
2114
+ * across renders — safe to add/remove in effects; the latest `fn` / `ms` /
2115
+ * `trailing` / `leading` / `rejectOnCancel` are mirrored into refs so every
2116
+ * call sees fresh values (upstream captures the flags once, at filter
2117
+ * creation). `ms` accepts a number or a ref-like `{ current: number }`
2118
+ * (upstream: `RefOrValue<number>`) and is re-read on every call. The
2119
+ * throttle filter logic is inlined (upstream: `utils/filters.ts`
2120
+ * `throttleFilter` — leading/trailing timestamps with a trailing invoke on
2121
+ * window end). The wrapper is cleaned up on unmount: any pending trailing
2122
+ * timer is cleared when the component unmounts — a React hygiene measure;
2123
+ * upstream registers no disposal at all (`@__NO_SIDE_EFFECTS__`), so a
2124
+ * pending call would still fire there after teardown.
2125
+ *
2126
+ * @param fn A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,
2127
+ * to `callback` when the throttled-function is executed.
2128
+ * @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.
2129
+ * (default value: 200)
2130
+ *
2131
+ * @param [trailing] if true, call fn again after the time is up (default value: true)
2132
+ *
2133
+ * @param [leading] if true, call fn on the leading edge of the ms timeout (default value: true)
2134
+ *
2135
+ * @param [rejectOnCancel] if true, reject the last call if it's been cancel (default value: false)
2136
+ *
2137
+ * @return A new, throttled, function.
2138
+ *
2139
+ * @example
2140
+ * const throttledFn = useThrottleFn(() => { ... }, 1000)
2141
+ * throttledFn()
2142
+ */
2143
+ function useThrottleFn(fn, ms = 200, trailing = true, leading = true, rejectOnCancel = false) {
2144
+ const fnRef = (0, react.useRef)(fn);
2145
+ fnRef.current = fn;
2146
+ const msRef = (0, react.useRef)(ms);
2147
+ msRef.current = ms;
2148
+ const trailingRef = (0, react.useRef)(trailing);
2149
+ trailingRef.current = trailing;
2150
+ const leadingRef = (0, react.useRef)(leading);
2151
+ leadingRef.current = leading;
2152
+ const rejectOnCancelRef = (0, react.useRef)(rejectOnCancel);
2153
+ rejectOnCancelRef.current = rejectOnCancel;
2154
+ const { throttled, clear } = (0, react.useMemo)(() => {
2155
+ let lastExec = 0;
2156
+ let timer;
2157
+ let isLeading = true;
2158
+ let lastRejector = noop;
2159
+ let lastValue;
2160
+ const clear = () => {
2161
+ if (timer !== void 0) {
2162
+ clearTimeout(timer);
2163
+ timer = void 0;
2164
+ lastRejector();
2165
+ lastRejector = noop;
2166
+ }
2167
+ };
2168
+ const handler = (_invoke) => {
2169
+ const duration = toValue(msRef.current);
2170
+ const elapsed = Date.now() - lastExec;
2171
+ const invoke = () => {
2172
+ return lastValue = _invoke();
2173
+ };
2174
+ clear();
2175
+ if (duration === void 0 || duration <= 0) {
2176
+ lastExec = Date.now();
2177
+ return invoke();
2178
+ }
2179
+ if (elapsed > duration) {
2180
+ lastExec = Date.now();
2181
+ if (leadingRef.current || !isLeading) invoke();
2182
+ } else if (trailingRef.current) lastValue = new Promise((resolve, reject) => {
2183
+ lastRejector = rejectOnCancelRef.current ? reject : resolve;
2184
+ timer = setTimeout(() => {
2185
+ lastExec = Date.now();
2186
+ isLeading = true;
2187
+ resolve(invoke());
2188
+ clear();
2189
+ }, Math.max(0, duration - elapsed));
2190
+ });
2191
+ if (!leadingRef.current && timer === void 0) timer = setTimeout(() => {
2192
+ isLeading = true;
2193
+ }, duration);
2194
+ isLeading = false;
2195
+ return lastValue;
2196
+ };
2197
+ const throttled = ((...args) => {
2198
+ return new Promise((resolve, reject) => {
2199
+ Promise.resolve(handler(() => fnRef.current(...args))).then(resolve).catch(reject);
2200
+ });
2201
+ });
2202
+ return {
2203
+ throttled,
2204
+ clear
2205
+ };
2206
+ }, []);
2207
+ (0, react.useEffect)(() => () => clear(), [clear]);
2208
+ return throttled;
2209
+ }
2210
+ //#endregion
2211
+ //#region useStateThrottled/index.tsx
2212
+ /**
2213
+ * Throttle changing of a state value — React port of VueUse's `refThrottled`.
2214
+ *
2215
+ * The `value` argument accepts any `State<T>` supported by
2216
+ * `useControllableState`: a plain value, lazy initializer, controlled tuple,
2217
+ * or `{ value, onChange }` source. The returned tuple contains the current
2218
+ * value, its setter, and a throttled mirror.
2219
+ *
2220
+ * A `delay <= 0` short-circuits like upstream (`if (delay <= 0) return value`):
2221
+ * the throttled element is the input itself — no throttling, no timers.
2222
+ *
2223
+ * @param value State source accepted by `useControllableState`.
2224
+ * @param delay Delay in milliseconds between commits (default: 200).
2225
+ * @param trailing Whether to commit the latest value after the window (default: true).
2226
+ * @param leading Whether to commit on the leading edge (default: true).
2227
+ */
2228
+ function useStateThrottled(value, delay = 200, trailing = true, leading = true) {
2229
+ const [input, setInput] = useControllableState(value, { passive: true });
2230
+ const [throttled, setThrottled] = (0, react.useState)(input);
2231
+ const inputRef = (0, react.useRef)(input);
2232
+ inputRef.current = input;
2233
+ const delayRef = (0, react.useRef)(delay);
2234
+ delayRef.current = delay;
2235
+ const throttledFn = useThrottleFn(() => {
2236
+ setThrottled(inputRef.current);
2237
+ }, delay, trailing, leading);
2238
+ const isFirstRunRef = (0, react.useRef)(true);
2239
+ (0, react.useEffect)(() => {
2240
+ if (isFirstRunRef.current) {
2241
+ isFirstRunRef.current = false;
2242
+ return;
2243
+ }
2244
+ if (delayRef.current > 0) throttledFn();
2245
+ }, [input, throttledFn]);
2246
+ if (delay <= 0) return [
2247
+ input,
2248
+ setInput,
2249
+ input
2250
+ ];
2251
+ return [
2252
+ input,
2253
+ setInput,
2254
+ throttled
2255
+ ];
2256
+ }
2257
+ //#endregion
2258
+ //#region useStateWithControl/index.tsx
2259
+ /**
2260
+ * A controlled source — a `[value, setter]` tuple or a `{ value, onChange }`
2261
+ * object — whose value is owned by the caller (re-rendered externally).
2262
+ */
2263
+ function isControlledSource(state) {
2264
+ return Array.isArray(state) && state.length === 2 && typeof state[1] === "function" || typeof state === "object" && state !== null && !Array.isArray(state) && "value" in state;
2265
+ }
2266
+ /**
2267
+ * Fine-grained controls over a state and its re-renders — React port of
2268
+ * VueUse's `refWithControl`.
2269
+ *
2270
+ * Map from @vueuse/shared `refWithControl`
2271
+ * (`source/vueuse/packages/shared/refWithControl/`). Upstream returns a single
2272
+ * writable Vue `Ref` extended with `get` / `set` / `untrackedGet` /
2273
+ * `silentSet` / `peek` / `lay`. This port owns the state like a `useState` and
2274
+ * returns the React tuple `const [num, setNum, control] = useStateWithControl(0)`
2275
+ * — the name follows this repo's `ref*` → `useState*` mapping rule. `setNum`
2276
+ * behaves like a normal `setState` (value or updater form — the updater base
2277
+ * is the current internal value, which may be ahead of the rendered value
2278
+ * after a silent write), while `control`
2279
+ * keeps the fine-grained get/set pair: `set(value, false)` (and `lay` /
2280
+ * `silentSet`) updates the value without re-rendering (upstream: without
2281
+ * triggering reactivity), and `peek` / `untrackedGet` read it back — in React
2282
+ * there is no dependency tracking during render, so those are plain aliases
2283
+ * for the current value. `reset()` (a small addition, upstream has no
2284
+ * equivalent) restores the initial value and participates in the change
2285
+ * callbacks (`onBeforeChange` can dismiss it, `onChanged` fires when
2286
+ * accepted). Option names are kept from upstream:
2287
+ * `onBeforeChange` can dismiss a change by returning `false`, and `onChanged`
2288
+ * fires synchronously after an accepted change.
2289
+ *
2290
+ * @param state State source: a plain value, getter, ref-like value, state
2291
+ * tuple, or `{ value, onChange }` controllable state.
2292
+ * @param options
2293
+ * @return A tuple `[value, setValue, control]` — the current value, a
2294
+ * `setState`-like setter and the fine-grained control object.
2295
+ *
2296
+ * @example
2297
+ * const [num, setNum, control] = useStateWithControl(0)
2298
+ *
2299
+ * setNum(42) // just like a normal useState setter
2300
+ * control.set(30, false) // set the value without re-rendering
2301
+ * control.peek() // get the value without tracking
2302
+ */
2303
+ function useStateWithControl(state, options = {}) {
2304
+ const { onBeforeChange, onChanged } = options;
2305
+ const initialRef = (0, react.useRef)(toValue(state));
2306
+ const sourceRef = (0, react.useRef)(initialRef.current);
2307
+ const [value, setState] = useControllableState(state, { passive: true });
2308
+ const lastTriggeredRef = (0, react.useRef)(void 0);
2309
+ if (isControlledSource(state) && !Object.is(value, lastTriggeredRef.current)) {
2310
+ sourceRef.current = value;
2311
+ lastTriggeredRef.current = value;
2312
+ }
2313
+ const callbacksRef = (0, react.useRef)({
2314
+ onBeforeChange,
2315
+ onChanged
2316
+ });
2317
+ callbacksRef.current = {
2318
+ onBeforeChange,
2319
+ onChanged
2320
+ };
2321
+ const set = (0, react.useCallback)((nextValue, triggering = true) => {
2322
+ var _callbacksRef$current, _callbacksRef$current2, _callbacksRef$current3, _callbacksRef$current4;
2323
+ if (nextValue === sourceRef.current) return;
2324
+ const old = sourceRef.current;
2325
+ if (((_callbacksRef$current = (_callbacksRef$current2 = callbacksRef.current).onBeforeChange) === null || _callbacksRef$current === void 0 ? void 0 : _callbacksRef$current.call(_callbacksRef$current2, nextValue, old)) === false) return;
2326
+ sourceRef.current = nextValue;
2327
+ (_callbacksRef$current3 = (_callbacksRef$current4 = callbacksRef.current).onChanged) === null || _callbacksRef$current3 === void 0 || _callbacksRef$current3.call(_callbacksRef$current4, nextValue, old);
2328
+ if (triggering) {
2329
+ lastTriggeredRef.current = nextValue;
2330
+ setState(nextValue);
2331
+ }
2332
+ }, []);
2333
+ const get = (0, react.useCallback)((_tracking = true) => {
2334
+ return sourceRef.current;
2335
+ }, []);
2336
+ const untrackedGet = (0, react.useCallback)(() => get(false), [get]);
2337
+ const silentSet = (0, react.useCallback)((nextValue) => set(nextValue, false), [set]);
2338
+ const peek = (0, react.useCallback)(() => get(false), [get]);
2339
+ const lay = (0, react.useCallback)((nextValue) => set(nextValue, false), [set]);
2340
+ const reset = (0, react.useCallback)(() => set(initialRef.current), [set]);
2341
+ return [
2342
+ value,
2343
+ (0, react.useCallback)((nextValue) => {
2344
+ const resolved = typeof nextValue === "function" ? nextValue(sourceRef.current) : nextValue;
2345
+ set(resolved);
2346
+ }, [set]),
2347
+ {
2348
+ get,
2349
+ set,
2350
+ untrackedGet,
2351
+ silentSet,
2352
+ peek,
2353
+ lay,
2354
+ reset
2355
+ }
2356
+ ];
2357
+ }
2358
+ //#endregion
2359
+ //#region useTimeout/index.tsx
2360
+ function useTimeout(interval = 1e3, options = {}) {
2361
+ const { controls: exposeControls = false, callback, immediate = true, immediateCallback = false } = options;
2362
+ const [isPending, setIsPending] = (0, react.useState)(immediate);
2363
+ const intervalRef = (0, react.useRef)(interval);
2364
+ intervalRef.current = interval;
2365
+ const callbackRef = (0, react.useRef)(callback);
2366
+ callbackRef.current = callback;
2367
+ const immediateCallbackRef = (0, react.useRef)(immediateCallback);
2368
+ immediateCallbackRef.current = immediateCallback;
2369
+ const timerRef = (0, react.useRef)(null);
2370
+ const stop = (0, react.useCallback)(() => {
2371
+ if (timerRef.current !== null) {
2372
+ clearTimeout(timerRef.current);
2373
+ timerRef.current = null;
2374
+ }
2375
+ setIsPending(false);
2376
+ }, []);
2377
+ const start = (0, react.useCallback)(() => {
2378
+ var _callbackRef$current;
2379
+ if (immediateCallbackRef.current) (_callbackRef$current = callbackRef.current) === null || _callbackRef$current === void 0 || _callbackRef$current.call(callbackRef);
2380
+ if (timerRef.current !== null) {
2381
+ clearTimeout(timerRef.current);
2382
+ timerRef.current = null;
2383
+ }
2384
+ setIsPending(true);
2385
+ const delay = toValue(intervalRef.current);
2386
+ timerRef.current = setTimeout(() => {
2387
+ var _callbackRef$current2;
2388
+ timerRef.current = null;
2389
+ setIsPending(false);
2390
+ (_callbackRef$current2 = callbackRef.current) === null || _callbackRef$current2 === void 0 || _callbackRef$current2.call(callbackRef);
2391
+ }, delay);
2392
+ }, []);
2393
+ (0, react.useEffect)(() => {
2394
+ if (immediate) start();
2395
+ return stop;
2396
+ }, []);
2397
+ const ready = !isPending;
2398
+ if (exposeControls) return {
2399
+ ready,
2400
+ isPending,
2401
+ start,
2402
+ stop
2403
+ };
2404
+ return ready;
2405
+ }
2406
+ //#endregion
2407
+ //#region useTimeoutFn/index.tsx
2408
+ /**
2409
+ * React port of VueUse's `useTimeoutFn` — wrapper for `setTimeout` with
2410
+ * controls.
2411
+ *
2412
+ * Map from @vueuse/shared `useTimeoutFn`
2413
+ * Mapping: upstream accepts `RefOrValue<number>` for the interval — this
2414
+ * port accepts a plain `number`. `isPending` becomes a boolean state
2415
+ * (upstream: a readonly shallow ref) that starts `false` and is set inside
2416
+ * the mount effect — like upstream's `shallowRef(false)` + `isClient` gate,
2417
+ * the server render does not report pending. `immediateCallback` runs the
2418
+ * callback synchronously on `start` (before the timer is armed). The timer
2419
+ * is scheduled in a mount effect (upstream starts synchronously during
2420
+ * setup) and a pending timer is cleared on unmount via effect cleanup. The
2421
+ * latest callback and interval are kept in refs so restarts always use the
2422
+ * newest ones.
2423
+ *
2424
+ * @example
2425
+ * const { isPending, start, stop } = useTimeoutFn(() => { ... }, 3000)
2426
+ */
2427
+ function useTimeoutFn(cb, interval, options = {}) {
2428
+ const { immediate = true, immediateCallback = false } = options;
2429
+ const [isPending, setIsPending] = (0, react.useState)(false);
2430
+ const cbRef = (0, react.useRef)(cb);
2431
+ const intervalRef = (0, react.useRef)(interval);
2432
+ const immediateCallbackRef = (0, react.useRef)(immediateCallback);
2433
+ const timerRef = (0, react.useRef)(null);
2434
+ cbRef.current = cb;
2435
+ intervalRef.current = interval;
2436
+ immediateCallbackRef.current = immediateCallback;
2437
+ function clear() {
2438
+ if (timerRef.current) {
2439
+ clearTimeout(timerRef.current);
2440
+ timerRef.current = null;
2441
+ }
2442
+ }
2443
+ const stop = (0, react.useCallback)(() => {
2444
+ setIsPending(false);
2445
+ clear();
2446
+ }, []);
2447
+ const start = (0, react.useCallback)((...args) => {
2448
+ if (immediateCallbackRef.current) cbRef.current();
2449
+ clear();
2450
+ setIsPending(true);
2451
+ timerRef.current = setTimeout(() => {
2452
+ timerRef.current = null;
2453
+ setIsPending(false);
2454
+ cbRef.current(...args);
2455
+ }, intervalRef.current);
2456
+ }, []);
2457
+ (0, react.useEffect)(() => {
2458
+ if (immediate) start();
2459
+ return () => {
2460
+ clear();
2461
+ };
2462
+ }, [immediate, start]);
2463
+ return {
2464
+ isPending,
2465
+ start,
2466
+ stop
2467
+ };
2468
+ }
2469
+ //#endregion
2470
+ //#region useToggle/index.tsx
2471
+ /**
2472
+ * React port of VueUse's `useToggle` — a toggler between a truthy and a falsy
2473
+ * value, both configurable.
2474
+ *
2475
+ * Map from @vueuse/shared `useToggle`
2476
+ * Mapping: `ref(initialValue)` → `useControllableState(initialValue)`,
2477
+ * `toggle()` → stable `useCallback`; accepts the full `State<T>` input.
2478
+ * `truthyValue` / `falsyValue` are plain values (upstream: `MaybeRefOrGetter` —
2479
+ * reactive refs/getters are not supported, see `RefOrValue`). Upstream's
2480
+ * `toggle` returns the new value synchronously; React state updates are async,
2481
+ * so here `toggle` is `() => void` and the new value is read from `value` on
2482
+ * the next render. Like upstream, a bare `toggle()` flips between
2483
+ * `truthyValue` and `falsyValue`, `toggle(value)` (including an explicit
2484
+ * `undefined`) forces the value, and a function argument is applied as a
2485
+ * functional update (React adaptation).
2486
+ *
2487
+ * @example
2488
+ * const [value, toggle] = useToggle()
2489
+ * toggle() // false → true
2490
+ * toggle(false) // force to false
2491
+ *
2492
+ * const [status, toggleStatus] = useToggle('on', { truthyValue: 'on', falsyValue: 'off' })
2493
+ * toggleStatus() // 'on' → 'off'
2494
+ */
2495
+ function useToggle(initialValue = false, options = {}) {
2496
+ const { truthyValue = true, falsyValue = false } = options;
2497
+ const [state, setState] = useControllableState(initialValue, { passive: true });
2498
+ const truthyRef = (0, react.useRef)(truthyValue);
2499
+ truthyRef.current = truthyValue;
2500
+ const falsyRef = (0, react.useRef)(falsyValue);
2501
+ falsyRef.current = falsyValue;
2502
+ return [state, (0, react.useCallback)((...args) => {
2503
+ const hasValue = args.length > 0;
2504
+ const value = args[0];
2505
+ setState((current) => {
2506
+ if (hasValue) {
2507
+ if (typeof value === "function") return value(current);
2508
+ return value;
2509
+ }
2510
+ return Object.is(current, truthyRef.current) ? falsyRef.current : truthyRef.current;
2511
+ });
2512
+ }, [setState])];
2513
+ }
2514
+ //#endregion
2515
+ //#region useToNumber/index.tsx
2516
+ /**
2517
+ * React port of VueUse's `useToNumber`.
2518
+ *
2519
+ * Map from @vueuse/shared `useToNumber`
2520
+ * Mapping: `ComputedRef<number>` → plain number recomputed from the current
2521
+ * value on every render (accepts `number | string`); no hook state needed.
2522
+ *
2523
+ * @__NO_SIDE_EFFECTS__
2524
+ * @example
2525
+ * useToNumber('123') // 123
2526
+ * useToNumber('0xFA', { method: 'parseInt', radix: 16 }) // 250
2527
+ */
2528
+ function useToNumber(value, options = {}) {
2529
+ const { method = "parseFloat", radix, nanToZero } = options;
2530
+ let resolved = value;
2531
+ if (typeof method === "function") resolved = method(resolved);
2532
+ else if (typeof resolved === "string") resolved = Number[method](resolved, radix);
2533
+ if (nanToZero && Number.isNaN(resolved)) resolved = 0;
2534
+ return resolved;
2535
+ }
2536
+ //#endregion
2537
+ //#region useToString/index.tsx
2538
+ /**
2539
+ * React port of VueUse's `useToString`.
2540
+ *
2541
+ * Map from @vueuse/shared `useToString`
2542
+ * Mapping: VueUse wraps the template-literal coercion in `computed(() => ...)`
2543
+ * and accepts a `MaybeRefOrGetter`; React has no reactive value tracking, so
2544
+ * this is a plain function returning the stringified value directly.
2545
+ *
2546
+ * The `value` param is a PLAIN read-only value — pass `ref.current` or the
2547
+ * state value. Getter inputs are intentionally not supported (getters were
2548
+ * removed repo-wide); unlike upstream, a getter passed here is coerced as-is
2549
+ * (its source text), not invoked.
2550
+ *
2551
+ * @example
2552
+ * useToString(123.345) // '123.345'
2553
+ * useToString('hi') // 'hi'
2554
+ * useToString({ foo: 'hi' }) // '[object Object]'
2555
+ */
2556
+ function useToString(value) {
2557
+ return `${value}`;
2558
+ }
2559
+ //#endregion
2560
+ //#region useUnmount/index.tsx
2561
+ /**
2562
+ * React port of react-use's `useUnmount`.
2563
+ *
2564
+ * Map from react-use `useUnmount`
2565
+ * Mapping: react-use's `useUnmount` keeps the callback in a `useRef`,
2566
+ * reassigning it on every render so the newest callback is invoked, and runs
2567
+ * it via an empty-dependency `useEffect` cleanup (react-use's `useEffectOnce`
2568
+ * is just `useEffect(effect, [])`). This port follows the same semantics.
2569
+ *
2570
+ * @example
2571
+ * useUnmount(() => cleanup())
2572
+ */
2573
+ function useUnmount(fn) {
2574
+ const fnRef = (0, react.useRef)(fn);
2575
+ fnRef.current = fn;
2576
+ (0, react.useEffect)(() => () => fnRef.current(), []);
2577
+ }
2578
+ //#endregion
2579
+ //#region useUpdate/index.tsx
2580
+ const updateReducer = (num) => (num + 1) % 1e6;
2581
+ /**
2582
+ * React port of react-use's `useUpdate`.
2583
+ *
2584
+ * Map from react-use `useUpdate`
2585
+ * Mapping: `useReducer` with a wrapping counter — the returned function
2586
+ * dispatches an update that forces a re-render and is stable across renders.
2587
+ *
2588
+ * @example
2589
+ * const update = useUpdate()
2590
+ * update() // forces a re-render
2591
+ */
2592
+ function useUpdate() {
2593
+ const [, update] = (0, react.useReducer)(updateReducer, 0);
2594
+ return update;
2595
+ }
2596
+ //#endregion
2597
+ //#region useWatch/index.tsx
2598
+ function useWatch(source, callback, options = {}) {
2599
+ const firstRender = (0, react.useRef)(true);
2600
+ const oldValueRef = (0, react.useRef)(void 0);
2601
+ (0, react.useEffect)(() => {
2602
+ const oldValue = oldValueRef.current;
2603
+ const first = firstRender.current;
2604
+ firstRender.current = false;
2605
+ if (!first || options.immediate) callback(source, oldValue);
2606
+ oldValueRef.current = source;
2607
+ }, Array.isArray(source) ? source : [source]);
2608
+ }
2609
+ //#endregion
2610
+ //#region useWatchArray/index.tsx
2611
+ /**
2612
+ * React port of VueUse's `watchArray` — watch for an array with additions and removals.
2613
+ *
2614
+ * Mapping: built on the house `useWatch` — the list is a plain array value tracked across
2615
+ * renders, `useWatch` handles the change detection, and the previous list is diffed against
2616
+ * the next one with item-identity matching (like upstream) so the callback receives
2617
+ * `(newList, oldList, added, removed)`. The list is wrapped as a single-element watch
2618
+ * source (`[list]`) so `useWatch` tracks it by reference identity instead of spreading a
2619
+ * variable-length list into its dependency list (React requires a constant deps size).
2620
+ *
2621
+ * Divergences from the upstream Vue API:
2622
+ * - `source` is a plain array value — Vue's `WatchSource` forms (ref / getter / reactive)
2623
+ * have no React equivalent, compute the array during render and pass it directly.
2624
+ * - The list is tracked by reference identity: replacing it with a new array fires the
2625
+ * callback even when the items are identical (like a Vue ref reassignment), while
2626
+ * re-renders that keep the same array reference do not fire.
2627
+ * - In-place mutations (`push` / `splice`) do not re-render — produce a new array
2628
+ * (`setList([...list, item])`) to trigger the watch.
2629
+ * - The upstream `onCleanup` callback parameter is not ported — `useWatch` has no
2630
+ * watch-cleanup equivalent, use `useEffect` cleanup in the component instead.
2631
+ * - The return value is `void` — upstream returns a stop `WatchHandle`; watching
2632
+ * ends when the component unmounts.
2633
+ *
2634
+ * @example
2635
+ * ```ts
2636
+ * useWatchArray(list, (newList, oldList, added, removed) => {
2637
+ * console.log('added:', added, 'removed:', removed)
2638
+ * })
2639
+ * ```
2640
+ */
2641
+ function useWatchArray(source, cb, options) {
2642
+ useWatch([source], (watched, watchedOld) => {
2643
+ var _watchedOld$;
2644
+ const newList = watched[0];
2645
+ const prevList = [...(_watchedOld$ = watchedOld === null || watchedOld === void 0 ? void 0 : watchedOld[0]) !== null && _watchedOld$ !== void 0 ? _watchedOld$ : []];
2646
+ const oldListRemains = Array.from({ length: prevList.length });
2647
+ const added = [];
2648
+ for (const obj of newList) {
2649
+ let found = false;
2650
+ for (let i = 0; i < prevList.length; i++) if (!oldListRemains[i] && obj === prevList[i]) {
2651
+ oldListRemains[i] = true;
2652
+ found = true;
2653
+ break;
2654
+ }
2655
+ if (!found) added.push(obj);
2656
+ }
2657
+ cb(newList, prevList, added, prevList.filter((_, i) => !oldListRemains[i]));
2658
+ }, options);
2659
+ }
2660
+ //#endregion
2661
+ //#region useWatchAtMost/index.tsx
2662
+ /**
2663
+ * React port of VueUse's `watchAtMost` — `watch` with the number of times
2664
+ * triggered.
2665
+ *
2666
+ * Map from @vueuse/shared `watchAtMost`
2667
+ * Mapping: built on the house `useWatch`. The callback is wrapped with a fire
2668
+ * counter: each invocation increments the `count` state (exposed in the
2669
+ * return so components re-render), and once the limit — `options.count` — is
2670
+ * reached the wrapper marks the watcher as stopped so further source changes
2671
+ * are ignored. A manual `stop()` has the same effect before the limit.
2672
+ *
2673
+ * Divergences from upstream:
2674
+ * - upstream stops the underlying watcher via `stop()` scheduled on
2675
+ * `nextTick`; this port keeps the effect registered but the wrapped callback
2676
+ * becomes a no-op — observable behavior is identical (the callback fires at
2677
+ * most `count` times).
2678
+ * - `pause` / `resume` (upstream: inherited from `watchWithFilter`) are ported
2679
+ * as a skip flag on the wrapped callback — React has no watcher to detach,
2680
+ * but the observable behavior matches the Pausable controls.
2681
+ * - upstream's `count` return is a shallow ref; here it is React state so
2682
+ * reads re-render.
2683
+ * - upstream's `WatchWithFilterOptions` members beyond `immediate` (`deep`,
2684
+ * `flush`, `onTrack`, `onTrigger`) are not accepted — they are not
2685
+ * expressible in React (no reactive graph, no configurable commit, no
2686
+ * reactivity bookkeeping), and the option type rejects them.
2687
+ *
2688
+ * @example
2689
+ * ```tsx
2690
+ * const { count, stop } = useWatchAtMost(num, (value, oldValue) => {
2691
+ * console.log(value, oldValue)
2692
+ * }, { count: 3 })
2693
+ * ```
2694
+ */
2695
+ function useWatchAtMost(source, callback, options) {
2696
+ const { count: maxCount, ...watchOptions } = options;
2697
+ const [count, setCount] = (0, react.useState)(0);
2698
+ const firedRef = (0, react.useRef)(0);
2699
+ const stoppedRef = (0, react.useRef)(false);
2700
+ const pausedRef = (0, react.useRef)(false);
2701
+ const maxCountRef = (0, react.useRef)(maxCount);
2702
+ maxCountRef.current = maxCount;
2703
+ const stop = (0, react.useCallback)(() => {
2704
+ stoppedRef.current = true;
2705
+ }, []);
2706
+ const pause = (0, react.useCallback)(() => {
2707
+ pausedRef.current = true;
2708
+ }, []);
2709
+ const resume = (0, react.useCallback)(() => {
2710
+ pausedRef.current = false;
2711
+ }, []);
2712
+ function wrapped(value, oldValue) {
2713
+ if (stoppedRef.current || pausedRef.current) return;
2714
+ firedRef.current += 1;
2715
+ setCount(firedRef.current);
2716
+ callback(value, oldValue);
2717
+ if (firedRef.current >= maxCountRef.current) stoppedRef.current = true;
2718
+ }
2719
+ useWatch(source, wrapped, watchOptions);
2720
+ return {
2721
+ count,
2722
+ stop,
2723
+ pause,
2724
+ resume
2725
+ };
2726
+ }
2727
+ //#endregion
2728
+ //#region useWatchDebounced/index.tsx
2729
+ function useWatchDebounced(source, callback, options = {}) {
2730
+ const { debounce = 0, maxWait, rejectOnCancel } = options;
2731
+ useWatch(source, useDebounceFn((value, oldValue) => callback(value, oldValue), debounce, {
2732
+ maxWait,
2733
+ rejectOnCancel
2734
+ }), { immediate: options.immediate });
2735
+ }
2736
+ //#endregion
2737
+ //#region useWatchDeep/index.tsx
2738
+ /**
2739
+ * Structural equality, mirroring the semantics of test `toEqual`: primitives
2740
+ * are compared with `Object.is`, and `Date`, `RegExp`, `Array`, `Map`, `Set`
2741
+ * and objects (plain or class instances) are compared by contents. Functions
2742
+ * compare by reference, and `Map` keys are matched by reference because key
2743
+ * lookups cannot deep-match, while `Map` values and `Set` items are compared
2744
+ * deeply.
2745
+ *
2746
+ * Shared single source of truth — used by {@link useWatchDeep} and imported
2747
+ * from `@reause/shared` by core hooks that need deep change detection
2748
+ * (e.g. `useCloned`).
2749
+ */
2750
+ function deepEqual(a, b) {
2751
+ if (Object.is(a, b)) return true;
2752
+ if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
2753
+ const aRecord = a;
2754
+ const bRecord = b;
2755
+ if (aRecord.constructor !== bRecord.constructor) return false;
2756
+ if (a instanceof Date) return a.getTime() === b.getTime();
2757
+ if (a instanceof RegExp) return a.source === b.source && a.flags === b.flags;
2758
+ if (Array.isArray(a)) {
2759
+ const bArray = b;
2760
+ return a.length === bArray.length && a.every((item, index) => deepEqual(item, bArray[index]));
2761
+ }
2762
+ if (a instanceof Map) {
2763
+ const bMap = b;
2764
+ if (a.size !== bMap.size) return false;
2765
+ for (const [key, value] of a) if (!bMap.has(key) || !deepEqual(value, bMap.get(key))) return false;
2766
+ return true;
2767
+ }
2768
+ if (a instanceof Set) {
2769
+ const bSet = b;
2770
+ if (a.size !== bSet.size) return false;
2771
+ const unmatched = [...bSet];
2772
+ for (const item of a) {
2773
+ const index = unmatched.findIndex((candidate) => deepEqual(item, candidate));
2774
+ if (index === -1) return false;
2775
+ unmatched.splice(index, 1);
2776
+ }
2777
+ return true;
2778
+ }
2779
+ const aKeys = Object.keys(aRecord);
2780
+ if (aKeys.length !== Object.keys(bRecord).length) return false;
2781
+ return aKeys.every((key) => Object.hasOwn(bRecord, key) && deepEqual(aRecord[key], bRecord[key]));
2782
+ }
2783
+ /**
2784
+ * Deep clone pairing with {@link deepEqual}'s type coverage — `Date`, `RegExp`,
2785
+ * `Array`, `Map`, `Set` and objects (plain or class instances) are copied
2786
+ * structurally, primitives and functions pass through. Used to snapshot a live
2787
+ * value into an isolated baseline for change detection (e.g. `useCloned`'s
2788
+ * source / cloned baselines, which must stay unaffected by in-place mutations).
2789
+ */
2790
+ function deepClone(value) {
2791
+ if (value === null || typeof value !== "object") return value;
2792
+ if (value instanceof Date) return new Date(value.getTime());
2793
+ if (value instanceof RegExp) return new RegExp(value.source, value.flags);
2794
+ if (Array.isArray(value)) return value.map((item) => deepClone(item));
2795
+ if (value instanceof Map) {
2796
+ const result = /* @__PURE__ */ new Map();
2797
+ for (const [key, item] of value) result.set(key, deepClone(item));
2798
+ return result;
2799
+ }
2800
+ if (value instanceof Set) {
2801
+ const result = /* @__PURE__ */ new Set();
2802
+ for (const item of value) result.add(deepClone(item));
2803
+ return result;
2804
+ }
2805
+ const result = Object.create(Object.getPrototypeOf(value));
2806
+ for (const key of Object.keys(value)) result[key] = deepClone(value[key]);
2807
+ return result;
2808
+ }
2809
+ function useWatchDeep(source, callback, options = {}) {
2810
+ const immediateCall = (0, react.useRef)(options.immediate === true);
2811
+ useWatch(source, (value, oldValue) => {
2812
+ if (immediateCall.current) {
2813
+ immediateCall.current = false;
2814
+ callback(value, oldValue);
2815
+ return;
2816
+ }
2817
+ if (!deepEqual(value, oldValue)) callback(value, oldValue);
2818
+ }, options);
2819
+ }
2820
+ //#endregion
2821
+ //#region useWatchIgnorable/index.tsx
2822
+ function useWatchIgnorable(source, callback, options = {}) {
2823
+ const { immediate, once } = options;
2824
+ const lastSeenRef = (0, react.useRef)(source);
2825
+ const snapshotRef = (0, react.useRef)(source);
2826
+ const ignoreRef = (0, react.useRef)(false);
2827
+ const stoppedRef = (0, react.useRef)(false);
2828
+ useWatch(source, (value, oldValue) => {
2829
+ lastSeenRef.current = value;
2830
+ const ignore = ignoreRef.current;
2831
+ ignoreRef.current = false;
2832
+ if (ignore || stoppedRef.current) return;
2833
+ callback(value, oldValue);
2834
+ if (once) stoppedRef.current = true;
2835
+ }, { immediate });
2836
+ (0, react.useEffect)(() => {
2837
+ if (ignoreRef.current && Object.is(source, snapshotRef.current)) ignoreRef.current = false;
2838
+ });
2839
+ return {
2840
+ ignoreUpdates: (0, react.useCallback)((updater) => {
2841
+ snapshotRef.current = lastSeenRef.current;
2842
+ updater();
2843
+ ignoreRef.current = true;
2844
+ }, []),
2845
+ ignorePrevAsyncUpdates: (0, react.useCallback)(() => {
2846
+ snapshotRef.current = lastSeenRef.current;
2847
+ ignoreRef.current = true;
2848
+ }, []),
2849
+ stop: (0, react.useCallback)(() => {
2850
+ stoppedRef.current = true;
2851
+ }, [])
2852
+ };
2853
+ }
2854
+ //#endregion
2855
+ //#region useWatchImmediate/index.tsx
2856
+ function useWatchImmediate(source, callback) {
2857
+ useWatch(source, callback, { immediate: true });
2858
+ }
2859
+ //#endregion
2860
+ //#region useWatchOnce/index.tsx
2861
+ /**
2862
+ * Shorthand for watching value with `{ once: true }` — the callback fires at
2863
+ * most once (the first matching change) and the watcher stops afterwards —
2864
+ * React port of VueUse's `watchOnce`.
2865
+ *
2866
+ * Map from @vueuse/shared `watchOnce`.
2867
+ *
2868
+ * Mapping: upstream is a shorthand for
2869
+ * `watch(source, cb, { ...options, once: true })`. This port builds the same
2870
+ * shorthand on the house `useWatch` (like `useWatchAtMost` does with
2871
+ * `count: 1`): the callback is wrapped with a `stopped` ref — the first
2872
+ * invocation forwards `(value, oldValue)` and marks the watcher stopped, so
2873
+ * every further source change is ignored. An `immediate: true` call counts
2874
+ * toward the once, matching upstream.
2875
+ *
2876
+ * Divergences from upstream:
2877
+ * - Returns `{ stop }` instead of the full Vue `WatchHandle` — `stop` disables
2878
+ * further fires early (matching upstream's `stop()`); disposal otherwise
2879
+ * follows the component lifecycle.
2880
+ * - The source is a plain value (or array of values) tracked across renders —
2881
+ * Vue's `WatchSource` forms (ref / getter / reactive) have no React
2882
+ * equivalent, and the `deep` / `flush` watch options don't apply.
2883
+ *
2884
+ * @example
2885
+ * ```ts
2886
+ * useWatchOnce(count, (value, oldValue) => console.log(value, oldValue))
2887
+ * ```
2888
+ */
2889
+ function useWatchOnce(source, callback, options = {}) {
2890
+ const stoppedRef = (0, react.useRef)(false);
2891
+ const stop = (0, react.useCallback)(() => {
2892
+ stoppedRef.current = true;
2893
+ }, []);
2894
+ function wrapped(value, oldValue) {
2895
+ if (stoppedRef.current) return;
2896
+ stoppedRef.current = true;
2897
+ callback(value, oldValue);
2898
+ }
2899
+ useWatch(source, wrapped, options);
2900
+ return { stop };
2901
+ }
2902
+ //#endregion
2903
+ //#region useWatchPausable/index.tsx
2904
+ function useWatchPausable(source, callback, options = {}) {
2905
+ const { initialState = "active", immediate } = options;
2906
+ const [isActive, setIsActive] = (0, react.useState)(initialState === "active");
2907
+ const activeRef = (0, react.useRef)(initialState === "active");
2908
+ const stoppedRef = (0, react.useRef)(false);
2909
+ const pause = (0, react.useCallback)(() => {
2910
+ activeRef.current = false;
2911
+ setIsActive(false);
2912
+ }, []);
2913
+ const resume = (0, react.useCallback)(() => {
2914
+ activeRef.current = true;
2915
+ setIsActive(true);
2916
+ }, []);
2917
+ const stop = (0, react.useCallback)(() => {
2918
+ stoppedRef.current = true;
2919
+ }, []);
2920
+ useWatch(source, (current, oldValue) => {
2921
+ if (!activeRef.current || stoppedRef.current) return;
2922
+ callback(current, oldValue);
2923
+ }, { immediate });
2924
+ return {
2925
+ pause,
2926
+ resume,
2927
+ isActive,
2928
+ stop
2929
+ };
2930
+ }
2931
+ //#endregion
2932
+ //#region useWatchThrottled/index.tsx
2933
+ function useWatchThrottled(source, callback, options = {}) {
2934
+ const { throttle = 0, trailing = true, leading = true } = options;
2935
+ useWatch(source, useThrottleFn((value, oldValue) => callback(value, oldValue), throttle, trailing, leading), { immediate: options.immediate });
2936
+ }
2937
+ //#endregion
2938
+ //#region useWatchTriggerable/index.tsx
2939
+ function useWatchTriggerable(source, callback, options = {}) {
2940
+ const { immediate } = options;
2941
+ const [, forceCommit] = (0, react.useState)(0);
2942
+ const cleanupFnRef = (0, react.useRef)(void 0);
2943
+ const onCleanup = (0, react.useCallback)((cleanupFn) => {
2944
+ cleanupFnRef.current = cleanupFn;
2945
+ }, []);
2946
+ const triggerableCallback = (0, react.useCallback)((value, oldValue) => {
2947
+ const cleanupFn = cleanupFnRef.current;
2948
+ if (cleanupFn) {
2949
+ cleanupFnRef.current = void 0;
2950
+ cleanupFn();
2951
+ }
2952
+ return callback(value, oldValue, onCleanup);
2953
+ }, [callback, onCleanup]);
2954
+ const lastSeenRef = (0, react.useRef)(source);
2955
+ const snapshotRef = (0, react.useRef)(source);
2956
+ const ignoreRef = (0, react.useRef)(false);
2957
+ const stoppedRef = (0, react.useRef)(false);
2958
+ useWatch(source, (value, oldValue) => {
2959
+ lastSeenRef.current = value;
2960
+ const ignore = ignoreRef.current;
2961
+ ignoreRef.current = false;
2962
+ if (ignore || stoppedRef.current) return;
2963
+ triggerableCallback(value, oldValue);
2964
+ }, { immediate });
2965
+ (0, react.useEffect)(() => {
2966
+ if (ignoreRef.current && isSameSource(source, snapshotRef.current)) ignoreRef.current = false;
2967
+ });
2968
+ const ignoreUpdates = (0, react.useCallback)((updater) => {
2969
+ snapshotRef.current = lastSeenRef.current;
2970
+ updater();
2971
+ ignoreRef.current = true;
2972
+ forceCommit((x) => x + 1);
2973
+ }, [forceCommit]);
2974
+ const ignorePrevAsyncUpdates = (0, react.useCallback)(() => {
2975
+ snapshotRef.current = lastSeenRef.current;
2976
+ ignoreRef.current = true;
2977
+ forceCommit((x) => x + 1);
2978
+ }, [forceCommit]);
2979
+ const stop = (0, react.useCallback)(() => {
2980
+ stoppedRef.current = true;
2981
+ }, []);
2982
+ return {
2983
+ trigger: (0, react.useCallback)(() => {
2984
+ let result;
2985
+ ignoreUpdates(() => {
2986
+ result = triggerableCallback(source, getOldValue(source));
2987
+ });
2988
+ return result;
2989
+ }, [
2990
+ source,
2991
+ triggerableCallback,
2992
+ ignoreUpdates
2993
+ ]),
2994
+ ignoreUpdates,
2995
+ ignorePrevAsyncUpdates,
2996
+ stop
2997
+ };
2998
+ }
2999
+ function getOldValue(source) {
3000
+ return Array.isArray(source) ? source.map(() => void 0) : void 0;
3001
+ }
3002
+ function isSameSource(a, b) {
3003
+ if (Object.is(a, b)) return true;
3004
+ return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, index) => Object.is(item, b[index]));
3005
+ }
3006
+ //#endregion
3007
+ //#region useWatchWithFilter/index.tsx
3008
+ function bypassFilter(invoke) {
3009
+ invoke();
3010
+ }
3011
+ /**
3012
+ * Create an EventFilter that debounce the events — in-house port of upstream
3013
+ * `@vueuse/shared` `debounceFilter` (trailing edge + `maxWait`).
3014
+ *
3015
+ * Mapping: same collapsing semantics as upstream (a newer call supersedes the
3016
+ * pending one; the `maxWait` timer survives re-scheduling and forces the call
3017
+ * with the latest `invoke`). Divergences: the promise-settlement plumbing
3018
+ * (`lastRejector` / `rejectOnCancel`) is dropped — the house `EventFilter`
3019
+ * contract returns `void` and the watch path consumes no promise, so
3020
+ * `rejectOnCancel` has no observable effect — and `isPending` is a plain
3021
+ * getter instead of a reactive ref. `ms` accepts a plain number or a React
3022
+ * ref (upstream: `RefOrValue<number>`) and is re-read on every call. Pending
3023
+ * timers are cleared by `cancel()` — the `useWatchWithFilter` hook calls it
3024
+ * on stop / unmount.
3025
+ *
3026
+ * @example
3027
+ * ```ts
3028
+ * useWatchWithFilter(input, callback, { eventFilter: debounceFilter(300, { maxWait: 1000 }) })
3029
+ * ```
3030
+ */
3031
+ function debounceFilter(ms = 200, options = {}) {
3032
+ let timer;
3033
+ let maxTimer;
3034
+ let pending = false;
3035
+ let lastInvoker;
3036
+ const clearTimers = () => {
3037
+ if (timer !== void 0) {
3038
+ clearTimeout(timer);
3039
+ timer = void 0;
3040
+ }
3041
+ if (maxTimer !== void 0) {
3042
+ clearTimeout(maxTimer);
3043
+ maxTimer = void 0;
3044
+ }
3045
+ };
3046
+ const handler = (invoke) => {
3047
+ const duration = toValue(ms);
3048
+ const maxDuration = toValue(options.maxWait);
3049
+ if (timer !== void 0) {
3050
+ clearTimeout(timer);
3051
+ timer = void 0;
3052
+ }
3053
+ if (duration === void 0 || duration <= 0 || maxDuration !== void 0 && maxDuration <= 0) {
3054
+ clearTimers();
3055
+ pending = false;
3056
+ invoke();
3057
+ return;
3058
+ }
3059
+ pending = true;
3060
+ lastInvoker = invoke;
3061
+ if (maxDuration !== void 0 && maxTimer === void 0) maxTimer = setTimeout(() => {
3062
+ maxTimer = void 0;
3063
+ if (timer !== void 0) {
3064
+ clearTimeout(timer);
3065
+ timer = void 0;
3066
+ }
3067
+ pending = false;
3068
+ lastInvoker === null || lastInvoker === void 0 || lastInvoker();
3069
+ }, maxDuration);
3070
+ timer = setTimeout(() => {
3071
+ timer = void 0;
3072
+ if (maxTimer !== void 0) {
3073
+ clearTimeout(maxTimer);
3074
+ maxTimer = void 0;
3075
+ }
3076
+ pending = false;
3077
+ invoke();
3078
+ }, duration);
3079
+ };
3080
+ const filter = handler;
3081
+ filter.cancel = () => {
3082
+ clearTimers();
3083
+ pending = false;
3084
+ lastInvoker = void 0;
3085
+ };
3086
+ filter.flush = () => {
3087
+ if (!pending) return;
3088
+ clearTimers();
3089
+ pending = false;
3090
+ const invoker = lastInvoker;
3091
+ lastInvoker = void 0;
3092
+ invoker === null || invoker === void 0 || invoker();
3093
+ };
3094
+ Object.defineProperty(filter, "isPending", {
3095
+ enumerable: true,
3096
+ get: () => pending
3097
+ });
3098
+ return filter;
3099
+ }
3100
+ /**
3101
+ * Create an EventFilter that throttle the events — in-house port of upstream
3102
+ * `@vueuse/shared` `throttleFilter` (leading/trailing edges with a trailing
3103
+ * invoke on window end).
3104
+ *
3105
+ * Mapping: same collapsing semantics as upstream — a call inside the throttle
3106
+ * window re-schedules the trailing timer with the remaining time, collapsing
3107
+ * bursts into one trailing call carrying the latest `invoke`. Divergences:
3108
+ * the promise-settlement plumbing (`rejectOnCancel`, upstream's fourth
3109
+ * parameter) is dropped — the house `EventFilter` contract returns `void` —
3110
+ * and the object options form is not ported (positional
3111
+ * `throttleFilter(ms, trailing, leading)` like the house `useThrottleFn`).
3112
+ * `ms` accepts a plain number or a React ref (upstream:
3113
+ * `RefOrValue<number>`) and is re-read on every call.
3114
+ *
3115
+ * @example
3116
+ * ```ts
3117
+ * useWatchWithFilter(scrollY, callback, { eventFilter: throttleFilter(100, true, false) })
3118
+ * ```
3119
+ */
3120
+ function throttleFilter(ms = 200, trailing = true, leading = true) {
3121
+ let lastExec = 0;
3122
+ let timer;
3123
+ let isLeading = true;
3124
+ const clear = () => {
3125
+ if (timer !== void 0) {
3126
+ clearTimeout(timer);
3127
+ timer = void 0;
3128
+ }
3129
+ };
3130
+ return (invoke) => {
3131
+ const duration = toValue(ms);
3132
+ const elapsed = Date.now() - lastExec;
3133
+ clear();
3134
+ if (duration === void 0 || duration <= 0) {
3135
+ lastExec = Date.now();
3136
+ invoke();
3137
+ return;
3138
+ }
3139
+ if (elapsed > duration) {
3140
+ lastExec = Date.now();
3141
+ if (leading || !isLeading) invoke();
3142
+ } else if (trailing) timer = setTimeout(() => {
3143
+ lastExec = Date.now();
3144
+ isLeading = true;
3145
+ invoke();
3146
+ clear();
3147
+ }, Math.max(0, duration - elapsed));
3148
+ if (!leading && timer === void 0) timer = setTimeout(() => {
3149
+ isLeading = true;
3150
+ }, duration);
3151
+ isLeading = false;
3152
+ };
3153
+ }
3154
+ /**
3155
+ * `watch` with additional EventFilter control — React port of VueUse's
3156
+ * `watchWithFilter`.
3157
+ * Map from @vueuse/shared watchWithFilter.
3158
+ *
3159
+ * Mapping: upstream builds `watch(source, createFilterWrapper(eventFilter, cb),
3160
+ * watchOptions)` — the event filter wraps the watch trigger, so every source
3161
+ * change hands an `invoke` closure to the filter, which decides whether and
3162
+ * when the callback actually runs. This port builds the same wrapper on the
3163
+ * house `useWatch` (Vue's reactive dependency tracking becomes the effect
3164
+ * dependency list): every source change invokes the captured `eventFilter`
3165
+ * with an `invoke` closure carrying the latest `(value, oldValue)` pair. The
3166
+ * hook holds no state of its own — the source is the caller's own value — and
3167
+ * returns a `stop` function (upstream's `WatchHandle`, reduced to the stop
3168
+ * capability): after `stop()`, further source changes and any pending
3169
+ * filtered invocation no longer fire the callback, and cancelable filters
3170
+ * (`debounceFilter`) are cancelled outright.
3171
+ *
3172
+ * Divergences from upstream:
3173
+ * - React batching: source changes made in the same tick collapse into a
3174
+ * single effect run, so the filter sees ONE trigger where Vue's watcher
3175
+ * would fire per mutation. For a trailing filter the collapsed call is
3176
+ * identical (the latest `(value, oldValue)` pair); a leading-edge filter
3177
+ * fires at most once per tick instead of once per mutation.
3178
+ * - `deep` is not ported: React values are not deeply reactive. The source is
3179
+ * tracked by reference across renders (the effect dependency list), so
3180
+ * mutating an object in place is invisible and `deep: true` would have
3181
+ * nothing to recurse into — watch a derived primitive (or key) instead.
3182
+ * The same applies to the `flush` watch option: React effects always run
3183
+ * after the commit, there is no pre/post/sync choice.
3184
+ * - The filter instance is captured once on mount (upstream evaluates watch
3185
+ * options once during setup) — an inline `debounceFilter(ms)` is safe; use
3186
+ * a getter-based delay for dynamic values.
3187
+ * - `stop()` also suppresses a pending filtered invocation (upstream: an
3188
+ * already-scheduled filtered invoke still fires after stop), and pending
3189
+ * timers are cancelled when the component unmounts (upstream leaves
3190
+ * disposal to the effect scope).
3191
+ * - The promise-settlement plumbing of upstream filters (`lastRejector` /
3192
+ * `rejectOnCancel`) is dropped — the house `EventFilter` contract returns
3193
+ * `void`, so `rejectOnCancel` has no observable effect.
3194
+ *
3195
+ * @example
3196
+ * ```ts
3197
+ * const stop = useWatchWithFilter(count, (value, oldValue) => console.log(value, oldValue))
3198
+ * useWatchWithFilter(count, callback, { eventFilter: debounceFilter(300) })
3199
+ * stop()
3200
+ * ```
3201
+ */
3202
+ function useWatchWithFilter(source, callback, options = {}) {
3203
+ const { eventFilter = bypassFilter, immediate = false } = options;
3204
+ const stoppedRef = (0, react.useRef)(false);
3205
+ const callbackRef = (0, react.useRef)(callback);
3206
+ callbackRef.current = callback;
3207
+ const filterRef = (0, react.useRef)(eventFilter);
3208
+ function wrapped(value, oldValue) {
3209
+ if (stoppedRef.current) return;
3210
+ filterRef.current(() => {
3211
+ if (stoppedRef.current) return;
3212
+ callbackRef.current(value, oldValue);
3213
+ });
3214
+ }
3215
+ useWatch(source, wrapped, { immediate });
3216
+ const stop = (0, react.useCallback)(() => {
3217
+ stoppedRef.current = true;
3218
+ const cancelable = filterRef.current;
3219
+ if (typeof cancelable.cancel === "function") cancelable.cancel();
3220
+ }, []);
3221
+ (0, react.useEffect)(() => stop, [stop]);
3222
+ return stop;
3223
+ }
3224
+ //#endregion
3225
+ //#region useWhenever/index.tsx
3226
+ /**
3227
+ * React port of VueUse's `whenever`.
3228
+ *
3229
+ * Map from @vueuse/shared `whenever`
3230
+ * Mapping: upstream `whenever` is Vue's `watch` plus a truthy guard — the
3231
+ * callback runs every time the source CHANGES to a truthy value (a re-render
3232
+ * with the same truthy value never fires). In React this becomes a `useEffect`
3233
+ * watching `[value]`: the initial mount is skipped unless `immediate` (which
3234
+ * fires with `oldValue` `undefined`), later runs fire when the value is truthy
3235
+ * and actually changed, and the previous value is tracked in a ref updated on
3236
+ * every run — mirroring `watch`'s `oldValue`, which advances through falsy
3237
+ * values too. The callback is kept in a ref so re-renders always invoke the
3238
+ * newest one.
3239
+ *
3240
+ * The `once` option stops the watch after the first truthy fire — expressible
3241
+ * in React as a one-shot flag consulted by the effect, mirroring upstream's
3242
+ * `if (options?.once) nextTick(() => stop())`.
3243
+ *
3244
+ * The return value is a `stop` function — upstream's `WatchHandle`, reduced to
3245
+ * the stop capability (house `useWatch` has no stop-handle infrastructure).
3246
+ * `stop()` is also called when the component unmounts.
3247
+ *
3248
+ * The upstream 3-arg callback `(value, oldValue, onInvalidate)` becomes a
3249
+ * 2-arg `(value, oldValue)` in this port — `onInvalidate` (Vue's effect
3250
+ * invalidation registration) has no React equivalent, so it is dropped.
3251
+ *
3252
+ * @see https://vueuse.org/shared/whenever/
3253
+ *
3254
+ * @example
3255
+ * useWhenever(ready, () => console.log(state))
3256
+ * useWhenever(ready, () => console.log(state), { immediate: true })
3257
+ * useWhenever(ready, () => console.log(state), { once: true })
3258
+ */
3259
+ function useWhenever(value, cb, options) {
3260
+ const cbRef = (0, react.useRef)(cb);
3261
+ cbRef.current = cb;
3262
+ const oldValueRef = (0, react.useRef)(void 0);
3263
+ const isFirstRenderRef = (0, react.useRef)(true);
3264
+ const stoppedRef = (0, react.useRef)(false);
3265
+ (0, react.useEffect)(() => {
3266
+ if (stoppedRef.current) return;
3267
+ const isFirstRender = isFirstRenderRef.current;
3268
+ isFirstRenderRef.current = false;
3269
+ const isMountFire = isFirstRender && (options === null || options === void 0 ? void 0 : options.immediate) === true;
3270
+ const isChange = !Object.is(oldValueRef.current, value);
3271
+ if (value && (isMountFire || !isFirstRender && isChange)) {
3272
+ if (options === null || options === void 0 ? void 0 : options.once) stoppedRef.current = true;
3273
+ cbRef.current(value, oldValueRef.current);
3274
+ }
3275
+ oldValueRef.current = value;
3276
+ }, [value]);
3277
+ const stop = (0, react.useCallback)(() => {
3278
+ stoppedRef.current = true;
3279
+ }, []);
3280
+ (0, react.useEffect)(() => stop, [stop]);
3281
+ return stop;
3282
+ }
3283
+ //#endregion
3284
+ //#region index.ts
3285
+ /**
3286
+ * @reause/shared — React port of @vueuse/shared
3287
+ * Shared utilities shared across all reause packages.
3288
+ *
3289
+ * Mapping note: @vueuse/shared exposes pure utilities + composables that
3290
+ * don't depend on the renderer. In the React world those become either
3291
+ * plain functions (no hook) or hooks without rendering logic.
3292
+ */
3293
+ const isClient = typeof window !== "undefined";
3294
+ function noop() {}
3295
+ //#endregion
3296
+ exports.assert = assert;
3297
+ exports.clamp = clamp;
3298
+ exports.createEventHook = createEventHook;
3299
+ exports.createGlobalState = createGlobalState;
3300
+ exports.createInjectionState = createInjectionState;
3301
+ exports.createSharedHook = createSharedHook;
3302
+ exports.createSingletonPromise = createSingletonPromise;
3303
+ exports.debounceFilter = debounceFilter;
3304
+ exports.deepClone = deepClone;
3305
+ exports.deepEqual = deepEqual;
3306
+ exports.formatDate = formatDate;
3307
+ exports.hasOwn = hasOwn;
3308
+ exports.hyphenate = hyphenate;
3309
+ exports.increaseWithUnit = increaseWithUnit;
3310
+ exports.isClient = isClient;
3311
+ exports.isDef = isDef;
3312
+ exports.isDefined = isDefined;
3313
+ exports.isIOS = isIOS;
3314
+ exports.isObject = isObject;
3315
+ exports.isRefLike = isRefLike;
3316
+ exports.makeDestructurable = makeDestructurable;
3317
+ exports.noop = noop;
3318
+ exports.normalizeDate = normalizeDate;
3319
+ exports.now = now;
3320
+ exports.objectOmit = objectOmit;
3321
+ exports.objectPick = objectPick;
3322
+ exports.promiseTimeout = promiseTimeout;
3323
+ exports.pxValue = pxValue;
3324
+ exports.rand = rand;
3325
+ exports.syncState = syncState;
3326
+ exports.syncStates = syncStates;
3327
+ exports.throttleFilter = throttleFilter;
3328
+ exports.timestamp = timestamp;
3329
+ exports.toArray = toArray;
3330
+ exports.toValue = toValue;
3331
+ exports.until = until;
3332
+ exports.useArrayDifference = useArrayDifference;
3333
+ exports.useArrayEvery = useArrayEvery;
3334
+ exports.useArrayFilter = useArrayFilter;
3335
+ exports.useArrayFind = useArrayFind;
3336
+ exports.useArrayFindIndex = useArrayFindIndex;
3337
+ exports.useArrayFindLast = useArrayFindLast;
3338
+ exports.useArrayIncludes = useArrayIncludes;
3339
+ exports.useArrayJoin = useArrayJoin;
3340
+ exports.useArrayMap = useArrayMap;
3341
+ exports.useArrayReduce = useArrayReduce;
3342
+ exports.useArraySome = useArraySome;
3343
+ exports.useArrayUnique = useArrayUnique;
3344
+ exports.useControllableState = useControllableState;
3345
+ exports.useCounter = useCounter;
3346
+ exports.useDateFormat = useDateFormat;
3347
+ exports.useDebounceFn = useDebounceFn;
3348
+ exports.useInterval = useInterval;
3349
+ exports.useIntervalFn = useIntervalFn;
3350
+ exports.useLastChanged = useLastChanged;
3351
+ exports.useListener = useListener;
3352
+ exports.useMount = useMount;
3353
+ exports.useStateAutoReset = useStateAutoReset;
3354
+ exports.useStateDebounced = useStateDebounced;
3355
+ exports.useStateDefault = useStateDefault;
3356
+ exports.useStateManualReset = useStateManualReset;
3357
+ exports.useStateThrottled = useStateThrottled;
3358
+ exports.useStateWithControl = useStateWithControl;
3359
+ exports.useThrottleFn = useThrottleFn;
3360
+ exports.useTimeout = useTimeout;
3361
+ exports.useTimeoutFn = useTimeoutFn;
3362
+ exports.useToNumber = useToNumber;
3363
+ exports.useToString = useToString;
3364
+ exports.useToggle = useToggle;
3365
+ exports.useUnmount = useUnmount;
3366
+ exports.useUpdate = useUpdate;
3367
+ exports.useWatch = useWatch;
3368
+ exports.useWatchArray = useWatchArray;
3369
+ exports.useWatchAtMost = useWatchAtMost;
3370
+ exports.useWatchDebounced = useWatchDebounced;
3371
+ exports.useWatchDeep = useWatchDeep;
3372
+ exports.useWatchIgnorable = useWatchIgnorable;
3373
+ exports.useWatchImmediate = useWatchImmediate;
3374
+ exports.useWatchOnce = useWatchOnce;
3375
+ exports.useWatchPausable = useWatchPausable;
3376
+ exports.useWatchThrottled = useWatchThrottled;
3377
+ exports.useWatchTriggerable = useWatchTriggerable;
3378
+ exports.useWatchWithFilter = useWatchWithFilter;
3379
+ exports.useWhenever = useWhenever;
3380
+ exports.writeState = writeState;
3381
+ })(this.reause = this.reause || {}, React);