@intlayer/design-system 5.3.13 → 5.4.0
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/.vite/manifest.json +74 -60
- package/dist/components/Button/Button.d.ts +2 -2
- package/dist/components/ClickOutsideDiv/index.cjs +1 -1
- package/dist/components/ClickOutsideDiv/index.cjs.map +1 -1
- package/dist/components/ClickOutsideDiv/index.d.ts +1 -1
- package/dist/components/ClickOutsideDiv/index.d.ts.map +1 -1
- package/dist/components/ClickOutsideDiv/index.mjs +1 -1
- package/dist/components/ClickOutsideDiv/index.mjs.map +1 -1
- package/dist/components/Container/index.d.ts +2 -2
- package/dist/components/DropDown/index.cjs +16 -0
- package/dist/components/DropDown/index.cjs.map +1 -1
- package/dist/components/DropDown/index.d.ts.map +1 -1
- package/dist/components/DropDown/index.mjs +16 -0
- package/dist/components/DropDown/index.mjs.map +1 -1
- package/dist/components/Headers/SectionScroller.cjs +1 -1
- package/dist/components/Headers/SectionScroller.cjs.map +1 -1
- package/dist/components/Headers/SectionScroller.mjs +1 -1
- package/dist/components/Headers/SectionScroller.mjs.map +1 -1
- package/dist/components/HeightResizer/index.cjs +96 -0
- package/dist/components/HeightResizer/index.cjs.map +1 -0
- package/dist/components/HeightResizer/index.d.ts +9 -0
- package/dist/components/HeightResizer/index.d.ts.map +1 -0
- package/dist/components/HeightResizer/index.mjs +96 -0
- package/dist/components/HeightResizer/index.mjs.map +1 -0
- package/dist/components/Input/Checkbox.d.ts +1 -1
- package/dist/components/Link/Link.d.ts +1 -1
- package/dist/components/Navbar/useNavigation.cjs +1 -1
- package/dist/components/Navbar/useNavigation.cjs.map +1 -1
- package/dist/components/Navbar/useNavigation.mjs +1 -1
- package/dist/components/Navbar/useNavigation.mjs.map +1 -1
- package/dist/components/PressableSpan/PressableSpan.cjs.map +1 -1
- package/dist/components/PressableSpan/PressableSpan.d.ts.map +1 -1
- package/dist/components/PressableSpan/PressableSpan.mjs.map +1 -1
- package/dist/components/RightDrawer/RightDrawer.cjs.map +1 -1
- package/dist/components/RightDrawer/RightDrawer.d.ts +1 -1
- package/dist/components/RightDrawer/RightDrawer.d.ts.map +1 -1
- package/dist/components/RightDrawer/RightDrawer.mjs.map +1 -1
- package/dist/components/Tag/index.d.ts +1 -1
- package/dist/components/TextArea/AutoSizeTextArea.cjs +8 -11
- package/dist/components/TextArea/AutoSizeTextArea.cjs.map +1 -1
- package/dist/components/TextArea/AutoSizeTextArea.d.ts.map +1 -1
- package/dist/components/TextArea/AutoSizeTextArea.mjs +9 -12
- package/dist/components/TextArea/AutoSizeTextArea.mjs.map +1 -1
- package/dist/components/WithResizer/index.cjs +2 -2
- package/dist/components/WithResizer/index.cjs.map +1 -1
- package/dist/components/WithResizer/index.d.ts +1 -1
- package/dist/components/WithResizer/index.d.ts.map +1 -1
- package/dist/components/WithResizer/index.mjs +2 -2
- package/dist/components/WithResizer/index.mjs.map +1 -1
- package/dist/components/index.cjs +137 -135
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.ts +37 -36
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.mjs +62 -60
- package/dist/components/index.mjs.map +1 -1
- package/dist/hooks/index.cjs +5 -0
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.mjs +6 -1
- package/dist/hooks/intlayerAPIHooks.cjs +1 -1
- package/dist/hooks/intlayerAPIHooks.cjs.map +1 -1
- package/dist/hooks/intlayerAPIHooks.d.ts +1 -1
- package/dist/hooks/intlayerAPIHooks.d.ts.map +1 -1
- package/dist/hooks/intlayerAPIHooks.mjs +1 -1
- package/dist/hooks/intlayerAPIHooks.mjs.map +1 -1
- package/dist/hooks/useAsync/useAsync.cjs +1 -0
- package/dist/hooks/useAsync/useAsync.cjs.map +1 -1
- package/dist/hooks/useAsync/useAsync.d.ts.map +1 -1
- package/dist/hooks/useAsync/useAsync.mjs +1 -0
- package/dist/hooks/useAsync/useAsync.mjs.map +1 -1
- package/dist/hooks/useDevice.cjs +15 -2
- package/dist/hooks/useDevice.cjs.map +1 -1
- package/dist/hooks/useDevice.d.ts +9 -0
- package/dist/hooks/useDevice.d.ts.map +1 -1
- package/dist/hooks/useDevice.mjs +15 -2
- package/dist/hooks/useDevice.mjs.map +1 -1
- package/dist/hooks/useIntlayerAPI.d.ts +1 -1
- package/dist/hooks/useIntlayerAPI.d.ts.map +1 -1
- package/dist/hooks/useItemSelector.cjs +6 -2
- package/dist/hooks/useItemSelector.cjs.map +1 -1
- package/dist/hooks/useItemSelector.d.ts.map +1 -1
- package/dist/hooks/useItemSelector.mjs +6 -2
- package/dist/hooks/useItemSelector.mjs.map +1 -1
- package/dist/hooks/useKeyboardDetector.cjs +3 -1
- package/dist/hooks/useKeyboardDetector.cjs.map +1 -1
- package/dist/hooks/useKeyboardDetector.d.ts.map +1 -1
- package/dist/hooks/useKeyboardDetector.mjs +3 -1
- package/dist/hooks/useKeyboardDetector.mjs.map +1 -1
- package/dist/hooks/usePersistedStore.cjs +10 -1
- package/dist/hooks/usePersistedStore.cjs.map +1 -1
- package/dist/hooks/usePersistedStore.d.ts +2 -2
- package/dist/hooks/usePersistedStore.d.ts.map +1 -1
- package/dist/hooks/usePersistedStore.mjs +10 -1
- package/dist/hooks/usePersistedStore.mjs.map +1 -1
- package/dist/hooks/useScrollDetection.cjs +4 -2
- package/dist/hooks/useScrollDetection.cjs.map +1 -1
- package/dist/hooks/useScrollDetection.d.ts.map +1 -1
- package/dist/hooks/useScrollDetection.mjs +4 -2
- package/dist/hooks/useScrollDetection.mjs.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +19 -19
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAsync.mjs","sources":["../../../src/hooks/useAsync/useAsync.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef } from 'react';\nimport { useAsyncState } from './useAsyncStateStore';\n\n// Pending promises cache to prevent parallel requests when multiple components use the hook\nconst pendingPromises = new Map();\n\n// Defines the base structure for the result of the custom hook.\ntype UseAsyncResultBase<T extends (...args: any[]) => Promise<any>> = {\n isFetched: boolean;\n isLoading: boolean;\n isInvalidated: boolean;\n isSuccess: boolean;\n isDisabled: boolean;\n isWaitingData: boolean;\n isRevalidating: boolean;\n error: string | null;\n data: Awaited<ReturnType<T>> | null;\n errorCount: number;\n revalidate: T;\n setData: (data: Awaited<ReturnType<T> | null>) => void;\n};\n\n// Options type for the hook, allowing customization of behavior.\nexport type UseAsyncOptions<T extends (...args: any[]) => Promise<any>> = {\n retryLimit?: number; // The number of times the hook should retry the function on failure before giving up\n retryTime?: number; // Time in milliseconds for retrying the data\n cache?: boolean; // Cache the result of the function\n store?: boolean; // Store the result of the function in local storage\n enable?: boolean; // Enable the hook\n autoFetch?: boolean; // Automatically fetch the data when the hook is mounted\n revalidation?: boolean; // Enable revalidation\n revalidateTime?: number; // Time in milliseconds for revalidating the data\n invalidateQueries?: string[]; // Invalidate other queries when the data is updated\n updateQueries?: string[]; // Update other queries when the data is updated\n onSuccess?: (data: Awaited<ReturnType<T>>) => void; // Callback function that is called when the asynchronous function resolves successfully\n onError?: (error: string) => void; // Callback function that is called when the asynchronous function rejects or encounters an error\n args?: Parameters<T>; // Arguments to pass to the asynchronous function\n};\n\n// Default values for the hook's options\nconst DEFAULT_CACHE_ENABLED = false;\nconst DEFAULT_STORE_ENABLED = false;\nconst DEFAULT_ENABLED = true;\nconst DEFAULT_AUTO_FETCH = false;\nconst DEFAULT_RETRY_LIMIT = 1;\nconst DEFAULT_REVALIDATION_ENABLED = false;\nconst DEFAULT_REVALIDATE_TIME = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_RETRY_TIME = 5 * 60 * 1000; // 5 minutes\n\n// The main hook type that includes the async function along with its additional properties.\nexport type UseAsyncResult<\n U extends string,\n T extends (...args: any[]) => Promise<any>,\n> = UseAsyncResultBase<T> & Record<U, T>;\n\nconst getArgs = (args?: any[]): any[] =>\n args ? (Array.isArray(args) ? args : [args]) : [];\n\nconst getKeyWithArgs = (key: string, args: any[]) =>\n getArgs(args).length > 0 ? `${key}/${JSON.stringify(args)}` : key;\n\n/**\n * A custom React hook that manages asynchronous operations, providing easy-to-use states and controls over fetching, caching, and retry mechanisms.\n * This hook abstracts away the complexity of handling loading, error, and success states for any asynchronous function.\n *\n *\n * ```tsx\n * // Example of using useAsync to manage fetching user data from an API.\n * const fetchUserData = async (userId) => {\n * const response = await fetch(`/api/users/${userId}`);\n * if (!response.ok) throw new Error('Failed to fetch');\n * return await response.json();\n * };\n *\n * const UserDetails = ({ userId }) => {\n * const {\n * isLoading,\n * data,\n * error,\n * revalidate,\n * } = useAsync('userDetails', fetchUserData, {\n * cache: true,\n * revalidateTime: 60000, // 1 minute\n * autoFetch: true,\n * onSuccess: (data) => console.log('User data fetched successfully:', data),\n * onError: (error) => console.error('Error fetching user data:', error),\n * });\n *\n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error}</div>;\n * return (\n * <div>\n * <h1>{data.name}</h1>\n * <button onClick={() => revalidate()}>Refresh</button>\n * </div>\n * );\n * };\n * ```\n */\nexport const useAsync = <\n U extends string,\n T extends (...args: any[]) => Promise<any>,\n>(\n key: U,\n asyncFunction: T,\n options?: UseAsyncOptions<T>\n): UseAsyncResult<U, T> => {\n // Resolving optional parameters with default values\n const retryLimit = options?.retryLimit ?? DEFAULT_RETRY_LIMIT;\n const autoFetch = options?.autoFetch ?? DEFAULT_AUTO_FETCH;\n const retryTime = options?.retryTime ?? DEFAULT_RETRY_TIME;\n const cacheEnabled = options?.cache ?? DEFAULT_CACHE_ENABLED;\n const storeEnabled = options?.store ?? DEFAULT_STORE_ENABLED;\n const enabled = options?.enable ?? DEFAULT_ENABLED;\n const revalidationEnabled =\n options?.revalidation ?? DEFAULT_REVALIDATION_ENABLED;\n const revalidateTime = options?.revalidateTime ?? DEFAULT_REVALIDATE_TIME;\n const updateQueries = options?.updateQueries ?? [];\n const invalidateQueries = options?.invalidateQueries ?? [];\n const onSuccess = options?.onSuccess;\n const onError = options?.onError;\n const args = getArgs(options?.args ?? []);\n\n // Using a custom hook to manage state specific to asynchronous operations\n const { getStates, setQueryState, setQueriesState, makeQueryInError } =\n useAsyncState();\n\n // Storing the last arguments used to call the async function\n const storedArgsRef = useRef<any[]>(args);\n\n const controllerRef = useRef<AbortController | null>(null);\n\n // Apply different key for different requests\n const keyWithArgs = getKeyWithArgs(key, storedArgsRef.current);\n\n // Retrieving the current state of async operations using the same custom hook\n const {\n isFetched,\n fetchedDateTime,\n isLoading,\n isEnabled,\n error,\n isSuccess,\n isInvalidated,\n data,\n errorCount,\n } = getStates(keyWithArgs);\n\n /**\n * FETCH FUNCTION\n *\n * Manage parallel fetching across multiple instances of the hook\n * Manage state updates on success and error\n * Manage eventual invalidation of other queries\n */\n const fetch: T = (async (...args) => {\n const keyWithArgs = getKeyWithArgs(key, args);\n\n /**\n * ABORT CONTROLLER\n *\n * cancel an unnecessary request.\n * For example, if a user navigates away from a page or triggers a new request that makes the previous one obsolete, you can abort the previous fetch\n */\n if (controllerRef.current) {\n // Abort the previous request\n controllerRef.current.abort();\n }\n\n // Create a new AbortController\n const controller = new AbortController();\n controllerRef.current = controller;\n\n /**\n * PENDING PROMISES\n *\n * This logic ensures that if two parts of your application trigger the same request simultaneously,\n * only one network call is made, and both receive the same result.\n */\n if (pendingPromises.has(keyWithArgs)) {\n // Return the existing pending promise\n return pendingPromises.get(keyWithArgs);\n }\n\n const promise = (async () => {\n setQueryState(keyWithArgs, { isLoading: true });\n let response = null;\n\n await asyncFunction(...args)\n .then((result) => {\n response = result;\n\n setQueryState(keyWithArgs, {\n data: result,\n errorCount: 0,\n isLoading: false,\n isFetched: true,\n fetchedDateTime: new Date(),\n isSuccess: true,\n isInvalidated: false,\n error: null,\n });\n\n onSuccess?.(result);\n\n // Invalidate other queries if necessary\n if (invalidateQueries.length > 0) {\n setQueriesState(invalidateQueries, {\n isInvalidated: true,\n });\n }\n\n // Update other queries if necessary\n if (updateQueries.length > 0) {\n setQueriesState(updateQueries, {\n data: result,\n });\n }\n\n // Store the result in local storage\n if (storeEnabled) {\n localStorage.setItem(keyWithArgs, JSON.stringify(result));\n }\n })\n .catch((error) => {\n const msg = error instanceof Error ? error.message : String(error);\n\n makeQueryInError(keyWithArgs, msg);\n onError?.(error.message);\n })\n .finally(() => {\n // Remove the pending promise from the cache\n pendingPromises.delete(keyWithArgs);\n });\n\n return response;\n })();\n\n // Store the pending promise in the cache\n pendingPromises.set(keyWithArgs, promise);\n\n return await promise;\n }) as T;\n\n /**\n * REVALIDATE FUNCTION\n *\n * Wrap core function to handle revalidation\n * Handle arguments caching\n *\n */\n const revalidate: T = (async (...args) => {\n if (!isEnabled || !enabled) return; // Hook is disabled\n\n if (args) {\n // Revalidation arguments can be different from the initial fetch arguments\n // If arguments are provided, store/update them for future periodic revalidation\n\n storedArgsRef.current = getArgs(args);\n }\n\n return await fetch(...storedArgsRef.current);\n }) as T;\n\n /**\n * EXECUTION FUNCTION\n *\n * Wrap revalidation function\n * If data is valid return it directly to avoid fetching again\n */\n const execute: T = (async (...args) => {\n if (!isEnabled || !enabled) return; // Hook is disabled\n if (isLoading) return; // Fetch is already in progress\n\n const shouldReturnData =\n !isInvalidated && // If data are invalidated, we should refetch to revalidate the data\n isSuccess &&\n cacheEnabled &&\n data;\n\n if (shouldReturnData) return data; // Data are already fetched and should be returned directly. Avoid fetching again.\n\n return await revalidate(...args);\n }) as T;\n\n /**\n * HANDLE SYNCHRONIZATION HOOKS DISACTIVATION\n *\n * If one instance of the hook is disabled, the other instances should be disabled too.\n * This is to prevent inconsistencies in the state of the hook.\n */\n useEffect(() => {\n if (enabled !== isEnabled) {\n setQueryState(keyWithArgs, {\n isEnabled,\n });\n }\n }, [enabled, isEnabled, keyWithArgs]);\n\n /**\n * HANDLE LOCAL STORAGE LOADING\n *\n * If store is enabled, load data from local storage\n */\n useEffect(() => {\n if (!isEnabled || !enabled) return; // Hook is disabled\n if (!storeEnabled) return; // Hook should not use local storage\n if (isInvalidated || isFetched || data) return; // Hook have been already mounted and fetched or invalidated\n\n const storedData = localStorage.getItem(keyWithArgs);\n\n // Wrap parsing in a try-catch block to handle invalid JSON data\n try {\n if (storedData) {\n setQueryState(keyWithArgs, {\n data: JSON.parse(storedData),\n });\n }\n } catch (error) {\n console.error(error);\n }\n }, [\n storeEnabled,\n keyWithArgs,\n isFetched,\n isInvalidated,\n isEnabled,\n enabled,\n data,\n ]);\n\n /**\n * HANDLE AUTO-FETCH ON HOOK MOUNT\n *\n * If autoFetch is enabled, fetch the data when the hook is mounted\n */\n useEffect(() => {\n if (!autoFetch) return; // Auto-fetch is disabled\n if (!isEnabled || !enabled) return; // Hook is disabled\n if (isFetched && !isInvalidated) return; // Hook have already fetched or invalidated\n if (isLoading) return; // Fetch is already in progress\n\n fetch(...storedArgsRef.current);\n }, [\n autoFetch,\n isEnabled,\n enabled,\n isFetched,\n isInvalidated,\n isLoading,\n fetch,\n ]);\n\n /**\n * HANDLE RETRY\n *\n * If fetching fails, retry the fetch after a certain time\n */\n useEffect(() => {\n const isRetryEnabled = errorCount > 0 && retryLimit > 0;\n const isRetryLimitReached = errorCount > retryLimit;\n\n if (!isEnabled || !enabled) return; // Hook is disabled\n if (!isRetryEnabled) return; // Retry is disabled\n if (isRetryLimitReached) return; // Retry limit has been reached\n if (!(cacheEnabled || storeEnabled)) return; // Useless to retry if caching is disabled\n if (isLoading) return; // Fetch is already in progress\n if (isSuccess) return; // Hook has already fetched successfully\n\n const timeout = setTimeout(() => {\n fetch(...storedArgsRef.current);\n }, retryTime);\n\n return () => clearTimeout(timeout);\n }, [\n isEnabled,\n errorCount,\n retryLimit,\n enabled,\n retryTime,\n cacheEnabled,\n storeEnabled,\n isSuccess,\n isLoading,\n fetch,\n ]);\n\n /**\n * HANDLE PERIODIC REVALIDATION\n *\n * If revalidation is enabled, revalidate the data periodically\n */\n useEffect(() => {\n if (!revalidationEnabled || revalidateTime <= 0) return; // Revalidation is disabled\n if (!isEnabled || !enabled) return; // Hook is disabled\n if (isLoading) return; // Fetch is already in progress\n if (!isSuccess || !fetchedDateTime) return; // Should retry either of revalidate\n if (!(cacheEnabled || storeEnabled)) return; // Useless to revalidate if caching is disabled\n\n const timeout = setTimeout(() => {\n fetch(...storedArgsRef.current);\n }, revalidateTime);\n\n return () => clearTimeout(timeout);\n }, [\n revalidationEnabled,\n revalidateTime,\n cacheEnabled,\n storeEnabled,\n isSuccess,\n fetchedDateTime,\n isLoading,\n isEnabled,\n enabled,\n fetch,\n ]);\n\n // Memoization of the setData function to prevent unnecessary re-renders\n const setDataMemo = (data: Awaited<ReturnType<T> | null>) => {\n setQueryState(keyWithArgs, {\n data,\n });\n };\n\n // Memoization to prevent unnecessary re-renders\n const memoResult = {\n isFetched,\n isInvalidated,\n error,\n data,\n errorCount,\n isSuccess,\n isEnabled,\n isDisabled: !isEnabled,\n isLoading,\n isWaitingData: isLoading && !isFetched && !data, // Check if the data is still being fetched. Stay at true during revalidation or if data are stored in local storage\n isRevalidating: isLoading && isFetched, // Check if the data is valid and is being revalidated\n [key]: execute, // Name the execute function as the given key to avoid conflicts with other hooks (e.g. `const { fetchUser } = useAsync('fetchUser', () => fetchUserFunction());`)\n revalidate,\n setData: setDataMemo,\n };\n\n useEffect(\n () => () => {\n // Clean up the controller on unmount\n if (controllerRef.current) {\n controllerRef.current.abort();\n }\n },\n []\n );\n\n // Return the hook's result, including all state and control functions\n return memoResult as UseAsyncResultBase<T> & Record<U, T>;\n};\n"],"names":["args","keyWithArgs","error","data"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAsync.mjs","sources":["../../../src/hooks/useAsync/useAsync.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef } from 'react';\nimport { useAsyncState } from './useAsyncStateStore';\n\n// Pending promises cache to prevent parallel requests when multiple components use the hook\nconst pendingPromises = new Map();\n\n// Defines the base structure for the result of the custom hook.\ntype UseAsyncResultBase<T extends (...args: any[]) => Promise<any>> = {\n isFetched: boolean;\n isLoading: boolean;\n isInvalidated: boolean;\n isSuccess: boolean;\n isDisabled: boolean;\n isWaitingData: boolean;\n isRevalidating: boolean;\n error: string | null;\n data: Awaited<ReturnType<T>> | null;\n errorCount: number;\n revalidate: T;\n setData: (data: Awaited<ReturnType<T> | null>) => void;\n};\n\n// Options type for the hook, allowing customization of behavior.\nexport type UseAsyncOptions<T extends (...args: any[]) => Promise<any>> = {\n retryLimit?: number; // The number of times the hook should retry the function on failure before giving up\n retryTime?: number; // Time in milliseconds for retrying the data\n cache?: boolean; // Cache the result of the function\n store?: boolean; // Store the result of the function in local storage\n enable?: boolean; // Enable the hook\n autoFetch?: boolean; // Automatically fetch the data when the hook is mounted\n revalidation?: boolean; // Enable revalidation\n revalidateTime?: number; // Time in milliseconds for revalidating the data\n invalidateQueries?: string[]; // Invalidate other queries when the data is updated\n updateQueries?: string[]; // Update other queries when the data is updated\n onSuccess?: (data: Awaited<ReturnType<T>>) => void; // Callback function that is called when the asynchronous function resolves successfully\n onError?: (error: string) => void; // Callback function that is called when the asynchronous function rejects or encounters an error\n args?: Parameters<T>; // Arguments to pass to the asynchronous function\n};\n\n// Default values for the hook's options\nconst DEFAULT_CACHE_ENABLED = false;\nconst DEFAULT_STORE_ENABLED = false;\nconst DEFAULT_ENABLED = true;\nconst DEFAULT_AUTO_FETCH = false;\nconst DEFAULT_RETRY_LIMIT = 1;\nconst DEFAULT_REVALIDATION_ENABLED = false;\nconst DEFAULT_REVALIDATE_TIME = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_RETRY_TIME = 5 * 60 * 1000; // 5 minutes\n\n// The main hook type that includes the async function along with its additional properties.\nexport type UseAsyncResult<\n U extends string,\n T extends (...args: any[]) => Promise<any>,\n> = UseAsyncResultBase<T> & Record<U, T>;\n\nconst getArgs = (args?: any[]): any[] =>\n args ? (Array.isArray(args) ? args : [args]) : [];\n\nconst getKeyWithArgs = (key: string, args: any[]) =>\n getArgs(args).length > 0 ? `${key}/${JSON.stringify(args)}` : key;\n\n/**\n * A custom React hook that manages asynchronous operations, providing easy-to-use states and controls over fetching, caching, and retry mechanisms.\n * This hook abstracts away the complexity of handling loading, error, and success states for any asynchronous function.\n *\n *\n * ```tsx\n * // Example of using useAsync to manage fetching user data from an API.\n * const fetchUserData = async (userId) => {\n * const response = await fetch(`/api/users/${userId}`);\n * if (!response.ok) throw new Error('Failed to fetch');\n * return await response.json();\n * };\n *\n * const UserDetails = ({ userId }) => {\n * const {\n * isLoading,\n * data,\n * error,\n * revalidate,\n * } = useAsync('userDetails', fetchUserData, {\n * cache: true,\n * revalidateTime: 60000, // 1 minute\n * autoFetch: true,\n * onSuccess: (data) => console.log('User data fetched successfully:', data),\n * onError: (error) => console.error('Error fetching user data:', error),\n * });\n *\n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error}</div>;\n * return (\n * <div>\n * <h1>{data.name}</h1>\n * <button onClick={() => revalidate()}>Refresh</button>\n * </div>\n * );\n * };\n * ```\n */\nexport const useAsync = <\n U extends string,\n T extends (...args: any[]) => Promise<any>,\n>(\n key: U,\n asyncFunction: T,\n options?: UseAsyncOptions<T>\n): UseAsyncResult<U, T> => {\n // Resolving optional parameters with default values\n const retryLimit = options?.retryLimit ?? DEFAULT_RETRY_LIMIT;\n const autoFetch = options?.autoFetch ?? DEFAULT_AUTO_FETCH;\n const retryTime = options?.retryTime ?? DEFAULT_RETRY_TIME;\n const cacheEnabled = options?.cache ?? DEFAULT_CACHE_ENABLED;\n const storeEnabled = options?.store ?? DEFAULT_STORE_ENABLED;\n const enabled = options?.enable ?? DEFAULT_ENABLED;\n const revalidationEnabled =\n options?.revalidation ?? DEFAULT_REVALIDATION_ENABLED;\n const revalidateTime = options?.revalidateTime ?? DEFAULT_REVALIDATE_TIME;\n const updateQueries = options?.updateQueries ?? [];\n const invalidateQueries = options?.invalidateQueries ?? [];\n const onSuccess = options?.onSuccess;\n const onError = options?.onError;\n const args = getArgs(options?.args ?? []);\n\n // Using a custom hook to manage state specific to asynchronous operations\n const { getStates, setQueryState, setQueriesState, makeQueryInError } =\n useAsyncState();\n\n // Storing the last arguments used to call the async function\n const storedArgsRef = useRef<any[]>(args);\n\n const controllerRef = useRef<AbortController | null>(null);\n\n // Apply different key for different requests\n const keyWithArgs = getKeyWithArgs(key, storedArgsRef.current);\n\n // Retrieving the current state of async operations using the same custom hook\n const {\n isFetched,\n fetchedDateTime,\n isLoading,\n isEnabled,\n error,\n isSuccess,\n isInvalidated,\n data,\n errorCount,\n } = getStates(keyWithArgs);\n\n /**\n * FETCH FUNCTION\n *\n * Manage parallel fetching across multiple instances of the hook\n * Manage state updates on success and error\n * Manage eventual invalidation of other queries\n */\n const fetch: T = (async (...args) => {\n const keyWithArgs = getKeyWithArgs(key, args);\n\n /**\n * ABORT CONTROLLER\n *\n * cancel an unnecessary request.\n * For example, if a user navigates away from a page or triggers a new request that makes the previous one obsolete, you can abort the previous fetch\n */\n if (controllerRef.current) {\n // Abort the previous request\n controllerRef.current.abort();\n }\n\n // Create a new AbortController\n const controller = new AbortController();\n controllerRef.current = controller;\n\n /**\n * PENDING PROMISES\n *\n * This logic ensures that if two parts of your application trigger the same request simultaneously,\n * only one network call is made, and both receive the same result.\n */\n if (pendingPromises.has(keyWithArgs)) {\n // Return the existing pending promise\n return pendingPromises.get(keyWithArgs);\n }\n\n const promise = (async () => {\n setQueryState(keyWithArgs, { isLoading: true });\n let response = null;\n\n await asyncFunction(...args)\n .then((result) => {\n response = result;\n\n setQueryState(keyWithArgs, {\n data: result,\n errorCount: 0,\n isLoading: false,\n isFetched: true,\n fetchedDateTime: new Date(),\n isSuccess: true,\n isInvalidated: false,\n error: null,\n });\n\n onSuccess?.(result);\n\n // Invalidate other queries if necessary\n if (invalidateQueries.length > 0) {\n setQueriesState(invalidateQueries, {\n isInvalidated: true,\n });\n }\n\n // Update other queries if necessary\n if (updateQueries.length > 0) {\n setQueriesState(updateQueries, {\n data: result,\n });\n }\n\n // Store the result in local storage\n if (storeEnabled) {\n localStorage.setItem(keyWithArgs, JSON.stringify(result));\n }\n })\n .catch((error) => {\n console.error({ error });\n const msg = error instanceof Error ? error.message : String(error);\n\n makeQueryInError(keyWithArgs, msg);\n onError?.(error.message);\n })\n .finally(() => {\n // Remove the pending promise from the cache\n pendingPromises.delete(keyWithArgs);\n });\n\n return response;\n })();\n\n // Store the pending promise in the cache\n pendingPromises.set(keyWithArgs, promise);\n\n return await promise;\n }) as T;\n\n /**\n * REVALIDATE FUNCTION\n *\n * Wrap core function to handle revalidation\n * Handle arguments caching\n *\n */\n const revalidate: T = (async (...args) => {\n if (!isEnabled || !enabled) return; // Hook is disabled\n\n if (args) {\n // Revalidation arguments can be different from the initial fetch arguments\n // If arguments are provided, store/update them for future periodic revalidation\n\n storedArgsRef.current = getArgs(args);\n }\n\n return await fetch(...storedArgsRef.current);\n }) as T;\n\n /**\n * EXECUTION FUNCTION\n *\n * Wrap revalidation function\n * If data is valid return it directly to avoid fetching again\n */\n const execute: T = (async (...args) => {\n if (!isEnabled || !enabled) return; // Hook is disabled\n if (isLoading) return; // Fetch is already in progress\n\n const shouldReturnData =\n !isInvalidated && // If data are invalidated, we should refetch to revalidate the data\n isSuccess &&\n cacheEnabled &&\n data;\n\n if (shouldReturnData) return data; // Data are already fetched and should be returned directly. Avoid fetching again.\n\n return await revalidate(...args);\n }) as T;\n\n /**\n * HANDLE SYNCHRONIZATION HOOKS DISACTIVATION\n *\n * If one instance of the hook is disabled, the other instances should be disabled too.\n * This is to prevent inconsistencies in the state of the hook.\n */\n useEffect(() => {\n if (enabled !== isEnabled) {\n setQueryState(keyWithArgs, {\n isEnabled,\n });\n }\n }, [enabled, isEnabled, keyWithArgs]);\n\n /**\n * HANDLE LOCAL STORAGE LOADING\n *\n * If store is enabled, load data from local storage\n */\n useEffect(() => {\n if (!isEnabled || !enabled) return; // Hook is disabled\n if (!storeEnabled) return; // Hook should not use local storage\n if (isInvalidated || isFetched || data) return; // Hook have been already mounted and fetched or invalidated\n\n const storedData = localStorage.getItem(keyWithArgs);\n\n // Wrap parsing in a try-catch block to handle invalid JSON data\n try {\n if (storedData) {\n setQueryState(keyWithArgs, {\n data: JSON.parse(storedData),\n });\n }\n } catch (error) {\n console.error(error);\n }\n }, [\n storeEnabled,\n keyWithArgs,\n isFetched,\n isInvalidated,\n isEnabled,\n enabled,\n data,\n ]);\n\n /**\n * HANDLE AUTO-FETCH ON HOOK MOUNT\n *\n * If autoFetch is enabled, fetch the data when the hook is mounted\n */\n useEffect(() => {\n if (!autoFetch) return; // Auto-fetch is disabled\n if (!isEnabled || !enabled) return; // Hook is disabled\n if (isFetched && !isInvalidated) return; // Hook have already fetched or invalidated\n if (isLoading) return; // Fetch is already in progress\n\n fetch(...storedArgsRef.current);\n }, [\n autoFetch,\n isEnabled,\n enabled,\n isFetched,\n isInvalidated,\n isLoading,\n fetch,\n ]);\n\n /**\n * HANDLE RETRY\n *\n * If fetching fails, retry the fetch after a certain time\n */\n useEffect(() => {\n const isRetryEnabled = errorCount > 0 && retryLimit > 0;\n const isRetryLimitReached = errorCount > retryLimit;\n\n if (!isEnabled || !enabled) return; // Hook is disabled\n if (!isRetryEnabled) return; // Retry is disabled\n if (isRetryLimitReached) return; // Retry limit has been reached\n if (!(cacheEnabled || storeEnabled)) return; // Useless to retry if caching is disabled\n if (isLoading) return; // Fetch is already in progress\n if (isSuccess) return; // Hook has already fetched successfully\n\n const timeout = setTimeout(() => {\n fetch(...storedArgsRef.current);\n }, retryTime);\n\n return () => clearTimeout(timeout);\n }, [\n isEnabled,\n errorCount,\n retryLimit,\n enabled,\n retryTime,\n cacheEnabled,\n storeEnabled,\n isSuccess,\n isLoading,\n fetch,\n ]);\n\n /**\n * HANDLE PERIODIC REVALIDATION\n *\n * If revalidation is enabled, revalidate the data periodically\n */\n useEffect(() => {\n if (!revalidationEnabled || revalidateTime <= 0) return; // Revalidation is disabled\n if (!isEnabled || !enabled) return; // Hook is disabled\n if (isLoading) return; // Fetch is already in progress\n if (!isSuccess || !fetchedDateTime) return; // Should retry either of revalidate\n if (!(cacheEnabled || storeEnabled)) return; // Useless to revalidate if caching is disabled\n\n const timeout = setTimeout(() => {\n fetch(...storedArgsRef.current);\n }, revalidateTime);\n\n return () => clearTimeout(timeout);\n }, [\n revalidationEnabled,\n revalidateTime,\n cacheEnabled,\n storeEnabled,\n isSuccess,\n fetchedDateTime,\n isLoading,\n isEnabled,\n enabled,\n fetch,\n ]);\n\n // Memoization of the setData function to prevent unnecessary re-renders\n const setDataMemo = (data: Awaited<ReturnType<T> | null>) => {\n setQueryState(keyWithArgs, {\n data,\n });\n };\n\n // Memoization to prevent unnecessary re-renders\n const memoResult = {\n isFetched,\n isInvalidated,\n error,\n data,\n errorCount,\n isSuccess,\n isEnabled,\n isDisabled: !isEnabled,\n isLoading,\n isWaitingData: isLoading && !isFetched && !data, // Check if the data is still being fetched. Stay at true during revalidation or if data are stored in local storage\n isRevalidating: isLoading && isFetched, // Check if the data is valid and is being revalidated\n [key]: execute, // Name the execute function as the given key to avoid conflicts with other hooks (e.g. `const { fetchUser } = useAsync('fetchUser', () => fetchUserFunction());`)\n revalidate,\n setData: setDataMemo,\n };\n\n useEffect(\n () => () => {\n // Clean up the controller on unmount\n if (controllerRef.current) {\n controllerRef.current.abort();\n }\n },\n []\n );\n\n // Return the hook's result, including all state and control functions\n return memoResult as UseAsyncResultBase<T> & Record<U, T>;\n};\n"],"names":["args","keyWithArgs","error","data"],"mappings":"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"}
|
package/dist/hooks/useDevice.cjs
CHANGED
|
@@ -26,11 +26,19 @@ const checkIsMobileUserAgent = () => {
|
|
|
26
26
|
userAgent
|
|
27
27
|
);
|
|
28
28
|
};
|
|
29
|
+
const checkIsIphoneOrSafariDevice = () => {
|
|
30
|
+
if (typeof window === "undefined") return;
|
|
31
|
+
const userAgent = window.navigator?.userAgent;
|
|
32
|
+
const isSafari = /Safari\/\d/i.test(userAgent) && // has “Safari/xxx”
|
|
33
|
+
!/Chrome|CriOS|FxiOS|Edg|OPR/i.test(userAgent);
|
|
34
|
+
const isAppleDevice = /Macintosh|iP(?:hone|ad|od)/.test(userAgent);
|
|
35
|
+
return isSafari && isAppleDevice;
|
|
36
|
+
};
|
|
29
37
|
const checkIsMobileScreen = (breakpoint) => {
|
|
30
38
|
if (typeof window === "undefined") return;
|
|
31
39
|
return (window?.innerWidth ?? 0) <= breakpoint;
|
|
32
40
|
};
|
|
33
|
-
const calculateIsMobile = (breakpoint) => {
|
|
41
|
+
const calculateIsMobile = (breakpoint = "md") => {
|
|
34
42
|
const breakpointValue = getBreakpointFromSize(breakpoint);
|
|
35
43
|
const isMobileUserAgent = checkIsMobileUserAgent();
|
|
36
44
|
const isMobileScreen = checkIsMobileScreen(breakpointValue);
|
|
@@ -52,10 +60,15 @@ const useDevice = (breakpoint = "md") => {
|
|
|
52
60
|
const handleResize = () => {
|
|
53
61
|
setResult(calculateIsMobile(breakpoint));
|
|
54
62
|
};
|
|
55
|
-
window.addEventListener("resize", handleResize);
|
|
63
|
+
window.addEventListener("resize", handleResize, { passive: true });
|
|
56
64
|
return () => window.removeEventListener("resize", handleResize);
|
|
57
65
|
}, [breakpoint]);
|
|
58
66
|
return result;
|
|
59
67
|
};
|
|
68
|
+
exports.calculateIsMobile = calculateIsMobile;
|
|
69
|
+
exports.checkIsIphoneOrSafariDevice = checkIsIphoneOrSafariDevice;
|
|
70
|
+
exports.checkIsMobileScreen = checkIsMobileScreen;
|
|
71
|
+
exports.checkIsMobileUserAgent = checkIsMobileUserAgent;
|
|
72
|
+
exports.getBreakpointFromSize = getBreakpointFromSize;
|
|
60
73
|
exports.useDevice = useDevice;
|
|
61
74
|
//# sourceMappingURL=useDevice.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDevice.cjs","sources":["../../src/hooks/useDevice.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\nexport type SizeType = 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\
|
|
1
|
+
{"version":3,"file":"useDevice.cjs","sources":["../../src/hooks/useDevice.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\nexport type SizeType = 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\nexport const getBreakpointFromSize = (breakpoint: SizeType | number) => {\n switch (breakpoint) {\n case 'sm':\n return 640;\n case 'md':\n return 768;\n case 'lg':\n return 1024;\n case 'xl':\n return 1280;\n case '2xl':\n return 1536;\n default:\n return breakpoint;\n }\n};\n\nexport const checkIsMobileUserAgent = (): boolean | undefined => {\n if (typeof window === 'undefined') return;\n\n const userAgent = window.navigator?.userAgent;\n\n if (typeof userAgent === 'undefined') return;\n\n return /android|bb\\d+|meego|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(?:hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(?:ob|in)i|palm(?: os)?|phone|p(?:ixi|re)\\/|plucker|pocket|psp|series(?:4|6)0|symbian|treo|up\\.(?:browser|link)|vodafone|wap|windows ce|windows phone|xda|xiino|zte-/i.test(\n userAgent\n );\n};\n\nexport const checkIsIphoneOrSafariDevice = (): boolean | undefined => {\n if (typeof window === 'undefined') return;\n\n const userAgent = window.navigator?.userAgent;\n\n /* 1 . is it Safari? (Chrome & co. also contain “Safari/…”, so exclude them) */\n const isSafari =\n /Safari\\/\\d/i.test(userAgent) && // has “Safari/xxx”\n !/Chrome|CriOS|FxiOS|Edg|OPR/i.test(userAgent); // …but not the other browsers\n\n /* 2. is it an Apple device? (macOS or iOS/iPadOS) */\n const isAppleDevice = /Macintosh|iP(?:hone|ad|od)/.test(userAgent);\n\n return isSafari && isAppleDevice; // true for mac-Safari & iOS-Safari\n};\n\nexport const checkIsMobileScreen = (\n breakpoint: number\n): boolean | undefined => {\n if (typeof window === 'undefined') return;\n\n return (window?.innerWidth ?? 0) <= breakpoint;\n};\n\ntype UseDeviceState = {\n isMobileScreen: boolean | undefined;\n isMobileUserAgent: boolean | undefined;\n isMobile: boolean | undefined;\n};\n\nexport const calculateIsMobile = (breakpoint: SizeType | number = 'md') => {\n const breakpointValue = getBreakpointFromSize(breakpoint);\n\n const isMobileUserAgent = checkIsMobileUserAgent();\n const isMobileScreen = checkIsMobileScreen(breakpointValue);\n const isMobile = isMobileScreen ?? isMobileUserAgent;\n\n return {\n isMobileScreen, // Is the screen width within a mobile breakpoint.\n isMobileUserAgent, // Is the user agent indicative of a mobile device.\n isMobile, // Combines both checks to determine if the device is mobile.\n };\n};\n\nexport const useDevice = (breakpoint: SizeType | number = 'md') => {\n const [result, setResult] = useState<UseDeviceState>(\n calculateIsMobile(breakpoint)\n );\n\n useEffect(() => {\n const handleResize = () => {\n setResult(calculateIsMobile(breakpoint));\n };\n\n window.addEventListener('resize', handleResize, { passive: true });\n\n // Cleanup listener on unmount\n return () => window.removeEventListener('resize', handleResize);\n }, [breakpoint]); // Empty dependency array ensures this effect runs only once on mount\n\n return result;\n};\n"],"names":["useState","useEffect"],"mappings":";;;;AAMa,MAAA,wBAAwB,CAAC,eAAkC;AACtE,UAAQ,YAAY;AAAA,IAClB,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT;AACS,aAAA;AAAA,EAAA;AAEb;AAEO,MAAM,yBAAyB,MAA2B;AAC3D,MAAA,OAAO,WAAW,YAAa;AAE7B,QAAA,YAAY,OAAO,WAAW;AAEhC,MAAA,OAAO,cAAc,YAAa;AAEtC,SAAO,mVAAmV;AAAA,IACxV;AAAA,EACF;AACF;AAEO,MAAM,8BAA8B,MAA2B;AAChE,MAAA,OAAO,WAAW,YAAa;AAE7B,QAAA,YAAY,OAAO,WAAW;AAG9B,QAAA,WACJ,cAAc,KAAK,SAAS;AAAA,EAC5B,CAAC,8BAA8B,KAAK,SAAS;AAGzC,QAAA,gBAAgB,6BAA6B,KAAK,SAAS;AAEjE,SAAO,YAAY;AACrB;AAEa,MAAA,sBAAsB,CACjC,eACwB;AACpB,MAAA,OAAO,WAAW,YAAa;AAE3B,UAAA,QAAQ,cAAc,MAAM;AACtC;AAQa,MAAA,oBAAoB,CAAC,aAAgC,SAAS;AACnE,QAAA,kBAAkB,sBAAsB,UAAU;AAExD,QAAM,oBAAoB,uBAAuB;AAC3C,QAAA,iBAAiB,oBAAoB,eAAe;AAC1D,QAAM,WAAW,kBAAkB;AAE5B,SAAA;AAAA,IACL;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,EACF;AACF;AAEa,MAAA,YAAY,CAAC,aAAgC,SAAS;AAC3D,QAAA,CAAC,QAAQ,SAAS,IAAIA,aAAA;AAAA,IAC1B,kBAAkB,UAAU;AAAA,EAC9B;AAEAC,eAAAA,UAAU,MAAM;AACd,UAAM,eAAe,MAAM;AACf,gBAAA,kBAAkB,UAAU,CAAC;AAAA,IACzC;AAEA,WAAO,iBAAiB,UAAU,cAAc,EAAE,SAAS,MAAM;AAGjE,WAAO,MAAM,OAAO,oBAAoB,UAAU,YAAY;AAAA,EAAA,GAC7D,CAAC,UAAU,CAAC;AAER,SAAA;AACT;;;;;;;"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
export type SizeType = 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
2
|
+
export declare const getBreakpointFromSize: (breakpoint: SizeType | number) => number;
|
|
3
|
+
export declare const checkIsMobileUserAgent: () => boolean | undefined;
|
|
4
|
+
export declare const checkIsIphoneOrSafariDevice: () => boolean | undefined;
|
|
5
|
+
export declare const checkIsMobileScreen: (breakpoint: number) => boolean | undefined;
|
|
2
6
|
type UseDeviceState = {
|
|
3
7
|
isMobileScreen: boolean | undefined;
|
|
4
8
|
isMobileUserAgent: boolean | undefined;
|
|
5
9
|
isMobile: boolean | undefined;
|
|
6
10
|
};
|
|
11
|
+
export declare const calculateIsMobile: (breakpoint?: SizeType | number) => {
|
|
12
|
+
isMobileScreen: boolean | undefined;
|
|
13
|
+
isMobileUserAgent: boolean | undefined;
|
|
14
|
+
isMobile: boolean | undefined;
|
|
15
|
+
};
|
|
7
16
|
export declare const useDevice: (breakpoint?: SizeType | number) => UseDeviceState;
|
|
8
17
|
export {};
|
|
9
18
|
//# sourceMappingURL=useDevice.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDevice.d.ts","sourceRoot":"","sources":["../../src/hooks/useDevice.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"useDevice.d.ts","sourceRoot":"","sources":["../../src/hooks/useDevice.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC;AAEzD,eAAO,MAAM,qBAAqB,GAAI,YAAY,QAAQ,GAAG,MAAM,WAelE,CAAC;AAEF,eAAO,MAAM,sBAAsB,QAAO,OAAO,GAAG,SAUnD,CAAC;AAEF,eAAO,MAAM,2BAA2B,QAAO,OAAO,GAAG,SAcxD,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,YAAY,MAAM,KACjB,OAAO,GAAG,SAIZ,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,cAAc,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,iBAAiB,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,aAAY,QAAQ,GAAG,MAAa;;;;CAYrE,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,aAAY,QAAQ,GAAG,MAAa,mBAiB7D,CAAC"}
|
package/dist/hooks/useDevice.mjs
CHANGED
|
@@ -24,11 +24,19 @@ const checkIsMobileUserAgent = () => {
|
|
|
24
24
|
userAgent
|
|
25
25
|
);
|
|
26
26
|
};
|
|
27
|
+
const checkIsIphoneOrSafariDevice = () => {
|
|
28
|
+
if (typeof window === "undefined") return;
|
|
29
|
+
const userAgent = window.navigator?.userAgent;
|
|
30
|
+
const isSafari = /Safari\/\d/i.test(userAgent) && // has “Safari/xxx”
|
|
31
|
+
!/Chrome|CriOS|FxiOS|Edg|OPR/i.test(userAgent);
|
|
32
|
+
const isAppleDevice = /Macintosh|iP(?:hone|ad|od)/.test(userAgent);
|
|
33
|
+
return isSafari && isAppleDevice;
|
|
34
|
+
};
|
|
27
35
|
const checkIsMobileScreen = (breakpoint) => {
|
|
28
36
|
if (typeof window === "undefined") return;
|
|
29
37
|
return (window?.innerWidth ?? 0) <= breakpoint;
|
|
30
38
|
};
|
|
31
|
-
const calculateIsMobile = (breakpoint) => {
|
|
39
|
+
const calculateIsMobile = (breakpoint = "md") => {
|
|
32
40
|
const breakpointValue = getBreakpointFromSize(breakpoint);
|
|
33
41
|
const isMobileUserAgent = checkIsMobileUserAgent();
|
|
34
42
|
const isMobileScreen = checkIsMobileScreen(breakpointValue);
|
|
@@ -50,12 +58,17 @@ const useDevice = (breakpoint = "md") => {
|
|
|
50
58
|
const handleResize = () => {
|
|
51
59
|
setResult(calculateIsMobile(breakpoint));
|
|
52
60
|
};
|
|
53
|
-
window.addEventListener("resize", handleResize);
|
|
61
|
+
window.addEventListener("resize", handleResize, { passive: true });
|
|
54
62
|
return () => window.removeEventListener("resize", handleResize);
|
|
55
63
|
}, [breakpoint]);
|
|
56
64
|
return result;
|
|
57
65
|
};
|
|
58
66
|
export {
|
|
67
|
+
calculateIsMobile,
|
|
68
|
+
checkIsIphoneOrSafariDevice,
|
|
69
|
+
checkIsMobileScreen,
|
|
70
|
+
checkIsMobileUserAgent,
|
|
71
|
+
getBreakpointFromSize,
|
|
59
72
|
useDevice
|
|
60
73
|
};
|
|
61
74
|
//# sourceMappingURL=useDevice.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDevice.mjs","sources":["../../src/hooks/useDevice.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\nexport type SizeType = 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\
|
|
1
|
+
{"version":3,"file":"useDevice.mjs","sources":["../../src/hooks/useDevice.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\nexport type SizeType = 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\nexport const getBreakpointFromSize = (breakpoint: SizeType | number) => {\n switch (breakpoint) {\n case 'sm':\n return 640;\n case 'md':\n return 768;\n case 'lg':\n return 1024;\n case 'xl':\n return 1280;\n case '2xl':\n return 1536;\n default:\n return breakpoint;\n }\n};\n\nexport const checkIsMobileUserAgent = (): boolean | undefined => {\n if (typeof window === 'undefined') return;\n\n const userAgent = window.navigator?.userAgent;\n\n if (typeof userAgent === 'undefined') return;\n\n return /android|bb\\d+|meego|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(?:hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(?:ob|in)i|palm(?: os)?|phone|p(?:ixi|re)\\/|plucker|pocket|psp|series(?:4|6)0|symbian|treo|up\\.(?:browser|link)|vodafone|wap|windows ce|windows phone|xda|xiino|zte-/i.test(\n userAgent\n );\n};\n\nexport const checkIsIphoneOrSafariDevice = (): boolean | undefined => {\n if (typeof window === 'undefined') return;\n\n const userAgent = window.navigator?.userAgent;\n\n /* 1 . is it Safari? (Chrome & co. also contain “Safari/…”, so exclude them) */\n const isSafari =\n /Safari\\/\\d/i.test(userAgent) && // has “Safari/xxx”\n !/Chrome|CriOS|FxiOS|Edg|OPR/i.test(userAgent); // …but not the other browsers\n\n /* 2. is it an Apple device? (macOS or iOS/iPadOS) */\n const isAppleDevice = /Macintosh|iP(?:hone|ad|od)/.test(userAgent);\n\n return isSafari && isAppleDevice; // true for mac-Safari & iOS-Safari\n};\n\nexport const checkIsMobileScreen = (\n breakpoint: number\n): boolean | undefined => {\n if (typeof window === 'undefined') return;\n\n return (window?.innerWidth ?? 0) <= breakpoint;\n};\n\ntype UseDeviceState = {\n isMobileScreen: boolean | undefined;\n isMobileUserAgent: boolean | undefined;\n isMobile: boolean | undefined;\n};\n\nexport const calculateIsMobile = (breakpoint: SizeType | number = 'md') => {\n const breakpointValue = getBreakpointFromSize(breakpoint);\n\n const isMobileUserAgent = checkIsMobileUserAgent();\n const isMobileScreen = checkIsMobileScreen(breakpointValue);\n const isMobile = isMobileScreen ?? isMobileUserAgent;\n\n return {\n isMobileScreen, // Is the screen width within a mobile breakpoint.\n isMobileUserAgent, // Is the user agent indicative of a mobile device.\n isMobile, // Combines both checks to determine if the device is mobile.\n };\n};\n\nexport const useDevice = (breakpoint: SizeType | number = 'md') => {\n const [result, setResult] = useState<UseDeviceState>(\n calculateIsMobile(breakpoint)\n );\n\n useEffect(() => {\n const handleResize = () => {\n setResult(calculateIsMobile(breakpoint));\n };\n\n window.addEventListener('resize', handleResize, { passive: true });\n\n // Cleanup listener on unmount\n return () => window.removeEventListener('resize', handleResize);\n }, [breakpoint]); // Empty dependency array ensures this effect runs only once on mount\n\n return result;\n};\n"],"names":[],"mappings":";;AAMa,MAAA,wBAAwB,CAAC,eAAkC;AACtE,UAAQ,YAAY;AAAA,IAClB,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT;AACS,aAAA;AAAA,EAAA;AAEb;AAEO,MAAM,yBAAyB,MAA2B;AAC3D,MAAA,OAAO,WAAW,YAAa;AAE7B,QAAA,YAAY,OAAO,WAAW;AAEhC,MAAA,OAAO,cAAc,YAAa;AAEtC,SAAO,mVAAmV;AAAA,IACxV;AAAA,EACF;AACF;AAEO,MAAM,8BAA8B,MAA2B;AAChE,MAAA,OAAO,WAAW,YAAa;AAE7B,QAAA,YAAY,OAAO,WAAW;AAG9B,QAAA,WACJ,cAAc,KAAK,SAAS;AAAA,EAC5B,CAAC,8BAA8B,KAAK,SAAS;AAGzC,QAAA,gBAAgB,6BAA6B,KAAK,SAAS;AAEjE,SAAO,YAAY;AACrB;AAEa,MAAA,sBAAsB,CACjC,eACwB;AACpB,MAAA,OAAO,WAAW,YAAa;AAE3B,UAAA,QAAQ,cAAc,MAAM;AACtC;AAQa,MAAA,oBAAoB,CAAC,aAAgC,SAAS;AACnE,QAAA,kBAAkB,sBAAsB,UAAU;AAExD,QAAM,oBAAoB,uBAAuB;AAC3C,QAAA,iBAAiB,oBAAoB,eAAe;AAC1D,QAAM,WAAW,kBAAkB;AAE5B,SAAA;AAAA,IACL;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,EACF;AACF;AAEa,MAAA,YAAY,CAAC,aAAgC,SAAS;AAC3D,QAAA,CAAC,QAAQ,SAAS,IAAI;AAAA,IAC1B,kBAAkB,UAAU;AAAA,EAC9B;AAEA,YAAU,MAAM;AACd,UAAM,eAAe,MAAM;AACf,gBAAA,kBAAkB,UAAU,CAAC;AAAA,IACzC;AAEA,WAAO,iBAAiB,UAAU,cAAc,EAAE,SAAS,MAAM;AAGjE,WAAO,MAAM,OAAO,oBAAoB,UAAU,YAAY;AAAA,EAAA,GAC7D,CAAC,UAAU,CAAC;AAER,SAAA;AACT;"}
|
|
@@ -75,7 +75,7 @@ export declare const useIntlayerAuth: (props?: UseIntlayerAuthProps) => {
|
|
|
75
75
|
auditContentDeclarationField: (body?: import('@intlayer/backend').AuditContentDeclarationFieldBody, otherOptions?: FetcherOptions) => Promise<import('@intlayer/backend').AuditContentDeclarationFieldResult>;
|
|
76
76
|
auditContentDeclarationMetadata: (body?: import('@intlayer/backend').AuditContentDeclarationMetadataBody, otherOptions?: FetcherOptions) => Promise<import('@intlayer/backend').AuditContentDeclarationMetadataResult>;
|
|
77
77
|
auditTag: (body?: import('@intlayer/backend').AuditTagBody, otherOptions?: FetcherOptions) => Promise<import('@intlayer/backend').AuditTagResult>;
|
|
78
|
-
askDocQuestion: (body?: import('
|
|
78
|
+
askDocQuestion: (body?: import('node_modules/@intlayer/api/dist/types/getIntlayerAPI/ai').AskDocQuestionBody, otherOptions?: FetcherOptions) => Promise<void>;
|
|
79
79
|
autocomplete: (body?: import('@intlayer/backend').AutocompleteBody, otherOptions?: FetcherOptions) => Promise<import('@intlayer/backend').AutocompleteResponse>;
|
|
80
80
|
};
|
|
81
81
|
tag: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIntlayerAPI.d.ts","sourceRoot":"","sources":["../../src/hooks/useIntlayerAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAI9D,KAAK,oBAAoB,GAAG;IAC1B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,qBAAqB,CAAC,EAAE,cAAc,CAAC;CACxC,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,oBAAoB;;kCAJ1D,CAAD,SAAS,mBACT,sCAAsC,CAAC,oCAGT,mBAAkB;iDAEnC,mBAAmB,sDAED,CAAC,oCAErB,mBAAmB;+CAIlB,mBAAkB,mCAE7B,CAAF,oCAEM,mBACG;6CAGmB,mBAAmB,yCAGjB,CAAC,oCAAoC,mBAAmB;kDAAkF,mBAAmB,sCAAsC,CAAC,oCAAoC,mBAAmB;iDAA8E,mBAAmB,6CAA6C,CAAC,oCAAoC,mBAAmB;yCAA6E,CAAC,oCAAoC,mBAAmB;oDAAiF,mBAAmB,yDAAyD,CAAC,oCAAoC,mBAAmB;2CAAwE,CAAC,oCAAoC,mBAAmB;;;6BAAkF,CAAC,SAAS,mBAAmB,iCAAiC,CAAC,oCAAoC,mBAAmB;qCAA2D,mBAAmB,8BAA8B,CAAC,oCAAoC,mBAAmB;wCAA6D,mBAAmB,iCAAiC,CAAC,oCAAoC,mBAAmB;4CAAoE,mBAAmB,wCAAwC,CAAC,oCAAoC,mBAAmB;gEAA+F,mBAAmB,4CAA4C,CAAC,oCAAoC,mBAAmB;oCAAuE,CAAC,oCAAoC,mBAAmB;0CAAkE,mBAAmB,+CAA+C,CAAC,oCAAoC,mBAAmB;sCAA8D,CAAC,oCAAoC,mBAAmB;4CAAsE,mBAAmB,mCAAmC,CAAC,oCAAoC,mBAAmB;2CAAuE,mBAAmB,+CAA+C,CAAC,oCAAoC,mBAAmB;4CAAwE,mBAAmB,gDAAgD,CAAC,oCAAoC,mBAAmB;;;kCAAkF,mBAAmB,8BAA8B,CAAC,oCAAoC,mBAAmB;0BAA+C,CAAC,SAAS,mBAAmB,8BAA8B,CAAC,oCAAoC,mBAAmB;qCAAwD,mBAAmB,2CAA2C,CAAC,oCAAoC,mBAAmB;qDAA2E,mBAAmB,gEAAgE,mBAAmB,kDAAkD,CAAC,oCAAoC,mBAAmB;uCAAkE,mBAAmB,6CAA6C,CAAC,oCAAoC,mBAAmB;kCAA2D,mBAAmB,8BAA8B,CAAC,oCAAoC,mBAAmB;iDAAsE,CAAC,oCAAoC,mBAAmB;;;6BAAqE,mBAAmB,yBAAyB,CAAC,oCAAoC,mBAAmB;+CAA+D,mBAAmB;+CAAoF,mBAAmB;gCAAqE,mBAAmB,qBAAqB,CAAC,SAAS,mBAAmB,6BAA6B,CAAC,oCAAoC,mBAAmB;6BAAgD,CAAC;gCAAmE,mBAAoB,cAAc,CAAC,6BAA6B,mBAAmB;yCAA4C,mBAAmB,kCAAkC,CAAC,oCAAoC,mBAAmB;yCAAkE,mBAAmB,6CAA6C,CAAC,oCAAoC,mBAAmB;6CAAwE,CAAC,oCAAoC,mBAAmB;iDAAkF,mBAAmB,gCAAgC,CAAC,oCAAoC,mBAAmB;0DAA+E,mBAAmB;sCAAmE,mBAAmB,kCAAkC,CAAC,oCAAoC,mBAAmB;qCAA8D,mBAAmB,iCAAiC,CAAC,oCAAoC,mBAAmB;iCAAyD,CAAC,SAAS,mBAAmB,2DAA2D,CAAC,oCAAoC,mBAAmB;mCAAmE,CAAC,oCAAoC,mBAAmB;2CAAkE,CAAC,oCAAoC,mBAAmB;;;iCAAmF,CAAC,SAAS,mBAAmB,qCAAqC,CAAC,oCAAoC,mBAAmB;0CAAoE,CAAC,oCAAoC,mBAAmB;8CAA4E,mBAAmB,+CAA+C,CAAC,SAAS,mBAAmB,6CAA6C,CAAC,oCAAoC,mBAAmB;gDAAwE,mBAAmB,oDAAoD,CAAC,oCAAoC,mBAAmB;qCAAgE,mBAAmB,iCAAiC,CAAC,oCAAoC,mBAAmB;gDAAwE,mBAAmB,4DAA4D,mBAAmB,oCAAoC,CAAC,oCAAoC,mBAAmB;sCAAiE,mBAAmB,qDAAqD,CAAC,oCAAoC,mBAAmB;;;yBAAyE,CAAC,SAAS,mBAAmB,8BAA8B,CAAC,oCAAoC,mBAAmB;8BAAmD,CAAC,SAAS,mBAAmB,sCAAsC,CAAC,oCAAoC,mBAAmB;yCAAsE,CAAC,oCAAoC,mBAAmB;;;sCAAoF,CAAC,SAAS,mBAAmB,2CAA2C,CAAC,oCAAoC,mBAAmB;2CAA6E,CAAC,SAAS,mBAAmB,gDAAgD,CAAC,oCAAoC,mBAAmB;8CAAqF,CAAC,SAAS,mBAAmB,mDAAmD,CAAC,oCAAoC,mBAAmB;uBAAiE,CAAC,SAAS,mBAAmB,4BAA4B,CAAC,oCAAoC,mBAAmB;6BAAgD,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"useIntlayerAPI.d.ts","sourceRoot":"","sources":["../../src/hooks/useIntlayerAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAI9D,KAAK,oBAAoB,GAAG;IAC1B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,qBAAqB,CAAC,EAAE,cAAc,CAAC;CACxC,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,oBAAoB;;kCAJ1D,CAAD,SAAS,mBACT,sCAAsC,CAAC,oCAGT,mBAAkB;iDAEnC,mBAAmB,sDAED,CAAC,oCAErB,mBAAmB;+CAIlB,mBAAkB,mCAE7B,CAAF,oCAEM,mBACG;6CAGmB,mBAAmB,yCAGjB,CAAC,oCAAoC,mBAAmB;kDAAkF,mBAAmB,sCAAsC,CAAC,oCAAoC,mBAAmB;iDAA8E,mBAAmB,6CAA6C,CAAC,oCAAoC,mBAAmB;yCAA6E,CAAC,oCAAoC,mBAAmB;oDAAiF,mBAAmB,yDAAyD,CAAC,oCAAoC,mBAAmB;2CAAwE,CAAC,oCAAoC,mBAAmB;;;6BAAkF,CAAC,SAAS,mBAAmB,iCAAiC,CAAC,oCAAoC,mBAAmB;qCAA2D,mBAAmB,8BAA8B,CAAC,oCAAoC,mBAAmB;wCAA6D,mBAAmB,iCAAiC,CAAC,oCAAoC,mBAAmB;4CAAoE,mBAAmB,wCAAwC,CAAC,oCAAoC,mBAAmB;gEAA+F,mBAAmB,4CAA4C,CAAC,oCAAoC,mBAAmB;oCAAuE,CAAC,oCAAoC,mBAAmB;0CAAkE,mBAAmB,+CAA+C,CAAC,oCAAoC,mBAAmB;sCAA8D,CAAC,oCAAoC,mBAAmB;4CAAsE,mBAAmB,mCAAmC,CAAC,oCAAoC,mBAAmB;2CAAuE,mBAAmB,+CAA+C,CAAC,oCAAoC,mBAAmB;4CAAwE,mBAAmB,gDAAgD,CAAC,oCAAoC,mBAAmB;;;kCAAkF,mBAAmB,8BAA8B,CAAC,oCAAoC,mBAAmB;0BAA+C,CAAC,SAAS,mBAAmB,8BAA8B,CAAC,oCAAoC,mBAAmB;qCAAwD,mBAAmB,2CAA2C,CAAC,oCAAoC,mBAAmB;qDAA2E,mBAAmB,gEAAgE,mBAAmB,kDAAkD,CAAC,oCAAoC,mBAAmB;uCAAkE,mBAAmB,6CAA6C,CAAC,oCAAoC,mBAAmB;kCAA2D,mBAAmB,8BAA8B,CAAC,oCAAoC,mBAAmB;iDAAsE,CAAC,oCAAoC,mBAAmB;;;6BAAqE,mBAAmB,yBAAyB,CAAC,oCAAoC,mBAAmB;+CAA+D,mBAAmB;+CAAoF,mBAAmB;gCAAqE,mBAAmB,qBAAqB,CAAC,SAAS,mBAAmB,6BAA6B,CAAC,oCAAoC,mBAAmB;6BAAgD,CAAC;gCAAmE,mBAAoB,cAAc,CAAC,6BAA6B,mBAAmB;yCAA4C,mBAAmB,kCAAkC,CAAC,oCAAoC,mBAAmB;yCAAkE,mBAAmB,6CAA6C,CAAC,oCAAoC,mBAAmB;6CAAwE,CAAC,oCAAoC,mBAAmB;iDAAkF,mBAAmB,gCAAgC,CAAC,oCAAoC,mBAAmB;0DAA+E,mBAAmB;sCAAmE,mBAAmB,kCAAkC,CAAC,oCAAoC,mBAAmB;qCAA8D,mBAAmB,iCAAiC,CAAC,oCAAoC,mBAAmB;iCAAyD,CAAC,SAAS,mBAAmB,2DAA2D,CAAC,oCAAoC,mBAAmB;mCAAmE,CAAC,oCAAoC,mBAAmB;2CAAkE,CAAC,oCAAoC,mBAAmB;;;iCAAmF,CAAC,SAAS,mBAAmB,qCAAqC,CAAC,oCAAoC,mBAAmB;0CAAoE,CAAC,oCAAoC,mBAAmB;8CAA4E,mBAAmB,+CAA+C,CAAC,SAAS,mBAAmB,6CAA6C,CAAC,oCAAoC,mBAAmB;gDAAwE,mBAAmB,oDAAoD,CAAC,oCAAoC,mBAAmB;qCAAgE,mBAAmB,iCAAiC,CAAC,oCAAoC,mBAAmB;gDAAwE,mBAAmB,4DAA4D,mBAAmB,oCAAoC,CAAC,oCAAoC,mBAAmB;sCAAiE,mBAAmB,qDAAqD,CAAC,oCAAoC,mBAAmB;;;yBAAyE,CAAC,SAAS,mBAAmB,8BAA8B,CAAC,oCAAoC,mBAAmB;8BAAmD,CAAC,SAAS,mBAAmB,sCAAsC,CAAC,oCAAoC,mBAAmB;yCAAsE,CAAC,oCAAoC,mBAAmB;;;sCAAoF,CAAC,SAAS,mBAAmB,2CAA2C,CAAC,oCAAoC,mBAAmB;2CAA6E,CAAC,SAAS,mBAAmB,gDAAgD,CAAC,oCAAoC,mBAAmB;8CAAqF,CAAC,SAAS,mBAAmB,mDAAmD,CAAC,oCAAoC,mBAAmB;uBAAiE,CAAC,SAAS,mBAAmB,4BAA4B,CAAC,oCAAoC,mBAAmB;6BAAgD,CAAC,SAAS,yDAAM,kCAAkC,CAAC;2BAA+D,CAAC,SAAS,mBAAmB,gCAAgC,CAAC,oCAAoC,mBAAmB;;;yBAAoE,CAAC,SAAS,mBAAmB,6BAA6B,CAAC,oCAAoC,mBAAmB;6BAA+C,mBAAmB,0BAA0B,CAAC,oCAAoC,mBAAmB;kCAAmD,mBAAmB,wCAAwC,mBAAmB,6BAA6B,CAAC,oCAAoC,mBAAmB;kCAAsD,mBAAmB,wCAAwC,CAAC,oCAAoC,mBAAmB;;;uCAAgF,CAAC,6BAA6B,sBAAsB;sCAAwC,2BAA4B,cAAc,CAAC,6BAA6B,6BAA6B;;CADxvU,CAAC"}
|
|
@@ -77,8 +77,12 @@ const useItemSelector = (optionsRefs, selector = selectorDefault, isHoverable =
|
|
|
77
77
|
};
|
|
78
78
|
if (isHoverable) {
|
|
79
79
|
optionsRefs.current.forEach((option) => {
|
|
80
|
-
option?.addEventListener("mouseenter", handleMouseEnter
|
|
81
|
-
|
|
80
|
+
option?.addEventListener("mouseenter", handleMouseEnter, {
|
|
81
|
+
passive: true
|
|
82
|
+
});
|
|
83
|
+
option?.addEventListener("mouseleave", handleMouseLeave, {
|
|
84
|
+
passive: true
|
|
85
|
+
});
|
|
82
86
|
});
|
|
83
87
|
}
|
|
84
88
|
return () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useItemSelector.cjs","sources":["../../src/hooks/useItemSelector.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, type MutableRefObject } from 'react';\n\ntype StyleState = {\n left: number;\n width: number;\n opacity: number;\n};\n\nconst selectorDefault = (option: HTMLElement) =>\n option?.getAttribute('aria-selected') === 'true';\n\nexport const useItemSelector = (\n optionsRefs: MutableRefObject<HTMLElement[]>,\n selector: (option: HTMLElement, index: number) => boolean = selectorDefault,\n isHoverable = false\n) => {\n const [choiceIndicatorPosition, setChoiceIndicatorPosition] =\n useState<StyleState | null>(null);\n\n const [hoveredItem, setHoveredItem] = useState<HTMLElement | null>(null);\n\n const itemsLength = optionsRefs.current.length;\n\n useEffect(() => {\n const calculatePosition = () => {\n let targetElement: HTMLElement | null = null;\n\n if (hoveredItem) {\n targetElement = hoveredItem;\n } else {\n targetElement = optionsRefs.current.find(selector) ?? null;\n }\n\n if (!targetElement) {\n setChoiceIndicatorPosition((prev) => ({\n left: 0,\n width: 0,\n ...prev,\n opacity: 0,\n }));\n return;\n }\n\n const left = targetElement.offsetLeft;\n const width = targetElement.offsetWidth;\n\n setChoiceIndicatorPosition({\n left,\n width,\n opacity: 1,\n });\n };\n\n calculatePosition();\n\n // Event listeners for window events\n window.addEventListener('resize', calculatePosition);\n window.addEventListener('DOMContentLoaded', calculatePosition);\n\n // MutationObserver to watch for 'aria-selected' changes\n const mutationObservers: MutationObserver[] = [];\n\n optionsRefs.current.forEach((option) => {\n if (option) {\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'aria-selected'\n ) {\n calculatePosition();\n break;\n }\n }\n });\n\n observer.observe(option, {\n attributes: true,\n attributeFilter: ['aria-selected'],\n });\n\n mutationObservers.push(observer);\n }\n });\n\n // ResizeObserver to watch for size changes\n const resizeObservers: ResizeObserver[] = [];\n\n const observeSize = (element: HTMLElement) => {\n if (!element) return;\n const resizeObserver = new ResizeObserver(() => {\n calculatePosition();\n });\n resizeObserver.observe(element);\n resizeObservers.push(resizeObserver);\n };\n\n // Observe the selected item\n const selectedItem = optionsRefs.current.find(selector) ?? null;\n\n if (selectedItem) {\n observeSize(selectedItem);\n }\n\n // Observe the hovered item\n if (hoveredItem) {\n observeSize(hoveredItem);\n }\n\n // Add hover event listeners\n const handleMouseEnter = (event: Event) => {\n setHoveredItem(event.currentTarget as HTMLElement);\n };\n\n const handleMouseLeave = () => {\n setHoveredItem(null);\n };\n\n if (isHoverable) {\n optionsRefs.current.forEach((option) => {\n option?.addEventListener('mouseenter', handleMouseEnter);\n option?.addEventListener('mouseleave', handleMouseLeave);\n });\n }\n\n return () => {\n // Cleanup window event listeners\n window.removeEventListener('resize', calculatePosition);\n window.removeEventListener('DOMContentLoaded', calculatePosition);\n\n // Disconnect MutationObservers\n mutationObservers.forEach((observer) => observer.disconnect());\n\n // Disconnect ResizeObservers\n resizeObservers.forEach((observer) => observer.disconnect());\n\n // Remove hover event listeners\n optionsRefs.current.forEach((option) => {\n option?.removeEventListener('mouseenter', handleMouseEnter);\n option?.removeEventListener('mouseleave', handleMouseLeave);\n });\n };\n }, [optionsRefs, selector, hoveredItem, itemsLength]);\n\n return { choiceIndicatorPosition };\n};\n"],"names":["useState","useEffect"],"mappings":";;;;AAUA,MAAM,kBAAkB,CAAC,WACvB,QAAQ,aAAa,eAAe,MAAM;AAErC,MAAM,kBAAkB,CAC7B,aACA,WAA4D,iBAC5D,cAAc,UACX;AACH,QAAM,CAAC,yBAAyB,0BAA0B,IACxDA,aAAAA,SAA4B,IAAI;AAElC,QAAM,CAAC,aAAa,cAAc,IAAIA,aAAAA,SAA6B,IAAI;AAEjE,QAAA,cAAc,YAAY,QAAQ;AAExCC,eAAAA,UAAU,MAAM;AACd,UAAM,oBAAoB,MAAM;AAC9B,UAAI,gBAAoC;AAExC,UAAI,aAAa;AACC,wBAAA;AAAA,MAAA,OACX;AACL,wBAAgB,YAAY,QAAQ,KAAK,QAAQ,KAAK;AAAA,MAAA;AAGxD,UAAI,CAAC,eAAe;AAClB,mCAA2B,CAAC,UAAU;AAAA,UACpC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,GAAG;AAAA,UACH,SAAS;AAAA,QAAA,EACT;AACF;AAAA,MAAA;AAGF,YAAM,OAAO,cAAc;AAC3B,YAAM,QAAQ,cAAc;AAED,iCAAA;AAAA,QACzB;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MAAA,CACV;AAAA,IACH;AAEkB,sBAAA;AAGX,WAAA,iBAAiB,UAAU,iBAAiB;AAC5C,WAAA,iBAAiB,oBAAoB,iBAAiB;AAG7D,UAAM,oBAAwC,CAAC;AAEnC,gBAAA,QAAQ,QAAQ,CAAC,WAAW;AACtC,UAAI,QAAQ;AACV,cAAM,WAAW,IAAI,iBAAiB,CAAC,cAAc;AACnD,qBAAW,YAAY,WAAW;AAChC,gBACE,SAAS,SAAS,gBAClB,SAAS,kBAAkB,iBAC3B;AACkB,gCAAA;AAClB;AAAA,YAAA;AAAA,UACF;AAAA,QACF,CACD;AAED,iBAAS,QAAQ,QAAQ;AAAA,UACvB,YAAY;AAAA,UACZ,iBAAiB,CAAC,eAAe;AAAA,QAAA,CAClC;AAED,0BAAkB,KAAK,QAAQ;AAAA,MAAA;AAAA,IACjC,CACD;AAGD,UAAM,kBAAoC,CAAC;AAErC,UAAA,cAAc,CAAC,YAAyB;AAC5C,UAAI,CAAC,QAAS;AACR,YAAA,iBAAiB,IAAI,eAAe,MAAM;AAC5B,0BAAA;AAAA,MAAA,CACnB;AACD,qBAAe,QAAQ,OAAO;AAC9B,sBAAgB,KAAK,cAAc;AAAA,IACrC;AAGA,UAAM,eAAe,YAAY,QAAQ,KAAK,QAAQ,KAAK;AAE3D,QAAI,cAAc;AAChB,kBAAY,YAAY;AAAA,IAAA;AAI1B,QAAI,aAAa;AACf,kBAAY,WAAW;AAAA,IAAA;AAInB,UAAA,mBAAmB,CAAC,UAAiB;AACzC,qBAAe,MAAM,aAA4B;AAAA,IACnD;AAEA,UAAM,mBAAmB,MAAM;AAC7B,qBAAe,IAAI;AAAA,IACrB;AAEA,QAAI,aAAa;AACH,kBAAA,QAAQ,QAAQ,CAAC,WAAW;AAC9B,gBAAA,iBAAiB,cAAc,
|
|
1
|
+
{"version":3,"file":"useItemSelector.cjs","sources":["../../src/hooks/useItemSelector.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, type MutableRefObject } from 'react';\n\ntype StyleState = {\n left: number;\n width: number;\n opacity: number;\n};\n\nconst selectorDefault = (option: HTMLElement) =>\n option?.getAttribute('aria-selected') === 'true';\n\nexport const useItemSelector = (\n optionsRefs: MutableRefObject<HTMLElement[]>,\n selector: (option: HTMLElement, index: number) => boolean = selectorDefault,\n isHoverable = false\n) => {\n const [choiceIndicatorPosition, setChoiceIndicatorPosition] =\n useState<StyleState | null>(null);\n\n const [hoveredItem, setHoveredItem] = useState<HTMLElement | null>(null);\n\n const itemsLength = optionsRefs.current.length;\n\n useEffect(() => {\n const calculatePosition = () => {\n let targetElement: HTMLElement | null = null;\n\n if (hoveredItem) {\n targetElement = hoveredItem;\n } else {\n targetElement = optionsRefs.current.find(selector) ?? null;\n }\n\n if (!targetElement) {\n setChoiceIndicatorPosition((prev) => ({\n left: 0,\n width: 0,\n ...prev,\n opacity: 0,\n }));\n return;\n }\n\n const left = targetElement.offsetLeft;\n const width = targetElement.offsetWidth;\n\n setChoiceIndicatorPosition({\n left,\n width,\n opacity: 1,\n });\n };\n\n calculatePosition();\n\n // Event listeners for window events\n window.addEventListener('resize', calculatePosition);\n window.addEventListener('DOMContentLoaded', calculatePosition);\n\n // MutationObserver to watch for 'aria-selected' changes\n const mutationObservers: MutationObserver[] = [];\n\n optionsRefs.current.forEach((option) => {\n if (option) {\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'aria-selected'\n ) {\n calculatePosition();\n break;\n }\n }\n });\n\n observer.observe(option, {\n attributes: true,\n attributeFilter: ['aria-selected'],\n });\n\n mutationObservers.push(observer);\n }\n });\n\n // ResizeObserver to watch for size changes\n const resizeObservers: ResizeObserver[] = [];\n\n const observeSize = (element: HTMLElement) => {\n if (!element) return;\n const resizeObserver = new ResizeObserver(() => {\n calculatePosition();\n });\n resizeObserver.observe(element);\n resizeObservers.push(resizeObserver);\n };\n\n // Observe the selected item\n const selectedItem = optionsRefs.current.find(selector) ?? null;\n\n if (selectedItem) {\n observeSize(selectedItem);\n }\n\n // Observe the hovered item\n if (hoveredItem) {\n observeSize(hoveredItem);\n }\n\n // Add hover event listeners\n const handleMouseEnter = (event: Event) => {\n setHoveredItem(event.currentTarget as HTMLElement);\n };\n\n const handleMouseLeave = () => {\n setHoveredItem(null);\n };\n\n if (isHoverable) {\n optionsRefs.current.forEach((option) => {\n option?.addEventListener('mouseenter', handleMouseEnter, {\n passive: true,\n });\n option?.addEventListener('mouseleave', handleMouseLeave, {\n passive: true,\n });\n });\n }\n\n return () => {\n // Cleanup window event listeners\n window.removeEventListener('resize', calculatePosition);\n window.removeEventListener('DOMContentLoaded', calculatePosition);\n\n // Disconnect MutationObservers\n mutationObservers.forEach((observer) => observer.disconnect());\n\n // Disconnect ResizeObservers\n resizeObservers.forEach((observer) => observer.disconnect());\n\n // Remove hover event listeners\n optionsRefs.current.forEach((option) => {\n option?.removeEventListener('mouseenter', handleMouseEnter);\n option?.removeEventListener('mouseleave', handleMouseLeave);\n });\n };\n }, [optionsRefs, selector, hoveredItem, itemsLength]);\n\n return { choiceIndicatorPosition };\n};\n"],"names":["useState","useEffect"],"mappings":";;;;AAUA,MAAM,kBAAkB,CAAC,WACvB,QAAQ,aAAa,eAAe,MAAM;AAErC,MAAM,kBAAkB,CAC7B,aACA,WAA4D,iBAC5D,cAAc,UACX;AACH,QAAM,CAAC,yBAAyB,0BAA0B,IACxDA,aAAAA,SAA4B,IAAI;AAElC,QAAM,CAAC,aAAa,cAAc,IAAIA,aAAAA,SAA6B,IAAI;AAEjE,QAAA,cAAc,YAAY,QAAQ;AAExCC,eAAAA,UAAU,MAAM;AACd,UAAM,oBAAoB,MAAM;AAC9B,UAAI,gBAAoC;AAExC,UAAI,aAAa;AACC,wBAAA;AAAA,MAAA,OACX;AACL,wBAAgB,YAAY,QAAQ,KAAK,QAAQ,KAAK;AAAA,MAAA;AAGxD,UAAI,CAAC,eAAe;AAClB,mCAA2B,CAAC,UAAU;AAAA,UACpC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,GAAG;AAAA,UACH,SAAS;AAAA,QAAA,EACT;AACF;AAAA,MAAA;AAGF,YAAM,OAAO,cAAc;AAC3B,YAAM,QAAQ,cAAc;AAED,iCAAA;AAAA,QACzB;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MAAA,CACV;AAAA,IACH;AAEkB,sBAAA;AAGX,WAAA,iBAAiB,UAAU,iBAAiB;AAC5C,WAAA,iBAAiB,oBAAoB,iBAAiB;AAG7D,UAAM,oBAAwC,CAAC;AAEnC,gBAAA,QAAQ,QAAQ,CAAC,WAAW;AACtC,UAAI,QAAQ;AACV,cAAM,WAAW,IAAI,iBAAiB,CAAC,cAAc;AACnD,qBAAW,YAAY,WAAW;AAChC,gBACE,SAAS,SAAS,gBAClB,SAAS,kBAAkB,iBAC3B;AACkB,gCAAA;AAClB;AAAA,YAAA;AAAA,UACF;AAAA,QACF,CACD;AAED,iBAAS,QAAQ,QAAQ;AAAA,UACvB,YAAY;AAAA,UACZ,iBAAiB,CAAC,eAAe;AAAA,QAAA,CAClC;AAED,0BAAkB,KAAK,QAAQ;AAAA,MAAA;AAAA,IACjC,CACD;AAGD,UAAM,kBAAoC,CAAC;AAErC,UAAA,cAAc,CAAC,YAAyB;AAC5C,UAAI,CAAC,QAAS;AACR,YAAA,iBAAiB,IAAI,eAAe,MAAM;AAC5B,0BAAA;AAAA,MAAA,CACnB;AACD,qBAAe,QAAQ,OAAO;AAC9B,sBAAgB,KAAK,cAAc;AAAA,IACrC;AAGA,UAAM,eAAe,YAAY,QAAQ,KAAK,QAAQ,KAAK;AAE3D,QAAI,cAAc;AAChB,kBAAY,YAAY;AAAA,IAAA;AAI1B,QAAI,aAAa;AACf,kBAAY,WAAW;AAAA,IAAA;AAInB,UAAA,mBAAmB,CAAC,UAAiB;AACzC,qBAAe,MAAM,aAA4B;AAAA,IACnD;AAEA,UAAM,mBAAmB,MAAM;AAC7B,qBAAe,IAAI;AAAA,IACrB;AAEA,QAAI,aAAa;AACH,kBAAA,QAAQ,QAAQ,CAAC,WAAW;AAC9B,gBAAA,iBAAiB,cAAc,kBAAkB;AAAA,UACvD,SAAS;AAAA,QAAA,CACV;AACO,gBAAA,iBAAiB,cAAc,kBAAkB;AAAA,UACvD,SAAS;AAAA,QAAA,CACV;AAAA,MAAA,CACF;AAAA,IAAA;AAGH,WAAO,MAAM;AAEJ,aAAA,oBAAoB,UAAU,iBAAiB;AAC/C,aAAA,oBAAoB,oBAAoB,iBAAiB;AAGhE,wBAAkB,QAAQ,CAAC,aAAa,SAAS,YAAY;AAG7D,sBAAgB,QAAQ,CAAC,aAAa,SAAS,YAAY;AAG/C,kBAAA,QAAQ,QAAQ,CAAC,WAAW;AAC9B,gBAAA,oBAAoB,cAAc,gBAAgB;AAClD,gBAAA,oBAAoB,cAAc,gBAAgB;AAAA,MAAA,CAC3D;AAAA,IACH;AAAA,KACC,CAAC,aAAa,UAAU,aAAa,WAAW,CAAC;AAEpD,SAAO,EAAE,wBAAwB;AACnC;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useItemSelector.d.ts","sourceRoot":"","sources":["../../src/hooks/useItemSelector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAEnE,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAKF,eAAO,MAAM,eAAe,GAC1B,aAAa,gBAAgB,CAAC,WAAW,EAAE,CAAC,EAC5C,WAAU,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,KAAK,OAAyB,EAC3E,qBAAmB;;
|
|
1
|
+
{"version":3,"file":"useItemSelector.d.ts","sourceRoot":"","sources":["../../src/hooks/useItemSelector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAEnE,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAKF,eAAO,MAAM,eAAe,GAC1B,aAAa,gBAAgB,CAAC,WAAW,EAAE,CAAC,EAC5C,WAAU,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,KAAK,OAAyB,EAC3E,qBAAmB;;CAuIpB,CAAC"}
|
|
@@ -75,8 +75,12 @@ const useItemSelector = (optionsRefs, selector = selectorDefault, isHoverable =
|
|
|
75
75
|
};
|
|
76
76
|
if (isHoverable) {
|
|
77
77
|
optionsRefs.current.forEach((option) => {
|
|
78
|
-
option?.addEventListener("mouseenter", handleMouseEnter
|
|
79
|
-
|
|
78
|
+
option?.addEventListener("mouseenter", handleMouseEnter, {
|
|
79
|
+
passive: true
|
|
80
|
+
});
|
|
81
|
+
option?.addEventListener("mouseleave", handleMouseLeave, {
|
|
82
|
+
passive: true
|
|
83
|
+
});
|
|
80
84
|
});
|
|
81
85
|
}
|
|
82
86
|
return () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useItemSelector.mjs","sources":["../../src/hooks/useItemSelector.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, type MutableRefObject } from 'react';\n\ntype StyleState = {\n left: number;\n width: number;\n opacity: number;\n};\n\nconst selectorDefault = (option: HTMLElement) =>\n option?.getAttribute('aria-selected') === 'true';\n\nexport const useItemSelector = (\n optionsRefs: MutableRefObject<HTMLElement[]>,\n selector: (option: HTMLElement, index: number) => boolean = selectorDefault,\n isHoverable = false\n) => {\n const [choiceIndicatorPosition, setChoiceIndicatorPosition] =\n useState<StyleState | null>(null);\n\n const [hoveredItem, setHoveredItem] = useState<HTMLElement | null>(null);\n\n const itemsLength = optionsRefs.current.length;\n\n useEffect(() => {\n const calculatePosition = () => {\n let targetElement: HTMLElement | null = null;\n\n if (hoveredItem) {\n targetElement = hoveredItem;\n } else {\n targetElement = optionsRefs.current.find(selector) ?? null;\n }\n\n if (!targetElement) {\n setChoiceIndicatorPosition((prev) => ({\n left: 0,\n width: 0,\n ...prev,\n opacity: 0,\n }));\n return;\n }\n\n const left = targetElement.offsetLeft;\n const width = targetElement.offsetWidth;\n\n setChoiceIndicatorPosition({\n left,\n width,\n opacity: 1,\n });\n };\n\n calculatePosition();\n\n // Event listeners for window events\n window.addEventListener('resize', calculatePosition);\n window.addEventListener('DOMContentLoaded', calculatePosition);\n\n // MutationObserver to watch for 'aria-selected' changes\n const mutationObservers: MutationObserver[] = [];\n\n optionsRefs.current.forEach((option) => {\n if (option) {\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'aria-selected'\n ) {\n calculatePosition();\n break;\n }\n }\n });\n\n observer.observe(option, {\n attributes: true,\n attributeFilter: ['aria-selected'],\n });\n\n mutationObservers.push(observer);\n }\n });\n\n // ResizeObserver to watch for size changes\n const resizeObservers: ResizeObserver[] = [];\n\n const observeSize = (element: HTMLElement) => {\n if (!element) return;\n const resizeObserver = new ResizeObserver(() => {\n calculatePosition();\n });\n resizeObserver.observe(element);\n resizeObservers.push(resizeObserver);\n };\n\n // Observe the selected item\n const selectedItem = optionsRefs.current.find(selector) ?? null;\n\n if (selectedItem) {\n observeSize(selectedItem);\n }\n\n // Observe the hovered item\n if (hoveredItem) {\n observeSize(hoveredItem);\n }\n\n // Add hover event listeners\n const handleMouseEnter = (event: Event) => {\n setHoveredItem(event.currentTarget as HTMLElement);\n };\n\n const handleMouseLeave = () => {\n setHoveredItem(null);\n };\n\n if (isHoverable) {\n optionsRefs.current.forEach((option) => {\n option?.addEventListener('mouseenter', handleMouseEnter);\n option?.addEventListener('mouseleave', handleMouseLeave);\n });\n }\n\n return () => {\n // Cleanup window event listeners\n window.removeEventListener('resize', calculatePosition);\n window.removeEventListener('DOMContentLoaded', calculatePosition);\n\n // Disconnect MutationObservers\n mutationObservers.forEach((observer) => observer.disconnect());\n\n // Disconnect ResizeObservers\n resizeObservers.forEach((observer) => observer.disconnect());\n\n // Remove hover event listeners\n optionsRefs.current.forEach((option) => {\n option?.removeEventListener('mouseenter', handleMouseEnter);\n option?.removeEventListener('mouseleave', handleMouseLeave);\n });\n };\n }, [optionsRefs, selector, hoveredItem, itemsLength]);\n\n return { choiceIndicatorPosition };\n};\n"],"names":[],"mappings":";;AAUA,MAAM,kBAAkB,CAAC,WACvB,QAAQ,aAAa,eAAe,MAAM;AAErC,MAAM,kBAAkB,CAC7B,aACA,WAA4D,iBAC5D,cAAc,UACX;AACH,QAAM,CAAC,yBAAyB,0BAA0B,IACxD,SAA4B,IAAI;AAElC,QAAM,CAAC,aAAa,cAAc,IAAI,SAA6B,IAAI;AAEjE,QAAA,cAAc,YAAY,QAAQ;AAExC,YAAU,MAAM;AACd,UAAM,oBAAoB,MAAM;AAC9B,UAAI,gBAAoC;AAExC,UAAI,aAAa;AACC,wBAAA;AAAA,MAAA,OACX;AACL,wBAAgB,YAAY,QAAQ,KAAK,QAAQ,KAAK;AAAA,MAAA;AAGxD,UAAI,CAAC,eAAe;AAClB,mCAA2B,CAAC,UAAU;AAAA,UACpC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,GAAG;AAAA,UACH,SAAS;AAAA,QAAA,EACT;AACF;AAAA,MAAA;AAGF,YAAM,OAAO,cAAc;AAC3B,YAAM,QAAQ,cAAc;AAED,iCAAA;AAAA,QACzB;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MAAA,CACV;AAAA,IACH;AAEkB,sBAAA;AAGX,WAAA,iBAAiB,UAAU,iBAAiB;AAC5C,WAAA,iBAAiB,oBAAoB,iBAAiB;AAG7D,UAAM,oBAAwC,CAAC;AAEnC,gBAAA,QAAQ,QAAQ,CAAC,WAAW;AACtC,UAAI,QAAQ;AACV,cAAM,WAAW,IAAI,iBAAiB,CAAC,cAAc;AACnD,qBAAW,YAAY,WAAW;AAChC,gBACE,SAAS,SAAS,gBAClB,SAAS,kBAAkB,iBAC3B;AACkB,gCAAA;AAClB;AAAA,YAAA;AAAA,UACF;AAAA,QACF,CACD;AAED,iBAAS,QAAQ,QAAQ;AAAA,UACvB,YAAY;AAAA,UACZ,iBAAiB,CAAC,eAAe;AAAA,QAAA,CAClC;AAED,0BAAkB,KAAK,QAAQ;AAAA,MAAA;AAAA,IACjC,CACD;AAGD,UAAM,kBAAoC,CAAC;AAErC,UAAA,cAAc,CAAC,YAAyB;AAC5C,UAAI,CAAC,QAAS;AACR,YAAA,iBAAiB,IAAI,eAAe,MAAM;AAC5B,0BAAA;AAAA,MAAA,CACnB;AACD,qBAAe,QAAQ,OAAO;AAC9B,sBAAgB,KAAK,cAAc;AAAA,IACrC;AAGA,UAAM,eAAe,YAAY,QAAQ,KAAK,QAAQ,KAAK;AAE3D,QAAI,cAAc;AAChB,kBAAY,YAAY;AAAA,IAAA;AAI1B,QAAI,aAAa;AACf,kBAAY,WAAW;AAAA,IAAA;AAInB,UAAA,mBAAmB,CAAC,UAAiB;AACzC,qBAAe,MAAM,aAA4B;AAAA,IACnD;AAEA,UAAM,mBAAmB,MAAM;AAC7B,qBAAe,IAAI;AAAA,IACrB;AAEA,QAAI,aAAa;AACH,kBAAA,QAAQ,QAAQ,CAAC,WAAW;AAC9B,gBAAA,iBAAiB,cAAc,
|
|
1
|
+
{"version":3,"file":"useItemSelector.mjs","sources":["../../src/hooks/useItemSelector.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, type MutableRefObject } from 'react';\n\ntype StyleState = {\n left: number;\n width: number;\n opacity: number;\n};\n\nconst selectorDefault = (option: HTMLElement) =>\n option?.getAttribute('aria-selected') === 'true';\n\nexport const useItemSelector = (\n optionsRefs: MutableRefObject<HTMLElement[]>,\n selector: (option: HTMLElement, index: number) => boolean = selectorDefault,\n isHoverable = false\n) => {\n const [choiceIndicatorPosition, setChoiceIndicatorPosition] =\n useState<StyleState | null>(null);\n\n const [hoveredItem, setHoveredItem] = useState<HTMLElement | null>(null);\n\n const itemsLength = optionsRefs.current.length;\n\n useEffect(() => {\n const calculatePosition = () => {\n let targetElement: HTMLElement | null = null;\n\n if (hoveredItem) {\n targetElement = hoveredItem;\n } else {\n targetElement = optionsRefs.current.find(selector) ?? null;\n }\n\n if (!targetElement) {\n setChoiceIndicatorPosition((prev) => ({\n left: 0,\n width: 0,\n ...prev,\n opacity: 0,\n }));\n return;\n }\n\n const left = targetElement.offsetLeft;\n const width = targetElement.offsetWidth;\n\n setChoiceIndicatorPosition({\n left,\n width,\n opacity: 1,\n });\n };\n\n calculatePosition();\n\n // Event listeners for window events\n window.addEventListener('resize', calculatePosition);\n window.addEventListener('DOMContentLoaded', calculatePosition);\n\n // MutationObserver to watch for 'aria-selected' changes\n const mutationObservers: MutationObserver[] = [];\n\n optionsRefs.current.forEach((option) => {\n if (option) {\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'aria-selected'\n ) {\n calculatePosition();\n break;\n }\n }\n });\n\n observer.observe(option, {\n attributes: true,\n attributeFilter: ['aria-selected'],\n });\n\n mutationObservers.push(observer);\n }\n });\n\n // ResizeObserver to watch for size changes\n const resizeObservers: ResizeObserver[] = [];\n\n const observeSize = (element: HTMLElement) => {\n if (!element) return;\n const resizeObserver = new ResizeObserver(() => {\n calculatePosition();\n });\n resizeObserver.observe(element);\n resizeObservers.push(resizeObserver);\n };\n\n // Observe the selected item\n const selectedItem = optionsRefs.current.find(selector) ?? null;\n\n if (selectedItem) {\n observeSize(selectedItem);\n }\n\n // Observe the hovered item\n if (hoveredItem) {\n observeSize(hoveredItem);\n }\n\n // Add hover event listeners\n const handleMouseEnter = (event: Event) => {\n setHoveredItem(event.currentTarget as HTMLElement);\n };\n\n const handleMouseLeave = () => {\n setHoveredItem(null);\n };\n\n if (isHoverable) {\n optionsRefs.current.forEach((option) => {\n option?.addEventListener('mouseenter', handleMouseEnter, {\n passive: true,\n });\n option?.addEventListener('mouseleave', handleMouseLeave, {\n passive: true,\n });\n });\n }\n\n return () => {\n // Cleanup window event listeners\n window.removeEventListener('resize', calculatePosition);\n window.removeEventListener('DOMContentLoaded', calculatePosition);\n\n // Disconnect MutationObservers\n mutationObservers.forEach((observer) => observer.disconnect());\n\n // Disconnect ResizeObservers\n resizeObservers.forEach((observer) => observer.disconnect());\n\n // Remove hover event listeners\n optionsRefs.current.forEach((option) => {\n option?.removeEventListener('mouseenter', handleMouseEnter);\n option?.removeEventListener('mouseleave', handleMouseLeave);\n });\n };\n }, [optionsRefs, selector, hoveredItem, itemsLength]);\n\n return { choiceIndicatorPosition };\n};\n"],"names":[],"mappings":";;AAUA,MAAM,kBAAkB,CAAC,WACvB,QAAQ,aAAa,eAAe,MAAM;AAErC,MAAM,kBAAkB,CAC7B,aACA,WAA4D,iBAC5D,cAAc,UACX;AACH,QAAM,CAAC,yBAAyB,0BAA0B,IACxD,SAA4B,IAAI;AAElC,QAAM,CAAC,aAAa,cAAc,IAAI,SAA6B,IAAI;AAEjE,QAAA,cAAc,YAAY,QAAQ;AAExC,YAAU,MAAM;AACd,UAAM,oBAAoB,MAAM;AAC9B,UAAI,gBAAoC;AAExC,UAAI,aAAa;AACC,wBAAA;AAAA,MAAA,OACX;AACL,wBAAgB,YAAY,QAAQ,KAAK,QAAQ,KAAK;AAAA,MAAA;AAGxD,UAAI,CAAC,eAAe;AAClB,mCAA2B,CAAC,UAAU;AAAA,UACpC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,GAAG;AAAA,UACH,SAAS;AAAA,QAAA,EACT;AACF;AAAA,MAAA;AAGF,YAAM,OAAO,cAAc;AAC3B,YAAM,QAAQ,cAAc;AAED,iCAAA;AAAA,QACzB;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MAAA,CACV;AAAA,IACH;AAEkB,sBAAA;AAGX,WAAA,iBAAiB,UAAU,iBAAiB;AAC5C,WAAA,iBAAiB,oBAAoB,iBAAiB;AAG7D,UAAM,oBAAwC,CAAC;AAEnC,gBAAA,QAAQ,QAAQ,CAAC,WAAW;AACtC,UAAI,QAAQ;AACV,cAAM,WAAW,IAAI,iBAAiB,CAAC,cAAc;AACnD,qBAAW,YAAY,WAAW;AAChC,gBACE,SAAS,SAAS,gBAClB,SAAS,kBAAkB,iBAC3B;AACkB,gCAAA;AAClB;AAAA,YAAA;AAAA,UACF;AAAA,QACF,CACD;AAED,iBAAS,QAAQ,QAAQ;AAAA,UACvB,YAAY;AAAA,UACZ,iBAAiB,CAAC,eAAe;AAAA,QAAA,CAClC;AAED,0BAAkB,KAAK,QAAQ;AAAA,MAAA;AAAA,IACjC,CACD;AAGD,UAAM,kBAAoC,CAAC;AAErC,UAAA,cAAc,CAAC,YAAyB;AAC5C,UAAI,CAAC,QAAS;AACR,YAAA,iBAAiB,IAAI,eAAe,MAAM;AAC5B,0BAAA;AAAA,MAAA,CACnB;AACD,qBAAe,QAAQ,OAAO;AAC9B,sBAAgB,KAAK,cAAc;AAAA,IACrC;AAGA,UAAM,eAAe,YAAY,QAAQ,KAAK,QAAQ,KAAK;AAE3D,QAAI,cAAc;AAChB,kBAAY,YAAY;AAAA,IAAA;AAI1B,QAAI,aAAa;AACf,kBAAY,WAAW;AAAA,IAAA;AAInB,UAAA,mBAAmB,CAAC,UAAiB;AACzC,qBAAe,MAAM,aAA4B;AAAA,IACnD;AAEA,UAAM,mBAAmB,MAAM;AAC7B,qBAAe,IAAI;AAAA,IACrB;AAEA,QAAI,aAAa;AACH,kBAAA,QAAQ,QAAQ,CAAC,WAAW;AAC9B,gBAAA,iBAAiB,cAAc,kBAAkB;AAAA,UACvD,SAAS;AAAA,QAAA,CACV;AACO,gBAAA,iBAAiB,cAAc,kBAAkB;AAAA,UACvD,SAAS;AAAA,QAAA,CACV;AAAA,MAAA,CACF;AAAA,IAAA;AAGH,WAAO,MAAM;AAEJ,aAAA,oBAAoB,UAAU,iBAAiB;AAC/C,aAAA,oBAAoB,oBAAoB,iBAAiB;AAGhE,wBAAkB,QAAQ,CAAC,aAAa,SAAS,YAAY;AAG7D,sBAAgB,QAAQ,CAAC,aAAa,SAAS,YAAY;AAG/C,kBAAA,QAAQ,QAAQ,CAAC,WAAW;AAC9B,gBAAA,oBAAoB,cAAc,gBAAgB;AAClD,gBAAA,oBAAoB,cAAc,gBAAgB;AAAA,MAAA,CAC3D;AAAA,IACH;AAAA,KACC,CAAC,aAAa,UAAU,aAAa,WAAW,CAAC;AAEpD,SAAO,EAAE,wBAAwB;AACnC;"}
|
|
@@ -15,7 +15,9 @@ const useKeyboardDetector = () => {
|
|
|
15
15
|
setWindowHeight(null);
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
|
-
window.visualViewport?.addEventListener("resize", updateHeight
|
|
18
|
+
window.visualViewport?.addEventListener("resize", updateHeight, {
|
|
19
|
+
passive: true
|
|
20
|
+
});
|
|
19
21
|
updateHeight();
|
|
20
22
|
return () => {
|
|
21
23
|
window.visualViewport?.removeEventListener("resize", updateHeight);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useKeyboardDetector.cjs","sources":["../../src/hooks/useKeyboardDetector.ts"],"sourcesContent":["'use client';\n\nimport {
|
|
1
|
+
{"version":3,"file":"useKeyboardDetector.cjs","sources":["../../src/hooks/useKeyboardDetector.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\nexport const useKeyboardDetector = () => {\n const [windowHeight, setWindowHeight] = useState<number | null>(null);\n\n useEffect(() => {\n const updateHeight = () => {\n const isKeyboardOpen = Boolean(\n window.visualViewport?.height &&\n window.visualViewport.height < window.innerHeight - 100\n );\n\n if (isKeyboardOpen && window.visualViewport) {\n setWindowHeight(window.visualViewport.height);\n } else {\n setWindowHeight(null);\n }\n };\n\n // Listen for changes in visualViewport height\n window.visualViewport?.addEventListener('resize', updateHeight, {\n passive: true,\n });\n updateHeight(); // Set initial height\n\n return () => {\n window.visualViewport?.removeEventListener('resize', updateHeight);\n };\n }, []);\n\n return { windowHeight, isKeyboardOpen: windowHeight !== null };\n};\n"],"names":["useState","useEffect"],"mappings":";;;;AAIO,MAAM,sBAAsB,MAAM;AACvC,QAAM,CAAC,cAAc,eAAe,IAAIA,aAAAA,SAAwB,IAAI;AAEpEC,eAAAA,UAAU,MAAM;AACd,UAAM,eAAe,MAAM;AACzB,YAAM,iBAAiB;AAAA,QACrB,OAAO,gBAAgB,UACrB,OAAO,eAAe,SAAS,OAAO,cAAc;AAAA,MACxD;AAEI,UAAA,kBAAkB,OAAO,gBAAgB;AAC3B,wBAAA,OAAO,eAAe,MAAM;AAAA,MAAA,OACvC;AACL,wBAAgB,IAAI;AAAA,MAAA;AAAA,IAExB;AAGO,WAAA,gBAAgB,iBAAiB,UAAU,cAAc;AAAA,MAC9D,SAAS;AAAA,IAAA,CACV;AACY,iBAAA;AAEb,WAAO,MAAM;AACJ,aAAA,gBAAgB,oBAAoB,UAAU,YAAY;AAAA,IACnE;AAAA,EACF,GAAG,EAAE;AAEL,SAAO,EAAE,cAAc,gBAAgB,iBAAiB,KAAK;AAC/D;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useKeyboardDetector.d.ts","sourceRoot":"","sources":["../../src/hooks/useKeyboardDetector.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,mBAAmB;;;
|
|
1
|
+
{"version":3,"file":"useKeyboardDetector.d.ts","sourceRoot":"","sources":["../../src/hooks/useKeyboardDetector.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,mBAAmB;;;CA6B/B,CAAC"}
|
|
@@ -13,7 +13,9 @@ const useKeyboardDetector = () => {
|
|
|
13
13
|
setWindowHeight(null);
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
-
window.visualViewport?.addEventListener("resize", updateHeight
|
|
16
|
+
window.visualViewport?.addEventListener("resize", updateHeight, {
|
|
17
|
+
passive: true
|
|
18
|
+
});
|
|
17
19
|
updateHeight();
|
|
18
20
|
return () => {
|
|
19
21
|
window.visualViewport?.removeEventListener("resize", updateHeight);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useKeyboardDetector.mjs","sources":["../../src/hooks/useKeyboardDetector.ts"],"sourcesContent":["'use client';\n\nimport {
|
|
1
|
+
{"version":3,"file":"useKeyboardDetector.mjs","sources":["../../src/hooks/useKeyboardDetector.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\nexport const useKeyboardDetector = () => {\n const [windowHeight, setWindowHeight] = useState<number | null>(null);\n\n useEffect(() => {\n const updateHeight = () => {\n const isKeyboardOpen = Boolean(\n window.visualViewport?.height &&\n window.visualViewport.height < window.innerHeight - 100\n );\n\n if (isKeyboardOpen && window.visualViewport) {\n setWindowHeight(window.visualViewport.height);\n } else {\n setWindowHeight(null);\n }\n };\n\n // Listen for changes in visualViewport height\n window.visualViewport?.addEventListener('resize', updateHeight, {\n passive: true,\n });\n updateHeight(); // Set initial height\n\n return () => {\n window.visualViewport?.removeEventListener('resize', updateHeight);\n };\n }, []);\n\n return { windowHeight, isKeyboardOpen: windowHeight !== null };\n};\n"],"names":[],"mappings":";;AAIO,MAAM,sBAAsB,MAAM;AACvC,QAAM,CAAC,cAAc,eAAe,IAAI,SAAwB,IAAI;AAEpE,YAAU,MAAM;AACd,UAAM,eAAe,MAAM;AACzB,YAAM,iBAAiB;AAAA,QACrB,OAAO,gBAAgB,UACrB,OAAO,eAAe,SAAS,OAAO,cAAc;AAAA,MACxD;AAEI,UAAA,kBAAkB,OAAO,gBAAgB;AAC3B,wBAAA,OAAO,eAAe,MAAM;AAAA,MAAA,OACvC;AACL,wBAAgB,IAAI;AAAA,MAAA;AAAA,IAExB;AAGO,WAAA,gBAAgB,iBAAiB,UAAU,cAAc;AAAA,MAC9D,SAAS;AAAA,IAAA,CACV;AACY,iBAAA;AAEb,WAAO,MAAM;AACJ,aAAA,gBAAgB,oBAAoB,UAAU,YAAY;AAAA,IACnE;AAAA,EACF,GAAG,EAAE;AAEL,SAAO,EAAE,cAAc,gBAAgB,iBAAiB,KAAK;AAC/D;"}
|
|
@@ -41,7 +41,16 @@ const usePersistedStore = (key, initialState) => {
|
|
|
41
41
|
},
|
|
42
42
|
[key, setState]
|
|
43
43
|
);
|
|
44
|
-
|
|
44
|
+
const loadState = ReactExports.useCallback(() => {
|
|
45
|
+
const savedState = localStorage?.getItem(key);
|
|
46
|
+
if (savedState) {
|
|
47
|
+
setState(JSON.parse(savedState));
|
|
48
|
+
}
|
|
49
|
+
}, [key, setState]);
|
|
50
|
+
return ReactExports.useMemo(
|
|
51
|
+
() => [state, setStateWrapper, loadState],
|
|
52
|
+
[state, setStateWrapper, loadState]
|
|
53
|
+
);
|
|
45
54
|
};
|
|
46
55
|
exports.usePersistedStore = usePersistedStore;
|
|
47
56
|
//# sourceMappingURL=usePersistedStore.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePersistedStore.cjs","sources":["../../src/hooks/usePersistedStore.ts"],"sourcesContent":["'use client';\n\nimport {\n
|
|
1
|
+
{"version":3,"file":"usePersistedStore.cjs","sources":["../../src/hooks/usePersistedStore.ts"],"sourcesContent":["'use client';\n\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n type Dispatch,\n type SetStateAction,\n} from 'react';\n\nexport const usePersistedStore = <S>(\n key: string,\n initialState?: S | (() => S)\n): [S, Dispatch<SetStateAction<S>>, () => void] => {\n const [state, setState] = useState<S>(() => {\n // If you have an initial value on the client, send a message out immediately\n if (initialState !== undefined) {\n const result: S =\n typeof initialState === 'function'\n ? (initialState as () => S)()\n : initialState;\n\n if (typeof window === 'undefined') return result;\n\n const persistedState = localStorage?.getItem(key);\n\n if (persistedState) {\n try {\n return JSON.parse(persistedState);\n } catch (e) {\n console.error(e);\n }\n }\n\n return result;\n }\n\n return undefined as S;\n });\n\n useEffect(() => {\n const persistedState = localStorage?.getItem(key);\n\n if (persistedState && state === undefined) {\n try {\n setState(JSON.parse(persistedState));\n } catch (e) {\n console.error(e);\n }\n } else if (initialState !== undefined && state === undefined) {\n setState(initialState);\n }\n }, [key, state]);\n\n /**\n * Allows setting state either directly or via a functional update.\n * If passed a function, we merge/update based on the previous state.\n */\n const setStateWrapper: typeof setState = useCallback(\n (valueOrUpdater: SetStateAction<S>) => {\n setState((prev) => {\n const newValue: S =\n typeof valueOrUpdater === 'function'\n ? (valueOrUpdater as (prevVal: S) => S)(prev)\n : valueOrUpdater;\n\n localStorage?.setItem(key, JSON.stringify(newValue));\n\n return newValue;\n });\n },\n [key, setState]\n );\n\n const loadState = useCallback(() => {\n const savedState = localStorage?.getItem(key);\n if (savedState) {\n setState(JSON.parse(savedState));\n }\n }, [key, setState]);\n\n return useMemo(\n () => [state, setStateWrapper, loadState],\n [state, setStateWrapper, loadState]\n );\n};\n"],"names":["useState","useEffect","useCallback","useMemo"],"mappings":";;;;AAWa,MAAA,oBAAoB,CAC/B,KACA,iBACiD;AACjD,QAAM,CAAC,OAAO,QAAQ,IAAIA,sBAAY,MAAM;AAE1C,QAAI,iBAAiB,QAAW;AAC9B,YAAM,SACJ,OAAO,iBAAiB,aACnB,aACD,IAAA;AAEF,UAAA,OAAO,WAAW,YAAoB,QAAA;AAEpC,YAAA,iBAAiB,cAAc,QAAQ,GAAG;AAEhD,UAAI,gBAAgB;AACd,YAAA;AACK,iBAAA,KAAK,MAAM,cAAc;AAAA,iBACzB,GAAG;AACV,kBAAQ,MAAM,CAAC;AAAA,QAAA;AAAA,MACjB;AAGK,aAAA;AAAA,IAAA;AAGF,WAAA;AAAA,EAAA,CACR;AAEDC,eAAAA,UAAU,MAAM;AACR,UAAA,iBAAiB,cAAc,QAAQ,GAAG;AAE5C,QAAA,kBAAkB,UAAU,QAAW;AACrC,UAAA;AACO,iBAAA,KAAK,MAAM,cAAc,CAAC;AAAA,eAC5B,GAAG;AACV,gBAAQ,MAAM,CAAC;AAAA,MAAA;AAAA,IAER,WAAA,iBAAiB,UAAa,UAAU,QAAW;AAC5D,eAAS,YAAY;AAAA,IAAA;AAAA,EACvB,GACC,CAAC,KAAK,KAAK,CAAC;AAMf,QAAM,kBAAmCC,aAAA;AAAA,IACvC,CAAC,mBAAsC;AACrC,eAAS,CAAC,SAAS;AACjB,cAAM,WACJ,OAAO,mBAAmB,aACrB,eAAqC,IAAI,IAC1C;AAEN,sBAAc,QAAQ,KAAK,KAAK,UAAU,QAAQ,CAAC;AAE5C,eAAA;AAAA,MAAA,CACR;AAAA,IACH;AAAA,IACA,CAAC,KAAK,QAAQ;AAAA,EAChB;AAEM,QAAA,YAAYA,aAAAA,YAAY,MAAM;AAC5B,UAAA,aAAa,cAAc,QAAQ,GAAG;AAC5C,QAAI,YAAY;AACL,eAAA,KAAK,MAAM,UAAU,CAAC;AAAA,IAAA;AAAA,EACjC,GACC,CAAC,KAAK,QAAQ,CAAC;AAEX,SAAAC,aAAA;AAAA,IACL,MAAM,CAAC,OAAO,iBAAiB,SAAS;AAAA,IACxC,CAAC,OAAO,iBAAiB,SAAS;AAAA,EACpC;AACF;;"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const usePersistedStore: <S>(key: string, initialState?: S | (() => S)) => [S, Dispatch<SetStateAction<S
|
|
1
|
+
import { Dispatch, SetStateAction } from 'react';
|
|
2
|
+
export declare const usePersistedStore: <S>(key: string, initialState?: S | (() => S)) => [S, Dispatch<SetStateAction<S>>, () => void];
|
|
3
3
|
//# sourceMappingURL=usePersistedStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePersistedStore.d.ts","sourceRoot":"","sources":["../../src/hooks/usePersistedStore.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"usePersistedStore.d.ts","sourceRoot":"","sources":["../../src/hooks/usePersistedStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,eAAO,MAAM,iBAAiB,GAAI,CAAC,EACjC,KAAK,MAAM,EACX,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAC3B,CAAC,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,CAwE7C,CAAC"}
|
|
@@ -39,7 +39,16 @@ const usePersistedStore = (key, initialState) => {
|
|
|
39
39
|
},
|
|
40
40
|
[key, setState]
|
|
41
41
|
);
|
|
42
|
-
|
|
42
|
+
const loadState = useCallback(() => {
|
|
43
|
+
const savedState = localStorage?.getItem(key);
|
|
44
|
+
if (savedState) {
|
|
45
|
+
setState(JSON.parse(savedState));
|
|
46
|
+
}
|
|
47
|
+
}, [key, setState]);
|
|
48
|
+
return useMemo(
|
|
49
|
+
() => [state, setStateWrapper, loadState],
|
|
50
|
+
[state, setStateWrapper, loadState]
|
|
51
|
+
);
|
|
43
52
|
};
|
|
44
53
|
export {
|
|
45
54
|
usePersistedStore
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePersistedStore.mjs","sources":["../../src/hooks/usePersistedStore.ts"],"sourcesContent":["'use client';\n\nimport {\n
|
|
1
|
+
{"version":3,"file":"usePersistedStore.mjs","sources":["../../src/hooks/usePersistedStore.ts"],"sourcesContent":["'use client';\n\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n type Dispatch,\n type SetStateAction,\n} from 'react';\n\nexport const usePersistedStore = <S>(\n key: string,\n initialState?: S | (() => S)\n): [S, Dispatch<SetStateAction<S>>, () => void] => {\n const [state, setState] = useState<S>(() => {\n // If you have an initial value on the client, send a message out immediately\n if (initialState !== undefined) {\n const result: S =\n typeof initialState === 'function'\n ? (initialState as () => S)()\n : initialState;\n\n if (typeof window === 'undefined') return result;\n\n const persistedState = localStorage?.getItem(key);\n\n if (persistedState) {\n try {\n return JSON.parse(persistedState);\n } catch (e) {\n console.error(e);\n }\n }\n\n return result;\n }\n\n return undefined as S;\n });\n\n useEffect(() => {\n const persistedState = localStorage?.getItem(key);\n\n if (persistedState && state === undefined) {\n try {\n setState(JSON.parse(persistedState));\n } catch (e) {\n console.error(e);\n }\n } else if (initialState !== undefined && state === undefined) {\n setState(initialState);\n }\n }, [key, state]);\n\n /**\n * Allows setting state either directly or via a functional update.\n * If passed a function, we merge/update based on the previous state.\n */\n const setStateWrapper: typeof setState = useCallback(\n (valueOrUpdater: SetStateAction<S>) => {\n setState((prev) => {\n const newValue: S =\n typeof valueOrUpdater === 'function'\n ? (valueOrUpdater as (prevVal: S) => S)(prev)\n : valueOrUpdater;\n\n localStorage?.setItem(key, JSON.stringify(newValue));\n\n return newValue;\n });\n },\n [key, setState]\n );\n\n const loadState = useCallback(() => {\n const savedState = localStorage?.getItem(key);\n if (savedState) {\n setState(JSON.parse(savedState));\n }\n }, [key, setState]);\n\n return useMemo(\n () => [state, setStateWrapper, loadState],\n [state, setStateWrapper, loadState]\n );\n};\n"],"names":[],"mappings":";;AAWa,MAAA,oBAAoB,CAC/B,KACA,iBACiD;AACjD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAY,MAAM;AAE1C,QAAI,iBAAiB,QAAW;AAC9B,YAAM,SACJ,OAAO,iBAAiB,aACnB,aACD,IAAA;AAEF,UAAA,OAAO,WAAW,YAAoB,QAAA;AAEpC,YAAA,iBAAiB,cAAc,QAAQ,GAAG;AAEhD,UAAI,gBAAgB;AACd,YAAA;AACK,iBAAA,KAAK,MAAM,cAAc;AAAA,iBACzB,GAAG;AACV,kBAAQ,MAAM,CAAC;AAAA,QAAA;AAAA,MACjB;AAGK,aAAA;AAAA,IAAA;AAGF,WAAA;AAAA,EAAA,CACR;AAED,YAAU,MAAM;AACR,UAAA,iBAAiB,cAAc,QAAQ,GAAG;AAE5C,QAAA,kBAAkB,UAAU,QAAW;AACrC,UAAA;AACO,iBAAA,KAAK,MAAM,cAAc,CAAC;AAAA,eAC5B,GAAG;AACV,gBAAQ,MAAM,CAAC;AAAA,MAAA;AAAA,IAER,WAAA,iBAAiB,UAAa,UAAU,QAAW;AAC5D,eAAS,YAAY;AAAA,IAAA;AAAA,EACvB,GACC,CAAC,KAAK,KAAK,CAAC;AAMf,QAAM,kBAAmC;AAAA,IACvC,CAAC,mBAAsC;AACrC,eAAS,CAAC,SAAS;AACjB,cAAM,WACJ,OAAO,mBAAmB,aACrB,eAAqC,IAAI,IAC1C;AAEN,sBAAc,QAAQ,KAAK,KAAK,UAAU,QAAQ,CAAC;AAE5C,eAAA;AAAA,MAAA,CACR;AAAA,IACH;AAAA,IACA,CAAC,KAAK,QAAQ;AAAA,EAChB;AAEM,QAAA,YAAY,YAAY,MAAM;AAC5B,UAAA,aAAa,cAAc,QAAQ,GAAG;AAC5C,QAAI,YAAY;AACL,eAAA,KAAK,MAAM,UAAU,CAAC;AAAA,IAAA;AAAA,EACjC,GACC,CAAC,KAAK,QAAQ,CAAC;AAEX,SAAA;AAAA,IACL,MAAM,CAAC,OAAO,iBAAiB,SAAS;AAAA,IACxC,CAAC,OAAO,iBAAiB,SAAS;AAAA,EACpC;AACF;"}
|
|
@@ -51,8 +51,10 @@ const useScrollDetection = (props) => {
|
|
|
51
51
|
);
|
|
52
52
|
ReactExports.useEffect(() => {
|
|
53
53
|
if (isEnabled) {
|
|
54
|
-
containerElement?.addEventListener("wheel", onScroll);
|
|
55
|
-
containerElement?.addEventListener("touchstart", onMobileMove
|
|
54
|
+
containerElement?.addEventListener("wheel", onScroll, { passive: true });
|
|
55
|
+
containerElement?.addEventListener("touchstart", onMobileMove, {
|
|
56
|
+
passive: true
|
|
57
|
+
});
|
|
56
58
|
} else {
|
|
57
59
|
setIsScrolled(false);
|
|
58
60
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScrollDetection.cjs","sources":["../../src/hooks/useScrollDetection.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\n\nimport { useGetElementOrWindow } from './useGetElementOrWindow';\nimport { useScrollBlockage } from './useScrollBlockage';\n\ntype useScrollDetectionProps = {\n isEnabled?: boolean;\n delta?: number; // how much user has to scroll to trigger the event\n deltaFromTop?: number; // how much user has to scroll from top to detect if the user has been scrolled\n onScrollDown?: (e: WheelEvent) => void;\n onScrollUp?: (e: WheelEvent) => void;\n element?: HTMLElement; // The element to detect the scroll on. If not defined, the window.document.body will be used\n};\n\nexport const useScrollDetection = (props?: useScrollDetectionProps) => {\n const {\n isEnabled = true,\n delta = 5,\n deltaFromTop = 0,\n onScrollDown,\n onScrollUp,\n element,\n } = props ?? {};\n\n const [isScrolled, setIsScrolled] = useState<boolean>(false);\n const [isScrollable, setIsScrollable] = useState<boolean>(false);\n\n const { isScrollBlocked } = useScrollBlockage();\n const containerElement = useGetElementOrWindow(element);\n\n const onMobileMove = useCallback(\n (event: globalThis.TouchEvent) => {\n const startY = event.touches?.[0]?.clientY ?? 0;\n\n const onMove = (event: globalThis.TouchEvent) => {\n if (isEnabled) {\n const currentY = event.touches?.[0]?.clientY ?? 0;\n const deltaY = startY - currentY;\n\n setIsScrolled(deltaY > 0);\n\n containerElement?.removeEventListener('touchmove', onMove);\n }\n };\n\n containerElement?.addEventListener('touchmove', onMove);\n },\n [isEnabled, containerElement]\n );\n\n const onScroll = useCallback(\n (e: WheelEvent) => {\n const isScrolledDown = e.deltaY > 0;\n\n if (isEnabled && !isScrollBlocked && isScrollable) {\n const isDeTected = Math.abs(e.deltaY) > Math.abs(delta);\n\n if (isDeTected) {\n if (isScrolledDown) {\n onScrollDown?.(e);\n } else {\n onScrollUp?.(e);\n }\n }\n\n setIsScrolled(window.scrollY > deltaFromTop);\n }\n },\n [isEnabled, isScrollBlocked, isScrollable]\n );\n\n useEffect(() => {\n if (isEnabled) {\n containerElement?.addEventListener('wheel', onScroll);\n containerElement?.addEventListener('touchstart', onMobileMove);\n } else {\n setIsScrolled(false);\n }\n\n return () => {\n containerElement?.removeEventListener('wheel', onScroll);\n containerElement?.removeEventListener('touchstart', onMobileMove);\n };\n }, [isEnabled, onScroll, onMobileMove, containerElement]);\n\n useEffect(() => {\n const isScrollable = window.innerHeight < window.document.body.scrollHeight;\n\n setIsScrollable(isScrollable);\n }, []);\n\n return { isScrolled, isScrollable };\n};\n"],"names":["useState","useScrollBlockage","useGetElementOrWindow","useCallback","event","useEffect","isScrollable"],"mappings":";;;;;;AAgBa,MAAA,qBAAqB,CAAC,UAAoC;AAC/D,QAAA;AAAA,IACJ,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,SAAS,CAAC;AAEd,QAAM,CAAC,YAAY,aAAa,IAAIA,aAAAA,SAAkB,KAAK;AAC3D,QAAM,CAAC,cAAc,eAAe,IAAIA,aAAAA,SAAkB,KAAK;AAEzD,QAAA,EAAE,gBAAgB,IAAIC,gDAAkB;AACxC,QAAA,mBAAmBC,kDAAsB,OAAO;AAEtD,QAAM,eAAeC,aAAA;AAAA,IACnB,CAAC,UAAiC;AAChC,YAAM,SAAS,MAAM,UAAU,CAAC,GAAG,WAAW;AAExC,YAAA,SAAS,CAACC,WAAiC;AAC/C,YAAI,WAAW;AACb,gBAAM,WAAWA,OAAM,UAAU,CAAC,GAAG,WAAW;AAChD,gBAAM,SAAS,SAAS;AAExB,wBAAc,SAAS,CAAC;AAEN,4BAAA,oBAAoB,aAAa,MAAM;AAAA,QAAA;AAAA,MAE7D;AAEkB,wBAAA,iBAAiB,aAAa,MAAM;AAAA,IACxD;AAAA,IACA,CAAC,WAAW,gBAAgB;AAAA,EAC9B;AAEA,QAAM,WAAWD,aAAA;AAAA,IACf,CAAC,MAAkB;AACX,YAAA,iBAAiB,EAAE,SAAS;AAE9B,UAAA,aAAa,CAAC,mBAAmB,cAAc;AAC3C,cAAA,aAAa,KAAK,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,KAAK;AAEtD,YAAI,YAAY;AACd,cAAI,gBAAgB;AAClB,2BAAe,CAAC;AAAA,UAAA,OACX;AACL,yBAAa,CAAC;AAAA,UAAA;AAAA,QAChB;AAGY,sBAAA,OAAO,UAAU,YAAY;AAAA,MAAA;AAAA,IAE/C;AAAA,IACA,CAAC,WAAW,iBAAiB,YAAY;AAAA,EAC3C;AAEAE,eAAAA,UAAU,MAAM;AACd,QAAI,WAAW;
|
|
1
|
+
{"version":3,"file":"useScrollDetection.cjs","sources":["../../src/hooks/useScrollDetection.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\n\nimport { useGetElementOrWindow } from './useGetElementOrWindow';\nimport { useScrollBlockage } from './useScrollBlockage';\n\ntype useScrollDetectionProps = {\n isEnabled?: boolean;\n delta?: number; // how much user has to scroll to trigger the event\n deltaFromTop?: number; // how much user has to scroll from top to detect if the user has been scrolled\n onScrollDown?: (e: WheelEvent) => void;\n onScrollUp?: (e: WheelEvent) => void;\n element?: HTMLElement; // The element to detect the scroll on. If not defined, the window.document.body will be used\n};\n\nexport const useScrollDetection = (props?: useScrollDetectionProps) => {\n const {\n isEnabled = true,\n delta = 5,\n deltaFromTop = 0,\n onScrollDown,\n onScrollUp,\n element,\n } = props ?? {};\n\n const [isScrolled, setIsScrolled] = useState<boolean>(false);\n const [isScrollable, setIsScrollable] = useState<boolean>(false);\n\n const { isScrollBlocked } = useScrollBlockage();\n const containerElement = useGetElementOrWindow(element);\n\n const onMobileMove = useCallback(\n (event: globalThis.TouchEvent) => {\n const startY = event.touches?.[0]?.clientY ?? 0;\n\n const onMove = (event: globalThis.TouchEvent) => {\n if (isEnabled) {\n const currentY = event.touches?.[0]?.clientY ?? 0;\n const deltaY = startY - currentY;\n\n setIsScrolled(deltaY > 0);\n\n containerElement?.removeEventListener('touchmove', onMove);\n }\n };\n\n containerElement?.addEventListener('touchmove', onMove);\n },\n [isEnabled, containerElement]\n );\n\n const onScroll = useCallback(\n (e: WheelEvent) => {\n const isScrolledDown = e.deltaY > 0;\n\n if (isEnabled && !isScrollBlocked && isScrollable) {\n const isDeTected = Math.abs(e.deltaY) > Math.abs(delta);\n\n if (isDeTected) {\n if (isScrolledDown) {\n onScrollDown?.(e);\n } else {\n onScrollUp?.(e);\n }\n }\n\n setIsScrolled(window.scrollY > deltaFromTop);\n }\n },\n [isEnabled, isScrollBlocked, isScrollable]\n );\n\n useEffect(() => {\n if (isEnabled) {\n containerElement?.addEventListener('wheel', onScroll, { passive: true });\n containerElement?.addEventListener('touchstart', onMobileMove, {\n passive: true,\n });\n } else {\n setIsScrolled(false);\n }\n\n return () => {\n containerElement?.removeEventListener('wheel', onScroll);\n containerElement?.removeEventListener('touchstart', onMobileMove);\n };\n }, [isEnabled, onScroll, onMobileMove, containerElement]);\n\n useEffect(() => {\n const isScrollable = window.innerHeight < window.document.body.scrollHeight;\n\n setIsScrollable(isScrollable);\n }, []);\n\n return { isScrolled, isScrollable };\n};\n"],"names":["useState","useScrollBlockage","useGetElementOrWindow","useCallback","event","useEffect","isScrollable"],"mappings":";;;;;;AAgBa,MAAA,qBAAqB,CAAC,UAAoC;AAC/D,QAAA;AAAA,IACJ,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,SAAS,CAAC;AAEd,QAAM,CAAC,YAAY,aAAa,IAAIA,aAAAA,SAAkB,KAAK;AAC3D,QAAM,CAAC,cAAc,eAAe,IAAIA,aAAAA,SAAkB,KAAK;AAEzD,QAAA,EAAE,gBAAgB,IAAIC,gDAAkB;AACxC,QAAA,mBAAmBC,kDAAsB,OAAO;AAEtD,QAAM,eAAeC,aAAA;AAAA,IACnB,CAAC,UAAiC;AAChC,YAAM,SAAS,MAAM,UAAU,CAAC,GAAG,WAAW;AAExC,YAAA,SAAS,CAACC,WAAiC;AAC/C,YAAI,WAAW;AACb,gBAAM,WAAWA,OAAM,UAAU,CAAC,GAAG,WAAW;AAChD,gBAAM,SAAS,SAAS;AAExB,wBAAc,SAAS,CAAC;AAEN,4BAAA,oBAAoB,aAAa,MAAM;AAAA,QAAA;AAAA,MAE7D;AAEkB,wBAAA,iBAAiB,aAAa,MAAM;AAAA,IACxD;AAAA,IACA,CAAC,WAAW,gBAAgB;AAAA,EAC9B;AAEA,QAAM,WAAWD,aAAA;AAAA,IACf,CAAC,MAAkB;AACX,YAAA,iBAAiB,EAAE,SAAS;AAE9B,UAAA,aAAa,CAAC,mBAAmB,cAAc;AAC3C,cAAA,aAAa,KAAK,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,KAAK;AAEtD,YAAI,YAAY;AACd,cAAI,gBAAgB;AAClB,2BAAe,CAAC;AAAA,UAAA,OACX;AACL,yBAAa,CAAC;AAAA,UAAA;AAAA,QAChB;AAGY,sBAAA,OAAO,UAAU,YAAY;AAAA,MAAA;AAAA,IAE/C;AAAA,IACA,CAAC,WAAW,iBAAiB,YAAY;AAAA,EAC3C;AAEAE,eAAAA,UAAU,MAAM;AACd,QAAI,WAAW;AACb,wBAAkB,iBAAiB,SAAS,UAAU,EAAE,SAAS,MAAM;AACrD,wBAAA,iBAAiB,cAAc,cAAc;AAAA,QAC7D,SAAS;AAAA,MAAA,CACV;AAAA,IAAA,OACI;AACL,oBAAc,KAAK;AAAA,IAAA;AAGrB,WAAO,MAAM;AACO,wBAAA,oBAAoB,SAAS,QAAQ;AACrC,wBAAA,oBAAoB,cAAc,YAAY;AAAA,IAClE;AAAA,KACC,CAAC,WAAW,UAAU,cAAc,gBAAgB,CAAC;AAExDA,eAAAA,UAAU,MAAM;AACd,UAAMC,gBAAe,OAAO,cAAc,OAAO,SAAS,KAAK;AAE/D,oBAAgBA,aAAY;AAAA,EAC9B,GAAG,EAAE;AAEE,SAAA,EAAE,YAAY,aAAa;AACpC;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScrollDetection.d.ts","sourceRoot":"","sources":["../../src/hooks/useScrollDetection.ts"],"names":[],"mappings":"AAOA,KAAK,uBAAuB,GAAG;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IACvC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,QAAQ,uBAAuB;;;
|
|
1
|
+
{"version":3,"file":"useScrollDetection.d.ts","sourceRoot":"","sources":["../../src/hooks/useScrollDetection.ts"],"names":[],"mappings":"AAOA,KAAK,uBAAuB,GAAG;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IACvC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,QAAQ,uBAAuB;;;CAgFjE,CAAC"}
|
|
@@ -49,8 +49,10 @@ const useScrollDetection = (props) => {
|
|
|
49
49
|
);
|
|
50
50
|
useEffect(() => {
|
|
51
51
|
if (isEnabled) {
|
|
52
|
-
containerElement?.addEventListener("wheel", onScroll);
|
|
53
|
-
containerElement?.addEventListener("touchstart", onMobileMove
|
|
52
|
+
containerElement?.addEventListener("wheel", onScroll, { passive: true });
|
|
53
|
+
containerElement?.addEventListener("touchstart", onMobileMove, {
|
|
54
|
+
passive: true
|
|
55
|
+
});
|
|
54
56
|
} else {
|
|
55
57
|
setIsScrolled(false);
|
|
56
58
|
}
|