Skip to content

Commit

Permalink
Implement support for children wrapped
Browse files Browse the repository at this point in the history
  • Loading branch information
VictorGa committed Oct 20, 2023
1 parent 2f34106 commit 2dca619
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 1 deletion.
33 changes: 33 additions & 0 deletions packages/react-animation/src/SplitTextWrapper/SplitTextWrapper.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,39 @@ function Component(): ReactElement {

<Canvas of={stories.Children} />

## Rendering children wraped in a parent element

The `SplitTextWrapper` renders to HTML inside the component to make sure that compnents from the
vDOM are not changed on render making them untargetable in the created SplitText instance. **_This
time the children being wrap in another parent element_**

> Warning: state inside the rendered children is lost when the children change.
```tsx
function Component(): ReactElement {
const splitTextRef = useRef<SplitText>(null);

useEffect(() => {
// Do something with `splitTextRef.current`
});

return (
<SplitTextWrapper ref={splitTextRef}>
<p>
Lorem ipsum dolor sit <i>amet consectetur</i>
<br /> adipisicing elit. <b>Tenetur perspiciatis</b> eius ea, ratione,
<br /> illo molestias, <code>quia sapiente</code> modi quo
<br /> molestiae temporibus.
</p>
</SplitTextWrapper>
);
}
```

### Demo

<Canvas of={stories.ChildrenWrap} />

## Using dangerouslySetInnerHTML

The children are rendered to a string, this is not necessary when the `dangerouslySetInnerHTML`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,80 @@ export const Children: Story = {
},
};

export const ChildrenWrap: Story = {
render(): ReactElement {
const splitTextRef = useRef<SplitText>(null);

const animation = useAnimation(() => {
if (!splitTextRef.current) {
return;
}

return gsap.from(splitTextRef.current.lines, {
paused: true,
y: 20,
opacity: 0,
duration: 0.2,
stagger: 0.05,
});
}, []);

const onPlay = useCallback(() => {
animation.current?.play(0);
}, [animation]);

return (
<>
<SplitTextWrapper ref={splitTextRef} variables={{ type: 'lines' }} data-testid="wrapper">
<p>
Lorem ipsum dolor sit <i>amet consectetur</i>
<br /> adipisicing elit. <b>Tenetur perspiciatis</b> eius ea, ratione,
<br /> illo molestias, <code data-testid="code">quia sapiente</code> modi quo
<br /> molestiae temporibus.
</p>
</SplitTextWrapper>
<button
onClick={onPlay}
type="button"
style={{
position: 'relative',
marginBlockStart: 20,
cursor: 'pointer',
}}
>
Play
</button>
</>
);
},
async play({ canvasElement }) {
const canvas = within(canvasElement);
const wrapper = canvas.getByTestId('wrapper');

expect(wrapper).toBeInTheDocument();
expect(wrapper.childElementCount).toEqual(4);

// Wait 2 ticks for styles to be initialized
await new Promise<void>((resolve) => {
setTimeout(resolve, 0);
});
await new Promise<void>((resolve) => {
setTimeout(resolve, 0);
});

expect(wrapper.children[0]).toHaveStyle({ opacity: '0' });
expect(wrapper.children[3]).toHaveStyle({ opacity: '0' });

await userEvent.click(canvas.getByText('Play'));
await new Promise<void>((resolve) => {
setTimeout(resolve, 200 + wrapper.childElementCount * 50);
});

expect(wrapper.children[0]).toHaveStyle({ opacity: '1' });
expect(wrapper.children[3]).toHaveStyle({ opacity: '1' });
},
};

export const DangerouslySetInnerHtml: Story = {
render(): ReactElement {
const splitTextRef = useRef<SplitText>(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ export const SplitTextWrapper: SplitTextWrapperComponent = ensuredForwardRef(
return;
}

ref.current = new SplitText(element, variables);
const content =
element.firstChild?.nodeType === Node.ELEMENT_NODE
? element.querySelector((element.firstChild as HTMLElement).tagName.toLowerCase())
: element;
ref.current = new SplitText(content, variables);
};

const Component = (as ?? 'div') as unknown as ComponentType<unknown>;
Expand Down

0 comments on commit 2dca619

Please sign in to comment.