Skip to content

Commit

Permalink
feat: Support forceRender
Browse files Browse the repository at this point in the history
  • Loading branch information
zombieJ committed Sep 28, 2020
1 parent aea47a3 commit 205e470
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 7 deletions.
22 changes: 20 additions & 2 deletions examples/CSSMotion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import './CSSMotion.less';

interface DemoState {
show: boolean;
forceRender: boolean;
motionLeaveImmediately: boolean;
removeOnLeave: boolean;
hasMotionClassName: boolean;
prepare: boolean;
}

async function forceDelay(): Promise<void> {
return new Promise((resolve) => {
return new Promise(resolve => {
setTimeout(resolve, 2000);
});
}
Expand All @@ -32,6 +33,7 @@ const Div = React.forwardRef<HTMLDivElement, any>((props, ref) => {
class Demo extends React.Component<{}, DemoState> {
state: DemoState = {
show: true,
forceRender: false,
motionLeaveImmediately: false,
removeOnLeave: true,
hasMotionClassName: true,
Expand All @@ -48,6 +50,10 @@ class Demo extends React.Component<{}, DemoState> {
this.setState(({ prepare }) => ({ prepare: !prepare }));
};

onForceRender = () => {
this.setState(({ forceRender }) => ({ forceRender: !forceRender }));
};

onRemoveOnLeave = () => {
this.setState(({ removeOnLeave }) => ({ removeOnLeave: !removeOnLeave }));
};
Expand Down Expand Up @@ -84,6 +90,7 @@ class Demo extends React.Component<{}, DemoState> {
render() {
const {
show,
forceRender,
motionLeaveImmediately,
removeOnLeave,
hasMotionClassName,
Expand All @@ -106,6 +113,15 @@ class Demo extends React.Component<{}, DemoState> {
hasMotionClassName
</label>

<label>
<input
type="checkbox"
onChange={this.onForceRender}
checked={forceRender}
/>{' '}
forceRender
</label>

<label>
<input
type="checkbox"
Expand All @@ -130,6 +146,7 @@ class Demo extends React.Component<{}, DemoState> {
<h2>With Transition Class</h2>
<CSSMotion
visible={show}
forceRender={forceRender}
motionName={hasMotionClassName ? 'transition' : null}
removeOnLeave={removeOnLeave}
leavedClassName="hidden"
Expand All @@ -140,7 +157,7 @@ class Demo extends React.Component<{}, DemoState> {
onLeaveActive={this.onCollapse}
onEnterEnd={this.skipColorTransition}
onLeaveEnd={this.skipColorTransition}
onVisibleChanged={(visible) => {
onVisibleChanged={visible => {
console.log('Visible Changed:', visible);
}}
>
Expand All @@ -158,6 +175,7 @@ class Demo extends React.Component<{}, DemoState> {
<h2>With Animation Class</h2>
<CSSMotion
visible={show}
forceRender={forceRender}
motionName={hasMotionClassName ? 'animation' : null}
removeOnLeave={removeOnLeave}
leavedClassName="hidden"
Expand Down
15 changes: 15 additions & 0 deletions src/CSSMotion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,17 @@ export interface CSSMotionProps {
motionLeave?: boolean;
motionLeaveImmediately?: boolean;
motionDeadline?: number;
/**
* Create element in view even the element is invisible.
* Will patch `display: none` style on it.
*/
forceRender?: boolean;
/**
* Remove element when motion end. This will not work when `forceRender` is set.
*/
removeOnLeave?: boolean;
leavedClassName?: string;
/** @private Used by CSSMotionList. Do not use in your production. */
eventProps?: object;

// Prepare groups
Expand Down Expand Up @@ -114,6 +123,7 @@ export function genCSSMotion(
visible = true,
removeOnLeave = true,

forceRender,
children,
motionName,
leavedClassName,
Expand Down Expand Up @@ -170,6 +180,11 @@ export function genCSSMotion(
{ ...eventProps, className: leavedClassName },
setNodeRef,
);
} else if (forceRender) {
motionChildren = children(
{ ...eventProps, style: { display: 'none' } },
setNodeRef,
);
} else {
motionChildren = null;
}
Expand Down
25 changes: 20 additions & 5 deletions tests/CSSMotion.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,7 @@ describe('CSSMotion', () => {
});
}

test(
'without ref',
React.forwardRef((props) => <div {...props} />),
);
test('without ref', React.forwardRef(props => <div {...props} />));

test(
'FC with ref',
Expand Down Expand Up @@ -509,7 +506,7 @@ describe('CSSMotion', () => {
let lockResolve: Function;
const onAppearPrepare = jest.fn(
() =>
new Promise((resolve) => {
new Promise(resolve => {
lockResolve = resolve;
}),
);
Expand Down Expand Up @@ -545,4 +542,22 @@ describe('CSSMotion', () => {
wrapper.find('.motion-box').hasClass('bamboo-appear-prepare'),
).toBeFalsy();
});

it('forceRender', () => {
const wrapper = mount(
<CSSMotion forceRender motionName="bamboo" visible={false}>
{({ style, className }) => (
<div style={style} className={classNames('motion-box', className)} />
)}
</CSSMotion>,
);

expect(wrapper.find('.motion-box').props().style).toEqual({
display: 'none',
});

// Reset should hide
wrapper.setProps({ forceRender: false });
expect(wrapper.find('.motion-box')).toHaveLength(0);
});
});

1 comment on commit 205e470

@vercel
Copy link

@vercel vercel bot commented on 205e470 Sep 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.