@dxos/react-hooks 0.8.4-main.ead640a → 0.8.4-main.effb148878

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.
Files changed (49) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +1 -0
  3. package/dist/lib/browser/index.mjs +187 -146
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/node-esm/index.mjs +187 -146
  7. package/dist/lib/node-esm/index.mjs.map +4 -4
  8. package/dist/lib/node-esm/meta.json +1 -1
  9. package/dist/types/src/index.d.ts +3 -2
  10. package/dist/types/src/index.d.ts.map +1 -1
  11. package/dist/types/src/useAsyncEffect.d.ts.map +1 -1
  12. package/dist/types/src/useAsyncState.d.ts.map +1 -1
  13. package/dist/types/src/useAtomState.d.ts +12 -0
  14. package/dist/types/src/useAtomState.d.ts.map +1 -0
  15. package/dist/types/src/useControlledState.d.ts +2 -3
  16. package/dist/types/src/useControlledState.d.ts.map +1 -1
  17. package/dist/types/src/useDebugDeps.d.ts +1 -1
  18. package/dist/types/src/useDebugDeps.d.ts.map +1 -1
  19. package/dist/types/src/useDefaultValue.d.ts.map +1 -1
  20. package/dist/types/src/useDefaults.d.ts.map +1 -1
  21. package/dist/types/src/useDynamicRef.d.ts +3 -3
  22. package/dist/types/src/useDynamicRef.d.ts.map +1 -1
  23. package/dist/types/src/useForwardedRef.d.ts +23 -3
  24. package/dist/types/src/useForwardedRef.d.ts.map +1 -1
  25. package/dist/types/src/useId.d.ts.map +1 -1
  26. package/dist/types/src/useIsFocused.d.ts.map +1 -1
  27. package/dist/types/src/useMediaQuery.d.ts +1 -1
  28. package/dist/types/src/useMediaQuery.d.ts.map +1 -1
  29. package/dist/types/src/useMulticastObservable.d.ts.map +1 -1
  30. package/dist/types/src/useTimeout.d.ts.map +1 -1
  31. package/dist/types/src/useTransitions.d.ts.map +1 -1
  32. package/dist/types/src/useViewportResize.d.ts +1 -1
  33. package/dist/types/src/useViewportResize.d.ts.map +1 -1
  34. package/dist/types/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +18 -15
  36. package/src/index.ts +4 -3
  37. package/src/useAtomState.ts +23 -0
  38. package/src/useControlledState.ts +22 -13
  39. package/src/useDebugDeps.ts +17 -8
  40. package/src/useDynamicRef.ts +5 -6
  41. package/src/useForwardedRef.ts +47 -13
  42. package/src/useId.ts +3 -2
  43. package/src/useIsFocused.ts +1 -1
  44. package/src/useMediaQuery.ts +7 -7
  45. package/src/useMulticastObservable.test.ts +1 -1
  46. package/src/useViewportResize.ts +29 -11
  47. package/dist/types/src/useSignals.d.ts +0 -10
  48. package/dist/types/src/useSignals.d.ts.map +0 -1
  49. package/src/useSignals.ts +0 -27
@@ -1,5 +1,9 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
 
3
+ // src/index.ts
4
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
5
+ import { useSize, useScroller } from "mini-virtual-list";
6
+
3
7
  // src/useAsyncEffect.ts
4
8
  import { useEffect } from "react";
5
9
  var useAsyncEffect = (cb, deps) => {
@@ -19,10 +23,28 @@ var useAsyncEffect = (cb, deps) => {
19
23
  }, deps ?? []);
20
24
  };
21
25
 
26
+ // src/useAtomState.ts
27
+ import { Atom, useAtomSet, useAtomValue } from "@effect-atom/atom-react";
28
+ import { useMemo, useState } from "react";
29
+ var useAtomState = (initialValue) => {
30
+ const [atom] = useState(() => Atom.make(initialValue));
31
+ const value = useAtomValue(atom);
32
+ const set = useAtomSet(atom);
33
+ return useMemo(() => ({
34
+ atom,
35
+ value,
36
+ set
37
+ }), [
38
+ atom,
39
+ value,
40
+ set
41
+ ]);
42
+ };
43
+
22
44
  // src/useAsyncState.ts
23
- import { useEffect as useEffect2, useState } from "react";
45
+ import { useEffect as useEffect2, useState as useState2 } from "react";
24
46
  var useAsyncState = (cb, deps = []) => {
25
- const [value, setValue] = useState();
47
+ const [value, setValue] = useState2();
26
48
  useEffect2(() => {
27
49
  let disposed = false;
28
50
  const t = setTimeout(async () => {
@@ -43,58 +65,101 @@ var useAsyncState = (cb, deps = []) => {
43
65
  };
44
66
 
45
67
  // src/useControlledState.ts
46
- import { useEffect as useEffect3, useState as useState2 } from "react";
47
- var useControlledState = (controlledValue, onChange, ...deps) => {
48
- const [value, setValue] = useState2(controlledValue);
49
- useEffect3(() => {
50
- if (controlledValue !== void 0) {
51
- setValue(controlledValue);
68
+ import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef2, useState as useState4 } from "react";
69
+
70
+ // src/useDynamicRef.ts
71
+ import { useCallback, useEffect as useEffect3, useRef, useState as useState3 } from "react";
72
+ var useStateWithRef = (valueProp) => {
73
+ const [value, setValue] = useState3(valueProp);
74
+ const valueRef = useRef(valueProp);
75
+ const setter = useCallback((value2) => {
76
+ if (typeof value2 === "function") {
77
+ setValue((current) => {
78
+ valueRef.current = value2(current);
79
+ return valueRef.current;
80
+ });
81
+ } else {
82
+ valueRef.current = value2;
83
+ setValue(value2);
52
84
  }
85
+ }, []);
86
+ return [
87
+ value,
88
+ setter,
89
+ valueRef
90
+ ];
91
+ };
92
+ var useDynamicRef = (value) => {
93
+ const valueRef = useRef(value);
94
+ useEffect3(() => {
95
+ valueRef.current = value;
53
96
  }, [
54
- controlledValue,
55
- ...deps
97
+ value
56
98
  ]);
57
- useEffect3(() => {
58
- onChange?.(value);
99
+ return valueRef;
100
+ };
101
+
102
+ // src/useControlledState.ts
103
+ var useControlledState = (valueProp, onChange) => {
104
+ const [value, setControlledValue] = useState4(valueProp);
105
+ useEffect4(() => {
106
+ setControlledValue(valueProp);
59
107
  }, [
60
- value,
61
- onChange
108
+ valueProp
109
+ ]);
110
+ const onChangeRef = useRef2(onChange);
111
+ const valueRef = useDynamicRef(valueProp);
112
+ const setValue = useCallback2((nextValue) => {
113
+ const value2 = isFunction(nextValue) ? nextValue(valueRef.current) : nextValue;
114
+ setControlledValue(value2);
115
+ onChangeRef.current?.(value2);
116
+ }, [
117
+ valueRef,
118
+ onChangeRef
62
119
  ]);
63
120
  return [
64
121
  value,
65
122
  setValue
66
123
  ];
67
124
  };
125
+ function isFunction(value) {
126
+ return typeof value === "function";
127
+ }
68
128
 
69
129
  // src/useDebugDeps.ts
70
- import { useEffect as useEffect4, useRef } from "react";
71
- var useDebugDeps = (deps = [], active = true) => {
72
- const lastDeps = useRef([]);
73
- useEffect4(() => {
74
- console.group("deps changed", {
75
- previous: lastDeps.current.length,
76
- current: deps.length
77
- });
130
+ import { useEffect as useEffect5, useRef as useRef3 } from "react";
131
+ import { log } from "@dxos/log";
132
+ var useDebugDeps = (deps = [], label = "useDebugDeps", active = true) => {
133
+ const lastDeps = useRef3([]);
134
+ useEffect5(() => {
135
+ if (!active) {
136
+ return;
137
+ }
138
+ const diff = {};
78
139
  for (let i = 0; i < Math.max(lastDeps.current.length ?? 0, deps.length ?? 0); i++) {
79
- if (lastDeps.current[i] !== deps[i] && active) {
80
- console.log("changed", {
81
- index: i,
140
+ if (lastDeps.current[i] !== deps[i] || i > lastDeps.current.length) {
141
+ diff[i] = {
82
142
  previous: lastDeps.current[i],
83
143
  current: deps[i]
84
- });
144
+ };
85
145
  }
86
146
  }
87
- console.groupEnd();
147
+ if (Object.keys(diff).length > 0) {
148
+ log.warn(`Updated: ${label} [${lastDeps.current.length}/${deps.length}]`, diff);
149
+ }
88
150
  lastDeps.current = deps;
89
- }, deps);
151
+ }, [
152
+ ...deps,
153
+ active
154
+ ]);
90
155
  };
91
156
 
92
157
  // src/useDefaultValue.ts
93
- import { useEffect as useEffect5, useMemo, useState as useState3 } from "react";
158
+ import { useEffect as useEffect6, useMemo as useMemo2, useState as useState5 } from "react";
94
159
  var useDefaultValue = (reactiveValue, getDefaultValue) => {
95
- const stableDefaultValue = useMemo(getDefaultValue, []);
96
- const [value, setValue] = useState3(reactiveValue ?? stableDefaultValue);
97
- useEffect5(() => {
160
+ const stableDefaultValue = useMemo2(getDefaultValue, []);
161
+ const [value, setValue] = useState5(reactiveValue ?? stableDefaultValue);
162
+ useEffect6(() => {
98
163
  setValue(reactiveValue ?? stableDefaultValue);
99
164
  }, [
100
165
  reactiveValue,
@@ -105,51 +170,18 @@ var useDefaultValue = (reactiveValue, getDefaultValue) => {
105
170
 
106
171
  // src/useDefaults.ts
107
172
  import defaultsDeep from "lodash.defaultsdeep";
108
- import { useMemo as useMemo2 } from "react";
173
+ import { useMemo as useMemo3 } from "react";
109
174
  var useDefaults = (value, defaults) => {
110
- return useMemo2(() => defaultsDeep({}, defaults, value), [
175
+ return useMemo3(() => defaultsDeep({}, defaults, value), [
111
176
  value,
112
177
  defaults
113
178
  ]);
114
179
  };
115
180
 
116
- // src/useDynamicRef.ts
117
- import { useCallback } from "@preact-signals/safe-react/react";
118
- import { useEffect as useEffect6, useRef as useRef2, useState as useState4 } from "react";
119
- var useStateWithRef = (valueParam) => {
120
- const [value, setValue] = useState4(valueParam);
121
- const valueRef = useRef2(valueParam);
122
- const setter = useCallback((value2) => {
123
- if (typeof value2 === "function") {
124
- setValue((current) => {
125
- valueRef.current = value2(current);
126
- return valueRef.current;
127
- });
128
- } else {
129
- valueRef.current = value2;
130
- setValue(value2);
131
- }
132
- }, []);
133
- return [
134
- value,
135
- setter,
136
- valueRef
137
- ];
138
- };
139
- var useDynamicRef = (value) => {
140
- const valueRef = useRef2(value);
141
- useEffect6(() => {
142
- valueRef.current = value;
143
- }, [
144
- value
145
- ]);
146
- return valueRef;
147
- };
148
-
149
181
  // src/useFileDownload.ts
150
- import { useMemo as useMemo3 } from "react";
182
+ import { useMemo as useMemo4 } from "react";
151
183
  var useFileDownload = () => {
152
- return useMemo3(() => (data, filename) => {
184
+ return useMemo4(() => (data, filename) => {
153
185
  const url = typeof data === "string" ? data : URL.createObjectURL(data);
154
186
  const element = document.createElement("a");
155
187
  element.setAttribute("href", url);
@@ -160,43 +192,61 @@ var useFileDownload = () => {
160
192
  };
161
193
 
162
194
  // src/useForwardedRef.ts
163
- import { useEffect as useEffect7, useRef as useRef3 } from "react";
164
- var useForwardedRef = (ref) => {
165
- const innerRef = useRef3(null);
195
+ import { useEffect as useEffect7, useMemo as useMemo5, useRef as useRef4 } from "react";
196
+ var useForwardedRef = (forwardedRef) => {
197
+ const localRef = useRef4(null);
166
198
  useEffect7(() => {
167
- updateRef(ref, innerRef.current);
199
+ setRef(forwardedRef, localRef.current);
168
200
  }, [
169
- ref
201
+ forwardedRef
170
202
  ]);
171
- return innerRef;
203
+ return localRef;
172
204
  };
173
- var updateRef = (ref, value) => {
174
- if (!ref) {
175
- return;
176
- }
205
+ function setRef(ref, value) {
177
206
  if (typeof ref === "function") {
178
- ref(value);
179
- } else {
207
+ return ref(value);
208
+ } else if (ref) {
180
209
  ref.current = value;
181
210
  }
211
+ }
212
+ var mergeRefs = (refs) => {
213
+ return (value) => {
214
+ const cleanups = [];
215
+ for (const ref of refs) {
216
+ const cleanup = setRef(ref, value);
217
+ cleanups.push(typeof cleanup === "function" ? cleanup : () => setRef(ref, null));
218
+ }
219
+ return () => {
220
+ for (const cleanup of cleanups) {
221
+ cleanup();
222
+ }
223
+ };
224
+ };
225
+ };
226
+ var useMergeRefs = (refs) => {
227
+ return useMemo5(() => mergeRefs(refs), [
228
+ ...refs
229
+ ]);
182
230
  };
183
231
 
184
232
  // src/useId.ts
185
233
  import alea from "alea";
186
- import { useMemo as useMemo4 } from "react";
234
+ import { useMemo as useMemo6 } from "react";
187
235
  var Alea = alea;
188
236
  var prng = new Alea("@dxos/react-hooks");
189
237
  var randomString = (n = 4) => prng().toString(16).slice(2, n + 2);
190
- var useId = (namespace, propsId, opts) => useMemo4(() => makeId(namespace, propsId, opts), [
191
- propsId
192
- ]);
238
+ var useId = (namespace, propsId, opts) => {
239
+ return useMemo6(() => makeId(namespace, propsId, opts), [
240
+ propsId
241
+ ]);
242
+ };
193
243
  var makeId = (namespace, propsId, opts) => propsId ?? `${namespace}-${randomString(opts?.n ?? 4)}`;
194
244
 
195
245
  // src/useIsFocused.ts
196
- import { useEffect as useEffect8, useRef as useRef4, useState as useState5 } from "react";
246
+ import { useEffect as useEffect8, useRef as useRef5, useState as useState6 } from "react";
197
247
  var useIsFocused = (inputRef) => {
198
- const [isFocused, setIsFocused] = useState5(void 0);
199
- const isFocusedRef = useRef4(isFocused);
248
+ const [isFocused, setIsFocused] = useState6(void 0);
249
+ const isFocusedRef = useRef5(isFocused);
200
250
  isFocusedRef.current = isFocused;
201
251
  useEffect8(() => {
202
252
  const input = inputRef.current;
@@ -222,7 +272,7 @@ var useIsFocused = (inputRef) => {
222
272
  };
223
273
 
224
274
  // src/useMediaQuery.ts
225
- import { useEffect as useEffect9, useState as useState6 } from "react";
275
+ import { useEffect as useEffect9, useState as useState7 } from "react";
226
276
  var breakpointMediaQueries = {
227
277
  sm: "(min-width: 640px)",
228
278
  md: "(min-width: 768px)",
@@ -239,7 +289,7 @@ var useMediaQuery = (query, options = {}) => {
239
289
  fallback
240
290
  ];
241
291
  fallbackValues = fallbackValues.filter((v) => v != null);
242
- const [value, setValue] = useState6(() => {
292
+ const [value, setValue] = useState7(() => {
243
293
  return queries.map((query2, index) => ({
244
294
  media: query2,
245
295
  matches: ssr ? !!fallbackValues[index] : document.defaultView?.matchMedia(query2).matches
@@ -287,9 +337,9 @@ var useMediaQuery = (query, options = {}) => {
287
337
  };
288
338
 
289
339
  // src/useMulticastObservable.ts
290
- import { useMemo as useMemo5, useSyncExternalStore } from "react";
340
+ import { useMemo as useMemo7, useSyncExternalStore } from "react";
291
341
  var useMulticastObservable = (observable) => {
292
- const subscribeFn = useMemo5(() => (listener) => {
342
+ const subscribeFn = useMemo7(() => (listener) => {
293
343
  const subscription = observable.subscribe(listener);
294
344
  return () => subscription.unsubscribe();
295
345
  }, [
@@ -299,9 +349,9 @@ var useMulticastObservable = (observable) => {
299
349
  };
300
350
 
301
351
  // src/useRefCallback.ts
302
- import { useState as useState7 } from "react";
352
+ import { useState as useState8 } from "react";
303
353
  var useRefCallback = () => {
304
- const [value, setValue] = useState7(null);
354
+ const [value, setValue] = useState8(null);
305
355
  return {
306
356
  refCallback: (value2) => setValue(value2),
307
357
  value
@@ -309,63 +359,55 @@ var useRefCallback = () => {
309
359
  };
310
360
 
311
361
  // src/useViewportResize.ts
312
- import { useLayoutEffect, useMemo as useMemo6 } from "react";
313
- var useViewportResize = (handler, deps = [], delay = 800) => {
314
- const debouncedHandler = useMemo6(() => {
362
+ import { useLayoutEffect, useMemo as useMemo8 } from "react";
363
+ var useViewportResize = (cb, deps = [], delay = 800) => {
364
+ const { handler: debouncedHandler, cancel } = useMemo8(() => {
315
365
  let timeout;
316
- return (event) => {
317
- clearTimeout(timeout);
318
- timeout = setTimeout(() => {
319
- handler(event);
320
- }, delay);
366
+ return {
367
+ handler: (event) => {
368
+ if (timeout !== void 0) {
369
+ clearTimeout(timeout);
370
+ }
371
+ timeout = setTimeout(() => {
372
+ timeout = void 0;
373
+ cb(event);
374
+ }, delay);
375
+ },
376
+ cancel: () => {
377
+ if (timeout !== void 0) {
378
+ clearTimeout(timeout);
379
+ timeout = void 0;
380
+ }
381
+ }
321
382
  };
322
383
  }, [
323
- handler,
384
+ cb,
324
385
  delay
325
386
  ]);
326
387
  return useLayoutEffect(() => {
327
388
  window.visualViewport?.addEventListener("resize", debouncedHandler);
328
389
  debouncedHandler();
329
- return () => window.visualViewport?.removeEventListener("resize", debouncedHandler);
390
+ return () => {
391
+ window.visualViewport?.removeEventListener("resize", debouncedHandler);
392
+ cancel();
393
+ };
330
394
  }, [
331
395
  debouncedHandler,
396
+ cancel,
332
397
  ...deps
333
398
  ]);
334
399
  };
335
400
 
336
- // src/useSignals.ts
337
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
338
- import { computed, effect } from "@preact-signals/safe-react";
339
- import { useRef as useRef5 } from "@preact-signals/safe-react/react";
340
- import { useEffect as useEffect10, useMemo as useMemo7 } from "react";
341
- var useSignalsEffect = (cb, deps) => {
342
- const callback = useRef5(cb);
343
- callback.current = cb;
344
- useEffect10(() => {
345
- return effect(() => {
346
- return callback.current();
347
- });
348
- }, deps ?? []);
349
- };
350
- var useSignalsMemo = (cb, deps) => {
351
- var _effect = _useSignals();
352
- try {
353
- return useMemo7(() => computed(cb), deps ?? []).value;
354
- } finally {
355
- _effect.f();
356
- }
357
- };
358
-
359
401
  // src/useTimeout.ts
360
- import { useEffect as useEffect11, useRef as useRef6 } from "react";
402
+ import { useEffect as useEffect10, useRef as useRef6 } from "react";
361
403
  var useTimeout = (callback, delay = 0, deps = []) => {
362
404
  const callbackRef = useRef6(callback);
363
- useEffect11(() => {
405
+ useEffect10(() => {
364
406
  callbackRef.current = callback;
365
407
  }, [
366
408
  callback
367
409
  ]);
368
- useEffect11(() => {
410
+ useEffect10(() => {
369
411
  if (delay == null) {
370
412
  return;
371
413
  }
@@ -378,12 +420,12 @@ var useTimeout = (callback, delay = 0, deps = []) => {
378
420
  };
379
421
  var useInterval = (callback, delay = 0, deps = []) => {
380
422
  const callbackRef = useRef6(callback);
381
- useEffect11(() => {
423
+ useEffect10(() => {
382
424
  callbackRef.current = callback;
383
425
  }, [
384
426
  callback
385
427
  ]);
386
- useEffect11(() => {
428
+ useEffect10(() => {
387
429
  if (delay == null) {
388
430
  return;
389
431
  }
@@ -401,16 +443,16 @@ var useInterval = (callback, delay = 0, deps = []) => {
401
443
  };
402
444
 
403
445
  // src/useTransitions.ts
404
- import { useEffect as useEffect12, useRef as useRef7, useState as useState8 } from "react";
405
- var isFunction = (functionToCheck) => {
446
+ import { useEffect as useEffect11, useRef as useRef7, useState as useState9 } from "react";
447
+ var isFunction2 = (functionToCheck) => {
406
448
  return functionToCheck instanceof Function;
407
449
  };
408
450
  var useDidTransition = (currentValue, fromValue, toValue) => {
409
- const [hasTransitioned, setHasTransitioned] = useState8(false);
451
+ const [hasTransitioned, setHasTransitioned] = useState9(false);
410
452
  const previousValue = useRef7(currentValue);
411
- useEffect12(() => {
412
- const toValueValid = isFunction(toValue) ? toValue(currentValue) : toValue === currentValue;
413
- const fromValueValid = isFunction(fromValue) ? fromValue(previousValue.current) : fromValue === previousValue.current;
453
+ useEffect11(() => {
454
+ const toValueValid = isFunction2(toValue) ? toValue(currentValue) : toValue === currentValue;
455
+ const fromValueValid = isFunction2(fromValue) ? fromValue(previousValue.current) : fromValue === previousValue.current;
414
456
  if (fromValueValid && toValueValid && !hasTransitioned) {
415
457
  setHasTransitioned(true);
416
458
  } else if ((!fromValueValid || !toValueValid) && hasTransitioned) {
@@ -428,13 +470,13 @@ var useDidTransition = (currentValue, fromValue, toValue) => {
428
470
  var useOnTransition = (currentValue, fromValue, toValue, callback) => {
429
471
  const dirty = useRef7(false);
430
472
  const hasTransitioned = useDidTransition(currentValue, fromValue, toValue);
431
- useEffect12(() => {
473
+ useEffect11(() => {
432
474
  dirty.current = false;
433
475
  }, [
434
476
  currentValue,
435
477
  dirty
436
478
  ]);
437
- useEffect12(() => {
479
+ useEffect11(() => {
438
480
  if (hasTransitioned && !dirty.current) {
439
481
  callback();
440
482
  dirty.current = true;
@@ -445,15 +487,15 @@ var useOnTransition = (currentValue, fromValue, toValue, callback) => {
445
487
  callback
446
488
  ]);
447
489
  };
448
-
449
- // src/index.ts
450
- import { useSize, useScroller } from "mini-virtual-list";
451
490
  export {
452
491
  makeId,
492
+ mergeRefs,
453
493
  randomString,
454
- updateRef,
494
+ setRef,
455
495
  useAsyncEffect,
456
496
  useAsyncState,
497
+ useAtomState,
498
+ useComposedRefs,
457
499
  useControlledState,
458
500
  useDebugDeps,
459
501
  useDefaultValue,
@@ -466,12 +508,11 @@ export {
466
508
  useInterval,
467
509
  useIsFocused,
468
510
  useMediaQuery,
511
+ useMergeRefs,
469
512
  useMulticastObservable,
470
513
  useOnTransition,
471
514
  useRefCallback,
472
515
  useScroller,
473
- useSignalsEffect,
474
- useSignalsMemo,
475
516
  useSize,
476
517
  useStateWithRef,
477
518
  useTimeout,