@vibehooks/react 0.0.1

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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -0
  3. package/dist/index.d.ts +54 -0
  4. package/dist/index.js +55 -0
  5. package/dist/useAsyncState.d.ts +52 -0
  6. package/dist/useAsyncState.js +173 -0
  7. package/dist/useAudio.d.ts +26 -0
  8. package/dist/useAudio.js +64 -0
  9. package/dist/useAutoScroll.d.ts +47 -0
  10. package/dist/useAutoScroll.js +122 -0
  11. package/dist/useBarcode.d.ts +77 -0
  12. package/dist/useBarcode.js +140 -0
  13. package/dist/useBatteryStatus.d.ts +53 -0
  14. package/dist/useBatteryStatus.js +67 -0
  15. package/dist/useBodyScrollFreeze.d.ts +36 -0
  16. package/dist/useBodyScrollFreeze.js +74 -0
  17. package/dist/useCameraCapture.d.ts +76 -0
  18. package/dist/useCameraCapture.js +116 -0
  19. package/dist/useCookies.d.ts +42 -0
  20. package/dist/useCookies.js +61 -0
  21. package/dist/useCopyToClipboard.d.ts +22 -0
  22. package/dist/useCopyToClipboard.js +31 -0
  23. package/dist/useCountDown.d.ts +80 -0
  24. package/dist/useCountDown.js +106 -0
  25. package/dist/useDebouncedState.d.ts +47 -0
  26. package/dist/useDebouncedState.js +47 -0
  27. package/dist/useExternalNotifications.d.ts +36 -0
  28. package/dist/useExternalNotifications.js +100 -0
  29. package/dist/useFile.d.ts +74 -0
  30. package/dist/useFile.js +74 -0
  31. package/dist/useFullScreen.d.ts +20 -0
  32. package/dist/useFullScreen.js +43 -0
  33. package/dist/useGeolocation.d.ts +47 -0
  34. package/dist/useGeolocation.js +68 -0
  35. package/dist/useHoverIntent.d.ts +45 -0
  36. package/dist/useHoverIntent.js +81 -0
  37. package/dist/useIdle.d.ts +47 -0
  38. package/dist/useIdle.js +59 -0
  39. package/dist/useIndexedDB.d.ts +60 -0
  40. package/dist/useIndexedDB.js +75 -0
  41. package/dist/useIntersectionObserver.d.ts +45 -0
  42. package/dist/useIntersectionObserver.js +70 -0
  43. package/dist/useIntervalSafe.d.ts +72 -0
  44. package/dist/useIntervalSafe.js +85 -0
  45. package/dist/useIsClient.d.ts +12 -0
  46. package/dist/useIsClient.js +21 -0
  47. package/dist/useIsDesktop.d.ts +12 -0
  48. package/dist/useIsDesktop.js +23 -0
  49. package/dist/useIsFirstRender.d.ts +12 -0
  50. package/dist/useIsFirstRender.js +21 -0
  51. package/dist/useList.d.ts +19 -0
  52. package/dist/useList.js +44 -0
  53. package/dist/useLocalNotifications.d.ts +23 -0
  54. package/dist/useLocalNotifications.js +50 -0
  55. package/dist/useLocalStorage.d.ts +45 -0
  56. package/dist/useLocalStorage.js +71 -0
  57. package/dist/useNetworkInformation.d.ts +138 -0
  58. package/dist/useNetworkInformation.js +76 -0
  59. package/dist/useOnline.d.ts +17 -0
  60. package/dist/useOnline.js +29 -0
  61. package/dist/usePageVisibility.d.ts +32 -0
  62. package/dist/usePageVisibility.js +65 -0
  63. package/dist/usePermissions.d.ts +28 -0
  64. package/dist/usePermissions.js +70 -0
  65. package/dist/usePictureInPicture.d.ts +47 -0
  66. package/dist/usePictureInPicture.js +60 -0
  67. package/dist/usePopover.d.ts +54 -0
  68. package/dist/usePopover.js +67 -0
  69. package/dist/usePreferredLanguage.d.ts +55 -0
  70. package/dist/usePreferredLanguage.js +127 -0
  71. package/dist/usePreferredTheme.d.ts +67 -0
  72. package/dist/usePreferredTheme.js +133 -0
  73. package/dist/usePreviousDistinct.d.ts +12 -0
  74. package/dist/usePreviousDistinct.js +23 -0
  75. package/dist/useResettableState.d.ts +15 -0
  76. package/dist/useResettableState.js +25 -0
  77. package/dist/useScreenOrientation.d.ts +48 -0
  78. package/dist/useScreenOrientation.js +51 -0
  79. package/dist/useScreenSize.d.ts +16 -0
  80. package/dist/useScreenSize.js +34 -0
  81. package/dist/useScreenWakeLock.d.ts +37 -0
  82. package/dist/useScreenWakeLock.js +48 -0
  83. package/dist/useServerSentEvent.d.ts +57 -0
  84. package/dist/useServerSentEvent.js +78 -0
  85. package/dist/useShoppingCart.d.ts +54 -0
  86. package/dist/useShoppingCart.js +122 -0
  87. package/dist/useSmartVideo.d.ts +35 -0
  88. package/dist/useSmartVideo.js +76 -0
  89. package/dist/useSpeech.d.ts +74 -0
  90. package/dist/useSpeech.js +156 -0
  91. package/dist/useSummarizer.d.ts +92 -0
  92. package/dist/useSummarizer.js +83 -0
  93. package/dist/useTaskQueue.d.ts +25 -0
  94. package/dist/useTaskQueue.js +51 -0
  95. package/dist/useThrottledCallback.d.ts +32 -0
  96. package/dist/useThrottledCallback.js +42 -0
  97. package/dist/useTimeout.d.ts +58 -0
  98. package/dist/useTimeout.js +70 -0
  99. package/dist/useToggle.d.ts +30 -0
  100. package/dist/useToggle.js +23 -0
  101. package/dist/useTraceUpdates.d.ts +22 -0
  102. package/dist/useTraceUpdates.js +38 -0
  103. package/dist/useTranslator.d.ts +110 -0
  104. package/dist/useTranslator.js +119 -0
  105. package/dist/useUserActivation.d.ts +40 -0
  106. package/dist/useUserActivation.js +63 -0
  107. package/dist/useVibration.d.ts +55 -0
  108. package/dist/useVibration.js +50 -0
  109. package/dist/useWebsocket.d.ts +80 -0
  110. package/dist/useWebsocket.js +125 -0
  111. package/package.json +70 -0
@@ -0,0 +1,92 @@
1
+ //#region src/useSummarizer.d.ts
2
+ type SummarizerAvailability = 'available' | 'unavailable' | 'downloadable';
3
+ type SummarizerType = 'tldr' | 'key-points' | 'headline' | 'paragraph';
4
+ type SummarizerFormat = 'plain-text' | 'markdown';
5
+ type SummarizerLength = 'short' | 'medium' | 'long';
6
+ interface SummarizerCreateOptions {
7
+ format?: SummarizerFormat;
8
+ inputLanguage?: string;
9
+ length?: SummarizerLength;
10
+ outputLanguage?: string;
11
+ signal?: AbortSignal;
12
+ type?: SummarizerType;
13
+ }
14
+ interface BrowserSummarizer {
15
+ destroy(): void;
16
+ summarize(text: string, options?: {
17
+ signal?: AbortSignal;
18
+ }): Promise<string>;
19
+ }
20
+ interface SummarizerStatic {
21
+ availability(options?: SummarizerCreateOptions): Promise<SummarizerAvailability>;
22
+ create(options?: SummarizerCreateOptions): Promise<BrowserSummarizer>;
23
+ }
24
+ declare global {
25
+ interface Window {
26
+ Summarizer: SummarizerStatic;
27
+ }
28
+ }
29
+ interface UseSummarizerReturn {
30
+ /**
31
+ * Cancels any pending create or summarize operation.
32
+ */
33
+ cancel(): void;
34
+ /**
35
+ * Checks whether the browser AI model can satisfy the given options.
36
+ */
37
+ checkAvailability(options?: SummarizerCreateOptions): Promise<SummarizerAvailability>;
38
+ /**
39
+ * Creates a Summarizer instance with the given options.
40
+ * Requires recent user interaction to be triggered.
41
+ */
42
+ create(options?: SummarizerCreateOptions): Promise<void>;
43
+ /**
44
+ * Destroys the active Summarizer instance.
45
+ */
46
+ destroy(): void;
47
+ /**
48
+ * Checks if the provided error is an AbortError.
49
+ */
50
+ isAbortError(error: unknown): boolean;
51
+ /**
52
+ * Indicates whether the Summarizer API exists in the current environment.
53
+ */
54
+ isSupported: boolean;
55
+ /**
56
+ * Runs a sumamrization request using the active Summarizer instance.
57
+ */
58
+ summarize(text: string): Promise<string>;
59
+ }
60
+ /**
61
+ * `useSummarizer` is React hook that provides low-level access to the browser Summarizer API.
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * const {
66
+ * isSupported,
67
+ * checkAvailability,
68
+ * create,
69
+ * summarize,
70
+ * destroy,
71
+ * } = useSummarizer();
72
+ *
73
+ * const run = async () => {
74
+ * const availability = await checkAvailability({
75
+ * type: 'tldr',
76
+ * format: 'markdown',
77
+ * });
78
+ *
79
+ * if (availability !== 'available') return;
80
+ *
81
+ * await create({ type: 'tldr' });
82
+ * const summary = await summarize(longText);
83
+ *
84
+ * console.log(summary);
85
+ * destroy();
86
+ * };
87
+ * ```
88
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Summarizer_API
89
+ */
90
+ declare function useSummarizer(): UseSummarizerReturn;
91
+ //#endregion
92
+ export { useSummarizer };
@@ -0,0 +1,83 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useSummarizer.ts
4
+ function isAbortError(error) {
5
+ return error instanceof DOMException && error.name === "AbortError";
6
+ }
7
+ /**
8
+ * `useSummarizer` is React hook that provides low-level access to the browser Summarizer API.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * const {
13
+ * isSupported,
14
+ * checkAvailability,
15
+ * create,
16
+ * summarize,
17
+ * destroy,
18
+ * } = useSummarizer();
19
+ *
20
+ * const run = async () => {
21
+ * const availability = await checkAvailability({
22
+ * type: 'tldr',
23
+ * format: 'markdown',
24
+ * });
25
+ *
26
+ * if (availability !== 'available') return;
27
+ *
28
+ * await create({ type: 'tldr' });
29
+ * const summary = await summarize(longText);
30
+ *
31
+ * console.log(summary);
32
+ * destroy();
33
+ * };
34
+ * ```
35
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Summarizer_API
36
+ */
37
+ function useSummarizer() {
38
+ const summarizerRef = React.useRef(null);
39
+ const abortRef = React.useRef(null);
40
+ const isSupported = typeof window !== "undefined" && typeof window.Summarizer !== "undefined";
41
+ const checkAvailability = React.useCallback(async (options) => {
42
+ if (!isSupported) return "unavailable";
43
+ return window.Summarizer.availability(options);
44
+ }, [isSupported]);
45
+ const create = React.useCallback(async (options) => {
46
+ if (!isSupported) throw new Error("Summarizer API not supported.");
47
+ abortRef.current?.abort();
48
+ abortRef.current = new AbortController();
49
+ summarizerRef.current = await window.Summarizer.create({ ...options });
50
+ }, [isSupported]);
51
+ const summarize = React.useCallback(async (text) => {
52
+ if (!summarizerRef.current) throw new Error("Summarizer instance not created.");
53
+ if (!abortRef.current) abortRef.current = new AbortController();
54
+ try {
55
+ return await summarizerRef.current.summarize(text, { signal: abortRef.current.signal });
56
+ } catch (err) {
57
+ if (isAbortError(err)) return Promise.reject(err);
58
+ throw err;
59
+ }
60
+ }, []);
61
+ const cancel = React.useCallback(() => {
62
+ if (abortRef.current) {
63
+ abortRef.current?.abort();
64
+ abortRef.current = null;
65
+ }
66
+ }, []);
67
+ return {
68
+ cancel,
69
+ checkAvailability,
70
+ create,
71
+ destroy: React.useCallback(() => {
72
+ summarizerRef.current?.destroy();
73
+ summarizerRef.current = null;
74
+ cancel();
75
+ }, [cancel]),
76
+ isAbortError,
77
+ isSupported,
78
+ summarize
79
+ };
80
+ }
81
+
82
+ //#endregion
83
+ export { useSummarizer };
@@ -0,0 +1,25 @@
1
+ //#region src/useTaskQueue.d.ts
2
+ interface Task<T = unknown> {
3
+ id: string;
4
+ run: () => Promise<T>;
5
+ }
6
+ interface UseTaskQueueReturn<T = unknown> {
7
+ enqueue: (task: Task<T>) => void;
8
+ queue: Task<T>[];
9
+ running: boolean;
10
+ }
11
+ /**
12
+ * `useTaskQueue` is a React hook that manages a queue of async tasks with concurrency control.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * const { enqueue, running, queue } = useTaskQueue();
17
+ *
18
+ * React.useEffect(() => {
19
+ * enqueue({ id: 'task1', run: async () => console.log('Task 1') });
20
+ * }, []);
21
+ * ```
22
+ */
23
+ declare function useTaskQueue<T = unknown>(): UseTaskQueueReturn<T>;
24
+ //#endregion
25
+ export { useTaskQueue };
@@ -0,0 +1,51 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useTaskQueue.ts
4
+ /**
5
+ * `useTaskQueue` is a React hook that manages a queue of async tasks with concurrency control.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const { enqueue, running, queue } = useTaskQueue();
10
+ *
11
+ * React.useEffect(() => {
12
+ * enqueue({ id: 'task1', run: async () => console.log('Task 1') });
13
+ * }, []);
14
+ * ```
15
+ */
16
+ function useTaskQueue() {
17
+ const [queue, setQueue] = React.useState([]);
18
+ const [running, setRunning] = React.useState(false);
19
+ const isProcessingRef = React.useRef(false);
20
+ React.useEffect(() => {
21
+ if (queue.length === 0) {
22
+ setRunning(false);
23
+ return;
24
+ }
25
+ if (isProcessingRef.current) return;
26
+ isProcessingRef.current = true;
27
+ const task = queue[0];
28
+ setRunning(true);
29
+ const run = async () => {
30
+ try {
31
+ await task?.run();
32
+ } catch (error) {
33
+ console.error(error);
34
+ } finally {
35
+ isProcessingRef.current = false;
36
+ setQueue((prev) => prev.slice(1));
37
+ }
38
+ };
39
+ run();
40
+ }, [queue]);
41
+ return {
42
+ enqueue: React.useCallback((task) => {
43
+ setQueue((prev) => [...prev, task]);
44
+ }, []),
45
+ queue,
46
+ running
47
+ };
48
+ }
49
+
50
+ //#endregion
51
+ export { useTaskQueue };
@@ -0,0 +1,32 @@
1
+ //#region src/useThrottledCallback.d.ts
2
+ interface UseThrottledCallbackOptions {
3
+ /**
4
+ * Minimum time in milliseconds between callback executions.
5
+ */
6
+ delay: number;
7
+ }
8
+ type ThrottledCallbackReturn<TArgs extends readonly unknown[]> = (...args: TArgs) => void;
9
+ /**
10
+ * `useThrottledCallback` is a React hook that returns a throttled version of a callback.
11
+ * The throttled callback will execute at most once every `delay` milliseconds, regardless of how many times it is invoked.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * * const onScroll = useThrottledCallback(
16
+ * (y: number) => {
17
+ * console.log(y);
18
+ * },
19
+ * { delay: 200 }
20
+ * );
21
+ *
22
+ * React.useEffect(() => {
23
+ * const handler = () => onScroll(window.scrollY);
24
+ * window.addEventListener('scroll', handler);
25
+ *
26
+ * return () => window.removeEventListener('scroll', handler);
27
+ * }, [onScroll]);
28
+ * ```
29
+ */
30
+ declare function useThrottledCallback<TArgs extends readonly unknown[]>(callback: (...args: TArgs) => void, options: UseThrottledCallbackOptions): ThrottledCallbackReturn<TArgs>;
31
+ //#endregion
32
+ export { useThrottledCallback };
@@ -0,0 +1,42 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useThrottledCallback.ts
4
+ /**
5
+ * `useThrottledCallback` is a React hook that returns a throttled version of a callback.
6
+ * The throttled callback will execute at most once every `delay` milliseconds, regardless of how many times it is invoked.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * * const onScroll = useThrottledCallback(
11
+ * (y: number) => {
12
+ * console.log(y);
13
+ * },
14
+ * { delay: 200 }
15
+ * );
16
+ *
17
+ * React.useEffect(() => {
18
+ * const handler = () => onScroll(window.scrollY);
19
+ * window.addEventListener('scroll', handler);
20
+ *
21
+ * return () => window.removeEventListener('scroll', handler);
22
+ * }, [onScroll]);
23
+ * ```
24
+ */
25
+ function useThrottledCallback(callback, options) {
26
+ const { delay } = options;
27
+ const lastCallRef = React.useRef(0);
28
+ const callbackRef = React.useRef(callback);
29
+ React.useEffect(() => {
30
+ callbackRef.current = callback;
31
+ }, [callback]);
32
+ return React.useCallback((...args) => {
33
+ const now = Date.now();
34
+ if (now - lastCallRef.current >= delay) {
35
+ lastCallRef.current = now;
36
+ callbackRef.current(...args);
37
+ }
38
+ }, [delay]);
39
+ }
40
+
41
+ //#endregion
42
+ export { useThrottledCallback };
@@ -0,0 +1,58 @@
1
+ //#region src/useTimeout.d.ts
2
+ interface UseTimeoutOptions {
3
+ /**
4
+ * Delay in milliseconds before the callback is executed.
5
+ * If null or undefined, the timeout won't be set.
6
+ */
7
+ delay: number | null;
8
+ /**
9
+ * Whether the timeout should start immediately on mount.
10
+ * @default true
11
+ */
12
+ startOnMount?: boolean;
13
+ }
14
+ interface UseTimeoutReturn {
15
+ /**
16
+ * Cancel the pending timeout.
17
+ */
18
+ cancel: () => void;
19
+ /**
20
+ * Whether the timeout is currently active.
21
+ */
22
+ isActive: boolean;
23
+ /**
24
+ * Reset the timeout (cancel and start again).
25
+ */
26
+ reset: () => void;
27
+ /**
28
+ * Start or restart the timeout.
29
+ */
30
+ start: () => void;
31
+ }
32
+ /**
33
+ * `useTimeout` is a custom hook for managing timeouts in a declarative way. It's sever-safe and unopinionated about when/how to trigger the timeout.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * // Auto-start timeout
38
+ * const timeout = useTimeout(() => {
39
+ * console.log('Executed after 2 seconds');
40
+ * }, { delay: 2000 });
41
+ *
42
+ * // Manual control
43
+ * const timeout = useTimeout(() => {
44
+ * showNotification('Session expired');
45
+ * }, { delay: 5000, startOnMount: false });
46
+ *
47
+ * // Start manually
48
+ * <button onClick={timeout.start}>Start Timer</button>
49
+ * <button onClick={timeout.cancel}>Cancel</button>
50
+ * <button onClick={timeout.reset}>Reset</button>
51
+ * ```
52
+ */
53
+ declare function useTimeout(callback: () => void, {
54
+ delay,
55
+ startOnMount
56
+ }: UseTimeoutOptions): UseTimeoutReturn;
57
+ //#endregion
58
+ export { useTimeout };
@@ -0,0 +1,70 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useTimeout.ts
4
+ /**
5
+ * `useTimeout` is a custom hook for managing timeouts in a declarative way. It's sever-safe and unopinionated about when/how to trigger the timeout.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * // Auto-start timeout
10
+ * const timeout = useTimeout(() => {
11
+ * console.log('Executed after 2 seconds');
12
+ * }, { delay: 2000 });
13
+ *
14
+ * // Manual control
15
+ * const timeout = useTimeout(() => {
16
+ * showNotification('Session expired');
17
+ * }, { delay: 5000, startOnMount: false });
18
+ *
19
+ * // Start manually
20
+ * <button onClick={timeout.start}>Start Timer</button>
21
+ * <button onClick={timeout.cancel}>Cancel</button>
22
+ * <button onClick={timeout.reset}>Reset</button>
23
+ * ```
24
+ */
25
+ function useTimeout(callback, { delay, startOnMount = true }) {
26
+ const timeoutRef = React.useRef(null);
27
+ const callbackRef = React.useRef(callback);
28
+ const [isActive, setIsActive] = React.useState(false);
29
+ React.useEffect(() => {
30
+ callbackRef.current = callback;
31
+ }, [callback]);
32
+ const cancel = React.useCallback(() => {
33
+ if (timeoutRef.current !== null) {
34
+ clearTimeout(timeoutRef.current);
35
+ timeoutRef.current = null;
36
+ setIsActive(false);
37
+ }
38
+ }, []);
39
+ const start = React.useCallback(() => {
40
+ cancel();
41
+ if (delay === null || delay === void 0) return;
42
+ setIsActive(true);
43
+ timeoutRef.current = setTimeout(() => {
44
+ callbackRef.current();
45
+ timeoutRef.current = null;
46
+ setIsActive(false);
47
+ }, delay);
48
+ }, [delay, cancel]);
49
+ const reset = React.useCallback(() => {
50
+ cancel();
51
+ start();
52
+ }, [cancel, start]);
53
+ React.useEffect(() => {
54
+ if (startOnMount) start();
55
+ return cancel;
56
+ }, [
57
+ startOnMount,
58
+ start,
59
+ cancel
60
+ ]);
61
+ return {
62
+ cancel,
63
+ isActive,
64
+ reset,
65
+ start
66
+ };
67
+ }
68
+
69
+ //#endregion
70
+ export { useTimeout };
@@ -0,0 +1,30 @@
1
+ //#region src/useToggle.d.ts
2
+ interface ToggleOptions {
3
+ /**
4
+ * Default value for the toggle.
5
+ */
6
+ defaultValue?: boolean;
7
+ }
8
+ interface ToggleReturn {
9
+ /**
10
+ * Handles the toggle.
11
+ */
12
+ handleToggle: () => void;
13
+ /**
14
+ * Current status of the toggle.
15
+ */
16
+ status: boolean;
17
+ }
18
+ /**
19
+ * `useToggle` returns a toggle state and a function to toggle the state.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * const { status, handleToggle } = useToggle({ defaultValue: false });
24
+ * ```
25
+ */
26
+ declare function useToggle({
27
+ defaultValue
28
+ }: ToggleOptions): ToggleReturn;
29
+ //#endregion
30
+ export { useToggle };
@@ -0,0 +1,23 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useToggle.ts
4
+ /**
5
+ * `useToggle` returns a toggle state and a function to toggle the state.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const { status, handleToggle } = useToggle({ defaultValue: false });
10
+ * ```
11
+ */
12
+ function useToggle({ defaultValue = false }) {
13
+ const [status, setStatus] = React.useState(defaultValue);
14
+ return {
15
+ handleToggle: React.useCallback(() => {
16
+ return setStatus((prev) => !prev);
17
+ }, []),
18
+ status
19
+ };
20
+ }
21
+
22
+ //#endregion
23
+ export { useToggle };
@@ -0,0 +1,22 @@
1
+ //#region src/useTraceUpdates.d.ts
2
+ /**
3
+ * `useTraceUpdates` is a React hook that logs all updates to the component tree.
4
+ * It is useful for debugging with React DevTools.
5
+ * It is only recommended for development purposes.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * // Trace state changes
10
+ * function Counter() {
11
+ * const [count, setCount] = React.useState(0);
12
+ * const [step, setStep] = React.useState(1);
13
+ *
14
+ * useTraceUpdates({ count }, 'Counter.count');
15
+ *
16
+ * return <button onClick={() => setCount(c => c + step)} />;
17
+ * }
18
+ * ```
19
+ */
20
+ declare function useTraceUpdates(value: Record<string, unknown>, name?: string): void;
21
+ //#endregion
22
+ export { useTraceUpdates };
@@ -0,0 +1,38 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useTraceUpdates.ts
4
+ /**
5
+ * `useTraceUpdates` is a React hook that logs all updates to the component tree.
6
+ * It is useful for debugging with React DevTools.
7
+ * It is only recommended for development purposes.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * // Trace state changes
12
+ * function Counter() {
13
+ * const [count, setCount] = React.useState(0);
14
+ * const [step, setStep] = React.useState(1);
15
+ *
16
+ * useTraceUpdates({ count }, 'Counter.count');
17
+ *
18
+ * return <button onClick={() => setCount(c => c + step)} />;
19
+ * }
20
+ * ```
21
+ */
22
+ function useTraceUpdates(value, name) {
23
+ const prev = React.useRef(null);
24
+ React.useEffect(() => {
25
+ if (prev.current) {
26
+ const changes = {};
27
+ for (const key in value) if (prev.current[key] !== value[key]) changes[key] = {
28
+ from: prev.current[key],
29
+ to: value[key]
30
+ };
31
+ if (Object.keys(changes).length > 0) console.log(`[useTraceUpdates] ${name ?? "Component"} changes:`, changes);
32
+ }
33
+ prev.current = value;
34
+ }, [value, name]);
35
+ }
36
+
37
+ //#endregion
38
+ export { useTraceUpdates };
@@ -0,0 +1,110 @@
1
+ //#region src/useTranslator.d.ts
2
+ interface TranslatorConfig {
3
+ sourceLanguage?: BCP47LanguageTag;
4
+ targetLanguage: BCP47LanguageTag;
5
+ }
6
+ type TranslatorAvailability = 'available' | 'unavailable' | 'downloadable';
7
+ interface Translator {
8
+ destroy(): void;
9
+ readonly inputQuota: number;
10
+ measureInputUsage(text: string): Promise<number>;
11
+ readonly sourceLanguage: BCP47LanguageTag;
12
+ readonly targetLanguage: BCP47LanguageTag;
13
+ translate(text: string): Promise<string>;
14
+ translateStreaming(text: string): ReadableStream<string>;
15
+ }
16
+ interface TranslatorConstructor {
17
+ availability(config: TranslatorConfig): Promise<TranslatorAvailability>;
18
+ create(config: TranslatorConfig): Promise<Translator>;
19
+ }
20
+ declare global {
21
+ interface Window {
22
+ Translator?: TranslatorConstructor;
23
+ }
24
+ }
25
+ /**
26
+ * BCP 47 language tag.
27
+ * Examples: "en", "en-US", "es", "es-PE", "fr", "pt-BR"
28
+ */
29
+ type BCP47LanguageTag = string;
30
+ interface TranslatorTranslateOptions {
31
+ /**
32
+ * Optional callback triggered after checking
33
+ * whether the language pair is supported.
34
+ */
35
+ onLanguageSupportCheck?: (supported: boolean) => void;
36
+ /**
37
+ * Source language (BCP 47).
38
+ * If undefined, the browser may attempt auto-detection (if supported).
39
+ */
40
+ sourceLanguage: BCP47LanguageTag;
41
+ /**
42
+ * Target language (BCP 47).
43
+ */
44
+ targetLanguage: BCP47LanguageTag;
45
+ }
46
+ interface UseTranslatorReturn {
47
+ /**
48
+ * Manually checks if the language pair is supported.
49
+ */
50
+ checkLanguageSupport: () => Promise<boolean>;
51
+ /**
52
+ * Last error produced by the hook.
53
+ */
54
+ error: Error | null;
55
+ /**
56
+ * Whether the configured language pair is supported.
57
+ * Null until checked.
58
+ */
59
+ isLanguagePairSupported: boolean | null;
60
+ /**
61
+ * Whether the Translator API is available in the current browser.
62
+ */
63
+ isSupported: boolean;
64
+ /**
65
+ * Indicates whether a translation is in progress.
66
+ */
67
+ isTranslating: boolean;
68
+ /**
69
+ * Translates a given text using the configured languages.
70
+ */
71
+ translate: (text: string) => Promise<string>;
72
+ /**
73
+ * Last translation result.
74
+ */
75
+ translation: string | null;
76
+ }
77
+ /**
78
+ * `useTranslator` is a React custom hook that provides a simple way to translate text using Translator API in Chrome to translate text with AI models provided in the browser.
79
+ *
80
+ * @example
81
+ * ```tsx
82
+ * const {
83
+ * isSupported,
84
+ * translate,
85
+ * checkLanguageSupport,
86
+ * isLanguagePairSupported,
87
+ * isTranslating,
88
+ * translation,
89
+ * error,
90
+ * } = useTranslator({
91
+ * sourceLanguage: "es",
92
+ * targetLanguage: "en-US",
93
+ * onLanguageSupportCheck: (supported) => {
94
+ * console.log("Language pair supported:", supported);
95
+ * },
96
+ * });
97
+ *
98
+ * React.useEffect(() => {
99
+ * checkLanguageSupport();
100
+ * }, [checkLanguageSupport]);
101
+ *
102
+ * const handleTranslate = async () => {
103
+ * await translate("Hola mundo");
104
+ * };
105
+ * ```
106
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Translator
107
+ */
108
+ declare function useTranslator(options: TranslatorTranslateOptions): UseTranslatorReturn;
109
+ //#endregion
110
+ export { useTranslator };