Skip to content

Commit

Permalink
Merge pull request #214 from mediamonks/#213-add-option-to-split-on-f…
Browse files Browse the repository at this point in the history
…irst-element-to-accommodate-a-rich-text-child-node

Add option to SplitTextWrapper to split on firstElementChild #213
  • Loading branch information
VictorGa authored Oct 20, 2023
2 parents 2f34106 + b342d7c commit ef1cd19
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,55 @@ export const DangerouslySetInnerHtml: Story = {
},
};

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

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

return gsap.from(splitTextRef.current.lines, {
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' }}
dangerouslySetInnerHTML={{
// eslint-disable-next-line @typescript-eslint/naming-convention
__html:
'<div>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.</div>',
}}
splitFirstElementChild
/>
<button
onClick={onPlay}
type="button"
style={{
position: 'relative',
marginBlockStart: 20,
cursor: 'pointer',
}}
>
Play
</button>
</>
);
},
};

export const AsProp: Story = {
render(): ReactElement {
const splitText1Ref = useRef<SplitText>(null);
Expand Down
20 changes: 18 additions & 2 deletions packages/react-animation/src/SplitTextWrapper/SplitTextWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ type SplitTextWrapperProps<T extends KnownTarget> = {
* The element type to render, the default is `div`
*/
as?: T;

/**
* Split the first element child instead of the element itself to
* accommodate for rich text children
*/
splitFirstElementChild?: boolean;
};

/**
Expand All @@ -43,7 +49,7 @@ type SplitTextWrapperComponent = <T extends KnownTarget = 'div'>(

// @ts-expect-error polymorphic type is not compatible with ensuredForwardRef function factory
export const SplitTextWrapper: SplitTextWrapperComponent = ensuredForwardRef(
({ variables = {}, as, children, ...props }, ref) => {
({ variables = {}, as, children, splitFirstElementChild = false, ...props }, ref) => {
/**
* Not using useCallback on purpose so that a new SplitText instance is
* created whenever this component rerenders the children
Expand All @@ -53,7 +59,17 @@ export const SplitTextWrapper: SplitTextWrapperComponent = ensuredForwardRef(
return;
}

ref.current = new SplitText(element, variables);
if (splitFirstElementChild && element.childElementCount > 1) {
// eslint-disable-next-line no-console
console.warn(
"Split text wrapper should only contain 1 element when 'splitFirstElementChild' is set to true",
);
}

ref.current = new SplitText(
splitFirstElementChild ? element.firstElementChild : element,
variables,
);
};

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

0 comments on commit ef1cd19

Please sign in to comment.