├── .babelrc.js
├── .editorconfig
├── .gitignore
├── .prettierrc
├── .storybook
└── config.js
├── HISTORY.md
├── LICENSE.md
├── README.md
├── package.json
├── src
├── Event.js
├── classes.js
└── index.js
└── stories
├── collapse.js
├── events.js
├── simple.js
└── style.js
/.babelrc.js:
--------------------------------------------------------------------------------
1 | console.log('Load babel config');
2 |
3 | module.exports = {
4 | presets: [
5 | [
6 | '@babel/preset-env',
7 | {
8 | modules: false,
9 | },
10 | ],
11 | ],
12 | };
13 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # top-most EditorConfig file
2 | root = true
3 |
4 | # Unix-style newlines with a newline ending every file
5 | [*.{js,css}]
6 | end_of_line = lf
7 | insert_final_newline = true
8 | indent_style = space
9 | indent_size = 2
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | *.log
3 | .idea/
4 | .ipr
5 | .iws
6 | *~
7 | ~*
8 | *.diff
9 | *.patch
10 | *.bak
11 | .DS_Store
12 | Thumbs.db
13 | .project
14 | .*proj
15 | .svn/
16 | *.swp
17 | *.swo
18 | *.pyc
19 | *.pyo
20 | .build
21 | node_modules
22 | .cache
23 | dist
24 | assets/**/*.css
25 | build
26 | lib
27 | coverage
28 | yarn.lock
29 | /pkg/
30 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/.storybook/config.js:
--------------------------------------------------------------------------------
1 | import { addParameters, configure } from '@storybook/react';
2 |
3 | addParameters({
4 | options: {
5 | showAddonsPanel: false,
6 | theme: {
7 | brandTitle: 'css-animation',
8 | brandUrl: 'https://github.com/yiminghe/css-animation/',
9 | }
10 | }
11 | });
12 |
13 | // automatically import all files ending in *.stories.js
14 | const req = require.context('../stories', true, /.js$/);
15 |
16 | function loadStories() {
17 | req.keys().forEach(filename => req(filename));
18 | }
19 |
20 | configure(loadStories, module);
21 |
--------------------------------------------------------------------------------
/HISTORY.md:
--------------------------------------------------------------------------------
1 | # History
2 | ----
3 |
4 | ## 2.0.0 / 2019-07-28
5 |
6 | - use pack
7 |
8 | ## 1.5.0 / 2018-11-12
9 |
10 | - support startEventListenter
11 |
12 | ## 1.4.0 / 2017-08-16
13 |
14 | - add es version
15 |
16 | ## 1.3.0 / 2016-08-01
17 |
18 | - support animationName as object
19 |
20 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-present yiminghe
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # css-animation
2 | ---
3 |
4 | make css animation easier
5 |
6 | [![NPM version][npm-image]][npm-url]
7 |
8 | [npm-image]: http://img.shields.io/npm/v/css-animation.svg?style=flat-square
9 | [npm-url]: http://npmjs.org/package/css-animation
10 |
11 | ## Development
12 |
13 | ```
14 | npm install
15 | npm start
16 | ```
17 |
18 | ## Example
19 |
20 | http://localhost:6006/
21 |
22 | online example: http://yiminghe.github.io/css-animation/
23 |
24 |
25 | ## Feature
26 |
27 | * support ie8,ie8+,chrome,firefox,safari
28 |
29 | ## install
30 |
31 | [](https://npmjs.org/package/css-animation)
32 |
33 | ## Usage
34 |
35 | ```js
36 | import anim from 'css-animation';
37 | anim(el,animationName,function(){});
38 | ```
39 |
40 | ## API
41 |
42 | ### void anim(el:DOMElement, animationName:String, callback:Function)
43 |
44 |
45 |
46 |
47 | name
48 | type
49 | default
50 | description
51 |
52 |
53 |
54 |
55 | el
56 | DOMElement
57 |
58 | dom element to be animated
59 |
60 |
61 | animationName
62 | String|Object
63 |
64 | will add animationName (if string) or animationName.name (if object) as class to el, then setTimeout 0 to add ${animationName}-active (if string) or animationName.active (if object) to el
65 |
66 |
67 | callback
68 | Function
69 |
70 | triggered when anim caused by animationName is done
71 |
72 |
73 |
74 |
75 | ## License
76 |
77 | css-animation is released under the MIT license.
78 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "css-animation",
3 | "version": "2.0.4",
4 | "description": "css-animation",
5 | "keywords": [
6 | "css-animation"
7 | ],
8 | "homepage": "http://github.com/yiminghe/css-animation",
9 | "author": "",
10 | "repository": {
11 | "type": "git",
12 | "url": "git@github.com:yiminghe/css-animation.git"
13 | },
14 | "bugs": {
15 | "url": "http://github.com/yiminghe/css-animation/issues"
16 | },
17 | "license": "MIT",
18 | "@pika/pack": {
19 | "pipeline": [
20 | [
21 | "@pika/plugin-standard-pkg",
22 | {
23 | "exclude": [
24 | "__tests__/**/*"
25 | ]
26 | }
27 | ],
28 | [
29 | "pika-plugin-build-web-babel"
30 | ],
31 | [
32 | "@pika/plugin-build-node"
33 | ],
34 | [
35 | "pika-plugin-clean-dist-src"
36 | ]
37 | ]
38 | },
39 | "scripts": {
40 | "prettier": "prettier --write \"{src,stories}/**/*.{js,tsx}\"",
41 | "start": "start-storybook -p 6006",
42 | "pub": "npm run build && npm publish pkg && git push",
43 | "build": "pack build",
44 | "deploy": "storybook-to-ghpages",
45 | "lint-staged": "lint-staged"
46 | },
47 | "devDependencies": {
48 | "@pika/plugin-build-node": "0.6.x",
49 | "@pika/plugin-build-types": "0.6.x",
50 | "@pika/plugin-standard-pkg": "0.6.x",
51 | "@pika/types": "0.6.x",
52 | "@storybook/react": "^5.1.9",
53 | "@storybook/storybook-deployer": "^2.8.1",
54 | "babel-loader": "^8.0.6",
55 | "lint-staged": "^9.2.1",
56 | "pika-plugin-build-web-babel": "0.6.x",
57 | "pika-plugin-clean-dist-src": "^0.1.1",
58 | "pre-commit": "1.x",
59 | "prettier": "^1.18.2",
60 | "react": "16.x",
61 | "react-dom": "16.x"
62 | },
63 | "lint-staged": {
64 | "*.{tsx,js,jsx,ts}": [
65 | "prettier --write",
66 | "git add"
67 | ]
68 | },
69 | "pre-commit": [
70 | "lint-staged"
71 | ]
72 | }
73 |
--------------------------------------------------------------------------------
/src/Event.js:
--------------------------------------------------------------------------------
1 | const START_EVENT_NAME_MAP = {
2 | transitionstart: {
3 | transition: 'transitionstart',
4 | WebkitTransition: 'webkitTransitionStart',
5 | MozTransition: 'mozTransitionStart',
6 | OTransition: 'oTransitionStart',
7 | msTransition: 'MSTransitionStart',
8 | },
9 |
10 | animationstart: {
11 | animation: 'animationstart',
12 | WebkitAnimation: 'webkitAnimationStart',
13 | MozAnimation: 'mozAnimationStart',
14 | OAnimation: 'oAnimationStart',
15 | msAnimation: 'MSAnimationStart',
16 | },
17 | };
18 |
19 | const END_EVENT_NAME_MAP = {
20 | transitionend: {
21 | transition: 'transitionend',
22 | WebkitTransition: 'webkitTransitionEnd',
23 | MozTransition: 'mozTransitionEnd',
24 | OTransition: 'oTransitionEnd',
25 | msTransition: 'MSTransitionEnd',
26 | },
27 |
28 | animationend: {
29 | animation: 'animationend',
30 | WebkitAnimation: 'webkitAnimationEnd',
31 | MozAnimation: 'mozAnimationEnd',
32 | OAnimation: 'oAnimationEnd',
33 | msAnimation: 'MSAnimationEnd',
34 | },
35 | };
36 |
37 | const startEvents = [];
38 | const endEvents = [];
39 |
40 | function detectEvents() {
41 | const testEl = document.createElement('div');
42 | const style = testEl.style;
43 |
44 | if (!('AnimationEvent' in window)) {
45 | delete START_EVENT_NAME_MAP.animationstart.animation;
46 | delete END_EVENT_NAME_MAP.animationend.animation;
47 | }
48 |
49 | if (!('TransitionEvent' in window)) {
50 | delete START_EVENT_NAME_MAP.transitionstart.transition;
51 | delete END_EVENT_NAME_MAP.transitionend.transition;
52 | }
53 |
54 | function process(EVENT_NAME_MAP, events) {
55 | for (const baseEventName in EVENT_NAME_MAP) {
56 | if (EVENT_NAME_MAP.hasOwnProperty(baseEventName)) {
57 | const baseEvents = EVENT_NAME_MAP[baseEventName];
58 | for (const styleName in baseEvents) {
59 | if (styleName in style) {
60 | events.push(baseEvents[styleName]);
61 | break;
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
68 | process(START_EVENT_NAME_MAP, startEvents);
69 | process(END_EVENT_NAME_MAP, endEvents);
70 | }
71 |
72 | if (typeof window !== 'undefined' && typeof document !== 'undefined') {
73 | detectEvents();
74 | }
75 |
76 | function addEventListener(node, eventName, eventListener) {
77 | node.addEventListener(eventName, eventListener, false);
78 | }
79 |
80 | function removeEventListener(node, eventName, eventListener) {
81 | node.removeEventListener(eventName, eventListener, false);
82 | }
83 |
84 | const TransitionEvents = {
85 | // Start events
86 | startEvents,
87 |
88 | addStartEventListener(node, eventListener) {
89 | if (startEvents.length === 0) {
90 | window.setTimeout(eventListener, 0);
91 | return;
92 | }
93 | startEvents.forEach(startEvent => {
94 | addEventListener(node, startEvent, eventListener);
95 | });
96 | },
97 |
98 | removeStartEventListener(node, eventListener) {
99 | if (startEvents.length === 0) {
100 | return;
101 | }
102 | startEvents.forEach(startEvent => {
103 | removeEventListener(node, startEvent, eventListener);
104 | });
105 | },
106 |
107 | // End events
108 | endEvents,
109 |
110 | addEndEventListener(node, eventListener) {
111 | if (endEvents.length === 0) {
112 | window.setTimeout(eventListener, 0);
113 | return;
114 | }
115 | endEvents.forEach(endEvent => {
116 | addEventListener(node, endEvent, eventListener);
117 | });
118 | },
119 |
120 | removeEndEventListener(node, eventListener) {
121 | if (endEvents.length === 0) {
122 | return;
123 | }
124 | endEvents.forEach(endEvent => {
125 | removeEventListener(node, endEvent, eventListener);
126 | });
127 | },
128 | };
129 |
130 | export default TransitionEvents;
131 |
--------------------------------------------------------------------------------
/src/classes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Module dependencies.
3 | */
4 |
5 | function index(arr, obj) {
6 | if (arr.indexOf) return arr.indexOf(obj);
7 | for (var i = 0; i < arr.length; ++i) {
8 | if (arr[i] === obj) return i;
9 | }
10 | return -1;
11 | }
12 |
13 | /**
14 | * Whitespace regexp.
15 | */
16 |
17 | var re = /\s+/;
18 |
19 | /**
20 | * toString reference.
21 | */
22 |
23 | var toString = Object.prototype.toString;
24 |
25 | /**
26 | * Wrap `el` in a `ClassList`.
27 | *
28 | * @param {Element} el
29 | * @return {ClassList}
30 | * @api public
31 | */
32 |
33 | export default function(el) {
34 | return new ClassList(el);
35 | }
36 |
37 | /**
38 | * Initialize a new ClassList for `el`.
39 | *
40 | * @param {Element} el
41 | * @api private
42 | */
43 |
44 | function ClassList(el) {
45 | if (!el || !el.nodeType) {
46 | throw new Error('A DOM element reference is required');
47 | }
48 | this.el = el;
49 | this.list = el.classList;
50 | }
51 |
52 | /**
53 | * Add class `name` if not already present.
54 | *
55 | * @param {String} name
56 | * @return {ClassList}
57 | * @api public
58 | */
59 |
60 | ClassList.prototype.add = function(name) {
61 | // classList
62 | if (this.list) {
63 | this.list.add(name);
64 | return this;
65 | }
66 |
67 | // fallback
68 | var arr = this.array();
69 | var i = index(arr, name);
70 | if (!~i) arr.push(name);
71 | this.el.className = arr.join(' ');
72 | return this;
73 | };
74 |
75 | /**
76 | * Remove class `name` when present, or
77 | * pass a regular expression to remove
78 | * any which match.
79 | *
80 | * @param {String|RegExp} name
81 | * @return {ClassList}
82 | * @api public
83 | */
84 |
85 | ClassList.prototype.remove = function(name) {
86 | if ('[object RegExp]' == toString.call(name)) {
87 | return this.removeMatching(name);
88 | }
89 |
90 | // classList
91 | if (this.list) {
92 | this.list.remove(name);
93 | return this;
94 | }
95 |
96 | // fallback
97 | var arr = this.array();
98 | var i = index(arr, name);
99 | if (~i) arr.splice(i, 1);
100 | this.el.className = arr.join(' ');
101 | return this;
102 | };
103 |
104 | /**
105 | * Remove all classes matching `re`.
106 | *
107 | * @param {RegExp} re
108 | * @return {ClassList}
109 | * @api private
110 | */
111 |
112 | ClassList.prototype.removeMatching = function(re) {
113 | var arr = this.array();
114 | for (var i = 0; i < arr.length; i++) {
115 | if (re.test(arr[i])) {
116 | this.remove(arr[i]);
117 | }
118 | }
119 | return this;
120 | };
121 |
122 | /**
123 | * Toggle class `name`, can force state via `force`.
124 | *
125 | * For browsers that support classList, but do not support `force` yet,
126 | * the mistake will be detected and corrected.
127 | *
128 | * @param {String} name
129 | * @param {Boolean} force
130 | * @return {ClassList}
131 | * @api public
132 | */
133 |
134 | ClassList.prototype.toggle = function(name, force) {
135 | // classList
136 | if (this.list) {
137 | if ('undefined' !== typeof force) {
138 | if (force !== this.list.toggle(name, force)) {
139 | this.list.toggle(name); // toggle again to correct
140 | }
141 | } else {
142 | this.list.toggle(name);
143 | }
144 | return this;
145 | }
146 |
147 | // fallback
148 | if ('undefined' !== typeof force) {
149 | if (!force) {
150 | this.remove(name);
151 | } else {
152 | this.add(name);
153 | }
154 | } else {
155 | if (this.has(name)) {
156 | this.remove(name);
157 | } else {
158 | this.add(name);
159 | }
160 | }
161 |
162 | return this;
163 | };
164 |
165 | /**
166 | * Return an array of classes.
167 | *
168 | * @return {Array}
169 | * @api public
170 | */
171 |
172 | ClassList.prototype.array = function() {
173 | var className = this.el.getAttribute('class') || '';
174 | var str = className.replace(/^\s+|\s+$/g, '');
175 | var arr = str.split(re);
176 | if ('' === arr[0]) arr.shift();
177 | return arr;
178 | };
179 |
180 | /**
181 | * Check if class `name` is present.
182 | *
183 | * @param {String} name
184 | * @return {ClassList}
185 | * @api public
186 | */
187 |
188 | ClassList.prototype.has = ClassList.prototype.contains = function(name) {
189 | return this.list ? this.list.contains(name) : !!~index(this.array(), name);
190 | };
191 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Event from './Event';
2 | import classes from './classes';
3 |
4 | const isCssAnimationSupported = Event.endEvents.length !== 0;
5 | const capitalPrefixes = [
6 | 'Webkit',
7 | 'Moz',
8 | 'O',
9 | // ms is special .... !
10 | 'ms',
11 | ];
12 | const prefixes = [ '-webkit-', '-moz-', '-o-', 'ms-', '' ];
13 |
14 | function getStyleProperty(node, name) {
15 | // old ff need null, https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
16 | const style = window.getComputedStyle(node, null);
17 | let ret = '';
18 | for (let i = 0; i < prefixes.length; i++) {
19 | ret = style.getPropertyValue(prefixes[i] + name);
20 | if (ret) {
21 | break;
22 | }
23 | }
24 | return ret;
25 | }
26 |
27 | function fixBrowserByTimeout(node) {
28 | if (isCssAnimationSupported) {
29 | const transitionDelay =
30 | parseFloat(getStyleProperty(node, 'transition-delay')) || 0;
31 | const transitionDuration =
32 | parseFloat(getStyleProperty(node, 'transition-duration')) || 0;
33 | const animationDelay =
34 | parseFloat(getStyleProperty(node, 'animation-delay')) || 0;
35 | const animationDuration =
36 | parseFloat(getStyleProperty(node, 'animation-duration')) || 0;
37 | const time = Math.max(
38 | transitionDuration + transitionDelay,
39 | animationDuration + animationDelay,
40 | );
41 | // sometimes, browser bug
42 | node.rcEndAnimTimeout = setTimeout(() => {
43 | node.rcEndAnimTimeout = null;
44 | if (node.rcEndListener) {
45 | node.rcEndListener();
46 | }
47 | }, time * 1000 + 200);
48 | }
49 | }
50 |
51 | function clearBrowserBugTimeout(node) {
52 | if (node.rcEndAnimTimeout) {
53 | clearTimeout(node.rcEndAnimTimeout);
54 | node.rcEndAnimTimeout = null;
55 | }
56 | }
57 |
58 | const cssAnimation = (node, transitionName, endCallback) => {
59 | const nameIsObj = typeof transitionName === 'object';
60 | const className = nameIsObj ? transitionName.name : transitionName;
61 | const activeClassName = nameIsObj
62 | ? transitionName.active
63 | : `${transitionName}-active`;
64 | let end = endCallback;
65 | let start;
66 | let active;
67 | const nodeClasses = classes(node);
68 |
69 | if (
70 | endCallback &&
71 | Object.prototype.toString.call(endCallback) === '[object Object]'
72 | ) {
73 | end = endCallback.end;
74 | start = endCallback.start;
75 | active = endCallback.active;
76 | }
77 |
78 | if (node.rcEndListener) {
79 | node.rcEndListener();
80 | }
81 |
82 | node.rcEndListener = e => {
83 | if (e && e.target !== node) {
84 | return;
85 | }
86 |
87 | if (node.rcAnimTimeout) {
88 | clearTimeout(node.rcAnimTimeout);
89 | node.rcAnimTimeout = null;
90 | }
91 |
92 | clearBrowserBugTimeout(node);
93 |
94 | nodeClasses.remove(className);
95 | nodeClasses.remove(activeClassName);
96 |
97 | Event.removeEndEventListener(node, node.rcEndListener);
98 | node.rcEndListener = null;
99 |
100 | // Usually this optional end is used for informing an owner of
101 | // a leave animation and telling it to remove the child.
102 | if (end) {
103 | end();
104 | }
105 | };
106 |
107 | Event.addEndEventListener(node, node.rcEndListener);
108 |
109 | if (start) {
110 | start();
111 | }
112 | nodeClasses.add(className);
113 |
114 | node.rcAnimTimeout = setTimeout(() => {
115 | node.rcAnimTimeout = null;
116 | nodeClasses.add(activeClassName);
117 | if (active) {
118 | setTimeout(active, 0);
119 | }
120 | fixBrowserByTimeout(node);
121 | // 30ms for firefox
122 | }, 30);
123 |
124 | return {
125 | stop() {
126 | if (node.rcEndListener) {
127 | node.rcEndListener();
128 | }
129 | },
130 | };
131 | };
132 |
133 | cssAnimation.style = (node, style, callback) => {
134 | if (node.rcEndListener) {
135 | node.rcEndListener();
136 | }
137 |
138 | node.rcEndListener = e => {
139 | if (e && e.target !== node) {
140 | return;
141 | }
142 |
143 | if (node.rcAnimTimeout) {
144 | clearTimeout(node.rcAnimTimeout);
145 | node.rcAnimTimeout = null;
146 | }
147 |
148 | clearBrowserBugTimeout(node);
149 |
150 | Event.removeEndEventListener(node, node.rcEndListener);
151 | node.rcEndListener = null;
152 |
153 | // Usually this optional callback is used for informing an owner of
154 | // a leave animation and telling it to remove the child.
155 | if (callback) {
156 | callback();
157 | }
158 | };
159 |
160 | Event.addEndEventListener(node, node.rcEndListener);
161 |
162 | node.rcAnimTimeout = setTimeout(() => {
163 | for (const s in style) {
164 | if (style.hasOwnProperty(s)) {
165 | node.style[s] = style[s];
166 | }
167 | }
168 | node.rcAnimTimeout = null;
169 | fixBrowserByTimeout(node);
170 | }, 0);
171 | };
172 |
173 | cssAnimation.setTransition = (node, p, value) => {
174 | let property = p;
175 | let v = value;
176 | if (value === undefined) {
177 | v = property;
178 | property = '';
179 | }
180 | property = property || '';
181 | capitalPrefixes.forEach(prefix => {
182 | node.style[`${prefix}Transition${property}`] = v;
183 | });
184 | };
185 |
186 | cssAnimation.isCssAnimationSupported = isCssAnimationSupported;
187 |
188 | export { isCssAnimationSupported, Event };
189 |
190 | export default cssAnimation;
191 |
--------------------------------------------------------------------------------
/stories/collapse.js:
--------------------------------------------------------------------------------
1 | import anim from '../src';
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import { storiesOf } from '@storybook/react';
5 | const style = `
6 |
7 | .box {
8 | background:red;
9 | width:100px;
10 | height:100px;
11 | }
12 | .collapse-active {
13 | transition: height .3s ease-out;
14 | }
15 |
16 | `;
17 |
18 | let show = true;
19 |
20 | function toggle() {
21 | const t = document.getElementById('t');
22 | const b = document.getElementById('b');
23 | b.disabled = true;
24 | t.style.display = '';
25 | let height;
26 | anim(t, `collapse`, {
27 | start() {
28 | if (show) {
29 | t.style.height = `${t.offsetHeight}px`;
30 | } else {
31 | height = t.offsetHeight;
32 | t.style.height = 0;
33 | }
34 | },
35 | active() {
36 | t.style.height = `${show ? height : 0}px`;
37 | },
38 | end() {
39 | t.style.display = show ? '' : 'none';
40 | b.disabled = false;
41 | t.style.height = '';
42 | },
43 | });
44 | show = !show;
45 | }
46 |
47 | const Demo = () => (
48 |
49 |
50 |
51 |
52 | toggle
53 |
54 |
55 | );
56 |
57 | Demo.story = 'collapse';
58 |
59 | storiesOf(Demo.story, module).add('demo', () => );
60 |
61 | export default Demo;
62 |
--------------------------------------------------------------------------------
/stories/events.js:
--------------------------------------------------------------------------------
1 | import Events from '../src/Event';
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import { storiesOf } from '@storybook/react';
5 | const style = `
6 | .box {
7 | background:red;
8 | width:100px;
9 | height:100px;
10 | animation-duration: 0.3s;
11 | animation-fill-mode: both;
12 | animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
13 | animation-play-state: paused;
14 |
15 | animation-name: fadeIn;
16 | animation-play-state: running;
17 | }
18 |
19 | .active {
20 | animation-name: fadeOut;
21 | animation-play-state: running;
22 | }
23 |
24 | @keyframes fadeIn {
25 | 0% {
26 | opacity: 0;
27 | }
28 | 100% {
29 | opacity: 1;
30 | }
31 | }
32 |
33 | @keyframes fadeOut {
34 | 0% {
35 | opacity: 1;
36 | }
37 | 100% {
38 | opacity: 0;
39 | }
40 | }
41 | `;
42 |
43 | setTimeout(() => {
44 | const t = document.getElementById('t');
45 | Events.addStartEventListener(t, () => {
46 | console.log('transition start...');
47 | });
48 | Events.addEndEventListener(t, () => {
49 | console.log('transition end...');
50 | });
51 | }, 100);
52 |
53 | let changed = false;
54 |
55 | function toggle() {
56 | const t = document.getElementById('t');
57 | changed = !changed;
58 |
59 | if (changed) {
60 | t.className = 'box active';
61 | } else {
62 | t.className = 'box';
63 | }
64 | }
65 |
66 | const Demo = () => (
67 |
68 |
69 |
70 |
toggle
71 |
72 | );
73 |
74 | Demo.story = 'events';
75 |
76 | storiesOf(Demo.story, module).add('demo', () => );
77 |
78 | export default Demo;
79 |
--------------------------------------------------------------------------------
/stories/simple.js:
--------------------------------------------------------------------------------
1 | import anim from '../src';
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import { storiesOf } from '@storybook/react';
5 | const style = `
6 |
7 | .box {
8 | background:red;
9 | width:100px;
10 | height:100px;
11 | }
12 | .fade-enter {
13 | opacity: 0;
14 | animation-duration: 0.3s;
15 | animation-fill-mode: both;
16 | animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
17 | animation-play-state: paused;
18 | }
19 |
20 | .fade-leave {
21 | animation-duration: 0.3s;
22 | animation-fill-mode: both;
23 | animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
24 | animation-play-state: paused;
25 | }
26 |
27 | .fade-enter.fade-enter-active {
28 | animation-name: rcDialogFadeIn;
29 | animation-play-state: running;
30 | }
31 |
32 | .fade-leave.fade-leave-active {
33 | animation-name: rcDialogFadeOut;
34 | animation-play-state: running;
35 | }
36 |
37 | @keyframes rcDialogFadeIn {
38 | 0% {
39 | opacity: 0;
40 | }
41 | 100% {
42 | opacity: 1;
43 | }
44 | }
45 |
46 | @keyframes rcDialogFadeOut {
47 | 0% {
48 | opacity: 1;
49 | }
50 | 100% {
51 | opacity: 0;
52 | }
53 | }
54 | `;
55 |
56 | let show = true;
57 |
58 | function toggle() {
59 | const t = document.getElementById('t');
60 | const b = document.getElementById('b');
61 | b.disabled = true;
62 | t.style.visibility = '';
63 | anim(t, `fade-${show ? 'leave' : 'enter'}`, () => {
64 | t.style.visibility = show ? '' : 'hidden';
65 | b.disabled = false;
66 | });
67 | show = !show;
68 | }
69 |
70 | const Demo = () => (
71 |
72 |
73 |
74 |
75 | toggle
76 |
77 |
78 | );
79 |
80 | Demo.story = 'simple';
81 |
82 | storiesOf(Demo.story, module).add('demo', () => );
83 |
84 | export default Demo;
85 |
--------------------------------------------------------------------------------
/stories/style.js:
--------------------------------------------------------------------------------
1 | import anim from '../src';
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import { storiesOf } from '@storybook/react';
5 |
6 | const style = `
7 | .box {
8 | background:red;
9 | width:100px;
10 | height:100px;
11 | }
12 | `;
13 |
14 | let show = true;
15 |
16 | function toggle() {
17 | const t = document.getElementById('t');
18 | const b = document.getElementById('b');
19 | b.disabled = true;
20 | t.style.visibility = '';
21 | t.style.opacity = show ? 1 : 0;
22 | anim.setTransition(t, 'opacity 2s ease-in');
23 | anim.style(
24 | t,
25 | show
26 | ? {
27 | opacity: 0,
28 | }
29 | : {
30 | opacity: 1,
31 | },
32 | () => {
33 | t.style.visibility = show ? '' : 'hidden';
34 | b.disabled = false;
35 | anim.setTransition(t, '');
36 | },
37 | );
38 | show = !show;
39 | }
40 |
41 | const Demo = () => (
42 |
43 |
44 |
45 |
46 | toggle
47 |
48 |
49 | );
50 |
51 | Demo.story = 'style';
52 |
53 | storiesOf(Demo.story, module).add('demo', () => );
54 |
55 | export default Demo;
56 |
--------------------------------------------------------------------------------