@dxos/react-hooks 0.8.4-main.dedc0f3 → 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.
- package/dist/lib/browser/index.mjs +35 -57
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +35 -57
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/index.d.ts +2 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/useControlledState.d.ts +1 -0
- package/dist/types/src/useControlledState.d.ts.map +1 -1
- package/dist/types/src/useDebugDeps.d.ts +1 -1
- package/dist/types/src/useDebugDeps.d.ts.map +1 -1
- package/dist/types/src/useDynamicRef.d.ts +1 -1
- package/dist/types/src/useDynamicRef.d.ts.map +1 -1
- package/dist/types/src/useForwardedRef.d.ts +3 -3
- package/dist/types/src/useForwardedRef.d.ts.map +1 -1
- package/dist/types/src/useIsFocused.d.ts +1 -1
- package/dist/types/src/useIsFocused.d.ts.map +1 -1
- package/dist/types/src/useMediaQuery.d.ts.map +1 -1
- package/dist/types/src/useMulticastObservable.test.d.ts.map +1 -1
- package/dist/types/src/useTransitions.d.ts +2 -1
- package/dist/types/src/useTransitions.d.ts.map +1 -1
- package/dist/types/src/useViewportResize.d.ts +3 -0
- package/dist/types/src/useViewportResize.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -9
- package/src/index.ts +3 -2
- package/src/useControlledState.ts +1 -0
- package/src/useDebugDeps.ts +2 -2
- package/src/useDynamicRef.ts +3 -3
- package/src/useForwardedRef.ts +17 -14
- package/src/useIsFocused.ts +1 -1
- package/src/useMediaQuery.ts +1 -2
- package/src/{useMulticastObservable.test.tsx → useMulticastObservable.test.ts} +1 -3
- package/src/useTransitions.ts +3 -1
- package/src/{useResize.ts → useViewportResize.ts} +1 -1
- package/dist/types/src/useAsyncEffect.stories.d.ts +0 -9
- package/dist/types/src/useAsyncEffect.stories.d.ts.map +0 -1
- package/dist/types/src/useResize.d.ts +0 -3
- package/dist/types/src/useResize.d.ts.map +0 -1
- package/dist/types/src/useTrackProps.d.ts +0 -5
- package/dist/types/src/useTrackProps.d.ts.map +0 -1
- package/src/useAsyncEffect.stories.tsx +0 -34
- package/src/useTrackProps.ts +0 -40
|
@@ -66,7 +66,7 @@ var useControlledState = (controlledValue, onChange, ...deps) => {
|
|
|
66
66
|
|
|
67
67
|
// src/useDebugDeps.ts
|
|
68
68
|
import { useEffect as useEffect4, useRef } from "react";
|
|
69
|
-
var useDebugDeps = (deps = []) => {
|
|
69
|
+
var useDebugDeps = (deps = [], active = true) => {
|
|
70
70
|
const lastDeps = useRef([]);
|
|
71
71
|
useEffect4(() => {
|
|
72
72
|
console.group("deps changed", {
|
|
@@ -74,7 +74,7 @@ var useDebugDeps = (deps = []) => {
|
|
|
74
74
|
current: deps.length
|
|
75
75
|
});
|
|
76
76
|
for (let i = 0; i < Math.max(lastDeps.current.length ?? 0, deps.length ?? 0); i++) {
|
|
77
|
-
if (lastDeps.current[i] !== deps[i]) {
|
|
77
|
+
if (lastDeps.current[i] !== deps[i] && active) {
|
|
78
78
|
console.log("changed", {
|
|
79
79
|
index: i,
|
|
80
80
|
previous: lastDeps.current[i],
|
|
@@ -114,9 +114,9 @@ var useDefaults = (value, defaults) => {
|
|
|
114
114
|
// src/useDynamicRef.ts
|
|
115
115
|
import { useCallback } from "@preact-signals/safe-react/react";
|
|
116
116
|
import { useEffect as useEffect6, useRef as useRef2, useState as useState4 } from "react";
|
|
117
|
-
var useStateWithRef = (
|
|
118
|
-
const [value, setValue] = useState4(
|
|
119
|
-
const valueRef = useRef2(
|
|
117
|
+
var useStateWithRef = (valueParam) => {
|
|
118
|
+
const [value, setValue] = useState4(valueParam);
|
|
119
|
+
const valueRef = useRef2(valueParam);
|
|
120
120
|
const setter = useCallback((value2) => {
|
|
121
121
|
if (typeof value2 === "function") {
|
|
122
122
|
setValue((current) => {
|
|
@@ -162,17 +162,22 @@ import { useEffect as useEffect7, useRef as useRef3 } from "react";
|
|
|
162
162
|
var useForwardedRef = (ref) => {
|
|
163
163
|
const innerRef = useRef3(null);
|
|
164
164
|
useEffect7(() => {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
ref(innerRef.current);
|
|
170
|
-
} else {
|
|
171
|
-
ref.current = innerRef.current;
|
|
172
|
-
}
|
|
173
|
-
});
|
|
165
|
+
updateRef(ref, innerRef.current);
|
|
166
|
+
}, [
|
|
167
|
+
ref
|
|
168
|
+
]);
|
|
174
169
|
return innerRef;
|
|
175
170
|
};
|
|
171
|
+
var updateRef = (ref, value) => {
|
|
172
|
+
if (!ref) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (typeof ref === "function") {
|
|
176
|
+
ref(value);
|
|
177
|
+
} else {
|
|
178
|
+
ref.current = value;
|
|
179
|
+
}
|
|
180
|
+
};
|
|
176
181
|
|
|
177
182
|
// src/useId.ts
|
|
178
183
|
import alea from "alea";
|
|
@@ -224,7 +229,7 @@ var breakpointMediaQueries = {
|
|
|
224
229
|
"2xl": "(min-width: 1536px)"
|
|
225
230
|
};
|
|
226
231
|
var useMediaQuery = (query, options = {}) => {
|
|
227
|
-
const { ssr =
|
|
232
|
+
const { ssr = false, fallback } = options;
|
|
228
233
|
const queries = (Array.isArray(query) ? query : [
|
|
229
234
|
query
|
|
230
235
|
]).map((query2) => query2 in breakpointMediaQueries ? breakpointMediaQueries[query2] : query2);
|
|
@@ -301,9 +306,9 @@ var useRefCallback = () => {
|
|
|
301
306
|
};
|
|
302
307
|
};
|
|
303
308
|
|
|
304
|
-
// src/
|
|
309
|
+
// src/useViewportResize.ts
|
|
305
310
|
import { useLayoutEffect, useMemo as useMemo6 } from "react";
|
|
306
|
-
var
|
|
311
|
+
var useViewportResize = (handler, deps = [], delay = 800) => {
|
|
307
312
|
const debouncedHandler = useMemo6(() => {
|
|
308
313
|
let timeout;
|
|
309
314
|
return (event) => {
|
|
@@ -393,47 +398,15 @@ var useInterval = (callback, delay = 0, deps = []) => {
|
|
|
393
398
|
]);
|
|
394
399
|
};
|
|
395
400
|
|
|
396
|
-
// src/useTrackProps.ts
|
|
397
|
-
import { useEffect as useEffect12, useRef as useRef7 } from "react";
|
|
398
|
-
import { log } from "@dxos/log";
|
|
399
|
-
var __dxlog_file = "/__w/dxos/dxos/packages/ui/primitives/react-hooks/src/useTrackProps.ts";
|
|
400
|
-
var useTrackProps = (props, componentName = "Component", active = true) => {
|
|
401
|
-
const prevProps = useRef7(props);
|
|
402
|
-
useEffect12(() => {
|
|
403
|
-
const changes = Object.entries(props).filter(([key]) => props[key] !== prevProps.current[key]);
|
|
404
|
-
if (changes.length > 0) {
|
|
405
|
-
if (active) {
|
|
406
|
-
log.info("props changed", {
|
|
407
|
-
componentName,
|
|
408
|
-
keys: changes.map(([key]) => key).join(","),
|
|
409
|
-
props: Object.fromEntries(changes.map(([key]) => [
|
|
410
|
-
key,
|
|
411
|
-
{
|
|
412
|
-
from: prevProps.current[key],
|
|
413
|
-
to: props[key]
|
|
414
|
-
}
|
|
415
|
-
]))
|
|
416
|
-
}, {
|
|
417
|
-
F: __dxlog_file,
|
|
418
|
-
L: 22,
|
|
419
|
-
S: void 0,
|
|
420
|
-
C: (f, a) => f(...a)
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
prevProps.current = props;
|
|
425
|
-
});
|
|
426
|
-
};
|
|
427
|
-
|
|
428
401
|
// src/useTransitions.ts
|
|
429
|
-
import { useEffect as
|
|
402
|
+
import { useEffect as useEffect12, useRef as useRef7, useState as useState8 } from "react";
|
|
430
403
|
var isFunction = (functionToCheck) => {
|
|
431
404
|
return functionToCheck instanceof Function;
|
|
432
405
|
};
|
|
433
406
|
var useDidTransition = (currentValue, fromValue, toValue) => {
|
|
434
407
|
const [hasTransitioned, setHasTransitioned] = useState8(false);
|
|
435
|
-
const previousValue =
|
|
436
|
-
|
|
408
|
+
const previousValue = useRef7(currentValue);
|
|
409
|
+
useEffect12(() => {
|
|
437
410
|
const toValueValid = isFunction(toValue) ? toValue(currentValue) : toValue === currentValue;
|
|
438
411
|
const fromValueValid = isFunction(fromValue) ? fromValue(previousValue.current) : fromValue === previousValue.current;
|
|
439
412
|
if (fromValueValid && toValueValid && !hasTransitioned) {
|
|
@@ -451,15 +424,15 @@ var useDidTransition = (currentValue, fromValue, toValue) => {
|
|
|
451
424
|
return hasTransitioned;
|
|
452
425
|
};
|
|
453
426
|
var useOnTransition = (currentValue, fromValue, toValue, callback) => {
|
|
454
|
-
const dirty =
|
|
427
|
+
const dirty = useRef7(false);
|
|
455
428
|
const hasTransitioned = useDidTransition(currentValue, fromValue, toValue);
|
|
456
|
-
|
|
429
|
+
useEffect12(() => {
|
|
457
430
|
dirty.current = false;
|
|
458
431
|
}, [
|
|
459
432
|
currentValue,
|
|
460
433
|
dirty
|
|
461
434
|
]);
|
|
462
|
-
|
|
435
|
+
useEffect12(() => {
|
|
463
436
|
if (hasTransitioned && !dirty.current) {
|
|
464
437
|
callback();
|
|
465
438
|
dirty.current = true;
|
|
@@ -470,9 +443,13 @@ var useOnTransition = (currentValue, fromValue, toValue, callback) => {
|
|
|
470
443
|
callback
|
|
471
444
|
]);
|
|
472
445
|
};
|
|
446
|
+
|
|
447
|
+
// src/index.ts
|
|
448
|
+
import { useSize, useScroller } from "mini-virtual-list";
|
|
473
449
|
export {
|
|
474
450
|
makeId,
|
|
475
451
|
randomString,
|
|
452
|
+
updateRef,
|
|
476
453
|
useAsyncEffect,
|
|
477
454
|
useAsyncState,
|
|
478
455
|
useControlledState,
|
|
@@ -490,11 +467,12 @@ export {
|
|
|
490
467
|
useMulticastObservable,
|
|
491
468
|
useOnTransition,
|
|
492
469
|
useRefCallback,
|
|
493
|
-
|
|
470
|
+
useScroller,
|
|
494
471
|
useSignalsEffect,
|
|
495
472
|
useSignalsMemo,
|
|
473
|
+
useSize,
|
|
496
474
|
useStateWithRef,
|
|
497
475
|
useTimeout,
|
|
498
|
-
|
|
476
|
+
useViewportResize
|
|
499
477
|
};
|
|
500
478
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../src/useAsyncEffect.ts", "../../../src/useAsyncState.ts", "../../../src/useControlledState.ts", "../../../src/useDebugDeps.ts", "../../../src/useDefaultValue.ts", "../../../src/useDefaults.ts", "../../../src/useDynamicRef.ts", "../../../src/useFileDownload.ts", "../../../src/useForwardedRef.ts", "../../../src/useId.ts", "../../../src/useIsFocused.ts", "../../../src/useMediaQuery.ts", "../../../src/useMulticastObservable.ts", "../../../src/useRefCallback.ts", "../../../src/
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { type DependencyList, type EffectCallback, useEffect } from 'react';\n\n/**\n * Async version of useEffect.\n * The `AbortController` can be used to detect if the component has been unmounted and\n * can be used to propagate abort signals to downstream async operations (e.g., `fetch`).\n */\nexport const useAsyncEffect = (\n cb: (controller: AbortController) => Promise<EffectCallback | void>,\n deps?: DependencyList,\n) => {\n useEffect(() => {\n const controller = new AbortController();\n let cleanup: EffectCallback | void;\n // NOTE: Timeout enables us to immediately cancel. if the component is unmounted.\n const t = setTimeout(async () => {\n if (!controller.signal.aborted) {\n cleanup = await cb(controller);\n }\n });\n\n return () => {\n clearTimeout(t);\n controller.abort();\n cleanup?.();\n };\n }, deps ?? []);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Dispatch, type SetStateAction, useEffect, useState } from 'react';\n\n/**\n * NOTE: Use with care and when necessary to be able to cancel an async operation when unmounting.\n */\nexport const useAsyncState = <T>(\n cb: () => Promise<T | undefined>,\n deps: any[] = [],\n): [T | undefined, Dispatch<SetStateAction<T | undefined>>] => {\n const [value, setValue] = useState<T | undefined>();\n useEffect(() => {\n let disposed = false;\n const t = setTimeout(async () => {\n const data = await cb();\n if (!disposed) {\n setValue(data);\n }\n });\n\n return () => {\n disposed = true;\n clearTimeout(t);\n };\n }, deps);\n\n return [value, setValue];\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Dispatch, type SetStateAction, useEffect, useState } from 'react';\n\n/**\n * A stateful hook with a controlled value.\n * NOTE: Be careful not to provide an inlinde default array.\n */\nexport const useControlledState = <T>(\n controlledValue: T,\n onChange?: (value: T) => void,\n ...deps: any[]\n): [T, Dispatch<SetStateAction<T>>] => {\n const [value, setValue] = useState<T>(controlledValue);\n useEffect(() => {\n if (controlledValue !== undefined) {\n setValue(controlledValue);\n }\n }, [controlledValue, ...deps]);\n\n useEffect(() => {\n onChange?.(value);\n }, [value, onChange]);\n\n return [value, setValue];\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type DependencyList, useEffect, useRef } from 'react';\n\n/**\n * Util to log deps that have changed.\n */\nexport const useDebugDeps = (deps: DependencyList = []) => {\n const lastDeps = useRef<DependencyList>([]);\n useEffect(() => {\n console.group('deps changed', { previous: lastDeps.current.length, current: deps.length });\n for (let i = 0; i < Math.max(lastDeps.current.length ?? 0, deps.length ?? 0); i++) {\n if (lastDeps.current[i] !== deps[i]) {\n console.log('changed', {\n index: i,\n previous: lastDeps.current[i],\n current: deps[i],\n });\n }\n }\n console.groupEnd();\n lastDeps.current = deps;\n }, deps);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { useEffect, useMemo, useState } from 'react';\n\n/**\n * A custom React hook that provides a stable default value for a potentially undefined reactive value.\n * The defaultValue is memoized upon component mount and remains unchanged until the component unmounts,\n * ensuring stability across all re-renders, even if the defaultValue prop changes.\n *\n * Note: The defaultValue is not reactive. It retains the same value from the component's mount to unmount.\n *\n * @param reactiveValue - The value that may change over time.\n * @param defaultValue - The initial value used when the reactiveValue is undefined. This value is not reactive.\n * @returns - The reactiveValue if it's defined, otherwise the defaultValue.\n */\nexport const useDefaultValue = <T>(reactiveValue: T | undefined | null, getDefaultValue: () => T): T => {\n // Memoize defaultValue with an empty dependency array.\n // This ensures that the defaultValue instance remains stable across all re-renders,\n // regardless of whether the defaultValue changes.\n const stableDefaultValue = useMemo(getDefaultValue, []);\n const [value, setValue] = useState(reactiveValue ?? stableDefaultValue);\n useEffect(() => {\n setValue(reactiveValue ?? stableDefaultValue);\n }, [reactiveValue, stableDefaultValue]);\n\n return value;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport defaultsDeep from 'lodash.defaultsdeep';\nimport { useMemo } from 'react';\n\n/**\n * Returns a memo-ized deep-merged object of the default and value.\n * If value is undefined or null, then returns the default.\n */\nexport const useDefaults = <T>(value: T | undefined | null, defaults: T): T => {\n return useMemo(() => defaultsDeep({}, defaults, value), [value, defaults]);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { useCallback } from '@preact-signals/safe-react/react';\nimport { type Dispatch, type MutableRefObject, type SetStateAction, useEffect, useRef, useState } from 'react';\n\n/**\n * Like `useState` but with an additional dynamic value.\n */\nexport const useStateWithRef = <T>(value$: T): [T, Dispatch<SetStateAction<T>>, MutableRefObject<T>] => {\n const [value, setValue] = useState<T>(value$);\n const valueRef = useRef<T>(value$);\n const setter = useCallback<Dispatch<SetStateAction<T>>>((value) => {\n if (typeof value === 'function') {\n setValue((current) => {\n valueRef.current = (value as Function)(current);\n return valueRef.current;\n });\n } else {\n valueRef.current = value;\n setValue(value);\n }\n }, []);\n\n return [value, setter, valueRef];\n};\n\n/**\n * Ref that is updated by a dependency.\n */\nexport const useDynamicRef = <T>(value: T): MutableRefObject<T> => {\n const valueRef = useRef<T>(value);\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n return valueRef;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { useMemo } from 'react';\n\n/**\n * File download anchor.\n *\n * ```\n * const download = useDownload();\n * const handleDownload = (data: string) => {\n * download(new Blob([data], { type: 'text/plain' }), 'test.txt');\n * };\n * ```\n */\nexport const useFileDownload = (): ((data: Blob | string, filename: string) => void) => {\n return useMemo(\n () => (data: Blob | string, filename: string) => {\n const url = typeof data === 'string' ? data : URL.createObjectURL(data);\n const element = document.createElement('a');\n element.setAttribute('href', url);\n element.setAttribute('download', filename);\n element.setAttribute('target', 'download');\n element.click();\n },\n [],\n );\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { type ForwardedRef, useEffect, useRef } from 'react';\n\n/**\n * Combines a possibly undefined forwarded ref with a locally defined ref.\n * @deprecated Use @radix-ui/react-compose-refs\n */\nexport const useForwardedRef = <T>(ref: ForwardedRef<T>) => {\n const innerRef = useRef<T>(null);\n useEffect(() => {\n if (!ref) {\n return;\n }\n\n if (typeof ref === 'function') {\n ref(innerRef.current);\n } else {\n ref.current = innerRef.current;\n }\n });\n\n return innerRef;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport alea from 'alea';\nimport { useMemo } from 'react';\n\ninterface PrngFactory {\n new (seed?: string): () => number;\n}\n\nconst Alea: PrngFactory = alea as unknown as PrngFactory;\n\nconst prng = new Alea('@dxos/react-hooks');\n\n// TODO(burdon): Replace with PublicKey.random().\nexport const randomString = (n = 4) =>\n prng()\n .toString(16)\n .slice(2, n + 2);\n\nexport const useId = (namespace: string, propsId?: string, opts?: Partial<{ n: number }>) =>\n useMemo(() => makeId(namespace, propsId, opts), [propsId]);\n\nexport const makeId = (namespace: string, propsId?: string, opts?: Partial<{ n: number }>) =>\n propsId ?? `${namespace}-${randomString(opts?.n ?? 4)}`;\n", "//\n// Copyright 2022 DXOS.org\n//\n\n// Based upon the useIsFocused hook which is part of the `rci` project:\n/// https://github.com/leonardodino/rci/blob/main/packages/use-is-focused\n\nimport { type RefObject, useEffect, useRef, useState } from 'react';\n\nexport const useIsFocused = (inputRef: RefObject<HTMLInputElement>) => {\n const [isFocused, setIsFocused] = useState<boolean | undefined>(undefined);\n const isFocusedRef = useRef<boolean | undefined>(isFocused);\n\n isFocusedRef.current = isFocused;\n\n useEffect(() => {\n const input = inputRef.current;\n if (!input) {\n return;\n }\n\n const onFocus = () => setIsFocused(true);\n const onBlur = () => setIsFocused(false);\n input.addEventListener('focus', onFocus);\n input.addEventListener('blur', onBlur);\n\n if (isFocusedRef.current === undefined) {\n setIsFocused(document.activeElement === input);\n }\n\n return () => {\n input.removeEventListener('focus', onFocus);\n input.removeEventListener('blur', onBlur);\n };\n }, [inputRef, setIsFocused]);\n\n return isFocused;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\n// This hook is based on Chakra UI’s `useMediaQuery`: https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/media-query/src/use-media-query.ts\n\nimport { useEffect, useState } from 'react';\n\nexport type UseMediaQueryOptions = {\n fallback?: boolean | boolean[];\n ssr?: boolean;\n};\n\n// TODO(thure): This should be derived from the same source of truth as the Tailwind theme config\nconst breakpointMediaQueries: Record<string, string> = {\n sm: '(min-width: 640px)',\n md: '(min-width: 768px)',\n lg: '(min-width: 1024px)',\n xl: '(min-width: 1280px)',\n '2xl': '(min-width: 1536px)',\n};\n\n/**\n * React hook that tracks state of a CSS media query\n *\n * @param query the media query to match, or a recognized breakpoint token\n * @param options the media query options { fallback, ssr }\n *\n * @see Docs https://chakra-ui.com/docs/hooks/use-media-query\n */\nexport const useMediaQuery = (query: string | string[], options: UseMediaQueryOptions = {}): boolean[] => {\n // TODO(wittjosiah): Why is the default here true?\n const { ssr = true, fallback } = options;\n\n const queries = (Array.isArray(query) ? query : [query]).map((query) =>\n query in breakpointMediaQueries ? breakpointMediaQueries[query] : query,\n );\n\n let fallbackValues = Array.isArray(fallback) ? fallback : [fallback];\n fallbackValues = fallbackValues.filter((v) => v != null) as boolean[];\n\n const [value, setValue] = useState(() => {\n return queries.map((query, index) => ({\n media: query,\n matches: ssr ? !!fallbackValues[index] : document.defaultView?.matchMedia(query).matches,\n }));\n });\n\n useEffect(() => {\n setValue(\n queries.map((query) => ({\n media: query,\n matches: document.defaultView?.matchMedia(query).matches,\n })),\n );\n\n const mql = queries.map((query) => document.defaultView?.matchMedia(query));\n\n const handler = (evt: MediaQueryListEvent) => {\n setValue((prev) => {\n return prev.slice().map((item) => {\n if (item.media === evt.media) {\n return { ...item, matches: evt.matches };\n }\n return item;\n });\n });\n };\n\n mql.forEach((mql) => {\n if (typeof mql?.addListener === 'function') {\n mql?.addListener(handler);\n } else {\n mql?.addEventListener('change', handler);\n }\n });\n\n return () => {\n mql.forEach((mql) => {\n if (typeof mql?.removeListener === 'function') {\n mql?.removeListener(handler);\n } else {\n mql?.removeEventListener('change', handler);\n }\n });\n };\n }, [document.defaultView]);\n\n return value.map((item) => !!item.matches);\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { useMemo, useSyncExternalStore } from 'react';\n\nimport { type MulticastObservable } from '@dxos/async';\n\n/**\n * Subscribe to a MulticastObservable and return the latest value.\n * @param observable the observable to subscribe to. Will resubscribe if the observable changes.\n */\n// TODO(burdon): Move to react-hooks.\nexport const useMulticastObservable = <T>(observable: MulticastObservable<T>): T => {\n // Make sure useSyncExternalStore is stable in respect to the observable.\n const subscribeFn = useMemo(\n () => (listener: () => void) => {\n const subscription = observable.subscribe(listener);\n return () => subscription.unsubscribe();\n },\n [observable],\n );\n\n // useSyncExternalStore will resubscribe to the observable and update the value if the subscribeFn changes.\n return useSyncExternalStore(subscribeFn, () => observable.get());\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type RefCallback, useState } from 'react';\n\n/**\n * Custom React Hook that creates a ref callback and a state variable.\n * The ref callback sets the state variable when the ref changes.\n *\n * @returns An object containing the ref callback and the current value of the ref.\n */\nexport const useRefCallback = <T = any>(): { refCallback: RefCallback<T>; value: T | null } => {\n const [value, setValue] = useState<T | null>(null);\n return { refCallback: (value: T) => setValue(value), value };\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useLayoutEffect, useMemo } from 'react';\n\nexport const useResize = (\n handler: (event?: Event) => void,\n deps: Parameters<typeof useLayoutEffect>[1] = [],\n delay: number = 800,\n) => {\n const debouncedHandler = useMemo(() => {\n let timeout: ReturnType<typeof setTimeout>;\n return (event?: Event) => {\n clearTimeout(timeout);\n timeout = setTimeout(() => {\n handler(event);\n }, delay);\n };\n }, [handler, delay]);\n\n return useLayoutEffect(() => {\n window.visualViewport?.addEventListener('resize', debouncedHandler);\n debouncedHandler();\n return () => window.visualViewport?.removeEventListener('resize', debouncedHandler);\n }, [debouncedHandler, ...deps]);\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { computed, effect } from '@preact-signals/safe-react';\nimport { useRef } from '@preact-signals/safe-react/react';\nimport { type DependencyList, useEffect, useMemo } from 'react';\n\n/**\n * Like `useEffect` but also tracks signals inside of the callback.\n */\nexport const useSignalsEffect = (cb: () => void | (() => void), deps?: DependencyList) => {\n const callback = useRef(cb);\n callback.current = cb;\n useEffect(() => {\n return effect(() => {\n return callback.current();\n });\n }, deps ?? []);\n};\n\n/**\n * Like `useMemo` but also tracks signals inside of the callback.\n */\nexport const useSignalsMemo = <T>(cb: () => T, deps?: DependencyList) => {\n return useMemo(() => computed(cb), deps ?? []).value;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useRef } from 'react';\n\nexport const useTimeout = (callback?: () => Promise<void>, delay = 0, deps: any[] = []) => {\n const callbackRef = useRef(callback);\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delay == null) {\n return;\n }\n\n const t = setTimeout(() => callbackRef.current?.(), delay);\n return () => clearTimeout(t);\n }, [delay, ...deps]);\n};\n\nexport const useInterval = (\n callback?: (() => Promise<void | boolean>) | (() => void | boolean),\n delay = 0,\n deps: any[] = [],\n) => {\n const callbackRef = useRef(callback);\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delay == null) {\n return;\n }\n\n const i = setInterval(async () => {\n const result = await callbackRef.current?.();\n if (result === false) {\n clearInterval(i);\n }\n }, delay);\n return () => clearInterval(i);\n }, [delay, ...deps]);\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useRef } from 'react';\n\nimport { log } from '@dxos/log';\n\n/**\n * Use to debug which props have changed to trigger re-renders in a React component.\n */\nexport const useTrackProps = <T extends Record<string, unknown>>(\n props: T,\n componentName = 'Component',\n active = true,\n) => {\n const prevProps = useRef<T>(props);\n useEffect(() => {\n const changes = Object.entries(props).filter(([key]) => props[key] !== prevProps.current[key]);\n if (changes.length > 0) {\n if (active) {\n log.info('props changed', {\n componentName,\n keys: changes.map(([key]) => key).join(','),\n props: Object.fromEntries(\n changes.map(([key]) => [\n key,\n {\n from: prevProps.current[key],\n to: props[key],\n },\n ]),\n ),\n });\n }\n }\n\n prevProps.current = props;\n });\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { useEffect, useRef, useState } from 'react';\n\nconst isFunction = <T>(functionToCheck: any): functionToCheck is (value: T) => boolean => {\n return functionToCheck instanceof Function;\n};\n\n/**\n * This is an internal custom hook that checks if a value has transitioned from a specified 'from' value to a 'to' value.\n *\n * @param currentValue - The value that is being monitored for transitions.\n * @param fromValue - The *from* value or a predicate function that determines the start of the transition.\n * @param toValue - The *to* value or a predicate function that determines the end of the transition.\n * @returns A boolean indicating whether the transition from *fromValue* to *toValue* has occurred.\n *\n * @internal Consider using `useOnTransition` for handling transitions instead of this hook.\n */\nexport const useDidTransition = <T>(\n currentValue: T,\n fromValue: T | ((value: T) => boolean),\n toValue: T | ((value: T) => boolean),\n) => {\n const [hasTransitioned, setHasTransitioned] = useState(false);\n const previousValue = useRef<T>(currentValue);\n\n useEffect(() => {\n const toValueValid = isFunction<T>(toValue) ? toValue(currentValue) : toValue === currentValue;\n const fromValueValid = isFunction<T>(fromValue)\n ? fromValue(previousValue.current)\n : fromValue === previousValue.current;\n\n if (fromValueValid && toValueValid && !hasTransitioned) {\n setHasTransitioned(true);\n } else if ((!fromValueValid || !toValueValid) && hasTransitioned) {\n setHasTransitioned(false);\n }\n\n previousValue.current = currentValue;\n }, [currentValue, fromValue, toValue, hasTransitioned]);\n\n return hasTransitioned;\n};\n\n/**\n * Executes a callback function when a specified transition occurs in a value.\n *\n * This function utilizes the `useDidTransition` hook to monitor changes in `currentValue`.\n * When `currentValue` transitions from `fromValue` to `toValue`, the provided `callback` function is executed. */\nexport const useOnTransition = <T>(\n currentValue: T,\n fromValue: T | ((value: T) => boolean),\n toValue: T | ((value: T) => boolean),\n callback: () => void,\n) => {\n const dirty = useRef(false);\n const hasTransitioned = useDidTransition(currentValue, fromValue, toValue);\n\n useEffect(() => {\n dirty.current = false;\n }, [currentValue, dirty]);\n\n useEffect(() => {\n if (hasTransitioned && !dirty.current) {\n callback();\n dirty.current = true;\n }\n }, [hasTransitioned, dirty, callback]);\n};\n"],
|
|
5
|
-
"mappings": ";AAIA,SAAmDA,iBAAiB;AAO7D,IAAMC,iBAAiB,CAC5BC,IACAC,SAAAA;AAEAC,YAAU,MAAA;AACR,UAAMC,aAAa,IAAIC,gBAAAA;AACvB,QAAIC;AAEJ,UAAMC,IAAIC,WAAW,YAAA;AACnB,UAAI,CAACJ,WAAWK,OAAOC,SAAS;AAC9BJ,kBAAU,MAAML,GAAGG,UAAAA;MACrB;IACF,CAAA;AAEA,WAAO,MAAA;AACLO,mBAAaJ,CAAAA;AACbH,iBAAWQ,MAAK;AAChBN,gBAAAA;IACF;EACF,GAAGJ,QAAQ,CAAA,CAAE;AACf;;;AC3BA,SAA6CW,aAAAA,YAAWC,gBAAgB;AAKjE,IAAMC,gBAAgB,CAC3BC,IACAC,OAAc,CAAA,MAAE;AAEhB,QAAM,CAACC,OAAOC,QAAAA,IAAYC,SAAAA;AAC1BC,EAAAA,WAAU,MAAA;AACR,QAAIC,WAAW;AACf,UAAMC,IAAIC,WAAW,YAAA;AACnB,YAAMC,OAAO,MAAMT,GAAAA;AACnB,UAAI,CAACM,UAAU;AACbH,iBAASM,IAAAA;MACX;IACF,CAAA;AAEA,WAAO,MAAA;AACLH,iBAAW;AACXI,mBAAaH,CAAAA;IACf;EACF,GAAGN,IAAAA;AAEH,SAAO;IAACC;IAAOC;;AACjB;;;AC1BA,SAA6CQ,aAAAA,YAAWC,YAAAA,iBAAgB;
|
|
6
|
-
"names": ["useEffect", "useAsyncEffect", "cb", "deps", "useEffect", "controller", "AbortController", "cleanup", "t", "setTimeout", "signal", "aborted", "clearTimeout", "abort", "useEffect", "useState", "useAsyncState", "cb", "deps", "value", "setValue", "useState", "useEffect", "disposed", "t", "setTimeout", "data", "clearTimeout", "useEffect", "useState", "useControlledState", "controlledValue", "onChange", "deps", "value", "setValue", "useState", "useEffect", "undefined", "useEffect", "useRef", "useDebugDeps", "deps", "lastDeps", "useRef", "useEffect", "console", "group", "previous", "current", "length", "i", "Math", "max", "log", "index", "groupEnd", "useEffect", "useMemo", "useState", "useDefaultValue", "reactiveValue", "getDefaultValue", "stableDefaultValue", "useMemo", "value", "setValue", "useState", "useEffect", "defaultsDeep", "useMemo", "useDefaults", "value", "defaults", "useMemo", "defaultsDeep", "useCallback", "useEffect", "useRef", "useState", "useStateWithRef", "
|
|
3
|
+
"sources": ["../../../src/useAsyncEffect.ts", "../../../src/useAsyncState.ts", "../../../src/useControlledState.ts", "../../../src/useDebugDeps.ts", "../../../src/useDefaultValue.ts", "../../../src/useDefaults.ts", "../../../src/useDynamicRef.ts", "../../../src/useFileDownload.ts", "../../../src/useForwardedRef.ts", "../../../src/useId.ts", "../../../src/useIsFocused.ts", "../../../src/useMediaQuery.ts", "../../../src/useMulticastObservable.ts", "../../../src/useRefCallback.ts", "../../../src/useViewportResize.ts", "../../../src/useSignals.ts", "../../../src/useTimeout.ts", "../../../src/useTransitions.ts", "../../../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { type DependencyList, type EffectCallback, useEffect } from 'react';\n\n/**\n * Async version of useEffect.\n * The `AbortController` can be used to detect if the component has been unmounted and\n * can be used to propagate abort signals to downstream async operations (e.g., `fetch`).\n */\nexport const useAsyncEffect = (\n cb: (controller: AbortController) => Promise<EffectCallback | void>,\n deps?: DependencyList,\n) => {\n useEffect(() => {\n const controller = new AbortController();\n let cleanup: EffectCallback | void;\n // NOTE: Timeout enables us to immediately cancel. if the component is unmounted.\n const t = setTimeout(async () => {\n if (!controller.signal.aborted) {\n cleanup = await cb(controller);\n }\n });\n\n return () => {\n clearTimeout(t);\n controller.abort();\n cleanup?.();\n };\n }, deps ?? []);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Dispatch, type SetStateAction, useEffect, useState } from 'react';\n\n/**\n * NOTE: Use with care and when necessary to be able to cancel an async operation when unmounting.\n */\nexport const useAsyncState = <T>(\n cb: () => Promise<T | undefined>,\n deps: any[] = [],\n): [T | undefined, Dispatch<SetStateAction<T | undefined>>] => {\n const [value, setValue] = useState<T | undefined>();\n useEffect(() => {\n let disposed = false;\n const t = setTimeout(async () => {\n const data = await cb();\n if (!disposed) {\n setValue(data);\n }\n });\n\n return () => {\n disposed = true;\n clearTimeout(t);\n };\n }, deps);\n\n return [value, setValue];\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Dispatch, type SetStateAction, useEffect, useState } from 'react';\n\n/**\n * A stateful hook with a controlled value.\n * NOTE: Be careful not to provide an inlinde default array.\n * @deprecated Use Radix `useControllableState`.\n */\nexport const useControlledState = <T>(\n controlledValue: T,\n onChange?: (value: T) => void,\n ...deps: any[]\n): [T, Dispatch<SetStateAction<T>>] => {\n const [value, setValue] = useState<T>(controlledValue);\n useEffect(() => {\n if (controlledValue !== undefined) {\n setValue(controlledValue);\n }\n }, [controlledValue, ...deps]);\n\n useEffect(() => {\n onChange?.(value);\n }, [value, onChange]);\n\n return [value, setValue];\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type DependencyList, useEffect, useRef } from 'react';\n\n/**\n * Util to log deps that have changed.\n */\nexport const useDebugDeps = (deps: DependencyList = [], active = true) => {\n const lastDeps = useRef<DependencyList>([]);\n useEffect(() => {\n console.group('deps changed', { previous: lastDeps.current.length, current: deps.length });\n for (let i = 0; i < Math.max(lastDeps.current.length ?? 0, deps.length ?? 0); i++) {\n if (lastDeps.current[i] !== deps[i] && active) {\n console.log('changed', {\n index: i,\n previous: lastDeps.current[i],\n current: deps[i],\n });\n }\n }\n console.groupEnd();\n lastDeps.current = deps;\n }, deps);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { useEffect, useMemo, useState } from 'react';\n\n/**\n * A custom React hook that provides a stable default value for a potentially undefined reactive value.\n * The defaultValue is memoized upon component mount and remains unchanged until the component unmounts,\n * ensuring stability across all re-renders, even if the defaultValue prop changes.\n *\n * Note: The defaultValue is not reactive. It retains the same value from the component's mount to unmount.\n *\n * @param reactiveValue - The value that may change over time.\n * @param defaultValue - The initial value used when the reactiveValue is undefined. This value is not reactive.\n * @returns - The reactiveValue if it's defined, otherwise the defaultValue.\n */\nexport const useDefaultValue = <T>(reactiveValue: T | undefined | null, getDefaultValue: () => T): T => {\n // Memoize defaultValue with an empty dependency array.\n // This ensures that the defaultValue instance remains stable across all re-renders,\n // regardless of whether the defaultValue changes.\n const stableDefaultValue = useMemo(getDefaultValue, []);\n const [value, setValue] = useState(reactiveValue ?? stableDefaultValue);\n useEffect(() => {\n setValue(reactiveValue ?? stableDefaultValue);\n }, [reactiveValue, stableDefaultValue]);\n\n return value;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport defaultsDeep from 'lodash.defaultsdeep';\nimport { useMemo } from 'react';\n\n/**\n * Returns a memo-ized deep-merged object of the default and value.\n * If value is undefined or null, then returns the default.\n */\nexport const useDefaults = <T>(value: T | undefined | null, defaults: T): T => {\n return useMemo(() => defaultsDeep({}, defaults, value), [value, defaults]);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { useCallback } from '@preact-signals/safe-react/react';\nimport { type Dispatch, type MutableRefObject, type SetStateAction, useEffect, useRef, useState } from 'react';\n\n/**\n * Like `useState` but with an additional dynamic value.\n */\nexport const useStateWithRef = <T>(valueParam: T): [T, Dispatch<SetStateAction<T>>, MutableRefObject<T>] => {\n const [value, setValue] = useState<T>(valueParam);\n const valueRef = useRef<T>(valueParam);\n const setter = useCallback<Dispatch<SetStateAction<T>>>((value) => {\n if (typeof value === 'function') {\n setValue((current) => {\n valueRef.current = (value as Function)(current);\n return valueRef.current;\n });\n } else {\n valueRef.current = value;\n setValue(value);\n }\n }, []);\n\n return [value, setter, valueRef];\n};\n\n/**\n * Ref that is updated by a dependency.\n */\nexport const useDynamicRef = <T>(value: T): MutableRefObject<T> => {\n const valueRef = useRef<T>(value);\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n return valueRef;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { useMemo } from 'react';\n\n/**\n * File download anchor.\n *\n * ```\n * const download = useDownload();\n * const handleDownload = (data: string) => {\n * download(new Blob([data], { type: 'text/plain' }), 'test.txt');\n * };\n * ```\n */\nexport const useFileDownload = (): ((data: Blob | string, filename: string) => void) => {\n return useMemo(\n () => (data: Blob | string, filename: string) => {\n const url = typeof data === 'string' ? data : URL.createObjectURL(data);\n const element = document.createElement('a');\n element.setAttribute('href', url);\n element.setAttribute('download', filename);\n element.setAttribute('target', 'download');\n element.click();\n },\n [],\n );\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { type ForwardedRef, type RefObject, useEffect, useRef } from 'react';\n\n/**\n * Combines a possibly undefined forwarded ref with a locally defined ref.\n */\nexport const useForwardedRef = <T>(ref: ForwardedRef<T>): RefObject<T | null> => {\n const innerRef = useRef<T | null>(null);\n useEffect(() => {\n updateRef(ref, innerRef.current);\n }, [ref]);\n\n return innerRef;\n};\n\nexport const updateRef = <T>(ref: ForwardedRef<T>, value: T): void => {\n if (!ref) {\n return;\n }\n\n if (typeof ref === 'function') {\n ref(value);\n } else {\n ref.current = value;\n }\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport alea from 'alea';\nimport { useMemo } from 'react';\n\ninterface PrngFactory {\n new (seed?: string): () => number;\n}\n\nconst Alea: PrngFactory = alea as unknown as PrngFactory;\n\nconst prng = new Alea('@dxos/react-hooks');\n\n// TODO(burdon): Replace with PublicKey.random().\nexport const randomString = (n = 4) =>\n prng()\n .toString(16)\n .slice(2, n + 2);\n\nexport const useId = (namespace: string, propsId?: string, opts?: Partial<{ n: number }>) =>\n useMemo(() => makeId(namespace, propsId, opts), [propsId]);\n\nexport const makeId = (namespace: string, propsId?: string, opts?: Partial<{ n: number }>) =>\n propsId ?? `${namespace}-${randomString(opts?.n ?? 4)}`;\n", "//\n// Copyright 2022 DXOS.org\n//\n\n// Based upon the useIsFocused hook which is part of the `rci` project:\n/// https://github.com/leonardodino/rci/blob/main/packages/use-is-focused\n\nimport { type RefObject, useEffect, useRef, useState } from 'react';\n\nexport const useIsFocused = (inputRef: RefObject<HTMLInputElement | null>) => {\n const [isFocused, setIsFocused] = useState<boolean | undefined>(undefined);\n const isFocusedRef = useRef<boolean | undefined>(isFocused);\n\n isFocusedRef.current = isFocused;\n\n useEffect(() => {\n const input = inputRef.current;\n if (!input) {\n return;\n }\n\n const onFocus = () => setIsFocused(true);\n const onBlur = () => setIsFocused(false);\n input.addEventListener('focus', onFocus);\n input.addEventListener('blur', onBlur);\n\n if (isFocusedRef.current === undefined) {\n setIsFocused(document.activeElement === input);\n }\n\n return () => {\n input.removeEventListener('focus', onFocus);\n input.removeEventListener('blur', onBlur);\n };\n }, [inputRef, setIsFocused]);\n\n return isFocused;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\n// This hook is based on Chakra UI’s `useMediaQuery`: https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/media-query/src/use-media-query.ts\n\nimport { useEffect, useState } from 'react';\n\nexport type UseMediaQueryOptions = {\n fallback?: boolean | boolean[];\n ssr?: boolean;\n};\n\n// TODO(thure): This should be derived from the same source of truth as the Tailwind theme config\nconst breakpointMediaQueries: Record<string, string> = {\n sm: '(min-width: 640px)',\n md: '(min-width: 768px)',\n lg: '(min-width: 1024px)',\n xl: '(min-width: 1280px)',\n '2xl': '(min-width: 1536px)',\n};\n\n/**\n * React hook that tracks state of a CSS media query\n *\n * @param query the media query to match, or a recognized breakpoint token\n * @param options the media query options { fallback, ssr }\n *\n * @see Docs https://chakra-ui.com/docs/hooks/use-media-query\n */\nexport const useMediaQuery = (query: string | string[], options: UseMediaQueryOptions = {}): boolean[] => {\n const { ssr = false, fallback } = options;\n\n const queries = (Array.isArray(query) ? query : [query]).map((query) =>\n query in breakpointMediaQueries ? breakpointMediaQueries[query] : query,\n );\n\n let fallbackValues = Array.isArray(fallback) ? fallback : [fallback];\n fallbackValues = fallbackValues.filter((v) => v != null) as boolean[];\n\n const [value, setValue] = useState(() => {\n return queries.map((query, index) => ({\n media: query,\n matches: ssr ? !!fallbackValues[index] : document.defaultView?.matchMedia(query).matches,\n }));\n });\n\n useEffect(() => {\n setValue(\n queries.map((query) => ({\n media: query,\n matches: document.defaultView?.matchMedia(query).matches,\n })),\n );\n\n const mql = queries.map((query) => document.defaultView?.matchMedia(query));\n\n const handler = (evt: MediaQueryListEvent) => {\n setValue((prev) => {\n return prev.slice().map((item) => {\n if (item.media === evt.media) {\n return { ...item, matches: evt.matches };\n }\n return item;\n });\n });\n };\n\n mql.forEach((mql) => {\n if (typeof mql?.addListener === 'function') {\n mql?.addListener(handler);\n } else {\n mql?.addEventListener('change', handler);\n }\n });\n\n return () => {\n mql.forEach((mql) => {\n if (typeof mql?.removeListener === 'function') {\n mql?.removeListener(handler);\n } else {\n mql?.removeEventListener('change', handler);\n }\n });\n };\n }, [document.defaultView]);\n\n return value.map((item) => !!item.matches);\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { useMemo, useSyncExternalStore } from 'react';\n\nimport { type MulticastObservable } from '@dxos/async';\n\n/**\n * Subscribe to a MulticastObservable and return the latest value.\n * @param observable the observable to subscribe to. Will resubscribe if the observable changes.\n */\n// TODO(burdon): Move to react-hooks.\nexport const useMulticastObservable = <T>(observable: MulticastObservable<T>): T => {\n // Make sure useSyncExternalStore is stable in respect to the observable.\n const subscribeFn = useMemo(\n () => (listener: () => void) => {\n const subscription = observable.subscribe(listener);\n return () => subscription.unsubscribe();\n },\n [observable],\n );\n\n // useSyncExternalStore will resubscribe to the observable and update the value if the subscribeFn changes.\n return useSyncExternalStore(subscribeFn, () => observable.get());\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type RefCallback, useState } from 'react';\n\n/**\n * Custom React Hook that creates a ref callback and a state variable.\n * The ref callback sets the state variable when the ref changes.\n *\n * @returns An object containing the ref callback and the current value of the ref.\n */\nexport const useRefCallback = <T = any>(): { refCallback: RefCallback<T>; value: T | null } => {\n const [value, setValue] = useState<T | null>(null);\n return { refCallback: (value: T) => setValue(value), value };\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useLayoutEffect, useMemo } from 'react';\n\nexport const useViewportResize = (\n handler: (event?: Event) => void,\n deps: Parameters<typeof useLayoutEffect>[1] = [],\n delay: number = 800,\n) => {\n const debouncedHandler = useMemo(() => {\n let timeout: ReturnType<typeof setTimeout>;\n return (event?: Event) => {\n clearTimeout(timeout);\n timeout = setTimeout(() => {\n handler(event);\n }, delay);\n };\n }, [handler, delay]);\n\n return useLayoutEffect(() => {\n window.visualViewport?.addEventListener('resize', debouncedHandler);\n debouncedHandler();\n return () => window.visualViewport?.removeEventListener('resize', debouncedHandler);\n }, [debouncedHandler, ...deps]);\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { computed, effect } from '@preact-signals/safe-react';\nimport { useRef } from '@preact-signals/safe-react/react';\nimport { type DependencyList, useEffect, useMemo } from 'react';\n\n/**\n * Like `useEffect` but also tracks signals inside of the callback.\n */\nexport const useSignalsEffect = (cb: () => void | (() => void), deps?: DependencyList) => {\n const callback = useRef(cb);\n callback.current = cb;\n useEffect(() => {\n return effect(() => {\n return callback.current();\n });\n }, deps ?? []);\n};\n\n/**\n * Like `useMemo` but also tracks signals inside of the callback.\n */\nexport const useSignalsMemo = <T>(cb: () => T, deps?: DependencyList) => {\n return useMemo(() => computed(cb), deps ?? []).value;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useRef } from 'react';\n\nexport const useTimeout = (callback?: () => Promise<void>, delay = 0, deps: any[] = []) => {\n const callbackRef = useRef(callback);\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delay == null) {\n return;\n }\n\n const t = setTimeout(() => callbackRef.current?.(), delay);\n return () => clearTimeout(t);\n }, [delay, ...deps]);\n};\n\nexport const useInterval = (\n callback?: (() => Promise<void | boolean>) | (() => void | boolean),\n delay = 0,\n deps: any[] = [],\n) => {\n const callbackRef = useRef(callback);\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delay == null) {\n return;\n }\n\n const i = setInterval(async () => {\n const result = await callbackRef.current?.();\n if (result === false) {\n clearInterval(i);\n }\n }, delay);\n return () => clearInterval(i);\n }, [delay, ...deps]);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { useEffect, useRef, useState } from 'react';\n\nconst isFunction = <T>(functionToCheck: any): functionToCheck is (value: T) => boolean => {\n return functionToCheck instanceof Function;\n};\n\n/**\n * This is an internal custom hook that checks if a value has transitioned from a specified 'from' value to a 'to' value.\n *\n * @param currentValue - The value that is being monitored for transitions.\n * @param fromValue - The *from* value or a predicate function that determines the start of the transition.\n * @param toValue - The *to* value or a predicate function that determines the end of the transition.\n * @returns A boolean indicating whether the transition from *fromValue* to *toValue* has occurred.\n *\n * @internal Consider using `useOnTransition` for handling transitions instead of this hook.\n */\nexport const useDidTransition = <T>(\n currentValue: T,\n fromValue: T | ((value: T) => boolean),\n toValue: T | ((value: T) => boolean),\n) => {\n const [hasTransitioned, setHasTransitioned] = useState(false);\n const previousValue = useRef<T>(currentValue);\n\n useEffect(() => {\n const toValueValid = isFunction<T>(toValue) ? toValue(currentValue) : toValue === currentValue;\n const fromValueValid = isFunction<T>(fromValue)\n ? fromValue(previousValue.current)\n : fromValue === previousValue.current;\n\n if (fromValueValid && toValueValid && !hasTransitioned) {\n setHasTransitioned(true);\n } else if ((!fromValueValid || !toValueValid) && hasTransitioned) {\n setHasTransitioned(false);\n }\n\n previousValue.current = currentValue;\n }, [currentValue, fromValue, toValue, hasTransitioned]);\n\n return hasTransitioned;\n};\n\n/**\n * Executes a callback function when a specified transition occurs in a value.\n *\n * This function utilizes the `useDidTransition` hook to monitor changes in `currentValue`.\n * When `currentValue` transitions from `fromValue` to `toValue`, the provided `callback` function is executed.\n */\n// TODO(wittjosiah): Seems overwrought.\nexport const useOnTransition = <T>(\n currentValue: T,\n fromValue: T | ((value: T) => boolean),\n toValue: T | ((value: T) => boolean),\n callback: () => void,\n) => {\n const dirty = useRef(false);\n const hasTransitioned = useDidTransition(currentValue, fromValue, toValue);\n\n useEffect(() => {\n dirty.current = false;\n }, [currentValue, dirty]);\n\n useEffect(() => {\n if (hasTransitioned && !dirty.current) {\n callback();\n dirty.current = true;\n }\n }, [hasTransitioned, dirty, callback]);\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nexport * from './useAsyncEffect';\nexport * from './useAsyncState';\nexport * from './useControlledState';\nexport * from './useDebugDeps';\nexport * from './useDefaultValue';\nexport * from './useDefaults';\nexport * from './useDynamicRef';\nexport * from './useFileDownload';\nexport * from './useForwardedRef';\nexport * from './useId';\nexport * from './useIsFocused';\nexport * from './useMediaQuery';\nexport * from './useMulticastObservable';\nexport * from './useRefCallback';\nexport * from './useViewportResize';\nexport * from './useSignals';\nexport * from './useTimeout';\nexport * from './useTransitions';\n\nexport { useSize, useScroller } from 'mini-virtual-list';\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["useEffect", "useAsyncEffect", "cb", "deps", "useEffect", "controller", "AbortController", "cleanup", "t", "setTimeout", "signal", "aborted", "clearTimeout", "abort", "useEffect", "useState", "useAsyncState", "cb", "deps", "value", "setValue", "useState", "useEffect", "disposed", "t", "setTimeout", "data", "clearTimeout", "useEffect", "useState", "useControlledState", "controlledValue", "onChange", "deps", "value", "setValue", "useState", "useEffect", "undefined", "useEffect", "useRef", "useDebugDeps", "deps", "active", "lastDeps", "useRef", "useEffect", "console", "group", "previous", "current", "length", "i", "Math", "max", "log", "index", "groupEnd", "useEffect", "useMemo", "useState", "useDefaultValue", "reactiveValue", "getDefaultValue", "stableDefaultValue", "useMemo", "value", "setValue", "useState", "useEffect", "defaultsDeep", "useMemo", "useDefaults", "value", "defaults", "useMemo", "defaultsDeep", "useCallback", "useEffect", "useRef", "useState", "useStateWithRef", "valueParam", "value", "setValue", "useState", "valueRef", "useRef", "setter", "useCallback", "current", "useDynamicRef", "useEffect", "useMemo", "useFileDownload", "useMemo", "data", "filename", "url", "URL", "createObjectURL", "element", "document", "createElement", "setAttribute", "click", "useEffect", "useRef", "useForwardedRef", "ref", "innerRef", "useRef", "useEffect", "updateRef", "current", "value", "alea", "useMemo", "Alea", "alea", "prng", "randomString", "n", "toString", "slice", "useId", "namespace", "propsId", "opts", "useMemo", "makeId", "useEffect", "useRef", "useState", "useIsFocused", "inputRef", "isFocused", "setIsFocused", "useState", "undefined", "isFocusedRef", "useRef", "current", "useEffect", "input", "onFocus", "onBlur", "addEventListener", "document", "activeElement", "removeEventListener", "useEffect", "useState", "breakpointMediaQueries", "sm", "md", "lg", "xl", "useMediaQuery", "query", "options", "ssr", "fallback", "queries", "Array", "isArray", "map", "fallbackValues", "filter", "v", "value", "setValue", "useState", "index", "media", "matches", "document", "defaultView", "matchMedia", "useEffect", "mql", "handler", "evt", "prev", "slice", "item", "forEach", "addListener", "addEventListener", "removeListener", "removeEventListener", "useMemo", "useSyncExternalStore", "useMulticastObservable", "observable", "subscribeFn", "useMemo", "listener", "subscription", "subscribe", "unsubscribe", "useSyncExternalStore", "get", "useState", "useRefCallback", "value", "setValue", "useState", "refCallback", "useLayoutEffect", "useMemo", "useViewportResize", "handler", "deps", "delay", "debouncedHandler", "useMemo", "timeout", "event", "clearTimeout", "setTimeout", "useLayoutEffect", "window", "visualViewport", "addEventListener", "removeEventListener", "computed", "effect", "useRef", "useEffect", "useMemo", "useSignalsEffect", "cb", "deps", "callback", "useRef", "current", "useEffect", "effect", "useSignalsMemo", "useMemo", "computed", "value", "useEffect", "useRef", "useTimeout", "callback", "delay", "deps", "callbackRef", "useRef", "useEffect", "current", "t", "setTimeout", "clearTimeout", "useInterval", "i", "setInterval", "result", "clearInterval", "useEffect", "useRef", "useState", "isFunction", "functionToCheck", "Function", "useDidTransition", "currentValue", "fromValue", "toValue", "hasTransitioned", "setHasTransitioned", "useState", "previousValue", "useRef", "useEffect", "toValueValid", "fromValueValid", "current", "useOnTransition", "callback", "dirty", "useSize", "useScroller"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/useAsyncEffect.ts":{"bytes":2988,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useAsyncState.ts":{"bytes":2577,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useControlledState.ts":{"bytes":
|
|
1
|
+
{"inputs":{"src/useAsyncEffect.ts":{"bytes":2988,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useAsyncState.ts":{"bytes":2577,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useControlledState.ts":{"bytes":2579,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useDebugDeps.ts":{"bytes":3142,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useDefaultValue.ts":{"bytes":4033,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useDefaults.ts":{"bytes":1591,"imports":[{"path":"lodash.defaultsdeep","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useDynamicRef.ts":{"bytes":3760,"imports":[{"path":"@preact-signals/safe-react/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useFileDownload.ts":{"bytes":2671,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useForwardedRef.ts":{"bytes":2278,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useId.ts":{"bytes":2466,"imports":[{"path":"alea","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useIsFocused.ts":{"bytes":3921,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useMediaQuery.ts":{"bytes":9254,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useMulticastObservable.ts":{"bytes":2972,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useRefCallback.ts":{"bytes":1818,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useViewportResize.ts":{"bytes":2878,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useSignals.ts":{"bytes":2923,"imports":[{"path":"@preact-signals/safe-react/tracking","kind":"import-statement","external":true},{"path":"@preact-signals/safe-react","kind":"import-statement","external":true},{"path":"@preact-signals/safe-react/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useTimeout.ts":{"bytes":3956,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/useTransitions.ts":{"bytes":7863,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":2454,"imports":[{"path":"src/useAsyncEffect.ts","kind":"import-statement","original":"./useAsyncEffect"},{"path":"src/useAsyncState.ts","kind":"import-statement","original":"./useAsyncState"},{"path":"src/useControlledState.ts","kind":"import-statement","original":"./useControlledState"},{"path":"src/useDebugDeps.ts","kind":"import-statement","original":"./useDebugDeps"},{"path":"src/useDefaultValue.ts","kind":"import-statement","original":"./useDefaultValue"},{"path":"src/useDefaults.ts","kind":"import-statement","original":"./useDefaults"},{"path":"src/useDynamicRef.ts","kind":"import-statement","original":"./useDynamicRef"},{"path":"src/useFileDownload.ts","kind":"import-statement","original":"./useFileDownload"},{"path":"src/useForwardedRef.ts","kind":"import-statement","original":"./useForwardedRef"},{"path":"src/useId.ts","kind":"import-statement","original":"./useId"},{"path":"src/useIsFocused.ts","kind":"import-statement","original":"./useIsFocused"},{"path":"src/useMediaQuery.ts","kind":"import-statement","original":"./useMediaQuery"},{"path":"src/useMulticastObservable.ts","kind":"import-statement","original":"./useMulticastObservable"},{"path":"src/useRefCallback.ts","kind":"import-statement","original":"./useRefCallback"},{"path":"src/useViewportResize.ts","kind":"import-statement","original":"./useViewportResize"},{"path":"src/useSignals.ts","kind":"import-statement","original":"./useSignals"},{"path":"src/useTimeout.ts","kind":"import-statement","original":"./useTimeout"},{"path":"src/useTransitions.ts","kind":"import-statement","original":"./useTransitions"},{"path":"mini-virtual-list","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":32524},"dist/lib/browser/index.mjs":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"lodash.defaultsdeep","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@preact-signals/safe-react/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"alea","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@preact-signals/safe-react/tracking","kind":"import-statement","external":true},{"path":"@preact-signals/safe-react","kind":"import-statement","external":true},{"path":"@preact-signals/safe-react/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"mini-virtual-list","kind":"import-statement","external":true}],"exports":["makeId","randomString","updateRef","useAsyncEffect","useAsyncState","useControlledState","useDebugDeps","useDefaultValue","useDefaults","useDidTransition","useDynamicRef","useFileDownload","useForwardedRef","useId","useInterval","useIsFocused","useMediaQuery","useMulticastObservable","useOnTransition","useRefCallback","useScroller","useSignalsEffect","useSignalsMemo","useSize","useStateWithRef","useTimeout","useViewportResize"],"entryPoint":"src/index.ts","inputs":{"src/useAsyncEffect.ts":{"bytesInOutput":405},"src/index.ts":{"bytesInOutput":58},"src/useAsyncState.ts":{"bytesInOutput":447},"src/useControlledState.ts":{"bytesInOutput":463},"src/useDebugDeps.ts":{"bytesInOutput":631},"src/useDefaultValue.ts":{"bytesInOutput":422},"src/useDefaults.ts":{"bytesInOutput":228},"src/useDynamicRef.ts":{"bytesInOutput":791},"src/useFileDownload.ts":{"bytesInOutput":416},"src/useForwardedRef.ts":{"bytesInOutput":395},"src/useId.ts":{"bytesInOutput":403},"src/useIsFocused.ts":{"bytesInOutput":833},"src/useMediaQuery.ts":{"bytesInOutput":1941},"src/useMulticastObservable.ts":{"bytesInOutput":368},"src/useRefCallback.ts":{"bytesInOutput":197},"src/useViewportResize.ts":{"bytesInOutput":627},"src/useSignals.ts":{"bytesInOutput":664},"src/useTimeout.ts":{"bytesInOutput":946},"src/useTransitions.ts":{"bytesInOutput":1406}},"bytes":12621}}}
|
|
@@ -68,7 +68,7 @@ var useControlledState = (controlledValue, onChange, ...deps) => {
|
|
|
68
68
|
|
|
69
69
|
// src/useDebugDeps.ts
|
|
70
70
|
import { useEffect as useEffect4, useRef } from "react";
|
|
71
|
-
var useDebugDeps = (deps = []) => {
|
|
71
|
+
var useDebugDeps = (deps = [], active = true) => {
|
|
72
72
|
const lastDeps = useRef([]);
|
|
73
73
|
useEffect4(() => {
|
|
74
74
|
console.group("deps changed", {
|
|
@@ -76,7 +76,7 @@ var useDebugDeps = (deps = []) => {
|
|
|
76
76
|
current: deps.length
|
|
77
77
|
});
|
|
78
78
|
for (let i = 0; i < Math.max(lastDeps.current.length ?? 0, deps.length ?? 0); i++) {
|
|
79
|
-
if (lastDeps.current[i] !== deps[i]) {
|
|
79
|
+
if (lastDeps.current[i] !== deps[i] && active) {
|
|
80
80
|
console.log("changed", {
|
|
81
81
|
index: i,
|
|
82
82
|
previous: lastDeps.current[i],
|
|
@@ -116,9 +116,9 @@ var useDefaults = (value, defaults) => {
|
|
|
116
116
|
// src/useDynamicRef.ts
|
|
117
117
|
import { useCallback } from "@preact-signals/safe-react/react";
|
|
118
118
|
import { useEffect as useEffect6, useRef as useRef2, useState as useState4 } from "react";
|
|
119
|
-
var useStateWithRef = (
|
|
120
|
-
const [value, setValue] = useState4(
|
|
121
|
-
const valueRef = useRef2(
|
|
119
|
+
var useStateWithRef = (valueParam) => {
|
|
120
|
+
const [value, setValue] = useState4(valueParam);
|
|
121
|
+
const valueRef = useRef2(valueParam);
|
|
122
122
|
const setter = useCallback((value2) => {
|
|
123
123
|
if (typeof value2 === "function") {
|
|
124
124
|
setValue((current) => {
|
|
@@ -164,17 +164,22 @@ import { useEffect as useEffect7, useRef as useRef3 } from "react";
|
|
|
164
164
|
var useForwardedRef = (ref) => {
|
|
165
165
|
const innerRef = useRef3(null);
|
|
166
166
|
useEffect7(() => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
ref(innerRef.current);
|
|
172
|
-
} else {
|
|
173
|
-
ref.current = innerRef.current;
|
|
174
|
-
}
|
|
175
|
-
});
|
|
167
|
+
updateRef(ref, innerRef.current);
|
|
168
|
+
}, [
|
|
169
|
+
ref
|
|
170
|
+
]);
|
|
176
171
|
return innerRef;
|
|
177
172
|
};
|
|
173
|
+
var updateRef = (ref, value) => {
|
|
174
|
+
if (!ref) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (typeof ref === "function") {
|
|
178
|
+
ref(value);
|
|
179
|
+
} else {
|
|
180
|
+
ref.current = value;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
178
183
|
|
|
179
184
|
// src/useId.ts
|
|
180
185
|
import alea from "alea";
|
|
@@ -226,7 +231,7 @@ var breakpointMediaQueries = {
|
|
|
226
231
|
"2xl": "(min-width: 1536px)"
|
|
227
232
|
};
|
|
228
233
|
var useMediaQuery = (query, options = {}) => {
|
|
229
|
-
const { ssr =
|
|
234
|
+
const { ssr = false, fallback } = options;
|
|
230
235
|
const queries = (Array.isArray(query) ? query : [
|
|
231
236
|
query
|
|
232
237
|
]).map((query2) => query2 in breakpointMediaQueries ? breakpointMediaQueries[query2] : query2);
|
|
@@ -303,9 +308,9 @@ var useRefCallback = () => {
|
|
|
303
308
|
};
|
|
304
309
|
};
|
|
305
310
|
|
|
306
|
-
// src/
|
|
311
|
+
// src/useViewportResize.ts
|
|
307
312
|
import { useLayoutEffect, useMemo as useMemo6 } from "react";
|
|
308
|
-
var
|
|
313
|
+
var useViewportResize = (handler, deps = [], delay = 800) => {
|
|
309
314
|
const debouncedHandler = useMemo6(() => {
|
|
310
315
|
let timeout;
|
|
311
316
|
return (event) => {
|
|
@@ -395,47 +400,15 @@ var useInterval = (callback, delay = 0, deps = []) => {
|
|
|
395
400
|
]);
|
|
396
401
|
};
|
|
397
402
|
|
|
398
|
-
// src/useTrackProps.ts
|
|
399
|
-
import { useEffect as useEffect12, useRef as useRef7 } from "react";
|
|
400
|
-
import { log } from "@dxos/log";
|
|
401
|
-
var __dxlog_file = "/__w/dxos/dxos/packages/ui/primitives/react-hooks/src/useTrackProps.ts";
|
|
402
|
-
var useTrackProps = (props, componentName = "Component", active = true) => {
|
|
403
|
-
const prevProps = useRef7(props);
|
|
404
|
-
useEffect12(() => {
|
|
405
|
-
const changes = Object.entries(props).filter(([key]) => props[key] !== prevProps.current[key]);
|
|
406
|
-
if (changes.length > 0) {
|
|
407
|
-
if (active) {
|
|
408
|
-
log.info("props changed", {
|
|
409
|
-
componentName,
|
|
410
|
-
keys: changes.map(([key]) => key).join(","),
|
|
411
|
-
props: Object.fromEntries(changes.map(([key]) => [
|
|
412
|
-
key,
|
|
413
|
-
{
|
|
414
|
-
from: prevProps.current[key],
|
|
415
|
-
to: props[key]
|
|
416
|
-
}
|
|
417
|
-
]))
|
|
418
|
-
}, {
|
|
419
|
-
F: __dxlog_file,
|
|
420
|
-
L: 22,
|
|
421
|
-
S: void 0,
|
|
422
|
-
C: (f, a) => f(...a)
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
prevProps.current = props;
|
|
427
|
-
});
|
|
428
|
-
};
|
|
429
|
-
|
|
430
403
|
// src/useTransitions.ts
|
|
431
|
-
import { useEffect as
|
|
404
|
+
import { useEffect as useEffect12, useRef as useRef7, useState as useState8 } from "react";
|
|
432
405
|
var isFunction = (functionToCheck) => {
|
|
433
406
|
return functionToCheck instanceof Function;
|
|
434
407
|
};
|
|
435
408
|
var useDidTransition = (currentValue, fromValue, toValue) => {
|
|
436
409
|
const [hasTransitioned, setHasTransitioned] = useState8(false);
|
|
437
|
-
const previousValue =
|
|
438
|
-
|
|
410
|
+
const previousValue = useRef7(currentValue);
|
|
411
|
+
useEffect12(() => {
|
|
439
412
|
const toValueValid = isFunction(toValue) ? toValue(currentValue) : toValue === currentValue;
|
|
440
413
|
const fromValueValid = isFunction(fromValue) ? fromValue(previousValue.current) : fromValue === previousValue.current;
|
|
441
414
|
if (fromValueValid && toValueValid && !hasTransitioned) {
|
|
@@ -453,15 +426,15 @@ var useDidTransition = (currentValue, fromValue, toValue) => {
|
|
|
453
426
|
return hasTransitioned;
|
|
454
427
|
};
|
|
455
428
|
var useOnTransition = (currentValue, fromValue, toValue, callback) => {
|
|
456
|
-
const dirty =
|
|
429
|
+
const dirty = useRef7(false);
|
|
457
430
|
const hasTransitioned = useDidTransition(currentValue, fromValue, toValue);
|
|
458
|
-
|
|
431
|
+
useEffect12(() => {
|
|
459
432
|
dirty.current = false;
|
|
460
433
|
}, [
|
|
461
434
|
currentValue,
|
|
462
435
|
dirty
|
|
463
436
|
]);
|
|
464
|
-
|
|
437
|
+
useEffect12(() => {
|
|
465
438
|
if (hasTransitioned && !dirty.current) {
|
|
466
439
|
callback();
|
|
467
440
|
dirty.current = true;
|
|
@@ -472,9 +445,13 @@ var useOnTransition = (currentValue, fromValue, toValue, callback) => {
|
|
|
472
445
|
callback
|
|
473
446
|
]);
|
|
474
447
|
};
|
|
448
|
+
|
|
449
|
+
// src/index.ts
|
|
450
|
+
import { useSize, useScroller } from "mini-virtual-list";
|
|
475
451
|
export {
|
|
476
452
|
makeId,
|
|
477
453
|
randomString,
|
|
454
|
+
updateRef,
|
|
478
455
|
useAsyncEffect,
|
|
479
456
|
useAsyncState,
|
|
480
457
|
useControlledState,
|
|
@@ -492,11 +469,12 @@ export {
|
|
|
492
469
|
useMulticastObservable,
|
|
493
470
|
useOnTransition,
|
|
494
471
|
useRefCallback,
|
|
495
|
-
|
|
472
|
+
useScroller,
|
|
496
473
|
useSignalsEffect,
|
|
497
474
|
useSignalsMemo,
|
|
475
|
+
useSize,
|
|
498
476
|
useStateWithRef,
|
|
499
477
|
useTimeout,
|
|
500
|
-
|
|
478
|
+
useViewportResize
|
|
501
479
|
};
|
|
502
480
|
//# sourceMappingURL=index.mjs.map
|