Skip to content

Commit

Permalink
chore(Animate): ts improve
Browse files Browse the repository at this point in the history
  • Loading branch information
eternalsky committed Jan 13, 2024
1 parent 9fbc0aa commit f96f841
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 115 deletions.
4 changes: 2 additions & 2 deletions components/animate/__docs__/demo/basic/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { Animate } from '@alifd/next';

class Demo extends React.Component {
constructor(props) {
class Demo extends React.Component<any, any> {
constructor(props: any) {
super(props);
this.state = { visible: true };
this.handleToggle = this.handleToggle.bind(this);
Expand Down
21 changes: 11 additions & 10 deletions components/animate/__docs__/demo/expand/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { Animate } from '@alifd/next';

class Demo extends React.Component {
constructor(props) {
class Demo extends React.Component<any, any> {
[key: string]: any;
constructor(props: any) {
super(props);
this.state = { expand: true };
[
Expand All @@ -25,30 +26,30 @@ class Demo extends React.Component {
});
}

beforeEnter(node) {
beforeEnter(node: HTMLElement) {
this.height = node.offsetHeight;
node.style.height = '0px';
}

onEnter(node) {
onEnter(node: HTMLElement) {
node.style.height = `${this.height}px`;
}

afterEnter(node) {
afterEnter(node: HTMLElement) {
this.height = null;
node.style.height = null;
node.style.setProperty('height', null);
}

beforeLeave(node) {
beforeLeave(node: HTMLElement) {
node.style.height = `${this.height}px`;
}

onLeave(node) {
onLeave(node: HTMLElement) {
node.style.height = '0px';
}

afterLeave(node) {
node.style.height = null;
afterLeave(node: HTMLElement) {
node.style.setProperty('height', null);
}

render() {
Expand Down
8 changes: 4 additions & 4 deletions components/animate/__docs__/demo/multiple/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { Animate } from '@alifd/next';

class TodoList extends React.Component {
constructor(props) {
class TodoList extends React.Component<any, any> {
constructor(props: any) {
super(props);
this.state = { items: ['hello', 'world', 'click', 'me'] };
}
Expand All @@ -18,7 +18,7 @@ class TodoList extends React.Component {
});
}

handleRemove(i) {
handleRemove(i: number) {
const newItems = this.state.items.slice();
newItems.splice(i, 1);
this.setState({ items: newItems });
Expand All @@ -42,7 +42,7 @@ class TodoList extends React.Component {
onLeave={() => console.log('leave')}
afterLeave={() => console.log('after leave')}
>
{this.state.items.map((item, i) => (
{this.state.items.map((item: string, i: number) => (
<div key={item}>
{item}
<button onClick={() => this.handleRemove(i)}>&times;</button>
Expand Down
29 changes: 12 additions & 17 deletions components/animate/animate.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import React, { Component, Children } from 'react';
import React, { Component, Children, type ReactNode, ReactElement } from 'react';
import PropTypes from 'prop-types';
import { TransitionGroup } from 'react-transition-group';
import AnimateChild from './child';
import type { AnimateProps } from './types';
import Expand from './expand';
import OverlayAnimate from './overlay-animate';

const noop = () => {};
const FirstChild = props => {
const FirstChild = (props: { children: ReactNode }) => {
const childrenArray = React.Children.toArray(props.children);
return childrenArray[0] || null;
};

/**
* Animate
*/
class Animate extends Component {
class Animate extends Component<AnimateProps> {
static Expand = Expand;
static OverlayAnimate = OverlayAnimate;
static displayName = 'Animate';
static propTypes = {
/**
* 动画 className
Expand All @@ -36,47 +42,38 @@ class Animate extends Component {
children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]),
/**
* 执行第一次挂载动画前触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
beforeAppear: PropTypes.func,
/**
* 执行第一次挂载动画,添加 xxx-appear-active 类名后触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
onAppear: PropTypes.func,
/**
* 执行完第一次挂载动画后触发的函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
afterAppear: PropTypes.func,
/**
* 执行进场动画前触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
beforeEnter: PropTypes.func,
/**
* 执行进场动画,添加 xxx-enter-active 类名后触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
onEnter: PropTypes.func,
/**
* 执行完进场动画后触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
afterEnter: PropTypes.func,
/**
* 执行离场动画前触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
beforeLeave: PropTypes.func,
/**
* 执行离场动画,添加 xxx-leave-active 类名后触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
onLeave: PropTypes.func,
/**
* 执行完离场动画后触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
afterLeave: PropTypes.func,
};
Expand All @@ -96,7 +93,7 @@ class Animate extends Component {
afterLeave: noop,
};

normalizeNames(names) {
normalizeNames(names: AnimateProps['animation']) {
if (typeof names === 'string') {
return {
appear: `${names}-appear`,
Expand All @@ -120,7 +117,6 @@ class Animate extends Component {
}

render() {
/* eslint-disable no-unused-vars */
const {
animation,
children,
Expand All @@ -138,13 +134,12 @@ class Animate extends Component {
afterLeave,
...others
} = this.props;
/* eslint-enable no-unused-vars */

const animateChildren = Children.map(children, child => {
return (
<AnimateChild
key={child.key}
names={this.normalizeNames(animation)}
key={(child as ReactElement)?.key}
names={this.normalizeNames(animation)!}
onAppear={beforeAppear}
onAppearing={onAppear}
onAppeared={afterAppear}
Expand Down
67 changes: 36 additions & 31 deletions components/animate/child.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Transition } from 'react-transition-group';
import { func, support, events, dom, guid } from '../util';
import type { AnimateChildProps } from './types';

const noop = () => {};
const { on, off } = events;
const { addClass, removeClass } = dom;
const prefixes = ['-webkit-', '-moz-', '-o-', 'ms-', ''];

function getStyleProperty(node, name) {
function getStyleProperty(node: HTMLElement, name: string) {
const style = window.getComputedStyle(node);
let ret = '';
for (let i = 0; i < prefixes.length; i++) {
Expand All @@ -20,7 +21,8 @@ function getStyleProperty(node, name) {
return ret;
}

export default class AnimateChild extends Component {
export default class AnimateChild extends Component<AnimateChildProps> {
static displayName = 'AnimateChild';
static propTypes = {
names: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
onAppear: PropTypes.func,
Expand All @@ -45,8 +47,13 @@ export default class AnimateChild extends Component {
onExiting: noop,
onExited: noop,
};
endListeners: Record<string, Array<(e: UIEvent) => void>>;
timeoutMap: Record<string, number>;
node: HTMLElement;
transitionOff: () => void;
animationOff: () => void;

constructor(props) {
constructor(props: AnimateChildProps) {
super(props);
func.bindCtx(this, [
'handleEnter',
Expand Down Expand Up @@ -76,9 +83,10 @@ export default class AnimateChild extends Component {
};
}

generateEndListener(node, done, eventName, id) {
generateEndListener(node: HTMLElement, done: () => void, eventName: string, id: string) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const _this = this;
return function endListener(e) {
return function endListener(e: UIEvent) {
if (e && e.target === node) {
if (_this.timeoutMap[id]) {
clearTimeout(_this.timeoutMap[id]);
Expand All @@ -94,7 +102,7 @@ export default class AnimateChild extends Component {
};
}

addEndListener(node, done) {
addEndListener(node: HTMLElement, done: () => void) {
if (support.transition || support.animation) {
const id = guid();

Expand Down Expand Up @@ -132,7 +140,7 @@ export default class AnimateChild extends Component {
animationDuration + animationDelay
);
if (time) {
this.timeoutMap[id] = setTimeout(
this.timeoutMap[id] = window.setTimeout(
() => {
done();
},
Expand All @@ -150,85 +158,84 @@ export default class AnimateChild extends Component {
this.animationOff && this.animationOff();
}

removeClassNames(node, names) {
Object.keys(names).forEach(key => {
removeClass(node, names[key]);
removeClassNames(node: HTMLElement, names: NonNullable<AnimateChildProps['names']>) {
Object.keys(names).forEach((key: keyof typeof names) => {
removeClass(node, names[key]!);
});
}

handleEnter(node, isAppearing) {
handleEnter(node: HTMLElement, isAppearing: boolean) {
const { names } = this.props;
if (names) {
this.removeClassNames(node, names);
const className = isAppearing ? 'appear' : 'enter';
addClass(node, names[className]);
addClass(node, names[className]!);
}

const hook = isAppearing ? this.props.onAppear : this.props.onEnter;
hook(node);
hook!(node);
}

handleEntering(node, isAppearing) {
handleEntering(node: HTMLElement, isAppearing: boolean) {
setTimeout(() => {
const { names } = this.props;
if (names) {
const className = isAppearing ? 'appearActive' : 'enterActive';
addClass(node, names[className]);
addClass(node, names[className]!);
}

const hook = isAppearing ? this.props.onAppearing : this.props.onEntering;
hook(node);
hook!(node);
}, 10);
}

handleEntered(node, isAppearing) {
handleEntered(node: HTMLElement, isAppearing: boolean) {
const { names } = this.props;
if (names) {
const classNames = isAppearing
? [names.appear, names.appearActive]
: [names.enter, names.enterActive];
classNames.forEach(className => {
removeClass(node, className);
removeClass(node, className!);
});
}

const hook = isAppearing ? this.props.onAppeared : this.props.onEntered;
hook(node);
hook!(node);
}

handleExit(node) {
handleExit(node: HTMLElement) {
const { names } = this.props;
if (names) {
this.removeClassNames(node, names);
addClass(node, names.leave);
addClass(node, names.leave!);
}

this.props.onExit(node);
this.props.onExit!(node);
}

handleExiting(node) {
handleExiting(node: HTMLElement) {
setTimeout(() => {
const { names } = this.props;
if (names) {
addClass(node, names.leaveActive);
addClass(node, names.leaveActive!);
}
this.props.onExiting(node);
this.props.onExiting!(node);
}, 10);
}

handleExited(node) {
handleExited(node: HTMLElement) {
const { names } = this.props;
if (names) {
[names.leave, names.leaveActive].forEach(className => {
removeClass(node, className);
removeClass(node, className!);
});
}

this.props.onExited(node);
this.props.onExited!(node);
}

render() {
/* eslint-disable no-unused-vars */
const {
names,
onAppear,
Expand All @@ -242,8 +249,6 @@ export default class AnimateChild extends Component {
onExited,
...others
} = this.props;
/* eslint-enable no-unused-vars */

return (
<Transition
{...others}
Expand Down
Loading

0 comments on commit f96f841

Please sign in to comment.