Convert NodeAnimator to TS

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
pull/21833/head
Šimon Brandner 2021-09-27 12:38:56 +02:00
parent 1fe96cae8a
commit b621f92805
No known key found for this signature in database
GPG Key ID: 55C211A1226CB17D
1 changed files with 36 additions and 31 deletions

View File

@ -1,6 +1,21 @@
import React from "react";
import ReactDom from "react-dom";
import PropTypes from 'prop-types';
interface IChildProps {
style: React.CSSProperties;
ref: (node: React.ReactInstance) => void;
}
interface IProps {
// either a list of child nodes, or a single child.
children: React.ReactNode;
// optional transition information for changing existing children
transition?: object;
// a list of state objects to apply to each child node in turn
startStyles: React.CSSProperties[];
}
/**
* The NodeAnimator contains components and animates transitions.
@ -9,55 +24,45 @@ import PropTypes from 'prop-types';
* from DOM order. This makes it a lot simpler and lighter: if you need fully
* automatic positional animation, look at react-shuffle or similar libraries.
*/
export default class NodeAnimator extends React.Component {
static propTypes = {
// either a list of child nodes, or a single child.
children: PropTypes.any,
// optional transition information for changing existing children
transition: PropTypes.object,
// a list of state objects to apply to each child node in turn
startStyles: PropTypes.array,
};
static defaultProps = {
export default class NodeAnimator extends React.Component<IProps> {
private nodes = {};
private children: { [key: string]: React.DetailedReactHTMLElement<any, HTMLElement> };
static defaultProps: Partial<IProps> = {
startStyles: [],
};
constructor(props) {
constructor(props: IProps) {
super(props);
this.nodes = {};
this._updateChildren(this.props.children);
this.updateChildren(this.props.children);
}
componentDidUpdate() {
this._updateChildren(this.props.children);
public componentDidUpdate(): void {
this.updateChildren(this.props.children);
}
/**
*
* @param {HTMLElement} node element to apply styles to
* @param {object} styles a key/value pair of CSS properties
* @param {React.CSSProperties} styles a key/value pair of CSS properties
* @returns {void}
*/
_applyStyles(node, styles) {
private applyStyles(node: HTMLElement, styles: React.CSSProperties): void {
Object.entries(styles).forEach(([property, value]) => {
node.style[property] = value;
});
}
_updateChildren(newChildren) {
private updateChildren(newChildren: React.ReactNode): void {
const oldChildren = this.children || {};
this.children = {};
React.Children.toArray(newChildren).forEach((c) => {
React.Children.toArray(newChildren).forEach((c: any) => {
if (oldChildren[c.key]) {
const old = oldChildren[c.key];
const oldNode = ReactDom.findDOMNode(this.nodes[old.key]);
if (oldNode && oldNode.style.left !== c.props.style.left) {
this._applyStyles(oldNode, { left: c.props.style.left });
if (oldNode && (oldNode as HTMLElement).style.left !== c.props.style.left) {
this.applyStyles(oldNode as HTMLElement, { left: c.props.style.left });
// console.log("translation: "+oldNode.style.left+" -> "+c.props.style.left);
}
// clone the old element with the props (and children) of the new element
@ -66,7 +71,7 @@ export default class NodeAnimator extends React.Component {
} else {
// new element. If we have a startStyle, use that as the style and go through
// the enter animations
const newProps = {};
const newProps: Partial<IChildProps> = {};
const restingStyle = c.props.style;
const startStyles = this.props.startStyles;
@ -76,7 +81,7 @@ export default class NodeAnimator extends React.Component {
// console.log("mounted@startstyle0: "+JSON.stringify(startStyle));
}
newProps.ref = ((n) => this._collectNode(
newProps.ref = ((n) => this.collectNode(
c.key, n, restingStyle,
));
@ -85,7 +90,7 @@ export default class NodeAnimator extends React.Component {
});
}
_collectNode(k, node, restingStyle) {
private collectNode(k: string, node: React.ReactInstance, restingStyle: React.CSSProperties): void {
if (
node &&
this.nodes[k] === undefined &&
@ -96,7 +101,7 @@ export default class NodeAnimator extends React.Component {
// start from startStyle 1: 0 is the one we gave it
// to start with, so now we animate 1 etc.
for (let i = 1; i < startStyles.length; ++i) {
this._applyStyles(domNode, startStyles[i]);
this.applyStyles(domNode as HTMLElement, startStyles[i]);
// console.log("start:"
// JSON.stringify(startStyles[i]),
// );
@ -104,7 +109,7 @@ export default class NodeAnimator extends React.Component {
// and then we animate to the resting state
setTimeout(() => {
this._applyStyles(domNode, restingStyle);
this.applyStyles(domNode as HTMLElement, restingStyle);
}, 0);
// console.log("enter:",
@ -113,7 +118,7 @@ export default class NodeAnimator extends React.Component {
this.nodes[k] = node;
}
render() {
public render(): JSX.Element {
return (
<>{ Object.values(this.children) }</>
);