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