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

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 (44) hide show
  1. package/dist/lib/browser/index.mjs +35 -57
  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 +35 -57
  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 +2 -2
  8. package/dist/types/src/index.d.ts.map +1 -1
  9. package/dist/types/src/useControlledState.d.ts +1 -0
  10. package/dist/types/src/useControlledState.d.ts.map +1 -1
  11. package/dist/types/src/useDebugDeps.d.ts +1 -1
  12. package/dist/types/src/useDebugDeps.d.ts.map +1 -1
  13. package/dist/types/src/useDynamicRef.d.ts +1 -1
  14. package/dist/types/src/useDynamicRef.d.ts.map +1 -1
  15. package/dist/types/src/useForwardedRef.d.ts +3 -3
  16. package/dist/types/src/useForwardedRef.d.ts.map +1 -1
  17. package/dist/types/src/useIsFocused.d.ts +1 -1
  18. package/dist/types/src/useIsFocused.d.ts.map +1 -1
  19. package/dist/types/src/useMediaQuery.d.ts.map +1 -1
  20. package/dist/types/src/useMulticastObservable.test.d.ts.map +1 -1
  21. package/dist/types/src/useTransitions.d.ts +2 -1
  22. package/dist/types/src/useTransitions.d.ts.map +1 -1
  23. package/dist/types/src/useViewportResize.d.ts +3 -0
  24. package/dist/types/src/useViewportResize.d.ts.map +1 -0
  25. package/dist/types/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +10 -9
  27. package/src/index.ts +3 -2
  28. package/src/useControlledState.ts +1 -0
  29. package/src/useDebugDeps.ts +2 -2
  30. package/src/useDynamicRef.ts +3 -3
  31. package/src/useForwardedRef.ts +17 -14
  32. package/src/useIsFocused.ts +1 -1
  33. package/src/useMediaQuery.ts +1 -2
  34. package/src/{useMulticastObservable.test.tsx → useMulticastObservable.test.ts} +1 -3
  35. package/src/useTransitions.ts +3 -1
  36. package/src/{useResize.ts → useViewportResize.ts} +1 -1
  37. package/dist/types/src/useAsyncEffect.stories.d.ts +0 -9
  38. package/dist/types/src/useAsyncEffect.stories.d.ts.map +0 -1
  39. package/dist/types/src/useResize.d.ts +0 -3
  40. package/dist/types/src/useResize.d.ts.map +0 -1
  41. package/dist/types/src/useTrackProps.d.ts +0 -5
  42. package/dist/types/src/useTrackProps.d.ts.map +0 -1
  43. package/src/useAsyncEffect.stories.tsx +0 -34
  44. package/src/useTrackProps.ts +0 -40
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-hooks",
3
- "version": "0.8.4-main.e098934",
3
+ "version": "0.8.4-main.ead640a",
4
4
  "description": "React hooks supporting DXOS React primitives.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -28,19 +28,20 @@
28
28
  "@preact-signals/safe-react": "^0.9.0",
29
29
  "alea": "^1.0.1",
30
30
  "lodash.defaultsdeep": "^4.6.1",
31
- "@dxos/async": "0.8.4-main.e098934",
32
- "@dxos/log": "0.8.4-main.e098934"
31
+ "mini-virtual-list": "^0.3.2",
32
+ "@dxos/async": "0.8.4-main.ead640a",
33
+ "@dxos/log": "0.8.4-main.ead640a"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@types/lodash.defaultsdeep": "^4.6.6",
36
- "@types/react": "~18.2.0",
37
- "@types/react-dom": "~18.2.0",
38
- "react": "~18.2.0",
39
- "react-dom": "~18.2.0"
37
+ "@types/react": "~19.2.2",
38
+ "@types/react-dom": "~19.2.1",
39
+ "react": "~19.2.0",
40
+ "react-dom": "~19.2.0"
40
41
  },
41
42
  "peerDependencies": {
42
- "react": "~18.2.0",
43
- "react-dom": "~18.2.0"
43
+ "react": "^19.0.0",
44
+ "react-dom": "^19.0.0"
44
45
  },
45
46
  "publishConfig": {
46
47
  "access": "public"
package/src/index.ts CHANGED
@@ -16,8 +16,9 @@ export * from './useIsFocused';
16
16
  export * from './useMediaQuery';
17
17
  export * from './useMulticastObservable';
18
18
  export * from './useRefCallback';
19
- export * from './useResize';
19
+ export * from './useViewportResize';
20
20
  export * from './useSignals';
21
21
  export * from './useTimeout';
22
- export * from './useTrackProps';
23
22
  export * from './useTransitions';
23
+
24
+ export { useSize, useScroller } from 'mini-virtual-list';
@@ -7,6 +7,7 @@ import { type Dispatch, type SetStateAction, useEffect, useState } from 'react';
7
7
  /**
8
8
  * A stateful hook with a controlled value.
9
9
  * NOTE: Be careful not to provide an inlinde default array.
10
+ * @deprecated Use Radix `useControllableState`.
10
11
  */
11
12
  export const useControlledState = <T>(
12
13
  controlledValue: T,
@@ -7,12 +7,12 @@ import { type DependencyList, useEffect, useRef } from 'react';
7
7
  /**
8
8
  * Util to log deps that have changed.
9
9
  */
10
- export const useDebugDeps = (deps: DependencyList = []) => {
10
+ export const useDebugDeps = (deps: DependencyList = [], active = true) => {
11
11
  const lastDeps = useRef<DependencyList>([]);
12
12
  useEffect(() => {
13
13
  console.group('deps changed', { previous: lastDeps.current.length, current: deps.length });
14
14
  for (let i = 0; i < Math.max(lastDeps.current.length ?? 0, deps.length ?? 0); i++) {
15
- if (lastDeps.current[i] !== deps[i]) {
15
+ if (lastDeps.current[i] !== deps[i] && active) {
16
16
  console.log('changed', {
17
17
  index: i,
18
18
  previous: lastDeps.current[i],
@@ -8,9 +8,9 @@ import { type Dispatch, type MutableRefObject, type SetStateAction, useEffect, u
8
8
  /**
9
9
  * Like `useState` but with an additional dynamic value.
10
10
  */
11
- export const useStateWithRef = <T>(value$: T): [T, Dispatch<SetStateAction<T>>, MutableRefObject<T>] => {
12
- const [value, setValue] = useState<T>(value$);
13
- const valueRef = useRef<T>(value$);
11
+ export const useStateWithRef = <T>(valueParam: T): [T, Dispatch<SetStateAction<T>>, MutableRefObject<T>] => {
12
+ const [value, setValue] = useState<T>(valueParam);
13
+ const valueRef = useRef<T>(valueParam);
14
14
  const setter = useCallback<Dispatch<SetStateAction<T>>>((value) => {
15
15
  if (typeof value === 'function') {
16
16
  setValue((current) => {
@@ -2,25 +2,28 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { type ForwardedRef, useEffect, useRef } from 'react';
5
+ import { type ForwardedRef, type RefObject, useEffect, useRef } from 'react';
6
6
 
7
7
  /**
8
8
  * Combines a possibly undefined forwarded ref with a locally defined ref.
9
- * @deprecated Use @radix-ui/react-compose-refs
10
9
  */
11
- export const useForwardedRef = <T>(ref: ForwardedRef<T>) => {
12
- const innerRef = useRef<T>(null);
10
+ export const useForwardedRef = <T>(ref: ForwardedRef<T>): RefObject<T | null> => {
11
+ const innerRef = useRef<T | null>(null);
13
12
  useEffect(() => {
14
- if (!ref) {
15
- return;
16
- }
17
-
18
- if (typeof ref === 'function') {
19
- ref(innerRef.current);
20
- } else {
21
- ref.current = innerRef.current;
22
- }
23
- });
13
+ updateRef(ref, innerRef.current);
14
+ }, [ref]);
24
15
 
25
16
  return innerRef;
26
17
  };
18
+
19
+ export const updateRef = <T>(ref: ForwardedRef<T>, value: T): void => {
20
+ if (!ref) {
21
+ return;
22
+ }
23
+
24
+ if (typeof ref === 'function') {
25
+ ref(value);
26
+ } else {
27
+ ref.current = value;
28
+ }
29
+ };
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { type RefObject, useEffect, useRef, useState } from 'react';
9
9
 
10
- export const useIsFocused = (inputRef: RefObject<HTMLInputElement>) => {
10
+ export const useIsFocused = (inputRef: RefObject<HTMLInputElement | null>) => {
11
11
  const [isFocused, setIsFocused] = useState<boolean | undefined>(undefined);
12
12
  const isFocusedRef = useRef<boolean | undefined>(isFocused);
13
13
 
@@ -29,8 +29,7 @@ const breakpointMediaQueries: Record<string, string> = {
29
29
  * @see Docs https://chakra-ui.com/docs/hooks/use-media-query
30
30
  */
31
31
  export const useMediaQuery = (query: string | string[], options: UseMediaQueryOptions = {}): boolean[] => {
32
- // TODO(wittjosiah): Why is the default here true?
33
- const { ssr = true, fallback } = options;
32
+ const { ssr = false, fallback } = options;
34
33
 
35
34
  const queries = (Array.isArray(query) ? query : [query]).map((query) =>
36
35
  query in breakpointMediaQueries ? breakpointMediaQueries[query] : query,
@@ -15,9 +15,7 @@ describe('useMulticastObservable', () => {
15
15
  const observable = MulticastObservable.from(event, 0);
16
16
  const { result } = renderHook(() => useMulticastObservable(observable));
17
17
  expect(result.current).toEqual(0);
18
-
19
- await act(() => event.emit(1));
20
-
18
+ act(() => event.emit(1));
21
19
  await expect.poll(() => result.current).toEqual(1);
22
20
  });
23
21
  });
@@ -48,7 +48,9 @@ export const useDidTransition = <T>(
48
48
  * Executes a callback function when a specified transition occurs in a value.
49
49
  *
50
50
  * This function utilizes the `useDidTransition` hook to monitor changes in `currentValue`.
51
- * When `currentValue` transitions from `fromValue` to `toValue`, the provided `callback` function is executed. */
51
+ * When `currentValue` transitions from `fromValue` to `toValue`, the provided `callback` function is executed.
52
+ */
53
+ // TODO(wittjosiah): Seems overwrought.
52
54
  export const useOnTransition = <T>(
53
55
  currentValue: T,
54
56
  fromValue: T | ((value: T) => boolean),
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { useLayoutEffect, useMemo } from 'react';
6
6
 
7
- export const useResize = (
7
+ export const useViewportResize = (
8
8
  handler: (event?: Event) => void,
9
9
  deps: Parameters<typeof useLayoutEffect>[1] = [],
10
10
  delay: number = 800,
@@ -1,9 +0,0 @@
1
- import '@dxos-theme';
2
- import { type StoryObj } from '@storybook/react-vite';
3
- declare const meta: {
4
- title: string;
5
- };
6
- export default meta;
7
- type Story = StoryObj<typeof meta>;
8
- export declare const Default: Story;
9
- //# sourceMappingURL=useAsyncEffect.stories.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useAsyncEffect.stories.d.ts","sourceRoot":"","sources":["../../../src/useAsyncEffect.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,aAAa,CAAC;AAErB,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAOjE,QAAA,MAAM,IAAI;;CAEM,CAAC;AAEjB,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAYrB,CAAC"}
@@ -1,3 +0,0 @@
1
- import { useLayoutEffect } from 'react';
2
- export declare const useResize: (handler: (event?: Event) => void, deps?: Parameters<typeof useLayoutEffect>[1], delay?: number) => void;
3
- //# sourceMappingURL=useResize.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useResize.d.ts","sourceRoot":"","sources":["../../../src/useResize.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAW,MAAM,OAAO,CAAC;AAEjD,eAAO,MAAM,SAAS,GACpB,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,EAChC,OAAM,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAM,EAChD,QAAO,MAAY,SAiBpB,CAAC"}
@@ -1,5 +0,0 @@
1
- /**
2
- * Use to debug which props have changed to trigger re-renders in a React component.
3
- */
4
- export declare const useTrackProps: <T extends Record<string, unknown>>(props: T, componentName?: string, active?: boolean) => void;
5
- //# sourceMappingURL=useTrackProps.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useTrackProps.d.ts","sourceRoot":"","sources":["../../../src/useTrackProps.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,OAAO,CAAC,EACR,sBAA2B,EAC3B,gBAAa,SAyBd,CAAC"}
@@ -1,34 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import '@dxos-theme';
6
-
7
- import { type Meta, type StoryObj } from '@storybook/react-vite';
8
- import React, { useState } from 'react';
9
-
10
- import { sleep } from '@dxos/async';
11
-
12
- import { useAsyncEffect } from './useAsyncEffect';
13
-
14
- const meta = {
15
- title: 'ui/react-hooks/useAsyncEffect',
16
- } satisfies Meta;
17
-
18
- export default meta;
19
-
20
- type Story = StoryObj<typeof meta>;
21
-
22
- export const Default: Story = {
23
- render: () => {
24
- const [value, setValue] = useState(0);
25
- useAsyncEffect(async (controller) => {
26
- await sleep(100);
27
- if (!controller.signal.aborted) {
28
- setValue((value) => value + 1);
29
- }
30
- }, []);
31
-
32
- return <div>{value}</div>;
33
- },
34
- };
@@ -1,40 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { useEffect, useRef } from 'react';
6
-
7
- import { log } from '@dxos/log';
8
-
9
- /**
10
- * Use to debug which props have changed to trigger re-renders in a React component.
11
- */
12
- export const useTrackProps = <T extends Record<string, unknown>>(
13
- props: T,
14
- componentName = 'Component',
15
- active = true,
16
- ) => {
17
- const prevProps = useRef<T>(props);
18
- useEffect(() => {
19
- const changes = Object.entries(props).filter(([key]) => props[key] !== prevProps.current[key]);
20
- if (changes.length > 0) {
21
- if (active) {
22
- log.info('props changed', {
23
- componentName,
24
- keys: changes.map(([key]) => key).join(','),
25
- props: Object.fromEntries(
26
- changes.map(([key]) => [
27
- key,
28
- {
29
- from: prevProps.current[key],
30
- to: props[key],
31
- },
32
- ]),
33
- ),
34
- });
35
- }
36
- }
37
-
38
- prevProps.current = props;
39
- });
40
- };