diff --git a/.changeset/honest-foxes-press.md b/.changeset/honest-foxes-press.md new file mode 100644 index 00000000..2c3ba0b8 --- /dev/null +++ b/.changeset/honest-foxes-press.md @@ -0,0 +1,7 @@ +--- +"usehooks-ts": patch +"www": patch +"eslint-config-custom": patch +--- + +Make Typescript and typescript-eslint stricter diff --git a/.changeset/two-jars-grow.md b/.changeset/two-jars-grow.md new file mode 100644 index 00000000..819214b0 --- /dev/null +++ b/.changeset/two-jars-grow.md @@ -0,0 +1,5 @@ +--- +"usehooks-ts": minor +--- + +Drop Map, Set and Date supports in use\*Storage hook's JSON deserializer diff --git a/apps/www/.eslintrc.js b/apps/www/.eslintrc.js index d748eb5c..1aaec51d 100644 --- a/apps/www/.eslintrc.js +++ b/apps/www/.eslintrc.js @@ -1,3 +1,6 @@ module.exports = { extends: ['next/core-web-vitals', 'custom'], + rules: { + '@typescript-eslint/require-await': 'off', + }, } diff --git a/apps/www/src/app/(marketing)/page.tsx b/apps/www/src/app/(marketing)/page.tsx index 9ef1ad34..4e356dff 100644 --- a/apps/www/src/app/(marketing)/page.tsx +++ b/apps/www/src/app/(marketing)/page.tsx @@ -69,8 +69,10 @@ async function getGitHubStars(): Promise { return null } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const json = await response.json() + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/dot-notation return parseInt(json['stargazers_count']).toLocaleString() } catch (error) { return null diff --git a/apps/www/src/components/main-nav.tsx b/apps/www/src/components/main-nav.tsx index a7840560..3603497c 100644 --- a/apps/www/src/components/main-nav.tsx +++ b/apps/www/src/components/main-nav.tsx @@ -49,7 +49,9 @@ export function MainNav({ items, children }: MainNavProps) { ) : null} - setTheme('light')}> + { + setTheme('light') + }} + > Light - setTheme('dark')}> + { + setTheme('dark') + }} + > Dark - setTheme('system')}> + { + setTheme('system') + }} + > System diff --git a/apps/www/src/lib/mdx.ts b/apps/www/src/lib/mdx.ts index b4e1d7d5..15f94f51 100644 --- a/apps/www/src/lib/mdx.ts +++ b/apps/www/src/lib/mdx.ts @@ -51,5 +51,5 @@ export const getPosts = (): Post[] => { export const getPost = (slug: string): Option => { const allPosts = getPosts() const post = allPosts.find(post => post.slug === slug) - return post || null + return post ?? null } diff --git a/packages/eslint-config-custom/.eslintrc.js b/packages/eslint-config-custom/.eslintrc.js index c170f329..b9dc77c5 100644 --- a/packages/eslint-config-custom/.eslintrc.js +++ b/packages/eslint-config-custom/.eslintrc.js @@ -3,18 +3,24 @@ module.exports = { parserOptions: { ecmaVersion: 2020, sourceType: 'module', + project: ['./tsconfig.json'], ecmaFeatures: { jsx: true, }, }, ignorePatterns: ['dist', '.eslintrc.*'], extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended-type-checked', + 'plugin:@typescript-eslint/strict-type-checked', + 'plugin:@typescript-eslint/stylistic-type-checked', 'plugin:react-hooks/recommended', 'plugin:react/recommended', 'plugin:jsx-a11y/recommended', 'plugin:import/typescript', ], plugins: [ + '@typescript-eslint', 'react', 'simple-import-sort', 'prettier', @@ -32,12 +38,18 @@ module.exports = { }, }, rules: { + // Format 'prettier/prettier': 'warn', + + // React 'react/prop-types': 'off', 'react/jsx-uses-react': 'off', 'react/react-in-jsx-scope': 'off', + + // Import 'sort-imports': 'off', 'import/order': 'off', + 'import/no-cycle': 'error', 'simple-import-sort/exports': 'warn', 'simple-import-sort/imports': [ 'warn', @@ -50,36 +62,30 @@ module.exports = { ], }, ], - 'import/no-cycle': 'error', - }, - overrides: [ - // Typescript related rules - { - files: ['*.ts', '*.tsx'], - plugins: ['@typescript-eslint/eslint-plugin'], - extends: ['plugin:@typescript-eslint/recommended'], - parserOptions: { - project: ['./tsconfig.json'], - }, - rules: { - // We should absolutely avoid using ts-ignore, but it"s not always possible. - // particular when a dependencies types are incorrect. - '@typescript-eslint/ban-ts-comment': [ - 'warn', - { 'ts-ignore': 'allow-with-description' }, - ], - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/no-unused-vars': [ - 'warn', - { - argsIgnorePattern: '^_', - ignoreRestSiblings: true, - }, - ], + // We should absolutely avoid using ts-ignore, but it"s not always possible. + // particular when a dependencies types are incorrect. + '@typescript-eslint/ban-ts-comment': [ + 'warn', + { 'ts-ignore': 'allow-with-description' }, + ], + + // Allow unused variables that start with an underscore. + '@typescript-eslint/no-unused-vars': [ + 'warn', + { + argsIgnorePattern: '^_', + ignoreRestSiblings: true, }, - }, + ], + // Disable some TypeScript rules + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/consistent-type-definitions': 'off', + '@typescript-eslint/no-unnecessary-condition': 'off', + '@typescript-eslint/prefer-ts-expect-error': 'off', + }, + overrides: [ // Specials rules for testing { extends: ['plugin:vitest/recommended'], diff --git a/packages/usehooks-ts/src/useBoolean/useBoolean.demo.tsx b/packages/usehooks-ts/src/useBoolean/useBoolean.demo.tsx index 9c0e4c03..c0314e69 100644 --- a/packages/usehooks-ts/src/useBoolean/useBoolean.demo.tsx +++ b/packages/usehooks-ts/src/useBoolean/useBoolean.demo.tsx @@ -4,7 +4,9 @@ export default function Component() { const { value, setValue, setTrue, setFalse, toggle } = useBoolean(false) // Just an example to use "setValue" - const customToggle = () => setValue((x: boolean) => !x) + const customToggle = () => { + setValue((x: boolean) => !x) + } return ( <> diff --git a/packages/usehooks-ts/src/useBoolean/useBoolean.ts b/packages/usehooks-ts/src/useBoolean/useBoolean.ts index 8f192d7d..e4abb2ec 100644 --- a/packages/usehooks-ts/src/useBoolean/useBoolean.ts +++ b/packages/usehooks-ts/src/useBoolean/useBoolean.ts @@ -30,9 +30,17 @@ interface UseBooleanOutput { export function useBoolean(defaultValue?: boolean): UseBooleanOutput { const [value, setValue] = useState(!!defaultValue) - const setTrue = useCallback(() => setValue(true), []) - const setFalse = useCallback(() => setValue(false), []) - const toggle = useCallback(() => setValue(x => !x), []) + const setTrue = useCallback(() => { + setValue(true) + }, []) + + const setFalse = useCallback(() => { + setValue(false) + }, []) + + const toggle = useCallback(() => { + setValue(x => !x) + }, []) return { value, setValue, setTrue, setFalse, toggle } } diff --git a/packages/usehooks-ts/src/useCopyToClipboard/useCopyToClipboard.demo.tsx b/packages/usehooks-ts/src/useCopyToClipboard/useCopyToClipboard.demo.tsx index 54ef833f..7faa4282 100644 --- a/packages/usehooks-ts/src/useCopyToClipboard/useCopyToClipboard.demo.tsx +++ b/packages/usehooks-ts/src/useCopyToClipboard/useCopyToClipboard.demo.tsx @@ -2,13 +2,24 @@ import { useCopyToClipboard } from './useCopyToClipboard' export default function Component() { const [copiedText, copy] = useCopyToClipboard() + + const handleCopy = (text: string) => () => { + copy(text) + .then(() => { + console.log('Copied!', { text }) + }) + .catch(error => { + console.error('Failed to copy!', error) + }) + } + return ( <>

Click to copy:

- - - + + +

Copied value: {copiedText ?? 'Nothing is copied yet!'}

diff --git a/packages/usehooks-ts/src/useCopyToClipboard/useCopyToClipboard.ts b/packages/usehooks-ts/src/useCopyToClipboard/useCopyToClipboard.ts index ef6b88ab..edf377fd 100644 --- a/packages/usehooks-ts/src/useCopyToClipboard/useCopyToClipboard.ts +++ b/packages/usehooks-ts/src/useCopyToClipboard/useCopyToClipboard.ts @@ -1,7 +1,16 @@ import { useCallback, useState } from 'react' +/** + * The copied text as `string` or `null` if nothing has been copied yet. + */ type CopiedValue = string | null -type CopyFn = (text: string) => Promise // Return success + +/** + * Function to copy text to the clipboard. + * @param text The text to copy to the clipboard. + * @returns {Promise} A promise that resolves to `true` if the text was copied successfully, or `false` otherwise. + */ +type CopyFn = (text: string) => Promise /** * Custom hook for copying text to the clipboard. diff --git a/packages/usehooks-ts/src/useCountdown/useCountdown.ts b/packages/usehooks-ts/src/useCountdown/useCountdown.ts index 2b739eb4..f49df8a0 100644 --- a/packages/usehooks-ts/src/useCountdown/useCountdown.ts +++ b/packages/usehooks-ts/src/useCountdown/useCountdown.ts @@ -100,7 +100,7 @@ export function useCountdown( intervalMs = countdownOptions.interval isIncrement = countdownOptions.isIncrement } else { - // eslint-disable-next-line @typescript-eslint/no-extra-semi + // eslint-disable-next-line @typescript-eslint/no-extra-semi, no-extra-semi ;({ countStart, intervalMs, isIncrement, countStop } = countdownOptions) } diff --git a/packages/usehooks-ts/src/useCounter/useCounter.demo.tsx b/packages/usehooks-ts/src/useCounter/useCounter.demo.tsx index 3e83c874..75956b3e 100644 --- a/packages/usehooks-ts/src/useCounter/useCounter.demo.tsx +++ b/packages/usehooks-ts/src/useCounter/useCounter.demo.tsx @@ -3,7 +3,9 @@ import { useCounter } from './useCounter' export default function Component() { const { count, setCount, increment, decrement, reset } = useCounter(0) - const multiplyBy2 = () => setCount((x: number) => x * 2) + const multiplyBy2 = () => { + setCount((x: number) => x * 2) + } return ( <> diff --git a/packages/usehooks-ts/src/useCounter/useCounter.ts b/packages/usehooks-ts/src/useCounter/useCounter.ts index 129a441c..4d649005 100644 --- a/packages/usehooks-ts/src/useCounter/useCounter.ts +++ b/packages/usehooks-ts/src/useCounter/useCounter.ts @@ -28,11 +28,17 @@ interface UseCounterOutput { * setCount(10); // Sets count to 10 */ export function useCounter(initialValue?: number): UseCounterOutput { - const [count, setCount] = useState(initialValue || 0) + const [count, setCount] = useState(initialValue ?? 0) - const increment = () => setCount(x => x + 1) - const decrement = () => setCount(x => x - 1) - const reset = () => setCount(initialValue || 0) + const increment = () => { + setCount(x => x + 1) + } + const decrement = () => { + setCount(x => x - 1) + } + const reset = () => { + setCount(initialValue ?? 0) + } return { count, diff --git a/packages/usehooks-ts/src/useDarkMode/useDarkMode.ts b/packages/usehooks-ts/src/useDarkMode/useDarkMode.ts index 5673f566..69f51859 100644 --- a/packages/usehooks-ts/src/useDarkMode/useDarkMode.ts +++ b/packages/usehooks-ts/src/useDarkMode/useDarkMode.ts @@ -40,9 +40,17 @@ export function useDarkMode( return { isDarkMode, - toggle: () => setDarkMode(prev => !prev), - enable: () => setDarkMode(true), - disable: () => setDarkMode(false), - set: value => setDarkMode(value), + toggle: () => { + setDarkMode(prev => !prev) + }, + enable: () => { + setDarkMode(true) + }, + disable: () => { + setDarkMode(false) + }, + set: value => { + setDarkMode(value) + }, } } diff --git a/packages/usehooks-ts/src/useDebounce/useDebounce.ts b/packages/usehooks-ts/src/useDebounce/useDebounce.ts index a36bb1e5..b0966c01 100644 --- a/packages/usehooks-ts/src/useDebounce/useDebounce.ts +++ b/packages/usehooks-ts/src/useDebounce/useDebounce.ts @@ -16,7 +16,9 @@ export function useDebounce(value: T, delay?: number): T { const [debouncedValue, setDebouncedValue] = useState(value) useEffect(() => { - const timer = setTimeout(() => setDebouncedValue(value), delay || 500) + const timer = setTimeout(() => { + setDebouncedValue(value) + }, delay ?? 500) return () => { clearTimeout(timer) diff --git a/packages/usehooks-ts/src/useDebounceCallback/useDebounceCallback.demo.tsx b/packages/usehooks-ts/src/useDebounceCallback/useDebounceCallback.demo.tsx index d1dfc1e0..79439c97 100644 --- a/packages/usehooks-ts/src/useDebounceCallback/useDebounceCallback.demo.tsx +++ b/packages/usehooks-ts/src/useDebounceCallback/useDebounceCallback.demo.tsx @@ -5,9 +5,7 @@ import { useDebounceCallback } from './useDebounceCallback' export default function Component() { const [value, setValue] = useState('') - const debounced = useDebounceCallback(value => { - setValue(value) - }, 500) + const debounced = useDebounceCallback(setValue, 500) return (
diff --git a/packages/usehooks-ts/src/useDebounceCallback/useDebounceCallback.test.ts b/packages/usehooks-ts/src/useDebounceCallback/useDebounceCallback.test.ts index d9a54deb..b2f9ee97 100644 --- a/packages/usehooks-ts/src/useDebounceCallback/useDebounceCallback.test.ts +++ b/packages/usehooks-ts/src/useDebounceCallback/useDebounceCallback.test.ts @@ -47,7 +47,7 @@ describe('useDebounceCallback()', () => { expect(debouncedCallback).toHaveBeenCalledTimes(1) }) - it('should debounce the callback function', async () => { + it('should debounce the callback function', () => { const callback = vitest.fn() const { result } = renderHook(() => useDebounceCallback(callback, 100)) @@ -66,7 +66,7 @@ describe('useDebounceCallback()', () => { expect(callback).toBeCalledWith('test3') }) - it('should cancel the debounced callback', async () => { + it('should cancel the debounced callback', () => { const delay = 500 const debouncedCallback = vitest.fn() const { result } = renderHook(() => diff --git a/packages/usehooks-ts/src/useDebounceValue/useDebounceValue.test.ts b/packages/usehooks-ts/src/useDebounceValue/useDebounceValue.test.ts index 2a86181b..bf74269e 100644 --- a/packages/usehooks-ts/src/useDebounceValue/useDebounceValue.test.ts +++ b/packages/usehooks-ts/src/useDebounceValue/useDebounceValue.test.ts @@ -33,7 +33,7 @@ describe('useDebounceValue()', () => { expect(result.current[0]).toBe('update3') }) - it('should handle options', async () => { + it('should handle options', () => { const delay = 500 const { result } = renderHook(() => useDebounceValue('initial', delay, { leading: true }), diff --git a/packages/usehooks-ts/src/useDebounceValue/useDebounceValue.ts b/packages/usehooks-ts/src/useDebounceValue/useDebounceValue.ts index 97cd7e9e..f52689a5 100644 --- a/packages/usehooks-ts/src/useDebounceValue/useDebounceValue.ts +++ b/packages/usehooks-ts/src/useDebounceValue/useDebounceValue.ts @@ -27,7 +27,7 @@ export function useDebounceValue( equalityFn?: (left: T, right: T) => boolean }, ): [T, DebouncedState<(value: T) => void>] { - const eq = options?.equalityFn || ((left: T, right: T) => left === right) + const eq = options?.equalityFn ?? ((left: T, right: T) => left === right) const unwrappedInitialValue = initialValue instanceof Function ? initialValue() : initialValue const [debouncedValue, setDebouncedValue] = useState(unwrappedInitialValue) diff --git a/packages/usehooks-ts/src/useDocumentTitle/useDocumentTitle.test.ts b/packages/usehooks-ts/src/useDocumentTitle/useDocumentTitle.test.ts index 4f2bd4b5..dc889fc4 100644 --- a/packages/usehooks-ts/src/useDocumentTitle/useDocumentTitle.test.ts +++ b/packages/usehooks-ts/src/useDocumentTitle/useDocumentTitle.test.ts @@ -4,7 +4,9 @@ import { useDocumentTitle } from './useDocumentTitle' describe('useDocumentTitle()', () => { it('title should be in the document', () => { - renderHook(() => useDocumentTitle('foo')) + renderHook(() => { + useDocumentTitle('foo') + }) expect(window.document.title).toEqual('foo') }) }) diff --git a/packages/usehooks-ts/src/useEffectOnce/useEffectOnce.demo.tsx b/packages/usehooks-ts/src/useEffectOnce/useEffectOnce.demo.tsx index 3e13e98d..fdb51bc2 100644 --- a/packages/usehooks-ts/src/useEffectOnce/useEffectOnce.demo.tsx +++ b/packages/usehooks-ts/src/useEffectOnce/useEffectOnce.demo.tsx @@ -15,7 +15,13 @@ export default function Component() { return (

Open your console

- +
) } diff --git a/packages/usehooks-ts/src/useEffectOnce/useEffectOnce.test.ts b/packages/usehooks-ts/src/useEffectOnce/useEffectOnce.test.ts index c6dd479d..e8c81471 100644 --- a/packages/usehooks-ts/src/useEffectOnce/useEffectOnce.test.ts +++ b/packages/usehooks-ts/src/useEffectOnce/useEffectOnce.test.ts @@ -5,7 +5,9 @@ import { useEffectOnce } from './useEffectOnce' describe('use effect once()', () => { it('should be triggered only once', () => { const effect = vitest.fn() - const { rerender } = renderHook(() => useEffectOnce(effect)) + const { rerender } = renderHook(() => { + useEffectOnce(effect) + }) expect(effect).toHaveBeenCalledTimes(1) diff --git a/packages/usehooks-ts/src/useElementSize/useElementSize.demo.tsx b/packages/usehooks-ts/src/useElementSize/useElementSize.demo.tsx index df66ad30..de91307c 100644 --- a/packages/usehooks-ts/src/useElementSize/useElementSize.demo.tsx +++ b/packages/usehooks-ts/src/useElementSize/useElementSize.demo.tsx @@ -6,7 +6,9 @@ export default function Component() { const [isVisible, setVisible] = useState(true) const [squareRef, { width, height }] = useElementSize() - const toggleVisibility = () => setVisible(x => !x) + const toggleVisibility = () => { + setVisible(x => !x) + } return ( <> diff --git a/packages/usehooks-ts/src/useElementSize/useElementSize.test.ts b/packages/usehooks-ts/src/useElementSize/useElementSize.test.ts index 6aed72d8..80a34976 100644 --- a/packages/usehooks-ts/src/useElementSize/useElementSize.test.ts +++ b/packages/usehooks-ts/src/useElementSize/useElementSize.test.ts @@ -4,15 +4,17 @@ import { useElementSize } from './useElementSize' const setupHook = () => renderHook(() => useElementSize()) +// eslint-disable-next-line @typescript-eslint/no-non-null-assertion const originalOffsetHeight = Object.getOwnPropertyDescriptor( HTMLElement.prototype, 'offsetHeight', -) as PropertyDescriptor +)! +// eslint-disable-next-line @typescript-eslint/no-non-null-assertion const originalOffsetWidth = Object.getOwnPropertyDescriptor( HTMLElement.prototype, 'offsetWidth', -) as PropertyDescriptor +)! const resizeElement = ( node: HTMLElement, diff --git a/packages/usehooks-ts/src/useElementSize/useElementSize.ts b/packages/usehooks-ts/src/useElementSize/useElementSize.ts index 131e1ab2..7fd45e02 100644 --- a/packages/usehooks-ts/src/useElementSize/useElementSize.ts +++ b/packages/usehooks-ts/src/useElementSize/useElementSize.ts @@ -38,8 +38,8 @@ export function useElementSize(): [ // Prevent too many rendering using useCallback const handleSize = useCallback(() => { setSize({ - width: ref?.offsetWidth || 0, - height: ref?.offsetHeight || 0, + width: ref?.offsetWidth ?? 0, + height: ref?.offsetHeight ?? 0, }) // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/packages/usehooks-ts/src/useEventListener/useEventListener.test.ts b/packages/usehooks-ts/src/useEventListener/useEventListener.test.ts index 7c829111..23a6e77e 100644 --- a/packages/usehooks-ts/src/useEventListener/useEventListener.test.ts +++ b/packages/usehooks-ts/src/useEventListener/useEventListener.test.ts @@ -44,7 +44,9 @@ describe('useEventListener()', () => { const handler = vitest.fn() const options = undefined - const { unmount } = renderHook(() => useEventListener(eventName, handler)) + const { unmount } = renderHook(() => { + useEventListener(eventName, handler) + }) expect(windowAddEventListenerSpy).toHaveBeenCalledWith( eventName, @@ -66,9 +68,9 @@ describe('useEventListener()', () => { const handler = vitest.fn() const options = undefined - const { unmount } = renderHook(() => - useEventListener(eventName, handler, ref, options), - ) + const { unmount } = renderHook(() => { + useEventListener(eventName, handler, ref, options) + }) expect(refAddEventListenerSpy).toHaveBeenCalledTimes(1) expect(refAddEventListenerSpy).toHaveBeenCalledWith( @@ -91,9 +93,9 @@ describe('useEventListener()', () => { const handler = vitest.fn() const options = undefined - const { unmount } = renderHook(() => - useEventListener(eventName, handler, docRef, options), - ) + const { unmount } = renderHook(() => { + useEventListener(eventName, handler, docRef, options) + }) expect(docAddEventListenerSpy).toHaveBeenCalledTimes(1) expect(docAddEventListenerSpy).toHaveBeenCalledWith( @@ -120,7 +122,9 @@ describe('useEventListener()', () => { capture: true, } - renderHook(() => useEventListener(eventName, handler, undefined, options)) + renderHook(() => { + useEventListener(eventName, handler, undefined, options) + }) expect(windowAddEventListenerSpy).toHaveBeenCalledWith( eventName, @@ -133,7 +137,9 @@ describe('useEventListener()', () => { const eventName = 'click' const handler = vitest.fn() - renderHook(() => useEventListener(eventName, handler, ref)) + renderHook(() => { + useEventListener(eventName, handler, ref) + }) fireEvent.click(ref.current) @@ -144,8 +150,12 @@ describe('useEventListener()', () => { const clickHandler = vitest.fn() const keydownHandler = vitest.fn() - renderHook(() => useEventListener('click', clickHandler, ref)) - renderHook(() => useEventListener('keydown', keydownHandler, ref)) + renderHook(() => { + useEventListener('click', clickHandler, ref) + }) + renderHook(() => { + useEventListener('keydown', keydownHandler, ref) + }) fireEvent.click(ref.current) fireEvent.keyDown(ref.current) diff --git a/packages/usehooks-ts/src/useEventListener/useEventListener.ts b/packages/usehooks-ts/src/useEventListener/useEventListener.ts index 7218477b..d884bf4b 100644 --- a/packages/usehooks-ts/src/useEventListener/useEventListener.ts +++ b/packages/usehooks-ts/src/useEventListener/useEventListener.ts @@ -42,7 +42,7 @@ function useEventListener( * @template KW - The type of event for window events. * @template KH - The type of event for HTML element events. * @template KM - The type of event for media query list events. - * @template T - The type of the DOM element (default is `void`). + * @template T - The type of the DOM element (default is `HTMLElement`). * @param {KW | KH | KM} eventName - The name of the event to listen for. * @param {(event: WindowEventMap[KW] | HTMLElementEventMap[KH] | MediaQueryListEventMap[KM] | Event) => void} handler - The event handler function. * @param {RefObject} [element] - The DOM element or media query list to attach the event listener to (optional). @@ -64,7 +64,7 @@ function useEventListener< KW extends keyof WindowEventMap, KH extends keyof HTMLElementEventMap, KM extends keyof MediaQueryListEventMap, - T extends HTMLElement | MediaQueryList | void = void, + T extends HTMLElement | MediaQueryList = HTMLElement, >( eventName: KW | KH | KM, handler: ( @@ -91,7 +91,9 @@ function useEventListener< if (!(targetElement && targetElement.addEventListener)) return // Create event listener that calls handler function stored in ref - const listener: typeof handler = event => savedHandler.current(event) + const listener: typeof handler = event => { + savedHandler.current(event) + } targetElement.addEventListener(eventName, listener, options) diff --git a/packages/usehooks-ts/src/useFetch/useFetch.test.ts b/packages/usehooks-ts/src/useFetch/useFetch.test.ts index a0a62ebb..7345ad25 100644 --- a/packages/usehooks-ts/src/useFetch/useFetch.test.ts +++ b/packages/usehooks-ts/src/useFetch/useFetch.test.ts @@ -2,6 +2,7 @@ import { act, renderHook, waitFor } from '@testing-library/react' import { useFetch } from './useFetch' +// TODO: Improve fetch() mocking and remove `eslint-disable` comments. const mockFetch = vitest.fn() global.fetch = mockFetch @@ -23,13 +24,15 @@ describe('useFetch()', () => { const mockOptions = {} let receivedURL: string | undefined let receivedOptions: object | undefined - mockFetch.mockImplementation(async (url, options) => { + mockFetch.mockImplementation((url, options) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment receivedURL = url + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment receivedOptions = options }) const { result } = renderHook(() => useFetch(TEST_URL, mockOptions)) - await waitFor(async () => { + await waitFor(() => { expect(receivedURL).toBeDefined() }) @@ -41,7 +44,7 @@ describe('useFetch()', () => { it('should return the JSON version of the fetched data', async () => { let resolvedJSON = false const mockData = {} - mockFetch.mockImplementation(async () => { + mockFetch.mockImplementation(() => { return { ok: true, json: () => @@ -53,7 +56,7 @@ describe('useFetch()', () => { }) const { result } = renderHook(() => useFetch(TEST_URL)) - await waitFor(async () => { + await waitFor(() => { expect(resolvedJSON).toBeTruthy() }) @@ -63,7 +66,8 @@ describe('useFetch()', () => { it('should handle non-ok responses by populating the error state', async () => { const mockStatusText = 'The status is bad' let receivedURL: string | undefined - mockFetch.mockImplementation(async url => { + mockFetch.mockImplementation(url => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment receivedURL = url return { ok: false, @@ -72,7 +76,7 @@ describe('useFetch()', () => { }) const { result } = renderHook(() => useFetch(TEST_URL)) - await waitFor(async () => { + await waitFor(() => { expect(receivedURL).toBeDefined() }) @@ -82,7 +86,7 @@ describe('useFetch()', () => { it('should return cached results without calling fetch() when data is in the cache', async () => { let resolvedJSON = false const mockData = {} - mockFetch.mockImplementation(async () => { + mockFetch.mockImplementation(() => { return { ok: true, json: () => @@ -94,7 +98,7 @@ describe('useFetch()', () => { }) const { result, rerender } = renderHook(() => useFetch(TEST_URL)) - await waitFor(async () => { + await waitFor(() => { expect(resolvedJSON).toBeTruthy() }) act(() => { @@ -108,7 +112,7 @@ describe('useFetch()', () => { it('should cancel the request when the hook is unmounted', async () => { let resolvedJSON = false - mockFetch.mockImplementation(async () => { + mockFetch.mockImplementation(() => { return { ok: false, json: () => @@ -121,7 +125,7 @@ describe('useFetch()', () => { const { result, unmount } = renderHook(() => useFetch(TEST_URL)) unmount() - await waitFor(async () => { + await waitFor(() => { expect(resolvedJSON).toBeDefined() }) diff --git a/packages/usehooks-ts/src/useFetch/useFetch.ts b/packages/usehooks-ts/src/useFetch/useFetch.ts index 469e99d9..ba331286 100644 --- a/packages/usehooks-ts/src/useFetch/useFetch.ts +++ b/packages/usehooks-ts/src/useFetch/useFetch.ts @@ -17,7 +17,7 @@ interface State { * @template T - The type of data stored in the cache. * @type {object} Cache */ -type Cache = { [url: string]: T } +type Cache = Record /** * Represents the possible actions that can be dispatched in the fetchReducer. diff --git a/packages/usehooks-ts/src/useHover/useHover.test.ts b/packages/usehooks-ts/src/useHover/useHover.test.ts index fe6b664d..01861b37 100644 --- a/packages/usehooks-ts/src/useHover/useHover.test.ts +++ b/packages/usehooks-ts/src/useHover/useHover.test.ts @@ -5,7 +5,7 @@ import { useHover } from './useHover' describe('useHover()', () => { const el = { - current: document.createElement('div') as HTMLDivElement, + current: document.createElement('div'), } it('result must be initially false', () => { diff --git a/packages/usehooks-ts/src/useHover/useHover.ts b/packages/usehooks-ts/src/useHover/useHover.ts index 33074e02..612038d7 100644 --- a/packages/usehooks-ts/src/useHover/useHover.ts +++ b/packages/usehooks-ts/src/useHover/useHover.ts @@ -18,8 +18,12 @@ export function useHover( ): boolean { const [value, setValue] = useState(false) - const handleMouseEnter = () => setValue(true) - const handleMouseLeave = () => setValue(false) + const handleMouseEnter = () => { + setValue(true) + } + const handleMouseLeave = () => { + setValue(false) + } useEventListener('mouseenter', handleMouseEnter, elementRef) useEventListener('mouseleave', handleMouseLeave, elementRef) diff --git a/packages/usehooks-ts/src/useImageOnLoad/useImageOnLoad.demo.tsx b/packages/usehooks-ts/src/useImageOnLoad/useImageOnLoad.demo.tsx index 7bc182a5..9e4d2a84 100644 --- a/packages/usehooks-ts/src/useImageOnLoad/useImageOnLoad.demo.tsx +++ b/packages/usehooks-ts/src/useImageOnLoad/useImageOnLoad.demo.tsx @@ -5,7 +5,7 @@ import { useImageOnLoad } from './useImageOnLoad' export default function Component() { const { handleImageOnLoad, css } = useImageOnLoad() - const style: { [key: string]: CSSProperties } = { + const style: Record = { wrap: { position: 'relative', width: 400, @@ -25,14 +25,14 @@ export default function Component() {
{/* Small image load fast */} thumbnail {/* Full size image */} fullImage diff --git a/packages/usehooks-ts/src/useIntersectionObserver/useIntersectionObserver.ts b/packages/usehooks-ts/src/useIntersectionObserver/useIntersectionObserver.ts index d24b252b..54ee120f 100644 --- a/packages/usehooks-ts/src/useIntersectionObserver/useIntersectionObserver.ts +++ b/packages/usehooks-ts/src/useIntersectionObserver/useIntersectionObserver.ts @@ -43,17 +43,20 @@ export function useIntersectionObserver( } useEffect(() => { - const node = elementRef?.current // DOM Ref - const hasIOSupport = !!window.IntersectionObserver + const node = elementRef.current // DOM Ref + if (!node) return - if (!hasIOSupport || frozen || !node) return + const hasIOSupport = !!window.IntersectionObserver + if (!hasIOSupport || frozen) return const observerParams = { threshold, root, rootMargin } const observer = new IntersectionObserver(updateEntry, observerParams) observer.observe(node) - return () => observer.disconnect() + return () => { + observer.disconnect() + } // eslint-disable-next-line react-hooks/exhaustive-deps }, [elementRef?.current, JSON.stringify(threshold), root, rootMargin, frozen]) diff --git a/packages/usehooks-ts/src/useInterval/useInterval.demo.tsx b/packages/usehooks-ts/src/useInterval/useInterval.demo.tsx index 83c5f40c..cc591f04 100644 --- a/packages/usehooks-ts/src/useInterval/useInterval.demo.tsx +++ b/packages/usehooks-ts/src/useInterval/useInterval.demo.tsx @@ -26,7 +26,11 @@ export default function Component() { return ( <>

{count}

-

diff --git a/packages/usehooks-ts/src/useInterval/useInterval.test.ts b/packages/usehooks-ts/src/useInterval/useInterval.test.ts index 11f2e829..a789dded 100644 --- a/packages/usehooks-ts/src/useInterval/useInterval.test.ts +++ b/packages/usehooks-ts/src/useInterval/useInterval.test.ts @@ -8,19 +8,23 @@ describe('useInterval()', () => { vitest.useFakeTimers() }) - it('should fire the callback function (1)', async () => { + it('should fire the callback function (1)', () => { const timeout = 500 const callback = vitest.fn() - renderHook(() => useInterval(callback, timeout)) + renderHook(() => { + useInterval(callback, timeout) + }) vitest.advanceTimersByTime(timeout) expect(callback).toHaveBeenCalledTimes(1) }) - it('should fire the callback function (2)', async () => { + it('should fire the callback function (2)', () => { const timeout = 500 const earlyTimeout = 400 const callback = vitest.fn() - renderHook(() => useInterval(callback, timeout)) + renderHook(() => { + useInterval(callback, timeout) + }) vitest.advanceTimersByTime(earlyTimeout) expect(callback).not.toHaveBeenCalled() }) @@ -29,7 +33,9 @@ describe('useInterval()', () => { mockSetInterval() const timeout = 1200 const callback = vitest.fn() - renderHook(() => useInterval(callback, timeout)) + renderHook(() => { + useInterval(callback, timeout) + }) expect(setInterval).toHaveBeenCalledTimes(1) expect(setInterval).toHaveBeenCalledWith(expect.any(Function), timeout) }) @@ -37,7 +43,9 @@ describe('useInterval()', () => { it('should call clearTimeout on unmount', () => { mockClearInterval() const callback = vitest.fn() - const { unmount } = renderHook(() => useInterval(callback, 1200)) + const { unmount } = renderHook(() => { + useInterval(callback, 1200) + }) unmount() expect(clearInterval).toHaveBeenCalledTimes(1) }) diff --git a/packages/usehooks-ts/src/useInterval/useInterval.ts b/packages/usehooks-ts/src/useInterval/useInterval.ts index d5c22d59..5d1597b5 100644 --- a/packages/usehooks-ts/src/useInterval/useInterval.ts +++ b/packages/usehooks-ts/src/useInterval/useInterval.ts @@ -30,8 +30,12 @@ export function useInterval(callback: () => void, delay: number | null) { return } - const id = setInterval(() => savedCallback.current(), delay) + const id = setInterval(() => { + savedCallback.current() + }, delay) - return () => clearInterval(id) + return () => { + clearInterval(id) + } }, [delay]) } diff --git a/packages/usehooks-ts/src/useIsClient/useIsClient.test.ts b/packages/usehooks-ts/src/useIsClient/useIsClient.test.ts index 3885b969..16c6b701 100644 --- a/packages/usehooks-ts/src/useIsClient/useIsClient.test.ts +++ b/packages/usehooks-ts/src/useIsClient/useIsClient.test.ts @@ -4,12 +4,12 @@ import { useIsClient } from './useIsClient' describe('useIsClient()', () => { // TODO: currently don't know how to simulate hydration of hooks. @see https://github.com/testing-library/react-testing-library/issues/1120 - it.skip('should be false when rendering on the server', async () => { + it.skip('should be false when rendering on the server', () => { const { result } = renderHook(() => useIsClient(), { hydrate: false }) expect(result.current).toBe(false) }) - it('should be true when after hydration', async () => { + it('should be true when after hydration', () => { const { result } = renderHook(() => useIsClient(), { hydrate: true }) expect(result.current).toBe(true) }) diff --git a/packages/usehooks-ts/src/useIsFirstRender/useIsFirstRender.demo.tsx b/packages/usehooks-ts/src/useIsFirstRender/useIsFirstRender.demo.tsx index 9b7091d5..035c54d6 100644 --- a/packages/usehooks-ts/src/useIsFirstRender/useIsFirstRender.demo.tsx +++ b/packages/usehooks-ts/src/useIsFirstRender/useIsFirstRender.demo.tsx @@ -14,7 +14,13 @@ export default function Component() {

Open your console

Is first render: {isFirst ? 'yes' : 'no'}

- +
) } diff --git a/packages/usehooks-ts/src/useIsMounted/useIsMounted.demo.tsx b/packages/usehooks-ts/src/useIsMounted/useIsMounted.demo.tsx index 386f568f..9b967618 100644 --- a/packages/usehooks-ts/src/useIsMounted/useIsMounted.demo.tsx +++ b/packages/usehooks-ts/src/useIsMounted/useIsMounted.demo.tsx @@ -21,7 +21,9 @@ function Child() { export default function Component() { const [isVisible, setVisible] = useState(false) - const toggleVisibility = () => setVisible(state => !state) + const toggleVisibility = () => { + setVisible(state => !state) + } return ( <> diff --git a/packages/usehooks-ts/src/useLocalStorage/useLocalStorage.ts b/packages/usehooks-ts/src/useLocalStorage/useLocalStorage.ts index 3dd9e26b..e2b9143d 100644 --- a/packages/usehooks-ts/src/useLocalStorage/useLocalStorage.ts +++ b/packages/usehooks-ts/src/useLocalStorage/useLocalStorage.ts @@ -81,21 +81,18 @@ export function useLocalStorage( return undefined as unknown as T } - const parsed = JSON.parse(value) - - if (initialValue instanceof Set) { - return new Set(parsed) - } - - if (initialValue instanceof Map) { - return new Map(Object.entries(parsed)) - } - - if (initialValue instanceof Date) { - return new Date(parsed) + const defaultValue = + initialValue instanceof Function ? initialValue() : initialValue + + let parsed: unknown + try { + parsed = JSON.parse(value) + } catch (error) { + console.error('Error parsing JSON:', error) + return defaultValue // Return initialValue if parsing fails } - return parsed + return parsed as T }, [options, initialValue], ) diff --git a/packages/usehooks-ts/src/useLockedBody/useLockedBody.ts b/packages/usehooks-ts/src/useLockedBody/useLockedBody.ts index f55167cb..5ab68354 100644 --- a/packages/usehooks-ts/src/useLockedBody/useLockedBody.ts +++ b/packages/usehooks-ts/src/useLockedBody/useLockedBody.ts @@ -4,8 +4,8 @@ import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect' /** * Custom hook for locking and unlocking the body scroll to prevent scrolling. - * @param {boolean} [initialLocked] - The initial state of body scroll lock. - * @param {string} [rootId] - The ID of the root element to calculate scrollbar width (optional). + * @param {?boolean} [initialLocked] - The initial state of body scroll lock (default to `false`). + * @param {?string} [rootId] - The ID of the root element to calculate scrollbar width (default to `___gatsby` to not introduce breaking change). * @returns {[boolean, (locked: boolean) => void]} A tuple containing the current state of body scroll lock and a function to set the state. * @see [Documentation](https://usehooks-ts.com/react-hook/use-locked-body) * @example @@ -14,8 +14,8 @@ import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect' * // Use setLocked to dynamically control the body scroll lock state. */ export function useLockedBody( - initialLocked: boolean = false, - rootId: string = '___gatsby', // Default to `___gatsby` to not introduce breaking change + initialLocked = false, + rootId = '___gatsby', ): [boolean, (locked: boolean) => void] { const [locked, setLocked] = useState(initialLocked) diff --git a/packages/usehooks-ts/src/useMap/useMap.demo.tsx b/packages/usehooks-ts/src/useMap/useMap.demo.tsx index 65df67a4..3e9b131c 100644 --- a/packages/usehooks-ts/src/useMap/useMap.demo.tsx +++ b/packages/usehooks-ts/src/useMap/useMap.demo.tsx @@ -11,10 +11,18 @@ const otherValues: MapOrEntries = [ export default function Component() { const [map, actions] = useMap(initialValues) - const set = () => actions.set(String(Date.now()), '📦') - const setAll = () => actions.setAll(otherValues) - const reset = () => actions.reset() - const remove = () => actions.remove('hello') + const set = () => { + actions.set(String(Date.now()), '📦') + } + const setAll = () => { + actions.setAll(otherValues) + } + const reset = () => { + actions.reset() + } + const remove = () => { + actions.remove('hello') + } return (
diff --git a/packages/usehooks-ts/src/useMap/useMap.test.ts b/packages/usehooks-ts/src/useMap/useMap.test.ts index e467881c..64af5ffa 100644 --- a/packages/usehooks-ts/src/useMap/useMap.test.ts +++ b/packages/usehooks-ts/src/useMap/useMap.test.ts @@ -29,7 +29,9 @@ describe('useMap()', () => { expect(result.current[0].get(1)).toBeUndefined() - act(() => actions.set(1, 'added')) + act(() => { + actions.set(1, 'added') + }) expect(result.current[0].get(1)).toBe('added') }) @@ -39,7 +41,9 @@ describe('useMap()', () => { const { result } = renderHook(() => useMap(initialMap)) const [, actions] = result.current - act(() => actions.set(1, 'edited')) + act(() => { + actions.set(1, 'edited') + }) expect(result.current[0].get(1)).toBe('edited') }) @@ -56,7 +60,9 @@ describe('useMap()', () => { expect(result.current[0].get(2)).toBe('example') expect(result.current[0].size).toBe(2) - act(() => actions.setAll([[1, 'edited']])) + act(() => { + actions.setAll([[1, 'edited']]) + }) expect(result.current[0].get(1)).toBe('edited') expect(result.current[0].size).toBe(1) @@ -67,7 +73,9 @@ describe('useMap()', () => { const { result } = renderHook(() => useMap(initialMap)) const [, actions] = result.current - act(() => actions.remove(1)) + act(() => { + actions.remove(1) + }) expect(result.current[0].get(1)).toBeUndefined() }) @@ -77,7 +85,9 @@ describe('useMap()', () => { const { result } = renderHook(() => useMap(initialMap)) const [, actions] = result.current - act(() => actions.reset()) + act(() => { + actions.reset() + }) expect(result.current[0].get(1)).toBeUndefined() expect(result.current[0].size).toBe(0) @@ -88,7 +98,9 @@ describe('useMap()', () => { const { result } = renderHook(() => useMap(initialMap)) const [originalMapRef, actions] = result.current - act(() => actions.set(1, 1)) + act(() => { + actions.set(1, 1) + }) expect(originalMapRef).not.toStrictEqual(result.current[0]) expect(originalMapRef.get(1)).toBeUndefined() @@ -101,7 +113,9 @@ describe('useMap()', () => { expect(result.current[1]).toStrictEqual(originalActionsRef) - act(() => originalActionsRef.set(1, 1)) + act(() => { + originalActionsRef.set(1, 1) + }) expect(originalActionsRef).toStrictEqual(result.current[1]) }) diff --git a/packages/usehooks-ts/src/useMediaQuery/useMediaQuery.ts b/packages/usehooks-ts/src/useMediaQuery/useMediaQuery.ts index 29283e35..3511823e 100644 --- a/packages/usehooks-ts/src/useMediaQuery/useMediaQuery.ts +++ b/packages/usehooks-ts/src/useMediaQuery/useMediaQuery.ts @@ -13,10 +13,7 @@ import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect' * const isSmallScreen = useMediaQuery('(max-width: 600px)'); * // Use `isSmallScreen` to conditionally apply styles or logic based on the screen size. */ -export function useMediaQuery( - query: string, - defaultValue: boolean = false, -): boolean { +export function useMediaQuery(query: string, defaultValue = false): boolean { const [matches, setMatches] = useState(defaultValue) const getMatches = (query: string): boolean => { diff --git a/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts b/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts index a25c55e7..fdd88dfe 100644 --- a/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts +++ b/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts @@ -22,7 +22,7 @@ export function useOnClickOutside( mouseEvent: 'mousedown' | 'mouseup' = 'mousedown', ): void { useEventListener(mouseEvent, event => { - const el = ref?.current + const el = ref.current // Do nothing if clicking ref's element or descendent elements if (!el || el.contains(event.target as Node)) { diff --git a/packages/usehooks-ts/src/useReadLocalStorage/useReadLocalStorage.ts b/packages/usehooks-ts/src/useReadLocalStorage/useReadLocalStorage.ts index 0f31e006..1f607c61 100644 --- a/packages/usehooks-ts/src/useReadLocalStorage/useReadLocalStorage.ts +++ b/packages/usehooks-ts/src/useReadLocalStorage/useReadLocalStorage.ts @@ -2,12 +2,6 @@ import { useCallback, useEffect, useState } from 'react' import { useEventListener } from '../useEventListener' -/** - * Represents the possible values for the stored value in local storage. - * @template T - The type of the stored value. - */ -type Value = T | null - const IS_SERVER = typeof window === 'undefined' /** @@ -33,11 +27,11 @@ interface Options { export function useReadLocalStorage( key: string, options: Options = {}, -): Value { +): T | null { // Pass null as initial value to support hydration server-client - const [storedValue, setStoredValue] = useState>(null) + const [storedValue, setStoredValue] = useState(null) - const deserializer = useCallback<(value: string) => T>( + const deserializer = useCallback<(value: string) => T | null>( value => { if (options.deserializer) { return options.deserializer(value) @@ -46,14 +40,23 @@ export function useReadLocalStorage( if (value === 'undefined') { return undefined as unknown as T } - return JSON.parse(value) + + let parsed: unknown + try { + parsed = JSON.parse(value) + } catch (error) { + console.error('Error parsing JSON:', error) + return null + } + + return parsed as T }, [options], ) // Get from local storage then // parse stored json or return initialValue - const readValue = useCallback((): Value => { + const readValue = useCallback((): T | null => { // Prevent build error "window is undefined" but keep keep working if (IS_SERVER) { return null diff --git a/packages/usehooks-ts/src/useSessionStorage/useSessionStorage.demo.tsx b/packages/usehooks-ts/src/useSessionStorage/useSessionStorage.demo.tsx index 0023ca78..53251eaf 100644 --- a/packages/usehooks-ts/src/useSessionStorage/useSessionStorage.demo.tsx +++ b/packages/usehooks-ts/src/useSessionStorage/useSessionStorage.demo.tsx @@ -6,8 +6,20 @@ export default function Component() { return (

Count: {value}

- - + +
) } diff --git a/packages/usehooks-ts/src/useSessionStorage/useSessionStorage.ts b/packages/usehooks-ts/src/useSessionStorage/useSessionStorage.ts index 2fadca72..7dfdbcc6 100644 --- a/packages/usehooks-ts/src/useSessionStorage/useSessionStorage.ts +++ b/packages/usehooks-ts/src/useSessionStorage/useSessionStorage.ts @@ -80,21 +80,18 @@ export function useSessionStorage( return undefined as unknown as T } - const parsed = JSON.parse(value) - - if (initialValue instanceof Set) { - return new Set(parsed) - } - - if (initialValue instanceof Map) { - return new Map(Object.entries(parsed)) - } - - if (initialValue instanceof Date) { - return new Date(parsed) + const defaultValue = + initialValue instanceof Function ? initialValue() : initialValue + + let parsed: unknown + try { + parsed = JSON.parse(value) + } catch (error) { + console.error('Error parsing JSON:', error) + return defaultValue // Return initialValue if parsing fails } - return parsed + return parsed as T }, [options, initialValue], ) diff --git a/packages/usehooks-ts/src/useSsr/useSsr.ts b/packages/usehooks-ts/src/useSsr/useSsr.ts index 80b8b273..ae758b14 100644 --- a/packages/usehooks-ts/src/useSsr/useSsr.ts +++ b/packages/usehooks-ts/src/useSsr/useSsr.ts @@ -6,9 +6,8 @@ */ export function useSsr() { const isDOM = - typeof window !== 'undefined' && - window.document && - window.document.documentElement + // eslint-disable-next-line @typescript-eslint/prefer-optional-chain + typeof window !== 'undefined' && !!window?.document?.documentElement return { isBrowser: isDOM, diff --git a/packages/usehooks-ts/src/useStep/useStep.demo.tsx b/packages/usehooks-ts/src/useStep/useStep.demo.tsx index 36662a38..083f6239 100644 --- a/packages/usehooks-ts/src/useStep/useStep.demo.tsx +++ b/packages/usehooks-ts/src/useStep/useStep.demo.tsx @@ -20,7 +20,13 @@ export default function Component() { - + ) } diff --git a/packages/usehooks-ts/src/useTernaryDarkMode/useTernaryDarkMode.demo.tsx b/packages/usehooks-ts/src/useTernaryDarkMode/useTernaryDarkMode.demo.tsx index 5522dfe3..a1acb572 100644 --- a/packages/usehooks-ts/src/useTernaryDarkMode/useTernaryDarkMode.demo.tsx +++ b/packages/usehooks-ts/src/useTernaryDarkMode/useTernaryDarkMode.demo.tsx @@ -24,9 +24,9 @@ export default function Component() {