-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a09cece
commit 1b6a91f
Showing
8 changed files
with
166 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
src | ||
**/*.stories.* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "@spark-ui/use-merge-refs", | ||
"version": "0.0.0", | ||
"description": "check the component's mount state", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"main": "./dist/index.js", | ||
"module": "./dist/index.mjs", | ||
"types": "./dist/index.d.ts", | ||
"scripts": { | ||
"build": "vite build" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git@github.com:adevinta/spark.git", | ||
"directory": "packages/hooks/use-mounted-state" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { useMergeRefs } from './useMergeRefs' |
36 changes: 36 additions & 0 deletions
36
packages/hooks/use-merge-refs/src/useMergeRefs.stories.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { Meta, Story } from '@storybook/addon-docs' | ||
import { StoryHeading } from '@docs/helpers/StoryHeading' | ||
|
||
<Meta title="Hooks/useMergeRefs" /> | ||
|
||
# useMountedState | ||
|
||
> The `useMergeRefs` hook has the purpose of merging and sync the passed references into a single one. It could be useful when implementing a component that receives a forwarded ref and that use internal refs, making it easier to pass a single ref to the DOM target. | ||
<StoryHeading label="Install" /> | ||
|
||
``` | ||
npm install @spark-ui/use-merge-refs | ||
``` | ||
|
||
<StoryHeading label="Import" /> | ||
|
||
``` | ||
import { useMergeRefs } from "@spark-ui/use-merge-refs" | ||
``` | ||
|
||
<StoryHeading label="Usage" /> | ||
|
||
```jsx | ||
import * as React from 'react' | ||
import { useMergeRefs } from '@spark-ui/use-merge-refs' | ||
|
||
const Demo = React.forwardRef((props, forwardedRef) => { | ||
const firstRef = useRef() | ||
const secondRef = useRef() | ||
|
||
const ref = useMergeRefs(firstRef, secondRef, forwardedRef) | ||
|
||
return <div ref={ref} {...props} /> | ||
}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { render } from '@testing-library/react' | ||
import React, { useEffect, useRef } from 'react' | ||
import { describe, expect, it } from 'vitest' | ||
|
||
import { useMergeRefs } from './index' | ||
|
||
describe('useMergeRefs', () => { | ||
interface refsInterface { | ||
first?: any | ||
second?: any | ||
third?: any | ||
} | ||
|
||
it('should merge all the passed refs into a single one', () => { | ||
// Given | ||
const refs = {} as refsInterface | ||
function TestComponent() { | ||
const firstRef = useRef() | ||
const secondRef = useRef() | ||
const thirdRef = useRef() | ||
|
||
const ref = useMergeRefs(firstRef, secondRef, thirdRef) | ||
|
||
useEffect(() => { | ||
refs.first = firstRef.current | ||
refs.second = secondRef.current | ||
refs.third = thirdRef.current | ||
}, []) | ||
|
||
return <div ref={ref} /> | ||
} | ||
|
||
render(<TestComponent />) | ||
|
||
expect(refs.first).toBe(refs.second) | ||
expect(refs.first).toBe(refs.third) | ||
expect(refs.second).toBe(refs.third) | ||
}) | ||
|
||
it('should merge both functional and object references', () => { | ||
const refs = {} as refsInterface | ||
|
||
const TestComponent = React.forwardRef(function TestComponent(props, forwardedRef) { | ||
const firstRef = useRef() | ||
const secondRef = useRef() | ||
|
||
const ref = useMergeRefs(firstRef, secondRef, forwardedRef) | ||
|
||
useEffect(() => { | ||
refs.first = firstRef.current | ||
refs.second = secondRef.current | ||
}, []) | ||
|
||
return <div ref={ref} {...props} /> | ||
}) | ||
|
||
const refToBeForwarded = React.createRef() | ||
render(<TestComponent ref={node => (refToBeForwarded.current = node)} />) | ||
|
||
expect(refs.first).toBe(refs.second) | ||
expect(refs.first).toBe(refToBeForwarded.current) | ||
expect(refs.second).toBe(refToBeForwarded.current) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { MutableRefObject, RefCallback, useMemo } from 'react' | ||
|
||
export type ReactRef<T> = RefCallback<T> | MutableRefObject<T> | ||
|
||
export function assignRef<T = any>(ref: ReactRef<T> | null | undefined, value: T) { | ||
if (ref == null) { | ||
return | ||
} | ||
|
||
if (typeof ref === 'function') { | ||
ref(value) | ||
|
||
return | ||
} | ||
|
||
try { | ||
ref.current = value | ||
} catch (error) { | ||
throw new Error(`Cannot assign value '${value}' to ref '${ref}'`) | ||
} | ||
} | ||
|
||
export function mergeRefs<T>(...refs: (ReactRef<T> | null | undefined)[]) { | ||
return (node: T | null) => { | ||
refs.forEach(ref => { | ||
assignRef(ref, node) | ||
}) | ||
} | ||
} | ||
|
||
export function useMergeRefs<T>(...refs: (ReactRef<T> | null | undefined)[]) { | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
return useMemo(() => mergeRefs(...refs), refs) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": "../../../tsconfig.json", | ||
"include": ["src/**/*", "../../../global.d.ts"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import path from 'path' | ||
import { getComponentConfiguration } from '../../../config/index' | ||
|
||
const { name } = require(path.resolve(__dirname, 'package.json')) | ||
|
||
export default getComponentConfiguration(name) |