@dxos/react-hooks 0.8.4-main.67995b8 → 0.8.4-main.70d3990

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 (58) hide show
  1. package/dist/lib/browser/index.mjs +193 -129
  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 +193 -129
  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/useIsFocused.d.ts +1 -1
  20. package/dist/types/src/useIsFocused.d.ts.map +1 -1
  21. package/dist/types/src/useMediaQuery.d.ts +1 -1
  22. package/dist/types/src/useMediaQuery.d.ts.map +1 -1
  23. package/dist/types/src/useMulticastObservable.test.d.ts.map +1 -1
  24. package/dist/types/src/useSignals.d.ts +10 -0
  25. package/dist/types/src/useSignals.d.ts.map +1 -0
  26. package/dist/types/src/useTimeout.d.ts +2 -1
  27. package/dist/types/src/useTimeout.d.ts.map +1 -1
  28. package/dist/types/src/useTransitions.d.ts +2 -1
  29. package/dist/types/src/useTransitions.d.ts.map +1 -1
  30. package/dist/types/src/useViewportResize.d.ts +3 -0
  31. package/dist/types/src/useViewportResize.d.ts.map +1 -0
  32. package/dist/types/tsconfig.tsbuildinfo +1 -1
  33. package/package.json +13 -11
  34. package/src/index.ts +5 -3
  35. package/src/useAsyncEffect.ts +19 -49
  36. package/src/useControlledState.ts +22 -11
  37. package/src/useDebugDeps.ts +26 -0
  38. package/src/useDefaultValue.ts +1 -1
  39. package/src/useDynamicRef.ts +26 -5
  40. package/src/useForwardedRef.ts +48 -13
  41. package/src/useIsFocused.ts +2 -2
  42. package/src/useMediaQuery.ts +8 -9
  43. package/src/{useMulticastObservable.test.tsx → useMulticastObservable.test.ts} +1 -3
  44. package/src/useSignals.ts +26 -0
  45. package/src/useTimeout.ts +28 -3
  46. package/src/useTransitions.ts +4 -2
  47. package/src/{useResize.ts → useViewportResize.ts} +1 -1
  48. package/dist/types/src/useAsyncEffect.test.d.ts +0 -2
  49. package/dist/types/src/useAsyncEffect.test.d.ts.map +0 -1
  50. package/dist/types/src/useDebugReactDeps.d.ts +0 -6
  51. package/dist/types/src/useDebugReactDeps.d.ts.map +0 -1
  52. package/dist/types/src/useResize.d.ts +0 -3
  53. package/dist/types/src/useResize.d.ts.map +0 -1
  54. package/dist/types/src/useTrackProps.d.ts +0 -5
  55. package/dist/types/src/useTrackProps.d.ts.map +0 -1
  56. package/src/useAsyncEffect.test.tsx +0 -51
  57. package/src/useDebugReactDeps.ts +0 -27
  58. 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,55 @@ 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), refs);
157
197
  };
158
198
 
159
199
  // src/useId.ts
160
200
  import alea from "alea";
161
- import { useMemo as useMemo4 } from "react";
201
+ import { useMemo as useMemo5 } from "react";
162
202
  var Alea = alea;
163
203
  var prng = new Alea("@dxos/react-hooks");
164
204
  var randomString = (n = 4) => prng().toString(16).slice(2, n + 2);
165
- var useId = (namespace, propsId, opts) => useMemo4(() => makeId(namespace, propsId, opts), [
205
+ var useId = (namespace, propsId, opts) => useMemo5(() => makeId(namespace, propsId, opts), [
166
206
  propsId
167
207
  ]);
168
208
  var makeId = (namespace, propsId, opts) => propsId ?? `${namespace}-${randomString(opts?.n ?? 4)}`;
169
209
 
170
210
  // src/useIsFocused.ts
171
- import { useEffect as useEffect8, useRef as useRef4, useState as useState4 } from "react";
211
+ import { useEffect as useEffect8, useRef as useRef5, useState as useState5 } from "react";
172
212
  var useIsFocused = (inputRef) => {
173
- const [isFocused, setIsFocused] = useState4(void 0);
174
- const isFocusedRef = useRef4(isFocused);
213
+ const [isFocused, setIsFocused] = useState5(void 0);
214
+ const isFocusedRef = useRef5(isFocused);
175
215
  isFocusedRef.current = isFocused;
176
216
  useEffect8(() => {
177
217
  const input = inputRef.current;
@@ -197,7 +237,7 @@ var useIsFocused = (inputRef) => {
197
237
  };
198
238
 
199
239
  // src/useMediaQuery.ts
200
- import { useEffect as useEffect9, useState as useState5 } from "react";
240
+ import { useEffect as useEffect9, useState as useState6 } from "react";
201
241
  var breakpointMediaQueries = {
202
242
  sm: "(min-width: 640px)",
203
243
  md: "(min-width: 768px)",
@@ -206,7 +246,7 @@ var breakpointMediaQueries = {
206
246
  "2xl": "(min-width: 1536px)"
207
247
  };
208
248
  var useMediaQuery = (query, options = {}) => {
209
- const { ssr = true, fallback } = options;
249
+ const { ssr = false, fallback } = options;
210
250
  const queries = (Array.isArray(query) ? query : [
211
251
  query
212
252
  ]).map((query2) => query2 in breakpointMediaQueries ? breakpointMediaQueries[query2] : query2);
@@ -214,7 +254,7 @@ var useMediaQuery = (query, options = {}) => {
214
254
  fallback
215
255
  ];
216
256
  fallbackValues = fallbackValues.filter((v) => v != null);
217
- const [value, setValue] = useState5(() => {
257
+ const [value, setValue] = useState6(() => {
218
258
  return queries.map((query2, index) => ({
219
259
  media: query2,
220
260
  matches: ssr ? !!fallbackValues[index] : document.defaultView?.matchMedia(query2).matches
@@ -262,9 +302,9 @@ var useMediaQuery = (query, options = {}) => {
262
302
  };
263
303
 
264
304
  // src/useMulticastObservable.ts
265
- import { useMemo as useMemo5, useSyncExternalStore } from "react";
305
+ import { useMemo as useMemo6, useSyncExternalStore } from "react";
266
306
  var useMulticastObservable = (observable) => {
267
- const subscribeFn = useMemo5(() => (listener) => {
307
+ const subscribeFn = useMemo6(() => (listener) => {
268
308
  const subscription = observable.subscribe(listener);
269
309
  return () => subscription.unsubscribe();
270
310
  }, [
@@ -274,19 +314,19 @@ var useMulticastObservable = (observable) => {
274
314
  };
275
315
 
276
316
  // src/useRefCallback.ts
277
- import { useState as useState6 } from "react";
317
+ import { useState as useState7 } from "react";
278
318
  var useRefCallback = () => {
279
- const [value, setValue] = useState6(null);
319
+ const [value, setValue] = useState7(null);
280
320
  return {
281
321
  refCallback: (value2) => setValue(value2),
282
322
  value
283
323
  };
284
324
  };
285
325
 
286
- // src/useResize.ts
287
- import { useLayoutEffect, useMemo as useMemo6 } from "react";
288
- var useResize = (handler, deps = [], delay = 800) => {
289
- const debouncedHandler = useMemo6(() => {
326
+ // src/useViewportResize.ts
327
+ import { useLayoutEffect, useMemo as useMemo7 } from "react";
328
+ var useViewportResize = (handler, deps = [], delay = 800) => {
329
+ const debouncedHandler = useMemo7(() => {
290
330
  let timeout;
291
331
  return (event) => {
292
332
  clearTimeout(timeout);
@@ -308,70 +348,83 @@ var useResize = (handler, deps = [], delay = 800) => {
308
348
  ]);
309
349
  };
310
350
 
351
+ // src/useSignals.ts
352
+ import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
353
+ import { computed, effect } from "@preact-signals/safe-react";
354
+ import { useEffect as useEffect10, useMemo as useMemo8, useRef as useRef6 } from "react";
355
+ var useSignalsEffect = (cb, deps) => {
356
+ const callback = useRef6(cb);
357
+ callback.current = cb;
358
+ useEffect10(() => {
359
+ return effect(() => {
360
+ return callback.current();
361
+ });
362
+ }, deps ?? []);
363
+ };
364
+ var useSignalsMemo = (cb, deps) => {
365
+ var _effect = _useSignals();
366
+ try {
367
+ return useMemo8(() => computed(cb), deps ?? []).value;
368
+ } finally {
369
+ _effect.f();
370
+ }
371
+ };
372
+
311
373
  // src/useTimeout.ts
312
- import { useEffect as useEffect10, useRef as useRef5 } from "react";
374
+ import { useEffect as useEffect11, useRef as useRef7 } from "react";
313
375
  var useTimeout = (callback, delay = 0, deps = []) => {
314
- const callbackRef = useRef5(callback);
315
- useEffect10(() => {
376
+ const callbackRef = useRef7(callback);
377
+ useEffect11(() => {
316
378
  callbackRef.current = callback;
317
379
  }, [
318
380
  callback
319
381
  ]);
320
- useEffect10(() => {
382
+ useEffect11(() => {
321
383
  if (delay == null) {
322
384
  return;
323
385
  }
324
- const timeout = setTimeout(() => callbackRef.current?.(), delay);
325
- return () => clearTimeout(timeout);
386
+ const t = setTimeout(() => callbackRef.current?.(), delay);
387
+ return () => clearTimeout(t);
326
388
  }, [
327
389
  delay,
328
390
  ...deps
329
391
  ]);
330
392
  };
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);
393
+ var useInterval = (callback, delay = 0, deps = []) => {
394
+ const callbackRef = useRef7(callback);
338
395
  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
- }
396
+ callbackRef.current = callback;
397
+ }, [
398
+ callback
399
+ ]);
400
+ useEffect11(() => {
401
+ if (delay == null) {
402
+ return;
359
403
  }
360
- prevProps.current = props;
361
- });
404
+ const i = setInterval(async () => {
405
+ const result = await callbackRef.current?.();
406
+ if (result === false) {
407
+ clearInterval(i);
408
+ }
409
+ }, delay);
410
+ return () => clearInterval(i);
411
+ }, [
412
+ delay,
413
+ ...deps
414
+ ]);
362
415
  };
363
416
 
364
417
  // src/useTransitions.ts
365
- import { useRef as useRef7, useEffect as useEffect12, useState as useState7 } from "react";
366
- var isFunction = (functionToCheck) => {
418
+ import { useEffect as useEffect12, useRef as useRef8, useState as useState8 } from "react";
419
+ var isFunction2 = (functionToCheck) => {
367
420
  return functionToCheck instanceof Function;
368
421
  };
369
422
  var useDidTransition = (currentValue, fromValue, toValue) => {
370
- const [hasTransitioned, setHasTransitioned] = useState7(false);
371
- const previousValue = useRef7(currentValue);
423
+ const [hasTransitioned, setHasTransitioned] = useState8(false);
424
+ const previousValue = useRef8(currentValue);
372
425
  useEffect12(() => {
373
- const toValueValid = isFunction(toValue) ? toValue(currentValue) : toValue === currentValue;
374
- const fromValueValid = isFunction(fromValue) ? fromValue(previousValue.current) : fromValue === previousValue.current;
426
+ const toValueValid = isFunction2(toValue) ? toValue(currentValue) : toValue === currentValue;
427
+ const fromValueValid = isFunction2(fromValue) ? fromValue(previousValue.current) : fromValue === previousValue.current;
375
428
  if (fromValueValid && toValueValid && !hasTransitioned) {
376
429
  setHasTransitioned(true);
377
430
  } else if ((!fromValueValid || !toValueValid) && hasTransitioned) {
@@ -387,7 +440,7 @@ var useDidTransition = (currentValue, fromValue, toValue) => {
387
440
  return hasTransitioned;
388
441
  };
389
442
  var useOnTransition = (currentValue, fromValue, toValue, callback) => {
390
- const dirty = useRef7(false);
443
+ const dirty = useRef8(false);
391
444
  const hasTransitioned = useDidTransition(currentValue, fromValue, toValue);
392
445
  useEffect12(() => {
393
446
  dirty.current = false;
@@ -406,13 +459,18 @@ var useOnTransition = (currentValue, fromValue, toValue, callback) => {
406
459
  callback
407
460
  ]);
408
461
  };
462
+
463
+ // src/index.ts
464
+ import { useSize, useScroller } from "mini-virtual-list";
409
465
  export {
410
466
  makeId,
467
+ mergeRefs,
411
468
  randomString,
469
+ setRef,
412
470
  useAsyncEffect,
413
471
  useAsyncState,
414
472
  useControlledState,
415
- useDebugReactDeps,
473
+ useDebugDeps,
416
474
  useDefaultValue,
417
475
  useDefaults,
418
476
  useDidTransition,
@@ -420,13 +478,19 @@ export {
420
478
  useFileDownload,
421
479
  useForwardedRef,
422
480
  useId,
481
+ useInterval,
423
482
  useIsFocused,
424
483
  useMediaQuery,
484
+ useMergeRefs,
425
485
  useMulticastObservable,
426
486
  useOnTransition,
427
487
  useRefCallback,
428
- useResize,
488
+ useScroller,
489
+ useSignalsEffect,
490
+ useSignalsMemo,
491
+ useSize,
492
+ useStateWithRef,
429
493
  useTimeout,
430
- useTrackProps
494
+ useViewportResize
431
495
  };
432
496
  //# sourceMappingURL=index.mjs.map