@dxos/react-hooks 0.8.4-main.67995b8 → 0.8.4-main.69d29f4

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 (57) hide show
  1. package/dist/lib/browser/index.mjs +189 -134
  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 +189 -134
  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 +3 -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/useTimeout.d.ts +2 -1
  26. package/dist/types/src/useTimeout.d.ts.map +1 -1
  27. package/dist/types/src/useTransitions.d.ts +2 -1
  28. package/dist/types/src/useTransitions.d.ts.map +1 -1
  29. package/dist/types/src/useViewportResize.d.ts +3 -0
  30. package/dist/types/src/useViewportResize.d.ts.map +1 -0
  31. package/dist/types/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +18 -13
  33. package/src/index.ts +4 -3
  34. package/src/useAsyncEffect.ts +19 -49
  35. package/src/useControlledState.ts +22 -11
  36. package/src/useDebugDeps.ts +35 -0
  37. package/src/useDefaultValue.ts +1 -1
  38. package/src/useDynamicRef.ts +26 -5
  39. package/src/useForwardedRef.ts +48 -13
  40. package/src/useId.ts +3 -2
  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/useTimeout.ts +28 -3
  45. package/src/useTransitions.ts +4 -2
  46. package/src/{useResize.ts → useViewportResize.ts} +1 -1
  47. package/dist/types/src/useAsyncEffect.test.d.ts +0 -2
  48. package/dist/types/src/useAsyncEffect.test.d.ts.map +0 -1
  49. package/dist/types/src/useDebugReactDeps.d.ts +0 -6
  50. package/dist/types/src/useDebugReactDeps.d.ts.map +0 -1
  51. package/dist/types/src/useResize.d.ts +0 -3
  52. package/dist/types/src/useResize.d.ts.map +0 -1
  53. package/dist/types/src/useTrackProps.d.ts +0 -5
  54. package/dist/types/src/useTrackProps.d.ts.map +0 -1
  55. package/src/useAsyncEffect.test.tsx +0 -51
  56. package/src/useDebugReactDeps.ts +0 -27
  57. 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,55 +43,107 @@ 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 = (valueProp) => {
51
+ const [value, setValue] = useState2(valueProp);
52
+ const valueRef = useRef(valueProp);
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 = (valueProp, onChange) => {
82
+ const [value, setControlledValue] = useState3(valueProp);
83
+ useEffect4(() => {
84
+ setControlledValue(valueProp);
65
85
  }, [
66
- value,
67
- onChange
86
+ valueProp
87
+ ]);
88
+ const onChangeRef = useRef2(onChange);
89
+ const valueRef = useDynamicRef(valueProp);
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(() => {
80
- console.group("deps changed", {
81
- old: lastDeps.current.length,
82
- new: deps.length
83
- });
107
+ // src/useDebugDeps.ts
108
+ import { useEffect as useEffect5, useRef as useRef3 } from "react";
109
+ import { log } from "@dxos/log";
110
+ var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-primitives/react-hooks/src/useDebugDeps.ts";
111
+ var useDebugDeps = (deps = [], label = "useDebugDeps", active = true) => {
112
+ const lastDeps = useRef3([]);
113
+ useEffect5(() => {
114
+ if (!active) {
115
+ return;
116
+ }
117
+ const diff = {};
84
118
  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]
119
+ if (lastDeps.current[i] !== deps[i] || i > lastDeps.current.length) {
120
+ diff[i] = {
121
+ previous: lastDeps.current[i],
122
+ current: deps[i]
123
+ };
124
+ }
125
+ }
126
+ if (Object.keys(diff).length > 0) {
127
+ log.warn(`Updated: ${label} [${lastDeps.current.length}/${deps.length}]`, diff, {
128
+ F: __dxlog_file,
129
+ L: 30,
130
+ S: void 0,
131
+ C: (f, a) => f(...a)
88
132
  });
89
133
  }
90
- console.groupEnd();
91
134
  lastDeps.current = deps;
92
- }, deps);
135
+ }, [
136
+ ...deps,
137
+ active
138
+ ]);
93
139
  };
94
140
 
95
141
  // src/useDefaultValue.ts
96
- import { useEffect as useEffect5, useState as useState3, useMemo } from "react";
142
+ import { useEffect as useEffect6, useMemo, useState as useState4 } from "react";
97
143
  var useDefaultValue = (reactiveValue, getDefaultValue) => {
98
144
  const stableDefaultValue = useMemo(getDefaultValue, []);
99
- const [value, setValue] = useState3(reactiveValue ?? stableDefaultValue);
100
- useEffect5(() => {
145
+ const [value, setValue] = useState4(reactiveValue ?? stableDefaultValue);
146
+ useEffect6(() => {
101
147
  setValue(reactiveValue ?? stableDefaultValue);
102
148
  }, [
103
149
  reactiveValue,
@@ -116,18 +162,6 @@ var useDefaults = (value, defaults) => {
116
162
  ]);
117
163
  };
118
164
 
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
165
  // src/useFileDownload.ts
132
166
  import { useMemo as useMemo3 } from "react";
133
167
  var useFileDownload = () => {
@@ -142,38 +176,59 @@ var useFileDownload = () => {
142
176
  };
143
177
 
144
178
  // src/useForwardedRef.ts
145
- import { useRef as useRef3, useEffect as useEffect7 } from "react";
146
- var useForwardedRef = (ref) => {
147
- const innerRef = useRef3(null);
179
+ import { useEffect as useEffect7, useMemo as useMemo4, useRef as useRef4 } from "react";
180
+ var useForwardedRef = (forwardedRef) => {
181
+ const localRef = useRef4(null);
148
182
  useEffect7(() => {
149
- if (!ref) {
150
- return;
151
- }
152
- if (typeof ref === "function") {
153
- ref(innerRef.current);
154
- } else {
155
- ref.current = innerRef.current;
183
+ setRef(forwardedRef, localRef.current);
184
+ }, [
185
+ forwardedRef
186
+ ]);
187
+ return localRef;
188
+ };
189
+ function setRef(ref, value) {
190
+ if (typeof ref === "function") {
191
+ return ref(value);
192
+ } else if (ref) {
193
+ ref.current = value;
194
+ }
195
+ }
196
+ var mergeRefs = (refs) => {
197
+ return (value) => {
198
+ const cleanups = [];
199
+ for (const ref of refs) {
200
+ const cleanup = setRef(ref, value);
201
+ cleanups.push(typeof cleanup === "function" ? cleanup : () => setRef(ref, null));
156
202
  }
157
- });
158
- return innerRef;
203
+ return () => {
204
+ for (const cleanup of cleanups) cleanup();
205
+ };
206
+ };
207
+ };
208
+ var useMergeRefs = (refs) => {
209
+ return useMemo4(() => mergeRefs(refs), [
210
+ ...refs
211
+ ]);
159
212
  };
160
213
 
161
214
  // src/useId.ts
162
215
  import alea from "alea";
163
- import { useMemo as useMemo4 } from "react";
216
+ import { useMemo as useMemo5 } from "react";
164
217
  var Alea = alea;
165
218
  var prng = new Alea("@dxos/react-hooks");
166
219
  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
- ]);
220
+ var useId = (namespace, propsId, opts) => {
221
+ return useMemo5(() => makeId(namespace, propsId, opts), [
222
+ propsId
223
+ ]);
224
+ };
170
225
  var makeId = (namespace, propsId, opts) => propsId ?? `${namespace}-${randomString(opts?.n ?? 4)}`;
171
226
 
172
227
  // src/useIsFocused.ts
173
- import { useEffect as useEffect8, useRef as useRef4, useState as useState4 } from "react";
228
+ import { useEffect as useEffect8, useRef as useRef5, useState as useState5 } from "react";
174
229
  var useIsFocused = (inputRef) => {
175
- const [isFocused, setIsFocused] = useState4(void 0);
176
- const isFocusedRef = useRef4(isFocused);
230
+ const [isFocused, setIsFocused] = useState5(void 0);
231
+ const isFocusedRef = useRef5(isFocused);
177
232
  isFocusedRef.current = isFocused;
178
233
  useEffect8(() => {
179
234
  const input = inputRef.current;
@@ -199,7 +254,7 @@ var useIsFocused = (inputRef) => {
199
254
  };
200
255
 
201
256
  // src/useMediaQuery.ts
202
- import { useEffect as useEffect9, useState as useState5 } from "react";
257
+ import { useEffect as useEffect9, useState as useState6 } from "react";
203
258
  var breakpointMediaQueries = {
204
259
  sm: "(min-width: 640px)",
205
260
  md: "(min-width: 768px)",
@@ -208,7 +263,7 @@ var breakpointMediaQueries = {
208
263
  "2xl": "(min-width: 1536px)"
209
264
  };
210
265
  var useMediaQuery = (query, options = {}) => {
211
- const { ssr = true, fallback } = options;
266
+ const { ssr = false, fallback } = options;
212
267
  const queries = (Array.isArray(query) ? query : [
213
268
  query
214
269
  ]).map((query2) => query2 in breakpointMediaQueries ? breakpointMediaQueries[query2] : query2);
@@ -216,7 +271,7 @@ var useMediaQuery = (query, options = {}) => {
216
271
  fallback
217
272
  ];
218
273
  fallbackValues = fallbackValues.filter((v) => v != null);
219
- const [value, setValue] = useState5(() => {
274
+ const [value, setValue] = useState6(() => {
220
275
  return queries.map((query2, index) => ({
221
276
  media: query2,
222
277
  matches: ssr ? !!fallbackValues[index] : document.defaultView?.matchMedia(query2).matches
@@ -264,9 +319,9 @@ var useMediaQuery = (query, options = {}) => {
264
319
  };
265
320
 
266
321
  // src/useMulticastObservable.ts
267
- import { useMemo as useMemo5, useSyncExternalStore } from "react";
322
+ import { useMemo as useMemo6, useSyncExternalStore } from "react";
268
323
  var useMulticastObservable = (observable) => {
269
- const subscribeFn = useMemo5(() => (listener) => {
324
+ const subscribeFn = useMemo6(() => (listener) => {
270
325
  const subscription = observable.subscribe(listener);
271
326
  return () => subscription.unsubscribe();
272
327
  }, [
@@ -276,19 +331,19 @@ var useMulticastObservable = (observable) => {
276
331
  };
277
332
 
278
333
  // src/useRefCallback.ts
279
- import { useState as useState6 } from "react";
334
+ import { useState as useState7 } from "react";
280
335
  var useRefCallback = () => {
281
- const [value, setValue] = useState6(null);
336
+ const [value, setValue] = useState7(null);
282
337
  return {
283
338
  refCallback: (value2) => setValue(value2),
284
339
  value
285
340
  };
286
341
  };
287
342
 
288
- // src/useResize.ts
289
- import { useLayoutEffect, useMemo as useMemo6 } from "react";
290
- var useResize = (handler, deps = [], delay = 800) => {
291
- const debouncedHandler = useMemo6(() => {
343
+ // src/useViewportResize.ts
344
+ import { useLayoutEffect, useMemo as useMemo7 } from "react";
345
+ var useViewportResize = (handler, deps = [], delay = 800) => {
346
+ const debouncedHandler = useMemo7(() => {
292
347
  let timeout;
293
348
  return (event) => {
294
349
  clearTimeout(timeout);
@@ -311,9 +366,9 @@ var useResize = (handler, deps = [], delay = 800) => {
311
366
  };
312
367
 
313
368
  // src/useTimeout.ts
314
- import { useEffect as useEffect10, useRef as useRef5 } from "react";
369
+ import { useEffect as useEffect10, useRef as useRef6 } from "react";
315
370
  var useTimeout = (callback, delay = 0, deps = []) => {
316
- const callbackRef = useRef5(callback);
371
+ const callbackRef = useRef6(callback);
317
372
  useEffect10(() => {
318
373
  callbackRef.current = callback;
319
374
  }, [
@@ -323,57 +378,48 @@ var useTimeout = (callback, delay = 0, deps = []) => {
323
378
  if (delay == null) {
324
379
  return;
325
380
  }
326
- const timeout = setTimeout(() => callbackRef.current?.(), delay);
327
- return () => clearTimeout(timeout);
381
+ const t = setTimeout(() => callbackRef.current?.(), delay);
382
+ return () => clearTimeout(t);
328
383
  }, [
329
384
  delay,
330
385
  ...deps
331
386
  ]);
332
387
  };
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);
340
- 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
- }
388
+ var useInterval = (callback, delay = 0, deps = []) => {
389
+ const callbackRef = useRef6(callback);
390
+ useEffect10(() => {
391
+ callbackRef.current = callback;
392
+ }, [
393
+ callback
394
+ ]);
395
+ useEffect10(() => {
396
+ if (delay == null) {
397
+ return;
361
398
  }
362
- prevProps.current = props;
363
- });
399
+ const i = setInterval(async () => {
400
+ const result = await callbackRef.current?.();
401
+ if (result === false) {
402
+ clearInterval(i);
403
+ }
404
+ }, delay);
405
+ return () => clearInterval(i);
406
+ }, [
407
+ delay,
408
+ ...deps
409
+ ]);
364
410
  };
365
411
 
366
412
  // src/useTransitions.ts
367
- import { useRef as useRef7, useEffect as useEffect12, useState as useState7 } from "react";
368
- var isFunction = (functionToCheck) => {
413
+ import { useEffect as useEffect11, useRef as useRef7, useState as useState8 } from "react";
414
+ var isFunction2 = (functionToCheck) => {
369
415
  return functionToCheck instanceof Function;
370
416
  };
371
417
  var useDidTransition = (currentValue, fromValue, toValue) => {
372
- const [hasTransitioned, setHasTransitioned] = useState7(false);
418
+ const [hasTransitioned, setHasTransitioned] = useState8(false);
373
419
  const previousValue = useRef7(currentValue);
374
- useEffect12(() => {
375
- const toValueValid = isFunction(toValue) ? toValue(currentValue) : toValue === currentValue;
376
- const fromValueValid = isFunction(fromValue) ? fromValue(previousValue.current) : fromValue === previousValue.current;
420
+ useEffect11(() => {
421
+ const toValueValid = isFunction2(toValue) ? toValue(currentValue) : toValue === currentValue;
422
+ const fromValueValid = isFunction2(fromValue) ? fromValue(previousValue.current) : fromValue === previousValue.current;
377
423
  if (fromValueValid && toValueValid && !hasTransitioned) {
378
424
  setHasTransitioned(true);
379
425
  } else if ((!fromValueValid || !toValueValid) && hasTransitioned) {
@@ -391,13 +437,13 @@ var useDidTransition = (currentValue, fromValue, toValue) => {
391
437
  var useOnTransition = (currentValue, fromValue, toValue, callback) => {
392
438
  const dirty = useRef7(false);
393
439
  const hasTransitioned = useDidTransition(currentValue, fromValue, toValue);
394
- useEffect12(() => {
440
+ useEffect11(() => {
395
441
  dirty.current = false;
396
442
  }, [
397
443
  currentValue,
398
444
  dirty
399
445
  ]);
400
- useEffect12(() => {
446
+ useEffect11(() => {
401
447
  if (hasTransitioned && !dirty.current) {
402
448
  callback();
403
449
  dirty.current = true;
@@ -408,13 +454,18 @@ var useOnTransition = (currentValue, fromValue, toValue, callback) => {
408
454
  callback
409
455
  ]);
410
456
  };
457
+
458
+ // src/index.ts
459
+ import { useSize, useScroller } from "mini-virtual-list";
411
460
  export {
412
461
  makeId,
462
+ mergeRefs,
413
463
  randomString,
464
+ setRef,
414
465
  useAsyncEffect,
415
466
  useAsyncState,
416
467
  useControlledState,
417
- useDebugReactDeps,
468
+ useDebugDeps,
418
469
  useDefaultValue,
419
470
  useDefaults,
420
471
  useDidTransition,
@@ -422,13 +473,17 @@ export {
422
473
  useFileDownload,
423
474
  useForwardedRef,
424
475
  useId,
476
+ useInterval,
425
477
  useIsFocused,
426
478
  useMediaQuery,
479
+ useMergeRefs,
427
480
  useMulticastObservable,
428
481
  useOnTransition,
429
482
  useRefCallback,
430
- useResize,
483
+ useScroller,
484
+ useSize,
485
+ useStateWithRef,
431
486
  useTimeout,
432
- useTrackProps
487
+ useViewportResize
433
488
  };
434
489
  //# sourceMappingURL=index.mjs.map