@dxos/react-hooks 0.8.4-main.2e9d522 → 0.8.4-main.3c1ae3b

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 (60) hide show
  1. package/dist/lib/browser/index.mjs +199 -131
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +199 -131
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/index.d.ts +4 -3
  8. package/dist/types/src/index.d.ts.map +1 -1
  9. package/dist/types/src/useAsyncEffect.d.ts +5 -29
  10. package/dist/types/src/useAsyncEffect.d.ts.map +1 -1
  11. package/dist/types/src/useControlledState.d.ts +2 -1
  12. package/dist/types/src/useControlledState.d.ts.map +1 -1
  13. package/dist/types/src/useDebugDeps.d.ts +6 -0
  14. package/dist/types/src/useDebugDeps.d.ts.map +1 -0
  15. package/dist/types/src/useDynamicRef.d.ts +6 -1
  16. package/dist/types/src/useDynamicRef.d.ts.map +1 -1
  17. package/dist/types/src/useForwardedRef.d.ts +23 -3
  18. package/dist/types/src/useForwardedRef.d.ts.map +1 -1
  19. package/dist/types/src/useId.d.ts.map +1 -1
  20. package/dist/types/src/useIsFocused.d.ts +1 -1
  21. package/dist/types/src/useIsFocused.d.ts.map +1 -1
  22. package/dist/types/src/useMediaQuery.d.ts +1 -1
  23. package/dist/types/src/useMediaQuery.d.ts.map +1 -1
  24. package/dist/types/src/useMulticastObservable.test.d.ts.map +1 -1
  25. package/dist/types/src/useSignals.d.ts +10 -0
  26. package/dist/types/src/useSignals.d.ts.map +1 -0
  27. package/dist/types/src/useTimeout.d.ts +2 -1
  28. package/dist/types/src/useTimeout.d.ts.map +1 -1
  29. package/dist/types/src/useTransitions.d.ts +2 -1
  30. package/dist/types/src/useTransitions.d.ts.map +1 -1
  31. package/dist/types/src/useViewportResize.d.ts +3 -0
  32. package/dist/types/src/useViewportResize.d.ts.map +1 -0
  33. package/dist/types/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +12 -9
  35. package/src/index.ts +5 -3
  36. package/src/useAsyncEffect.ts +19 -49
  37. package/src/useControlledState.ts +22 -11
  38. package/src/useDebugDeps.ts +26 -0
  39. package/src/useDefaultValue.ts +1 -1
  40. package/src/useDynamicRef.ts +26 -5
  41. package/src/useForwardedRef.ts +48 -13
  42. package/src/useId.ts +3 -2
  43. package/src/useIsFocused.ts +2 -2
  44. package/src/useMediaQuery.ts +8 -9
  45. package/src/{useMulticastObservable.test.tsx → useMulticastObservable.test.ts} +1 -3
  46. package/src/useSignals.ts +26 -0
  47. package/src/useTimeout.ts +28 -3
  48. package/src/useTransitions.ts +4 -2
  49. package/src/{useResize.ts → useViewportResize.ts} +1 -1
  50. package/dist/types/src/useAsyncEffect.test.d.ts +0 -2
  51. package/dist/types/src/useAsyncEffect.test.d.ts.map +0 -1
  52. package/dist/types/src/useDebugReactDeps.d.ts +0 -6
  53. package/dist/types/src/useDebugReactDeps.d.ts.map +0 -1
  54. package/dist/types/src/useResize.d.ts +0 -3
  55. package/dist/types/src/useResize.d.ts.map +0 -1
  56. package/dist/types/src/useTrackProps.d.ts +0 -5
  57. package/dist/types/src/useTrackProps.d.ts.map +0 -1
  58. package/src/useAsyncEffect.test.tsx +0 -51
  59. package/src/useDebugReactDeps.ts +0 -27
  60. package/src/useTrackProps.ts +0 -40
@@ -1,26 +1,20 @@
1
1
  // src/useAsyncEffect.ts
2
2
  import { useEffect } from "react";
3
- import { log } from "@dxos/log";
4
- var useAsyncEffect = (callback, destructor, deps) => {
5
- const [effectDestructor, effectDeps] = typeof destructor === "function" ? [
6
- destructor,
7
- deps
8
- ] : [
9
- void 0,
10
- destructor
11
- ];
3
+ var useAsyncEffect = (cb, deps) => {
12
4
  useEffect(() => {
13
- let mounted = true;
14
- let value;
15
- const asyncResult = callback(() => mounted);
16
- void Promise.resolve(asyncResult).then((result) => {
17
- value = result;
18
- }).catch(log.catch);
5
+ const controller = new AbortController();
6
+ let cleanup;
7
+ const t = setTimeout(async () => {
8
+ if (!controller.signal.aborted) {
9
+ cleanup = await cb(controller);
10
+ }
11
+ });
19
12
  return () => {
20
- mounted = false;
21
- effectDestructor?.(value);
13
+ clearTimeout(t);
14
+ controller.abort();
15
+ cleanup?.();
22
16
  };
23
- }, effectDeps);
17
+ }, deps ?? []);
24
18
  };
25
19
 
26
20
  // src/useAsyncState.ts
@@ -47,43 +41,84 @@ var useAsyncState = (cb, deps = []) => {
47
41
  };
48
42
 
49
43
  // src/useControlledState.ts
50
- import { useEffect as useEffect3, useState as useState2 } from "react";
51
- var useControlledState = (controlledValue, onChange, ...deps) => {
52
- const [value, setValue] = useState2(controlledValue);
53
- useEffect3(() => {
54
- if (controlledValue !== void 0) {
55
- setValue(controlledValue);
44
+ import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef2, useState as useState3 } from "react";
45
+
46
+ // src/useDynamicRef.ts
47
+ import { useCallback, useEffect as useEffect3, useRef, useState as useState2 } from "react";
48
+ var useStateWithRef = (valueParam) => {
49
+ const [value, setValue] = useState2(valueParam);
50
+ const valueRef = useRef(valueParam);
51
+ const setter = useCallback((value2) => {
52
+ if (typeof value2 === "function") {
53
+ setValue((current) => {
54
+ valueRef.current = value2(current);
55
+ return valueRef.current;
56
+ });
57
+ } else {
58
+ valueRef.current = value2;
59
+ setValue(value2);
56
60
  }
61
+ }, []);
62
+ return [
63
+ value,
64
+ setter,
65
+ valueRef
66
+ ];
67
+ };
68
+ var useDynamicRef = (value) => {
69
+ const valueRef = useRef(value);
70
+ useEffect3(() => {
71
+ valueRef.current = value;
57
72
  }, [
58
- controlledValue,
59
- ...deps
73
+ value
60
74
  ]);
61
- useEffect3(() => {
62
- onChange?.(value);
75
+ return valueRef;
76
+ };
77
+
78
+ // src/useControlledState.ts
79
+ var useControlledState = (valueParam, onChange) => {
80
+ const [value, setControlledValue] = useState3(valueParam);
81
+ useEffect4(() => {
82
+ setControlledValue(valueParam);
63
83
  }, [
64
- value,
65
- onChange
84
+ valueParam
85
+ ]);
86
+ const onChangeRef = useRef2(onChange);
87
+ const valueRef = useDynamicRef(valueParam);
88
+ const setValue = useCallback2((nextValue) => {
89
+ const value2 = isFunction(nextValue) ? nextValue(valueRef.current) : nextValue;
90
+ setControlledValue(value2);
91
+ onChangeRef.current?.(value2);
92
+ }, [
93
+ valueRef,
94
+ onChangeRef
66
95
  ]);
67
96
  return [
68
97
  value,
69
98
  setValue
70
99
  ];
71
100
  };
101
+ function isFunction(value) {
102
+ return typeof value === "function";
103
+ }
72
104
 
73
- // src/useDebugReactDeps.ts
74
- import { useEffect as useEffect4, useRef } from "react";
75
- var useDebugReactDeps = (deps = []) => {
76
- const lastDeps = useRef([]);
77
- useEffect4(() => {
105
+ // src/useDebugDeps.ts
106
+ import { useEffect as useEffect5, useRef as useRef3 } from "react";
107
+ var useDebugDeps = (deps = [], active = true) => {
108
+ const lastDeps = useRef3([]);
109
+ useEffect5(() => {
78
110
  console.group("deps changed", {
79
- old: lastDeps.current.length,
80
- new: deps.length
111
+ previous: lastDeps.current.length,
112
+ current: deps.length
81
113
  });
82
114
  for (let i = 0; i < Math.max(lastDeps.current.length ?? 0, deps.length ?? 0); i++) {
83
- console.log(i, lastDeps.current[i] === deps[i] ? "SAME" : "CHANGED", {
84
- previous: lastDeps.current[i],
85
- current: deps[i]
86
- });
115
+ if (lastDeps.current[i] !== deps[i] && active) {
116
+ console.log("changed", {
117
+ index: i,
118
+ previous: lastDeps.current[i],
119
+ current: deps[i]
120
+ });
121
+ }
87
122
  }
88
123
  console.groupEnd();
89
124
  lastDeps.current = deps;
@@ -91,11 +126,11 @@ var useDebugReactDeps = (deps = []) => {
91
126
  };
92
127
 
93
128
  // src/useDefaultValue.ts
94
- import { useEffect as useEffect5, useState as useState3, useMemo } from "react";
129
+ import { useEffect as useEffect6, useMemo, useState as useState4 } from "react";
95
130
  var useDefaultValue = (reactiveValue, getDefaultValue) => {
96
131
  const stableDefaultValue = useMemo(getDefaultValue, []);
97
- const [value, setValue] = useState3(reactiveValue ?? stableDefaultValue);
98
- useEffect5(() => {
132
+ const [value, setValue] = useState4(reactiveValue ?? stableDefaultValue);
133
+ useEffect6(() => {
99
134
  setValue(reactiveValue ?? stableDefaultValue);
100
135
  }, [
101
136
  reactiveValue,
@@ -114,18 +149,6 @@ var useDefaults = (value, defaults) => {
114
149
  ]);
115
150
  };
116
151
 
117
- // src/useDynamicRef.ts
118
- import { useEffect as useEffect6, useRef as useRef2 } from "react";
119
- var useDynamicRef = (value) => {
120
- const ref = useRef2(value);
121
- useEffect6(() => {
122
- ref.current = value;
123
- }, [
124
- value
125
- ]);
126
- return ref;
127
- };
128
-
129
152
  // src/useFileDownload.ts
130
153
  import { useMemo as useMemo3 } from "react";
131
154
  var useFileDownload = () => {
@@ -140,38 +163,59 @@ var useFileDownload = () => {
140
163
  };
141
164
 
142
165
  // src/useForwardedRef.ts
143
- import { useRef as useRef3, useEffect as useEffect7 } from "react";
144
- var useForwardedRef = (ref) => {
145
- const innerRef = useRef3(null);
166
+ import { useEffect as useEffect7, useMemo as useMemo4, useRef as useRef4 } from "react";
167
+ var useForwardedRef = (forwardedRef) => {
168
+ const localRef = useRef4(null);
146
169
  useEffect7(() => {
147
- if (!ref) {
148
- return;
149
- }
150
- if (typeof ref === "function") {
151
- ref(innerRef.current);
152
- } else {
153
- ref.current = innerRef.current;
170
+ setRef(forwardedRef, localRef.current);
171
+ }, [
172
+ forwardedRef
173
+ ]);
174
+ return localRef;
175
+ };
176
+ function setRef(ref, value) {
177
+ if (typeof ref === "function") {
178
+ return ref(value);
179
+ } else if (ref) {
180
+ ref.current = value;
181
+ }
182
+ }
183
+ var mergeRefs = (refs) => {
184
+ return (value) => {
185
+ const cleanups = [];
186
+ for (const ref of refs) {
187
+ const cleanup = setRef(ref, value);
188
+ cleanups.push(typeof cleanup === "function" ? cleanup : () => setRef(ref, null));
154
189
  }
155
- });
156
- return innerRef;
190
+ return () => {
191
+ for (const cleanup of cleanups) cleanup();
192
+ };
193
+ };
194
+ };
195
+ var useMergeRefs = (refs) => {
196
+ return useMemo4(() => mergeRefs(refs), [
197
+ ...refs
198
+ ]);
157
199
  };
158
200
 
159
201
  // src/useId.ts
160
202
  import alea from "alea";
161
- import { useMemo as useMemo4 } from "react";
203
+ import { useMemo as useMemo5 } from "react";
162
204
  var Alea = alea;
163
205
  var prng = new Alea("@dxos/react-hooks");
164
206
  var randomString = (n = 4) => prng().toString(16).slice(2, n + 2);
165
- var useId = (namespace, propsId, opts) => useMemo4(() => makeId(namespace, propsId, opts), [
166
- propsId
167
- ]);
207
+ var useId = (namespace, propsId, opts) => {
208
+ return useMemo5(() => makeId(namespace, propsId, opts), [
209
+ propsId
210
+ ]);
211
+ };
168
212
  var makeId = (namespace, propsId, opts) => propsId ?? `${namespace}-${randomString(opts?.n ?? 4)}`;
169
213
 
170
214
  // src/useIsFocused.ts
171
- import { useEffect as useEffect8, useRef as useRef4, useState as useState4 } from "react";
215
+ import { useEffect as useEffect8, useRef as useRef5, useState as useState5 } from "react";
172
216
  var useIsFocused = (inputRef) => {
173
- const [isFocused, setIsFocused] = useState4(void 0);
174
- const isFocusedRef = useRef4(isFocused);
217
+ const [isFocused, setIsFocused] = useState5(void 0);
218
+ const isFocusedRef = useRef5(isFocused);
175
219
  isFocusedRef.current = isFocused;
176
220
  useEffect8(() => {
177
221
  const input = inputRef.current;
@@ -197,7 +241,7 @@ var useIsFocused = (inputRef) => {
197
241
  };
198
242
 
199
243
  // src/useMediaQuery.ts
200
- import { useEffect as useEffect9, useState as useState5 } from "react";
244
+ import { useEffect as useEffect9, useState as useState6 } from "react";
201
245
  var breakpointMediaQueries = {
202
246
  sm: "(min-width: 640px)",
203
247
  md: "(min-width: 768px)",
@@ -206,7 +250,7 @@ var breakpointMediaQueries = {
206
250
  "2xl": "(min-width: 1536px)"
207
251
  };
208
252
  var useMediaQuery = (query, options = {}) => {
209
- const { ssr = true, fallback } = options;
253
+ const { ssr = false, fallback } = options;
210
254
  const queries = (Array.isArray(query) ? query : [
211
255
  query
212
256
  ]).map((query2) => query2 in breakpointMediaQueries ? breakpointMediaQueries[query2] : query2);
@@ -214,7 +258,7 @@ var useMediaQuery = (query, options = {}) => {
214
258
  fallback
215
259
  ];
216
260
  fallbackValues = fallbackValues.filter((v) => v != null);
217
- const [value, setValue] = useState5(() => {
261
+ const [value, setValue] = useState6(() => {
218
262
  return queries.map((query2, index) => ({
219
263
  media: query2,
220
264
  matches: ssr ? !!fallbackValues[index] : document.defaultView?.matchMedia(query2).matches
@@ -262,9 +306,9 @@ var useMediaQuery = (query, options = {}) => {
262
306
  };
263
307
 
264
308
  // src/useMulticastObservable.ts
265
- import { useMemo as useMemo5, useSyncExternalStore } from "react";
309
+ import { useMemo as useMemo6, useSyncExternalStore } from "react";
266
310
  var useMulticastObservable = (observable) => {
267
- const subscribeFn = useMemo5(() => (listener) => {
311
+ const subscribeFn = useMemo6(() => (listener) => {
268
312
  const subscription = observable.subscribe(listener);
269
313
  return () => subscription.unsubscribe();
270
314
  }, [
@@ -274,19 +318,19 @@ var useMulticastObservable = (observable) => {
274
318
  };
275
319
 
276
320
  // src/useRefCallback.ts
277
- import { useState as useState6 } from "react";
321
+ import { useState as useState7 } from "react";
278
322
  var useRefCallback = () => {
279
- const [value, setValue] = useState6(null);
323
+ const [value, setValue] = useState7(null);
280
324
  return {
281
325
  refCallback: (value2) => setValue(value2),
282
326
  value
283
327
  };
284
328
  };
285
329
 
286
- // src/useResize.ts
287
- import { useLayoutEffect, useMemo as useMemo6 } from "react";
288
- var useResize = (handler, deps = [], delay = 800) => {
289
- const debouncedHandler = useMemo6(() => {
330
+ // src/useViewportResize.ts
331
+ import { useLayoutEffect, useMemo as useMemo7 } from "react";
332
+ var useViewportResize = (handler, deps = [], delay = 800) => {
333
+ const debouncedHandler = useMemo7(() => {
290
334
  let timeout;
291
335
  return (event) => {
292
336
  clearTimeout(timeout);
@@ -308,70 +352,83 @@ var useResize = (handler, deps = [], delay = 800) => {
308
352
  ]);
309
353
  };
310
354
 
355
+ // src/useSignals.ts
356
+ import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
357
+ import { computed, effect } from "@preact-signals/safe-react";
358
+ import { useEffect as useEffect10, useMemo as useMemo8, useRef as useRef6 } from "react";
359
+ var useSignalsEffect = (cb, deps) => {
360
+ const callback = useRef6(cb);
361
+ callback.current = cb;
362
+ useEffect10(() => {
363
+ return effect(() => {
364
+ return callback.current();
365
+ });
366
+ }, deps ?? []);
367
+ };
368
+ var useSignalsMemo = (cb, deps) => {
369
+ var _effect = _useSignals();
370
+ try {
371
+ return useMemo8(() => computed(cb), deps ?? []).value;
372
+ } finally {
373
+ _effect.f();
374
+ }
375
+ };
376
+
311
377
  // src/useTimeout.ts
312
- import { useEffect as useEffect10, useRef as useRef5 } from "react";
378
+ import { useEffect as useEffect11, useRef as useRef7 } from "react";
313
379
  var useTimeout = (callback, delay = 0, deps = []) => {
314
- const callbackRef = useRef5(callback);
315
- useEffect10(() => {
380
+ const callbackRef = useRef7(callback);
381
+ useEffect11(() => {
316
382
  callbackRef.current = callback;
317
383
  }, [
318
384
  callback
319
385
  ]);
320
- useEffect10(() => {
386
+ useEffect11(() => {
321
387
  if (delay == null) {
322
388
  return;
323
389
  }
324
- const timeout = setTimeout(() => callbackRef.current?.(), delay);
325
- return () => clearTimeout(timeout);
390
+ const t = setTimeout(() => callbackRef.current?.(), delay);
391
+ return () => clearTimeout(t);
326
392
  }, [
327
393
  delay,
328
394
  ...deps
329
395
  ]);
330
396
  };
331
-
332
- // src/useTrackProps.ts
333
- import { useRef as useRef6, useEffect as useEffect11 } from "react";
334
- import { log as log2 } from "@dxos/log";
335
- var __dxlog_file = "/__w/dxos/dxos/packages/ui/primitives/react-hooks/src/useTrackProps.ts";
336
- var useTrackProps = (props, componentName = "Component", active = true) => {
337
- const prevProps = useRef6(props);
397
+ var useInterval = (callback, delay = 0, deps = []) => {
398
+ const callbackRef = useRef7(callback);
338
399
  useEffect11(() => {
339
- const changes = Object.entries(props).filter(([key]) => props[key] !== prevProps.current[key]);
340
- if (changes.length > 0) {
341
- if (active) {
342
- log2.info("props changed", {
343
- componentName,
344
- keys: changes.map(([key]) => key).join(","),
345
- props: Object.fromEntries(changes.map(([key]) => [
346
- key,
347
- {
348
- from: prevProps.current[key],
349
- to: props[key]
350
- }
351
- ]))
352
- }, {
353
- F: __dxlog_file,
354
- L: 22,
355
- S: void 0,
356
- C: (f, a) => f(...a)
357
- });
358
- }
400
+ callbackRef.current = callback;
401
+ }, [
402
+ callback
403
+ ]);
404
+ useEffect11(() => {
405
+ if (delay == null) {
406
+ return;
359
407
  }
360
- prevProps.current = props;
361
- });
408
+ const i = setInterval(async () => {
409
+ const result = await callbackRef.current?.();
410
+ if (result === false) {
411
+ clearInterval(i);
412
+ }
413
+ }, delay);
414
+ return () => clearInterval(i);
415
+ }, [
416
+ delay,
417
+ ...deps
418
+ ]);
362
419
  };
363
420
 
364
421
  // src/useTransitions.ts
365
- import { useRef as useRef7, useEffect as useEffect12, useState as useState7 } from "react";
366
- var isFunction = (functionToCheck) => {
422
+ import { useEffect as useEffect12, useRef as useRef8, useState as useState8 } from "react";
423
+ var isFunction2 = (functionToCheck) => {
367
424
  return functionToCheck instanceof Function;
368
425
  };
369
426
  var useDidTransition = (currentValue, fromValue, toValue) => {
370
- const [hasTransitioned, setHasTransitioned] = useState7(false);
371
- const previousValue = useRef7(currentValue);
427
+ const [hasTransitioned, setHasTransitioned] = useState8(false);
428
+ const previousValue = useRef8(currentValue);
372
429
  useEffect12(() => {
373
- const toValueValid = isFunction(toValue) ? toValue(currentValue) : toValue === currentValue;
374
- const fromValueValid = isFunction(fromValue) ? fromValue(previousValue.current) : fromValue === previousValue.current;
430
+ const toValueValid = isFunction2(toValue) ? toValue(currentValue) : toValue === currentValue;
431
+ const fromValueValid = isFunction2(fromValue) ? fromValue(previousValue.current) : fromValue === previousValue.current;
375
432
  if (fromValueValid && toValueValid && !hasTransitioned) {
376
433
  setHasTransitioned(true);
377
434
  } else if ((!fromValueValid || !toValueValid) && hasTransitioned) {
@@ -387,7 +444,7 @@ var useDidTransition = (currentValue, fromValue, toValue) => {
387
444
  return hasTransitioned;
388
445
  };
389
446
  var useOnTransition = (currentValue, fromValue, toValue, callback) => {
390
- const dirty = useRef7(false);
447
+ const dirty = useRef8(false);
391
448
  const hasTransitioned = useDidTransition(currentValue, fromValue, toValue);
392
449
  useEffect12(() => {
393
450
  dirty.current = false;
@@ -406,13 +463,18 @@ var useOnTransition = (currentValue, fromValue, toValue, callback) => {
406
463
  callback
407
464
  ]);
408
465
  };
466
+
467
+ // src/index.ts
468
+ import { useSize, useScroller } from "mini-virtual-list";
409
469
  export {
410
470
  makeId,
471
+ mergeRefs,
411
472
  randomString,
473
+ setRef,
412
474
  useAsyncEffect,
413
475
  useAsyncState,
414
476
  useControlledState,
415
- useDebugReactDeps,
477
+ useDebugDeps,
416
478
  useDefaultValue,
417
479
  useDefaults,
418
480
  useDidTransition,
@@ -420,13 +482,19 @@ export {
420
482
  useFileDownload,
421
483
  useForwardedRef,
422
484
  useId,
485
+ useInterval,
423
486
  useIsFocused,
424
487
  useMediaQuery,
488
+ useMergeRefs,
425
489
  useMulticastObservable,
426
490
  useOnTransition,
427
491
  useRefCallback,
428
- useResize,
492
+ useScroller,
493
+ useSignalsEffect,
494
+ useSignalsMemo,
495
+ useSize,
496
+ useStateWithRef,
429
497
  useTimeout,
430
- useTrackProps
498
+ useViewportResize
431
499
  };
432
500
  //# sourceMappingURL=index.mjs.map