diff --git a/tslint.json b/tslint.json index 8fa5f05..20e6d04 100644 --- a/tslint.json +++ b/tslint.json @@ -9,6 +9,9 @@ "quotemark": [true, "single", "jsx-double"], "array-type": [true, "generic"], "no-empty": false, + "max-line-length": [true, 140], + "member-ordering": [false], + "no-namespace": [false], "object-literal-sort-keys": false }, "rulesDirectory": [] diff --git a/typings/react-flip-move.d.ts b/typings/react-flip-move.d.ts index 0f2525d..0021367 100644 --- a/typings/react-flip-move.d.ts +++ b/typings/react-flip-move.d.ts @@ -1,71 +1,235 @@ -import * as React from 'react'; +// Type definitions for react-flip-move 2.9 +// Project: https://github.com/joshwcomeau/react-flip-move +// Definitions by: Joey Hain , +// Ville Saarinen +// TypeScript Version: 2.3 -export interface Styles { - [key: string]: string; -} +import { Component, ReactElement } from 'react'; -export interface ReactStyles { - [key: string]: string | number; -} +export as namespace FlipMove; +export = FlipMove; -export interface Animation { - from: Styles; - to: Styles; -} +declare class FlipMove extends Component { } -export interface Presets { - elevator: Animation; - fade: Animation; - accordionVertical: Animation; - accordionHorizontal: Animation; - none: null; -} +declare namespace FlipMove { + type AnimationPreset = 'elevator' | 'fade' | 'accordionVertical' | 'accordionHorizontal' | 'none'; -export type AnimationProp = keyof Presets | boolean | Animation; + interface Animation { + from: Partial; + to: Partial; + } -export interface ClientRect { - top: number; - right: number; - bottom: number; - left: number; - height: number; - width: number; -} + interface Styles { + [key: string]: string | number; + } -export type ChildHook = (element: React.ReactElement, node?: HTMLElement | null) => void; - -export type ChildrenHook = ( - elements: Array>, - nodes: Array, -) => void; - -export type GetPosition = (node: HTMLElement) => ClientRect; - -export type VerticalAlignment = 'top' | 'bottom'; - -export interface FlipMoveProps { - easing?: string; - duration?: string | number; - delay?: string | number; - staggerDurationBy?: string | number; - staggerDelayBy?: string | number; - typeName?: string; - enterAnimation?: AnimationProp; - leaveAnimation?: AnimationProp; - disableAllAnimations?: boolean; - getPosition?: GetPosition; - maintainContainerHeight?: boolean; - verticalAlignment?: VerticalAlignment; - onStart?: ChildHook; - onFinish?: ChildHook; - onStartAll?: ChildrenHook; - onFinishAll?: ChildrenHook; - style?: ReactStyles; - children: any; - appearAnimation?: AnimationProp; - disableAnimations?: boolean; // deprecated, use disableAllAnimations instead -} + type AnimationProp = AnimationPreset | Animation | boolean; + + interface FlipMoveProps { + className?: string; + + /** + * Any valid CSS3 timing function (eg. "linear", "ease-in", "cubic-bezier(1, 0, 0, 1)"). + * + * @default "ease-in-out" + */ + easing?: string; + + /** + * The length, in milliseconds, that the transition ought to take. + * + * @default 350 + */ + duration?: number | string; + + /** + * The length, in milliseconds, to wait before the animation begins. + * + * @default 0 + */ + delay?: number | string; + + /** + * The length, in milliseconds, to be added to the duration of each subsequent element. + * + * For example, if you are animating 4 elements with a `duration` of 200 and a `staggerDurationBy` of 20: + * + * - The first element will take 200ms to transition. + * - The second element will take 220ms to transition. + * - The third element will take 240ms to transition. + * - The fourth element will take 260ms to transition. + * + * This effect is great for "humanizing" transitions and making them feel less robotic. + * + * @default 0 + */ + staggerDurationBy?: number | string; + + /** + * The length, in milliseconds, to be added to the delay of each subsequent element. + * + * For example, if you are animating 4 elements with a `delay` of 0 and a `staggerDelayBy` of 20: + * + * - The first element will start transitioning immediately. + * - The second element will start transitioning after 20ms. + * - The third element will start transitioning after 40ms. + * - The fourth element will start transitioning after 60ms. + * + * Similarly to staggerDurationBy, This effect is great for "humanizing" transitions and making them feel less + * robotic. + * + * **Protip**: You can make elements animate one-at-a-time by using an identical duration and staggerDelayBy. + * + * @default 0 + */ + staggerDelayBy?: number | string; -declare class FlipMove extends React.Component {} + /** + * Control the appear animation that runs when the component mounts. Works identically to enterAnimation below, but + * only fires on the initial children. + */ + appearAnimation?: AnimationProp; -export default FlipMove; + /** + * Control the onEnter animation that runs when new items are added to the DOM. + * + * Accepts several types: + * + * **String:** You can enter one of the following presets to select that as your enter animation: + * + * - `elevator` (default) + * - `fade` + * - `accordionVertical` + * - `accordionHorizontal` + * - `none` + * + * **Boolean:** You can enter `false` to disable the enter animation, or `true` to select the default enter animation (elevator). + * + * **Object:** For fully granular control, you can pass in an object that contains the styles you'd like to animate. + * + * It requires two keys: `from` and `to`. Each key holds an object of CSS properties. You can supply any valid + * camelCase CSS properties, and flip-move will transition between the two, over the course of the specified + * `duration`. + * + * Example: + * + * const customEnterAnimation = { + * from: { transform: 'scale(0.5, 1)' }, + * to: { transform: 'scale(1, 1)' } + * }; + * + * + * {renderChildren()} + * + * + * @default "elevator" + */ + enterAnimation?: AnimationProp; + + /** + * Control the onLeave animation that runs when new items are removed from the DOM. + * + * This property functions identically to `enterAnimation`. + * + * @default "elevator" + */ + leaveAnimation?: AnimationProp; + + /** + * Do not collapse container height until after leaving animations complete. + * + * When false, children are immediately removed from the DOM flow as they animate away. Setting this value to true + * will maintain the height of the container until after their leaving animation completes. + * + * @default false + */ + maintainContainerHeight?: boolean; + + /** + * A callback to be invoked **once per child element** at the start of the animation. + * + * In general, it is advisable to ignore the domNode argument and work with the childElement. The domNode is just + * an escape hatch for doing complex things not otherwise possible. + * + * @param childElement A reference to the React Element being animated. + * @param domNode A reference to the unadulterated DOM node being animated. + */ + onStart?(childElement: ReactElement, domNode: HTMLElement): void; + + /** + * A callback to be invoked **once per child element** at the end of the animation. + * + * In general, it is advisable to ignore the `domNode` argument and work with the `childElement`. The `domNode` is + * just an escape hatch for doing complex things not otherwise possible. + * + * @param childElement A reference to the React Element being animated. + * @param domNode A reference to the unadulterated DOM node being animated. + */ + onFinish?(childElement: ReactElement, domNode: HTMLElement): void; + + /** + * A callback to be invoked **once per group** at the start of the animation. + * + * The callback arguments are similar to the ones provided for onStart, except we provide an array of the elements + * and nodes. The order of both arguments is guaranteed; this means you can use a zipping function like lodash's + * .zip to get pairs of element/node, if needed. + * + * In general, it is advisable to ignore the `domNodes` argument and work with the `childElements` The `domNodes` + * + * are just an escape hatch for doing complex things not otherwise possible. + * + * @param childElements An array of the references to the React Element(s) being animated. + * @param domNodes An array of the references to the unadulterated DOM node(s) being animated. + */ + onStartAll?(childElements: Array>, domNodes: Array): void; + + /** + * A callback to be invoked **once per group** at the end of the animation. + * + * The callback arguments are similar to the ones provided for onFinish, except we provide an array of the elements + * and nodes. The order of both arguments is guaranteed; this means you can use a zipping function like lodash's + * .zip to get pairs of element/node, if needed. + * + * In general, it is advisable to ignore the `domNodes` argument and work with the `childElements` The `domNodes` + * are just an escape hatch for doing complex things not otherwise possible. + * + * @param childElements An array of the references to the React Element(s) being animated. + * @param domNodes An array of the references to the unadulterated DOM node(s) being animated. + */ + onFinishAll?(childElements: Array>, domNodes: Array): void; + + /** + * Flip Move wraps your children in a container element. By default, this element is a div, but you may wish to + * provide a custom HTML element (for example, if your children are list items, you may wish to set this to ul). + * + * Any valid HTML element type is accepted, but peculiar things may happen if you use an unconventional element. + * + * @default "div" + */ + typeName?: string; + + /** + * Sometimes, you may wish to temporarily disable the animations and have the normal behaviour resumed. Setting this + * flag to true skips all animations. + * + * @default false + */ + disableAllAnimations?: boolean; + + /** + * This function is called with a DOM node as the only argument. It should return an object as specified by the + * getBoundingClientRect() spec. + * + * For normal usage of FlipMove you won't need this. An example of usage is when FlipMove is used in a container + * that is scaled using CSS. You can correct the values from getBoundingClientRect by using this prop. + */ + getPosition?(node: HTMLElement): ClientRect; + + /** + * @default "top" + */ + verticalAlignment?: string; + + style?: Styles; + } +} diff --git a/typings/test.tsx b/typings/test.tsx index 71317b0..8ba89a5 100644 --- a/typings/test.tsx +++ b/typings/test.tsx @@ -1,40 +1,113 @@ +// tslint:disable:max-classes-per-file + import * as React from 'react'; -import FlipMove from '..'; +import * as FlipMove from '..'; function childHook(el: React.ReactElement, node: HTMLElement) {} function childrenHook(els: Array>, nodes: Array) {} -// tslint:disable-next-line:no-unused-expression - ({ - top: 0, - right: 0, - bottom: 0, - left: 0, - height: 0, - width: 0, - })} - maintainContainerHeight={true} - verticalAlignment="top" - onStart={childHook} - onFinish={childHook} - onStartAll={childrenHook} - onFinishAll={childrenHook} - style={{ - height: 0, - color: 'red', - }} -> -
-
-; +class ExtendedTest extends React.Component { + public render() { + return ({ + top: 0, + right: 0, + bottom: 0, + left: 0, + height: 0, + width: 0, + })} + maintainContainerHeight={true} + verticalAlignment="top" + onStart={childHook} + onFinish={childHook} + onStartAll={childrenHook} + onFinishAll={childrenHook} + style={{ + height: 0, + color: 'red', + }} + > +
+
+ ; + } +} + +class DefaultTest extends React.Component { + public render() { + return ; + } +} + +class PresetTest extends React.Component { + public render() { + return ( + + ); + } +} + +class CustomAnimationTest extends React.Component { + public render() { + const enterAnimation: FlipMove.Animation = { + from: { opacity: '0' }, + to: { opacity: '1' }, + }; + + const leaveAnimation: FlipMove.Animation = { + from: { opacity: '1' }, + to: { opacity: '0' }, + }; + + return ( + + ); + } +} + +class FlipMoveTest extends React.Component { + public onStart = (childElement: React.ReactElement, domNode: HTMLElement) => {}; + + public onFinish = (childElement: React.ReactElement, domNode: HTMLElement) => {}; + + public onStartAll = (childElements: Array>, domNodes: Array) => {}; + + public onFinishAll = (childElements: Array>, domNodes: Array) => {}; + + public render() { + return ( + + ); + } +}