diff --git a/src/hooks/useIsIntersecting/useIsIntersecting.mdx b/src/hooks/useIsIntersecting/useIsIntersecting.mdx new file mode 100644 index 0000000..f9655ad --- /dev/null +++ b/src/hooks/useIsIntersecting/useIsIntersecting.mdx @@ -0,0 +1,30 @@ +import { Meta } from '@storybook/blocks'; + + + +# useIsIntersecting + +Please add a description about the `useIsIntersecting` hook. + +## Reference + +```ts +function useIsIntersecting(): void; +``` + +### Parameters + +- `TODO` - Describe the parameters here. + +### Returns + +- `TODO` - Define the return value here. + +## Usage + +```tsx +function DemoComponent() { + useIsIntersecting(); + return
; +} +``` diff --git a/src/hooks/useIsIntersecting/useIsIntersecting.stories.tsx b/src/hooks/useIsIntersecting/useIsIntersecting.stories.tsx new file mode 100644 index 0000000..67cc2f4 --- /dev/null +++ b/src/hooks/useIsIntersecting/useIsIntersecting.stories.tsx @@ -0,0 +1,37 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import type { ReactElement } from 'react'; +import { useIsIntersecting } from './useIsIntersecting.js'; + +const meta = { + title: 'Hooks / useIsIntersecting', +} satisfies Meta; + +type Story = StoryObj; + +function DemoComponent(): ReactElement { + useIsIntersecting(); + + return ( +
+
+

Instructions!

+

Add instructions about the hook here.

+
+
+ Value: {/* value */} +
+
+
Test Area
+
+

TODO: Implement a test case for the hook.

+
+
+
+ ); +} + +export const Demo: Story = { + render() { + return ; + }, +}; diff --git a/src/hooks/useIsIntersecting/useIsIntersecting.test.tsx b/src/hooks/useIsIntersecting/useIsIntersecting.test.tsx new file mode 100644 index 0000000..b676588 --- /dev/null +++ b/src/hooks/useIsIntersecting/useIsIntersecting.test.tsx @@ -0,0 +1,11 @@ +import { renderHook } from '@testing-library/react'; +import { describe, it } from 'vitest'; +import { useIsIntersecting } from './useIsIntersecting.js'; + +describe('useIsIntersecting', () => { + it('should not crash', async () => { + renderHook(() => { + return useIsIntersecting(); + }); + }); +}); diff --git a/src/hooks/useIsIntersecting/useIsIntersecting.ts b/src/hooks/useIsIntersecting/useIsIntersecting.ts new file mode 100644 index 0000000..28df3a3 --- /dev/null +++ b/src/hooks/useIsIntersecting/useIsIntersecting.ts @@ -0,0 +1,23 @@ +import { RefObject, useRef, useState } from 'react'; +import { useIntersectionObserver } from '../useIntersectionObserver/useIntersectionObserver.js'; + +/** + * @param targetOrTargets + * @param options + */ +export function useIsIntersecting( + targetOrTargets: RefObject | null>, + options?: IntersectionObserverInit, +): RefObject { + const isIntersectingRef = useRef(false); + + useIntersectionObserver( + targetOrTargets, + (entries) => { + isIntersectingRef.current = entries.every((entry) => entry.isIntersecting); + }, + options, + ); + + return isIntersectingRef; +} diff --git a/src/hooks/useIsIntersectingState/useIsIntersectingState.mdx b/src/hooks/useIsIntersectingState/useIsIntersectingState.mdx new file mode 100644 index 0000000..1bf4385 --- /dev/null +++ b/src/hooks/useIsIntersectingState/useIsIntersectingState.mdx @@ -0,0 +1,30 @@ +import { Meta } from '@storybook/blocks'; + + + +# useIsIntersectingState + +Please add a description about the `useIsIntersectingState` hook. + +## Reference + +```ts +function useIsIntersectingState(): void; +``` + +### Parameters + +- `TODO` - Describe the parameters here. + +### Returns + +- `TODO` - Define the return value here. + +## Usage + +```tsx +function DemoComponent() { + useIsIntersectingState(); + return
; +} +``` diff --git a/src/hooks/useIsIntersectingState/useIsIntersectingState.stories.tsx b/src/hooks/useIsIntersectingState/useIsIntersectingState.stories.tsx new file mode 100644 index 0000000..13ee7ec --- /dev/null +++ b/src/hooks/useIsIntersectingState/useIsIntersectingState.stories.tsx @@ -0,0 +1,37 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import type { ReactElement } from 'react'; +import { useIsIntersectingState } from './useIsIntersectingState.js'; + +const meta = { + title: 'Hooks / useIsIntersectingState', +} satisfies Meta; + +type Story = StoryObj; + +function DemoComponent(): ReactElement { + useIsIntersectingState(); + + return ( +
+
+

Instructions!

+

Add instructions about the hook here.

+
+
+ Value: {/* value */} +
+
+
Test Area
+
+

TODO: Implement a test case for the hook.

+
+
+
+ ); +} + +export const Demo: Story = { + render() { + return ; + }, +}; diff --git a/src/hooks/useIsIntersectingState/useIsIntersectingState.test.tsx b/src/hooks/useIsIntersectingState/useIsIntersectingState.test.tsx new file mode 100644 index 0000000..4b31cce --- /dev/null +++ b/src/hooks/useIsIntersectingState/useIsIntersectingState.test.tsx @@ -0,0 +1,11 @@ +import { renderHook } from '@testing-library/react'; +import { describe, it } from 'vitest'; +import { useIsIntersectingState } from './useIsIntersectingState.js'; + +describe('useIsIntersectingState', () => { + it('should not crash', async () => { + renderHook(() => { + return useIsIntersectingState(); + }); + }); +}); diff --git a/src/hooks/useIsIntersectingState/useIsIntersectingState.ts b/src/hooks/useIsIntersectingState/useIsIntersectingState.ts new file mode 100644 index 0000000..44139d8 --- /dev/null +++ b/src/hooks/useIsIntersectingState/useIsIntersectingState.ts @@ -0,0 +1,23 @@ +import { RefObject, useState } from 'react'; +import { useIntersectionObserver } from '../useIntersectionObserver/useIntersectionObserver.js'; + +/** + * @param targetOrTargets + * @param options + */ +export function useIsIntersectingState( + targetOrTargets: RefObject | null>, + options?: IntersectionObserverInit, +): boolean { + const [isIntersecting, setIsIntersecting] = useState(false); + + useIntersectionObserver( + targetOrTargets, + (entries) => { + setIsIntersecting(() => entries.every((entry) => entry.isIntersecting)); + }, + options, + ); + + return isIntersecting; +} diff --git a/src/index.ts b/src/index.ts index 0338099..9269fc7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,6 +18,8 @@ export * from './hooks/useForceRerender/useForceRerender.js'; export * from './hooks/useHasFocus/useHasFocus.js'; export * from './hooks/useIntersectionObserver/useIntersectionObserver.js'; export * from './hooks/useInterval/useInterval.js'; +export * from './hooks/useIsIntersecting/useIsIntersecting.js'; +export * from './hooks/useIsIntersectingState/useIsIntersectingState.js'; export * from './hooks/useMediaDuration/useMediaDuration.js'; export * from './hooks/useMediaQuery/useMediaQuery.js'; export * from './hooks/useMutationObserver/useMutationObserver.js';