react-transition-state 2.3.0 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,12 @@
1
+
1
2
  'use strict';
3
+ 'use client';
2
4
 
3
5
  Object.defineProperty(exports, '__esModule', { value: true });
6
+ const require_useTransitionState = require('./useTransitionState.cjs');
7
+ const require_useTransitionMap = require('./useTransitionMap.cjs');
4
8
 
5
- var useTransitionState = require('./hooks/useTransitionState.cjs');
6
- var useTransitionMap = require('./hooks/useTransitionMap.cjs');
7
-
8
-
9
-
10
- exports.default = useTransitionState.useTransitionState;
11
- exports.useTransition = useTransitionState.useTransitionState;
12
- exports.useTransitionState = useTransitionState.useTransitionState;
13
- exports.useTransitionMap = useTransitionMap.useTransitionMap;
9
+ exports.default = require_useTransitionState.useTransitionState;
10
+ exports.useTransition = require_useTransitionState.useTransitionState;
11
+ exports.useTransitionMap = require_useTransitionMap.useTransitionMap;
12
+ exports.useTransitionState = require_useTransitionState.useTransitionState;
@@ -0,0 +1,105 @@
1
+
2
+ 'use strict';
3
+ const require_utils = require('./utils.cjs');
4
+ let react = require("react");
5
+
6
+ //#region src/useTransitionMap.ts
7
+ const updateState = (key, status, setStateMap, latestStateMap, timeoutId, onChange) => {
8
+ clearTimeout(timeoutId);
9
+ const state = require_utils.getState(status);
10
+ const stateMap = new Map(latestStateMap.current);
11
+ stateMap.set(key, state);
12
+ setStateMap(stateMap);
13
+ latestStateMap.current = stateMap;
14
+ onChange && onChange({
15
+ key,
16
+ current: state
17
+ });
18
+ };
19
+ const useTransitionMap = ({ allowMultiple, enter = true, exit = true, preEnter, preExit, timeout, initialEntered, mountOnEnter, unmountOnExit, onStateChange: onChange } = {}) => {
20
+ const [stateMap, setStateMap] = (0, react.useState)(/* @__PURE__ */ new Map());
21
+ const latestStateMap = (0, react.useRef)(stateMap);
22
+ const configMap = (0, react.useRef)(/* @__PURE__ */ new Map());
23
+ const [enterTimeout, exitTimeout] = require_utils.getTimeout(timeout);
24
+ const setItem = (0, react.useCallback)((key, options) => {
25
+ const { initialEntered: _initialEntered = initialEntered } = options || {};
26
+ updateState(key, _initialEntered ? require_utils.ENTERED : require_utils.startOrEnd(mountOnEnter), setStateMap, latestStateMap);
27
+ configMap.current.set(key, {});
28
+ }, [initialEntered, mountOnEnter]);
29
+ const deleteItem = (0, react.useCallback)((key) => {
30
+ const newStateMap = new Map(latestStateMap.current);
31
+ if (newStateMap.delete(key)) {
32
+ setStateMap(newStateMap);
33
+ latestStateMap.current = newStateMap;
34
+ configMap.current.delete(key);
35
+ return true;
36
+ }
37
+ return false;
38
+ }, []);
39
+ const endTransition = (0, react.useCallback)((key) => {
40
+ const stateObj = latestStateMap.current.get(key);
41
+ if (!stateObj) {
42
+ if (process.env.NODE_ENV !== "production") console.error(`[React-Transition-State] cannot call endTransition: invalid key — ${key}`);
43
+ return;
44
+ }
45
+ const { timeoutId } = configMap.current.get(key);
46
+ const status = require_utils.getEndStatus(stateObj._s, unmountOnExit);
47
+ status && updateState(key, status, setStateMap, latestStateMap, timeoutId, onChange);
48
+ }, [onChange, unmountOnExit]);
49
+ const toggle = (0, react.useCallback)((key, toEnter) => {
50
+ const stateObj = latestStateMap.current.get(key);
51
+ if (!stateObj) {
52
+ if (process.env.NODE_ENV !== "production") console.error(`[React-Transition-State] cannot call toggle: invalid key — ${key}`);
53
+ return;
54
+ }
55
+ const config = configMap.current.get(key);
56
+ const transitState = (status) => {
57
+ updateState(key, status, setStateMap, latestStateMap, config.timeoutId, onChange);
58
+ switch (status) {
59
+ case require_utils.ENTERING:
60
+ if (enterTimeout >= 0) config.timeoutId = require_utils._setTimeout(() => endTransition(key), enterTimeout);
61
+ break;
62
+ case require_utils.EXITING:
63
+ if (exitTimeout >= 0) config.timeoutId = require_utils._setTimeout(() => endTransition(key), exitTimeout);
64
+ break;
65
+ case require_utils.PRE_ENTER:
66
+ case require_utils.PRE_EXIT:
67
+ config.timeoutId = require_utils.nextTick(transitState, status);
68
+ break;
69
+ }
70
+ };
71
+ const enterStage = stateObj.isEnter;
72
+ if (typeof toEnter !== "boolean") toEnter = !enterStage;
73
+ if (toEnter) {
74
+ if (!enterStage) {
75
+ transitState(enter ? preEnter ? require_utils.PRE_ENTER : require_utils.ENTERING : require_utils.ENTERED);
76
+ !allowMultiple && latestStateMap.current.forEach((_, _key) => _key !== key && toggle(_key, false));
77
+ }
78
+ } else if (enterStage) transitState(exit ? preExit ? require_utils.PRE_EXIT : require_utils.EXITING : require_utils.startOrEnd(unmountOnExit));
79
+ }, [
80
+ onChange,
81
+ endTransition,
82
+ allowMultiple,
83
+ enter,
84
+ exit,
85
+ preEnter,
86
+ preExit,
87
+ enterTimeout,
88
+ exitTimeout,
89
+ unmountOnExit
90
+ ]);
91
+ return {
92
+ stateMap,
93
+ toggle,
94
+ toggleAll: (0, react.useCallback)((toEnter) => {
95
+ if (!allowMultiple && toEnter !== false) return;
96
+ for (const key of latestStateMap.current.keys()) toggle(key, toEnter);
97
+ }, [allowMultiple, toggle]),
98
+ endTransition,
99
+ setItem,
100
+ deleteItem
101
+ };
102
+ };
103
+
104
+ //#endregion
105
+ exports.useTransitionMap = useTransitionMap;
@@ -0,0 +1,61 @@
1
+
2
+ 'use strict';
3
+ const require_utils = require('./utils.cjs');
4
+ let react = require("react");
5
+
6
+ //#region src/useTransitionState.ts
7
+ const updateState = (status, setState, latestState, timeoutId, onChange) => {
8
+ clearTimeout(timeoutId.current);
9
+ const state = require_utils.getState(status);
10
+ setState(state);
11
+ latestState.current = state;
12
+ onChange && onChange({ current: state });
13
+ };
14
+ const useTransitionState = ({ enter = true, exit = true, preEnter, preExit, timeout, initialEntered, mountOnEnter, unmountOnExit, onStateChange: onChange } = {}) => {
15
+ const [state, setState] = (0, react.useState)(() => require_utils.getState(initialEntered ? require_utils.ENTERED : require_utils.startOrEnd(mountOnEnter)));
16
+ const latestState = (0, react.useRef)(state);
17
+ const timeoutId = (0, react.useRef)(0);
18
+ const [enterTimeout, exitTimeout] = require_utils.getTimeout(timeout);
19
+ const endTransition = (0, react.useCallback)(() => {
20
+ const status = require_utils.getEndStatus(latestState.current._s, unmountOnExit);
21
+ status && updateState(status, setState, latestState, timeoutId, onChange);
22
+ }, [onChange, unmountOnExit]);
23
+ return [
24
+ state,
25
+ (0, react.useCallback)((toEnter) => {
26
+ const transitState = (status) => {
27
+ updateState(status, setState, latestState, timeoutId, onChange);
28
+ switch (status) {
29
+ case require_utils.ENTERING:
30
+ if (enterTimeout >= 0) timeoutId.current = require_utils._setTimeout(endTransition, enterTimeout);
31
+ break;
32
+ case require_utils.EXITING:
33
+ if (exitTimeout >= 0) timeoutId.current = require_utils._setTimeout(endTransition, exitTimeout);
34
+ break;
35
+ case require_utils.PRE_ENTER:
36
+ case require_utils.PRE_EXIT:
37
+ timeoutId.current = require_utils.nextTick(transitState, status);
38
+ break;
39
+ }
40
+ };
41
+ const enterStage = latestState.current.isEnter;
42
+ if (typeof toEnter !== "boolean") toEnter = !enterStage;
43
+ if (toEnter) !enterStage && transitState(enter ? preEnter ? require_utils.PRE_ENTER : require_utils.ENTERING : require_utils.ENTERED);
44
+ else enterStage && transitState(exit ? preExit ? require_utils.PRE_EXIT : require_utils.EXITING : require_utils.startOrEnd(unmountOnExit));
45
+ }, [
46
+ endTransition,
47
+ onChange,
48
+ enter,
49
+ exit,
50
+ preEnter,
51
+ preExit,
52
+ enterTimeout,
53
+ exitTimeout,
54
+ unmountOnExit
55
+ ]),
56
+ endTransition
57
+ ];
58
+ };
59
+
60
+ //#endregion
61
+ exports.useTransitionState = useTransitionState;
@@ -0,0 +1,54 @@
1
+
2
+ 'use strict';
3
+
4
+ //#region src/utils.ts
5
+ const PRE_ENTER = 0;
6
+ const ENTERING = 1;
7
+ const ENTERED = 2;
8
+ const PRE_EXIT = 3;
9
+ const EXITING = 4;
10
+ const EXITED = 5;
11
+ const UNMOUNTED = 6;
12
+ const STATUS = [
13
+ "preEnter",
14
+ "entering",
15
+ "entered",
16
+ "preExit",
17
+ "exiting",
18
+ "exited",
19
+ "unmounted"
20
+ ];
21
+ const getState = (status) => ({
22
+ _s: status,
23
+ status: STATUS[status],
24
+ isEnter: status < PRE_EXIT,
25
+ isMounted: status !== UNMOUNTED,
26
+ isResolved: status === ENTERED || status > EXITING
27
+ });
28
+ const startOrEnd = (unmounted) => unmounted ? UNMOUNTED : EXITED;
29
+ const getEndStatus = (status, unmountOnExit) => {
30
+ switch (status) {
31
+ case ENTERING:
32
+ case PRE_ENTER: return ENTERED;
33
+ case EXITING:
34
+ case PRE_EXIT: return startOrEnd(unmountOnExit);
35
+ }
36
+ };
37
+ const getTimeout = (timeout) => typeof timeout === "object" ? [timeout.enter, timeout.exit] : [timeout, timeout];
38
+ const _setTimeout = setTimeout;
39
+ const nextTick = (transitState, status) => _setTimeout(() => {
40
+ isNaN(document.body.offsetTop) || transitState(status + 1);
41
+ }, 0);
42
+
43
+ //#endregion
44
+ exports.ENTERED = ENTERED;
45
+ exports.ENTERING = ENTERING;
46
+ exports.EXITING = EXITING;
47
+ exports.PRE_ENTER = PRE_ENTER;
48
+ exports.PRE_EXIT = PRE_EXIT;
49
+ exports._setTimeout = _setTimeout;
50
+ exports.getEndStatus = getEndStatus;
51
+ exports.getState = getState;
52
+ exports.getTimeout = getTimeout;
53
+ exports.nextTick = nextTick;
54
+ exports.startOrEnd = startOrEnd;
@@ -1,2 +1,6 @@
1
- export { useTransitionState as default, useTransitionState as useTransition, useTransitionState } from './hooks/useTransitionState.mjs';
2
- export { useTransitionMap } from './hooks/useTransitionMap.mjs';
1
+ 'use client';
2
+
3
+ import { useTransitionState } from "./useTransitionState.mjs";
4
+ import { useTransitionMap } from "./useTransitionMap.mjs";
5
+
6
+ export { useTransitionState as default, useTransitionState as useTransition, useTransitionMap, useTransitionState };
@@ -0,0 +1,103 @@
1
+ import { ENTERED, ENTERING, EXITING, PRE_ENTER, PRE_EXIT, _setTimeout, getEndStatus, getState, getTimeout, nextTick, startOrEnd } from "./utils.mjs";
2
+ import { useCallback, useRef, useState } from "react";
3
+
4
+ //#region src/useTransitionMap.ts
5
+ const updateState = (key, status, setStateMap, latestStateMap, timeoutId, onChange) => {
6
+ clearTimeout(timeoutId);
7
+ const state = getState(status);
8
+ const stateMap = new Map(latestStateMap.current);
9
+ stateMap.set(key, state);
10
+ setStateMap(stateMap);
11
+ latestStateMap.current = stateMap;
12
+ onChange && onChange({
13
+ key,
14
+ current: state
15
+ });
16
+ };
17
+ const useTransitionMap = ({ allowMultiple, enter = true, exit = true, preEnter, preExit, timeout, initialEntered, mountOnEnter, unmountOnExit, onStateChange: onChange } = {}) => {
18
+ const [stateMap, setStateMap] = useState(/* @__PURE__ */ new Map());
19
+ const latestStateMap = useRef(stateMap);
20
+ const configMap = useRef(/* @__PURE__ */ new Map());
21
+ const [enterTimeout, exitTimeout] = getTimeout(timeout);
22
+ const setItem = useCallback((key, options) => {
23
+ const { initialEntered: _initialEntered = initialEntered } = options || {};
24
+ updateState(key, _initialEntered ? ENTERED : startOrEnd(mountOnEnter), setStateMap, latestStateMap);
25
+ configMap.current.set(key, {});
26
+ }, [initialEntered, mountOnEnter]);
27
+ const deleteItem = useCallback((key) => {
28
+ const newStateMap = new Map(latestStateMap.current);
29
+ if (newStateMap.delete(key)) {
30
+ setStateMap(newStateMap);
31
+ latestStateMap.current = newStateMap;
32
+ configMap.current.delete(key);
33
+ return true;
34
+ }
35
+ return false;
36
+ }, []);
37
+ const endTransition = useCallback((key) => {
38
+ const stateObj = latestStateMap.current.get(key);
39
+ if (!stateObj) {
40
+ if (process.env.NODE_ENV !== "production") console.error(`[React-Transition-State] cannot call endTransition: invalid key — ${key}`);
41
+ return;
42
+ }
43
+ const { timeoutId } = configMap.current.get(key);
44
+ const status = getEndStatus(stateObj._s, unmountOnExit);
45
+ status && updateState(key, status, setStateMap, latestStateMap, timeoutId, onChange);
46
+ }, [onChange, unmountOnExit]);
47
+ const toggle = useCallback((key, toEnter) => {
48
+ const stateObj = latestStateMap.current.get(key);
49
+ if (!stateObj) {
50
+ if (process.env.NODE_ENV !== "production") console.error(`[React-Transition-State] cannot call toggle: invalid key — ${key}`);
51
+ return;
52
+ }
53
+ const config = configMap.current.get(key);
54
+ const transitState = (status) => {
55
+ updateState(key, status, setStateMap, latestStateMap, config.timeoutId, onChange);
56
+ switch (status) {
57
+ case ENTERING:
58
+ if (enterTimeout >= 0) config.timeoutId = _setTimeout(() => endTransition(key), enterTimeout);
59
+ break;
60
+ case EXITING:
61
+ if (exitTimeout >= 0) config.timeoutId = _setTimeout(() => endTransition(key), exitTimeout);
62
+ break;
63
+ case PRE_ENTER:
64
+ case PRE_EXIT:
65
+ config.timeoutId = nextTick(transitState, status);
66
+ break;
67
+ }
68
+ };
69
+ const enterStage = stateObj.isEnter;
70
+ if (typeof toEnter !== "boolean") toEnter = !enterStage;
71
+ if (toEnter) {
72
+ if (!enterStage) {
73
+ transitState(enter ? preEnter ? PRE_ENTER : ENTERING : ENTERED);
74
+ !allowMultiple && latestStateMap.current.forEach((_, _key) => _key !== key && toggle(_key, false));
75
+ }
76
+ } else if (enterStage) transitState(exit ? preExit ? PRE_EXIT : EXITING : startOrEnd(unmountOnExit));
77
+ }, [
78
+ onChange,
79
+ endTransition,
80
+ allowMultiple,
81
+ enter,
82
+ exit,
83
+ preEnter,
84
+ preExit,
85
+ enterTimeout,
86
+ exitTimeout,
87
+ unmountOnExit
88
+ ]);
89
+ return {
90
+ stateMap,
91
+ toggle,
92
+ toggleAll: useCallback((toEnter) => {
93
+ if (!allowMultiple && toEnter !== false) return;
94
+ for (const key of latestStateMap.current.keys()) toggle(key, toEnter);
95
+ }, [allowMultiple, toggle]),
96
+ endTransition,
97
+ setItem,
98
+ deleteItem
99
+ };
100
+ };
101
+
102
+ //#endregion
103
+ export { useTransitionMap };
@@ -0,0 +1,59 @@
1
+ import { ENTERED, ENTERING, EXITING, PRE_ENTER, PRE_EXIT, _setTimeout, getEndStatus, getState, getTimeout, nextTick, startOrEnd } from "./utils.mjs";
2
+ import { useCallback, useRef, useState } from "react";
3
+
4
+ //#region src/useTransitionState.ts
5
+ const updateState = (status, setState, latestState, timeoutId, onChange) => {
6
+ clearTimeout(timeoutId.current);
7
+ const state = getState(status);
8
+ setState(state);
9
+ latestState.current = state;
10
+ onChange && onChange({ current: state });
11
+ };
12
+ const useTransitionState = ({ enter = true, exit = true, preEnter, preExit, timeout, initialEntered, mountOnEnter, unmountOnExit, onStateChange: onChange } = {}) => {
13
+ const [state, setState] = useState(() => getState(initialEntered ? ENTERED : startOrEnd(mountOnEnter)));
14
+ const latestState = useRef(state);
15
+ const timeoutId = useRef(0);
16
+ const [enterTimeout, exitTimeout] = getTimeout(timeout);
17
+ const endTransition = useCallback(() => {
18
+ const status = getEndStatus(latestState.current._s, unmountOnExit);
19
+ status && updateState(status, setState, latestState, timeoutId, onChange);
20
+ }, [onChange, unmountOnExit]);
21
+ return [
22
+ state,
23
+ useCallback((toEnter) => {
24
+ const transitState = (status) => {
25
+ updateState(status, setState, latestState, timeoutId, onChange);
26
+ switch (status) {
27
+ case ENTERING:
28
+ if (enterTimeout >= 0) timeoutId.current = _setTimeout(endTransition, enterTimeout);
29
+ break;
30
+ case EXITING:
31
+ if (exitTimeout >= 0) timeoutId.current = _setTimeout(endTransition, exitTimeout);
32
+ break;
33
+ case PRE_ENTER:
34
+ case PRE_EXIT:
35
+ timeoutId.current = nextTick(transitState, status);
36
+ break;
37
+ }
38
+ };
39
+ const enterStage = latestState.current.isEnter;
40
+ if (typeof toEnter !== "boolean") toEnter = !enterStage;
41
+ if (toEnter) !enterStage && transitState(enter ? preEnter ? PRE_ENTER : ENTERING : ENTERED);
42
+ else enterStage && transitState(exit ? preExit ? PRE_EXIT : EXITING : startOrEnd(unmountOnExit));
43
+ }, [
44
+ endTransition,
45
+ onChange,
46
+ enter,
47
+ exit,
48
+ preEnter,
49
+ preExit,
50
+ enterTimeout,
51
+ exitTimeout,
52
+ unmountOnExit
53
+ ]),
54
+ endTransition
55
+ ];
56
+ };
57
+
58
+ //#endregion
59
+ export { useTransitionState };
@@ -0,0 +1,41 @@
1
+ //#region src/utils.ts
2
+ const PRE_ENTER = 0;
3
+ const ENTERING = 1;
4
+ const ENTERED = 2;
5
+ const PRE_EXIT = 3;
6
+ const EXITING = 4;
7
+ const EXITED = 5;
8
+ const UNMOUNTED = 6;
9
+ const STATUS = [
10
+ "preEnter",
11
+ "entering",
12
+ "entered",
13
+ "preExit",
14
+ "exiting",
15
+ "exited",
16
+ "unmounted"
17
+ ];
18
+ const getState = (status) => ({
19
+ _s: status,
20
+ status: STATUS[status],
21
+ isEnter: status < PRE_EXIT,
22
+ isMounted: status !== UNMOUNTED,
23
+ isResolved: status === ENTERED || status > EXITING
24
+ });
25
+ const startOrEnd = (unmounted) => unmounted ? UNMOUNTED : EXITED;
26
+ const getEndStatus = (status, unmountOnExit) => {
27
+ switch (status) {
28
+ case ENTERING:
29
+ case PRE_ENTER: return ENTERED;
30
+ case EXITING:
31
+ case PRE_EXIT: return startOrEnd(unmountOnExit);
32
+ }
33
+ };
34
+ const getTimeout = (timeout) => typeof timeout === "object" ? [timeout.enter, timeout.exit] : [timeout, timeout];
35
+ const _setTimeout = setTimeout;
36
+ const nextTick = (transitState, status) => _setTimeout(() => {
37
+ isNaN(document.body.offsetTop) || transitState(status + 1);
38
+ }, 0);
39
+
40
+ //#endregion
41
+ export { ENTERED, ENTERING, EXITING, PRE_ENTER, PRE_EXIT, _setTimeout, getEndStatus, getState, getTimeout, nextTick, startOrEnd };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-transition-state",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "description": "Zero dependency React transition state machine.",
5
5
  "author": "Zheng Song",
6
6
  "license": "MIT",
@@ -15,7 +15,7 @@
15
15
  "sideEffects": false,
16
16
  "files": [
17
17
  "dist/",
18
- "types/*.d.ts"
18
+ "types/"
19
19
  ],
20
20
  "keywords": [
21
21
  "react",
@@ -26,17 +26,16 @@
26
26
  "state machine"
27
27
  ],
28
28
  "scripts": {
29
- "start": "rollup -c -w",
30
- "clean": "rm -Rf dist",
31
- "bundle": "rollup -c",
32
- "test": "jest",
33
- "eg": "npm start --prefix example",
34
- "types": "cd types && tsc",
29
+ "clean": "rm -Rf dist/ types/",
30
+ "start": "rolldown -w -c",
31
+ "bundle": "rolldown -c",
32
+ "test": "vitest run",
33
+ "tc": "tsc",
35
34
  "lint": "eslint .",
36
- "lint:fix": "eslint --fix .",
37
35
  "pret": "prettier -c .",
38
36
  "pret:fix": "prettier -w .",
39
- "build": "run-s pret clean lint types bundle"
37
+ "prepare": "rm -Rf types/__tests__",
38
+ "build": "run-s pret clean tc lint bundle"
40
39
  },
41
40
  "exports": {
42
41
  ".": {
@@ -51,31 +50,26 @@
51
50
  "react-dom": ">=16.8.0"
52
51
  },
53
52
  "devDependencies": {
54
- "@babel/core": "^7.26.7",
55
- "@babel/preset-env": "^7.26.7",
56
- "@rollup/plugin-babel": "^6.0.4",
57
- "@testing-library/react": "^16.2.0",
58
- "@types/jest": "^29.5.14",
59
- "babel-plugin-pure-annotations": "^0.1.2",
60
- "eslint": "^9.19.0",
61
- "eslint-config-prettier": "^10.0.1",
62
- "eslint-plugin-jest": "^28.11.0",
63
- "eslint-plugin-react": "^7.37.4",
64
- "eslint-plugin-react-hooks": "^5.1.0",
65
- "eslint-plugin-react-hooks-addons": "^0.4.1",
66
- "globals": "^15.14.0",
67
- "jest": "^29.7.0",
68
- "jest-environment-jsdom": "^29.7.0",
53
+ "@testing-library/react": "^16.3.1",
54
+ "@types/node": "^25.0.3",
55
+ "@types/react": "^19.2.7",
56
+ "@vitest/coverage-istanbul": "^4.0.16",
57
+ "@vitest/eslint-plugin": "^1.6.4",
58
+ "eslint": "^9.39.2",
59
+ "eslint-config-prettier": "^10.1.8",
60
+ "eslint-plugin-react": "^7.37.5",
61
+ "eslint-plugin-react-hooks": "^7.0.1",
62
+ "eslint-plugin-react-hooks-addons": "^0.5.0",
63
+ "globals": "^16.5.0",
64
+ "jsdom": "^27.4.0",
69
65
  "npm-run-all": "^4.1.5",
70
- "prettier": "^3.4.2",
71
- "react": "^19",
72
- "react-dom": "^19",
73
- "rollup": "^4.32.1",
74
- "typescript": "^5.7.3"
75
- },
76
- "overrides": {
77
- "whatwg-url@11.0.0": {
78
- "tr46": "^4"
79
- }
66
+ "prettier": "^3.7.4",
67
+ "react": "^19.2.3",
68
+ "react-dom": "^19.2.3",
69
+ "rolldown": "^1.0.0-beta.57",
70
+ "rollup-plugin-add-directive": "^1.0.0",
71
+ "typescript": "^5.9.3",
72
+ "typescript-eslint": "^8.51.0",
73
+ "vitest": "^4.0.16"
80
74
  }
81
75
  }
package/types/index.d.ts CHANGED
@@ -1,63 +1,11 @@
1
- export type TransitionStatus =
2
- | 'preEnter'
3
- | 'entering'
4
- | 'entered'
5
- | 'preExit'
6
- | 'exiting'
7
- | 'exited'
8
- | 'unmounted';
9
-
10
- export type TransitionState = Readonly<{
11
- status: TransitionStatus;
12
- isMounted: boolean;
13
- isEnter: boolean;
14
- isResolved: boolean;
15
- }>;
16
-
17
- export interface TransitionOptions {
18
- initialEntered?: boolean;
19
- mountOnEnter?: boolean;
20
- unmountOnExit?: boolean;
21
- preEnter?: boolean;
22
- preExit?: boolean;
23
- enter?: boolean;
24
- exit?: boolean;
25
- timeout?: number | { enter?: number; exit?: number };
26
- onStateChange?: (event: { current: TransitionState }) => void;
27
- }
28
-
29
- export interface TransitionItemOptions {
30
- initialEntered?: boolean;
31
- }
32
-
33
- export interface TransitionMapOptions<K> extends Omit<TransitionOptions, 'onStateChange'> {
34
- allowMultiple?: boolean;
35
- onStateChange?: (event: { key: K; current: TransitionState }) => void;
36
- }
37
-
38
- export type TransitionResult = [TransitionState, (toEnter?: boolean) => void, () => void];
39
-
40
- export interface TransitionMapResult<K> {
41
- stateMap: ReadonlyMap<K, TransitionState>;
42
- toggle: (key: K, toEnter?: boolean) => void;
43
- toggleAll: (toEnter?: boolean) => void;
44
- endTransition: (key: K) => void;
45
- setItem: (key: K, options?: TransitionItemOptions) => void;
46
- deleteItem: (key: K) => boolean;
47
- }
48
-
49
- export const useTransitionState: (options?: TransitionOptions) => TransitionResult;
50
-
51
- export const useTransitionMap: <K>(options?: TransitionMapOptions<K>) => TransitionMapResult<K>;
52
-
53
- export {
54
- /**
55
- * @deprecated The `useTransition` alias will be removed in v3.0.0. Use `useTransitionState` instead.
56
- */
57
- useTransitionState as useTransition
58
- };
59
-
1
+ export * from './types';
2
+ export { useTransitionState,
3
+ /**
4
+ * @deprecated The `useTransition` alias will be removed in v3.0.0. Use `useTransitionState` instead.
5
+ */
6
+ useTransitionState as useTransition,
60
7
  /**
61
8
  * @deprecated The default export will be removed in v3.0.0. Use the named export `useTransitionState` instead.
62
9
  */
63
- export default useTransitionState;
10
+ useTransitionState as default } from './useTransitionState';
11
+ export { useTransitionMap } from './useTransitionMap';
@@ -0,0 +1,42 @@
1
+ export type TransitionStatus = 'preEnter' | 'entering' | 'entered' | 'preExit' | 'exiting' | 'exited' | 'unmounted';
2
+ export type TransitionState = Readonly<{
3
+ status: TransitionStatus;
4
+ isMounted: boolean;
5
+ isEnter: boolean;
6
+ isResolved: boolean;
7
+ }>;
8
+ export interface TransitionOptions {
9
+ initialEntered?: boolean;
10
+ mountOnEnter?: boolean;
11
+ unmountOnExit?: boolean;
12
+ preEnter?: boolean;
13
+ preExit?: boolean;
14
+ enter?: boolean;
15
+ exit?: boolean;
16
+ timeout?: number | {
17
+ enter?: number;
18
+ exit?: number;
19
+ };
20
+ onStateChange?: (event: {
21
+ current: TransitionState;
22
+ }) => void;
23
+ }
24
+ export interface TransitionItemOptions {
25
+ initialEntered?: boolean;
26
+ }
27
+ export interface TransitionMapOptions<TKey> extends Omit<TransitionOptions, 'onStateChange'> {
28
+ allowMultiple?: boolean;
29
+ onStateChange?: (event: {
30
+ key: TKey;
31
+ current: TransitionState;
32
+ }) => void;
33
+ }
34
+ export type TransitionResult = [TransitionState, (toEnter?: boolean) => void, () => void];
35
+ export interface TransitionMapResult<TKey> {
36
+ stateMap: ReadonlyMap<TKey, TransitionState>;
37
+ toggle: (key: TKey, toEnter?: boolean) => void;
38
+ toggleAll: (toEnter?: boolean) => void;
39
+ endTransition: (key: TKey) => void;
40
+ setItem: (key: TKey, options?: TransitionItemOptions) => void;
41
+ deleteItem: (key: TKey) => boolean;
42
+ }
@@ -0,0 +1,3 @@
1
+ import type { TransitionMapOptions, TransitionMapResult } from './types';
2
+ declare const useTransitionMap: <TKey>({ allowMultiple, enter, exit, preEnter, preExit, timeout, initialEntered, mountOnEnter, unmountOnExit, onStateChange: onChange }?: TransitionMapOptions<TKey>) => TransitionMapResult<TKey>;
3
+ export { useTransitionMap };
@@ -0,0 +1,2 @@
1
+ import type { TransitionOptions, TransitionResult } from './types';
2
+ export declare const useTransitionState: ({ enter, exit, preEnter, preExit, timeout, initialEntered, mountOnEnter, unmountOnExit, onStateChange: onChange }?: TransitionOptions) => TransitionResult;
@@ -0,0 +1,22 @@
1
+ import type { TransitionOptions, TransitionState } from './types';
2
+ export declare const PRE_ENTER = 0;
3
+ export declare const ENTERING = 1;
4
+ export declare const ENTERED = 2;
5
+ export declare const PRE_EXIT = 3;
6
+ export declare const EXITING = 4;
7
+ export declare const EXITED = 5;
8
+ export declare const UNMOUNTED = 6;
9
+ /** @internal [INTERNAL ONLY – DO NOT USE] */
10
+ export type Status = typeof PRE_ENTER | typeof ENTERING | typeof ENTERED | typeof PRE_EXIT | typeof EXITING | typeof EXITED | typeof UNMOUNTED;
11
+ /** @internal [INTERNAL ONLY – DO NOT USE] */
12
+ export type State = {
13
+ _s: Status;
14
+ } & TransitionState;
15
+ export declare const STATUS: readonly ["preEnter", "entering", "entered", "preExit", "exiting", "exited", "unmounted"];
16
+ export declare const getState: (status: Status) => State;
17
+ export declare const startOrEnd: (unmounted: boolean | undefined) => 5 | 6;
18
+ export declare const getEndStatus: (status: Status, unmountOnExit: boolean | undefined) => 2 | 5 | 6 | undefined;
19
+ export declare const getTimeout: (timeout: TransitionOptions["timeout"]) => (number | undefined)[];
20
+ declare const _setTimeout: typeof window.setTimeout;
21
+ export { _setTimeout as setTimeout };
22
+ export declare const nextTick: (transitState: (status: Status) => void, status: Status) => number;
@@ -1,113 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('react');
4
- var utils = require('./utils.cjs');
5
-
6
- const updateState = (key, status, setStateMap, latestStateMap, timeoutId, onChange) => {
7
- clearTimeout(timeoutId);
8
- const state = utils.getState(status);
9
- const stateMap = new Map(latestStateMap.current);
10
- stateMap.set(key, state);
11
- setStateMap(stateMap);
12
- latestStateMap.current = stateMap;
13
- onChange && onChange({
14
- key,
15
- current: state
16
- });
17
- };
18
- const useTransitionMap = ({
19
- allowMultiple,
20
- enter = true,
21
- exit = true,
22
- preEnter,
23
- preExit,
24
- timeout,
25
- initialEntered,
26
- mountOnEnter,
27
- unmountOnExit,
28
- onStateChange: onChange
29
- } = {}) => {
30
- const [stateMap, setStateMap] = react.useState(new Map());
31
- const latestStateMap = react.useRef(stateMap);
32
- const configMap = react.useRef(new Map());
33
- const [enterTimeout, exitTimeout] = utils.getTimeout(timeout);
34
- const setItem = react.useCallback((key, config) => {
35
- const {
36
- initialEntered: _initialEntered = initialEntered
37
- } = config || {};
38
- const status = _initialEntered ? utils.ENTERED : utils.startOrEnd(mountOnEnter);
39
- updateState(key, status, setStateMap, latestStateMap);
40
- configMap.current.set(key, {});
41
- }, [initialEntered, mountOnEnter]);
42
- const deleteItem = react.useCallback(key => {
43
- const newStateMap = new Map(latestStateMap.current);
44
- if (newStateMap.delete(key)) {
45
- setStateMap(newStateMap);
46
- latestStateMap.current = newStateMap;
47
- configMap.current.delete(key);
48
- return true;
49
- }
50
- return false;
51
- }, []);
52
- const endTransition = react.useCallback(key => {
53
- const stateObj = latestStateMap.current.get(key);
54
- if (!stateObj) {
55
- process.env.NODE_ENV !== 'production' && console.error(`[React-Transition-State] invalid key: ${key}`);
56
- return;
57
- }
58
- const {
59
- timeoutId
60
- } = configMap.current.get(key);
61
- const status = utils.getEndStatus(stateObj._s, unmountOnExit);
62
- status && updateState(key, status, setStateMap, latestStateMap, timeoutId, onChange);
63
- }, [onChange, unmountOnExit]);
64
- const toggle = react.useCallback((key, toEnter) => {
65
- const stateObj = latestStateMap.current.get(key);
66
- if (!stateObj) {
67
- process.env.NODE_ENV !== 'production' && console.error(`[React-Transition-State] invalid key: ${key}`);
68
- return;
69
- }
70
- const config = configMap.current.get(key);
71
- const transitState = status => {
72
- updateState(key, status, setStateMap, latestStateMap, config.timeoutId, onChange);
73
- switch (status) {
74
- case utils.ENTERING:
75
- if (enterTimeout >= 0) config.timeoutId = setTimeout(() => endTransition(key), enterTimeout);
76
- break;
77
- case utils.EXITING:
78
- if (exitTimeout >= 0) config.timeoutId = setTimeout(() => endTransition(key), exitTimeout);
79
- break;
80
- case utils.PRE_ENTER:
81
- case utils.PRE_EXIT:
82
- config.timeoutId = utils.nextTick(transitState, status);
83
- break;
84
- }
85
- };
86
- const enterStage = stateObj.isEnter;
87
- if (typeof toEnter !== 'boolean') toEnter = !enterStage;
88
- if (toEnter) {
89
- if (!enterStage) {
90
- transitState(enter ? preEnter ? utils.PRE_ENTER : utils.ENTERING : utils.ENTERED);
91
- !allowMultiple && latestStateMap.current.forEach((_, _key) => _key !== key && toggle(_key, false));
92
- }
93
- } else {
94
- if (enterStage) {
95
- transitState(exit ? preExit ? utils.PRE_EXIT : utils.EXITING : utils.startOrEnd(unmountOnExit));
96
- }
97
- }
98
- }, [onChange, endTransition, allowMultiple, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
99
- const toggleAll = react.useCallback(toEnter => {
100
- if (!allowMultiple && toEnter !== false) return;
101
- for (const key of latestStateMap.current.keys()) toggle(key, toEnter);
102
- }, [allowMultiple, toggle]);
103
- return {
104
- stateMap,
105
- toggle,
106
- toggleAll,
107
- endTransition,
108
- setItem,
109
- deleteItem
110
- };
111
- };
112
-
113
- exports.useTransitionMap = useTransitionMap;
@@ -1,62 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('react');
4
- var utils = require('./utils.cjs');
5
-
6
- const updateState = (status, setState, latestState, timeoutId, onChange) => {
7
- clearTimeout(timeoutId.current);
8
- const state = utils.getState(status);
9
- setState(state);
10
- latestState.current = state;
11
- onChange && onChange({
12
- current: state
13
- });
14
- };
15
- const useTransitionState = ({
16
- enter = true,
17
- exit = true,
18
- preEnter,
19
- preExit,
20
- timeout,
21
- initialEntered,
22
- mountOnEnter,
23
- unmountOnExit,
24
- onStateChange: onChange
25
- } = {}) => {
26
- const [state, setState] = react.useState(() => utils.getState(initialEntered ? utils.ENTERED : utils.startOrEnd(mountOnEnter)));
27
- const latestState = react.useRef(state);
28
- const timeoutId = react.useRef();
29
- const [enterTimeout, exitTimeout] = utils.getTimeout(timeout);
30
- const endTransition = react.useCallback(() => {
31
- const status = utils.getEndStatus(latestState.current._s, unmountOnExit);
32
- status && updateState(status, setState, latestState, timeoutId, onChange);
33
- }, [onChange, unmountOnExit]);
34
- const toggle = react.useCallback(toEnter => {
35
- const transitState = status => {
36
- updateState(status, setState, latestState, timeoutId, onChange);
37
- switch (status) {
38
- case utils.ENTERING:
39
- if (enterTimeout >= 0) timeoutId.current = setTimeout(endTransition, enterTimeout);
40
- break;
41
- case utils.EXITING:
42
- if (exitTimeout >= 0) timeoutId.current = setTimeout(endTransition, exitTimeout);
43
- break;
44
- case utils.PRE_ENTER:
45
- case utils.PRE_EXIT:
46
- timeoutId.current = utils.nextTick(transitState, status);
47
- break;
48
- }
49
- };
50
- const enterStage = latestState.current.isEnter;
51
- if (typeof toEnter !== 'boolean') toEnter = !enterStage;
52
- if (toEnter) {
53
- !enterStage && transitState(enter ? preEnter ? utils.PRE_ENTER : utils.ENTERING : utils.ENTERED);
54
- } else {
55
- enterStage && transitState(exit ? preExit ? utils.PRE_EXIT : utils.EXITING : utils.startOrEnd(unmountOnExit));
56
- }
57
- }, [endTransition, onChange, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
58
- react.useEffect(() => () => clearTimeout(timeoutId.current), []);
59
- return [state, toggle, endTransition];
60
- };
61
-
62
- exports.useTransitionState = useTransitionState;
@@ -1,47 +0,0 @@
1
- 'use strict';
2
-
3
- const PRE_ENTER = 0;
4
- const ENTERING = 1;
5
- const ENTERED = 2;
6
- const PRE_EXIT = 3;
7
- const EXITING = 4;
8
- const EXITED = 5;
9
- const UNMOUNTED = 6;
10
- const STATUS = ['preEnter', 'entering', 'entered', 'preExit', 'exiting', 'exited', 'unmounted'];
11
- const getState = status => ({
12
- _s: status,
13
- status: STATUS[status],
14
- isEnter: status < PRE_EXIT,
15
- isMounted: status !== UNMOUNTED,
16
- isResolved: status === ENTERED || status > EXITING
17
- });
18
- const startOrEnd = unmounted => unmounted ? UNMOUNTED : EXITED;
19
- const getEndStatus = (status, unmountOnExit) => {
20
- switch (status) {
21
- case ENTERING:
22
- case PRE_ENTER:
23
- return ENTERED;
24
- case EXITING:
25
- case PRE_EXIT:
26
- return startOrEnd(unmountOnExit);
27
- }
28
- };
29
- const getTimeout = timeout => typeof timeout === 'object' ? [timeout.enter, timeout.exit] : [timeout, timeout];
30
- const nextTick = (transitState, status) => setTimeout(() => {
31
- // Reading document.body.offsetTop can force browser to repaint before transition to the next state
32
- isNaN(document.body.offsetTop) || transitState(status + 1);
33
- }, 0);
34
-
35
- exports.ENTERED = ENTERED;
36
- exports.ENTERING = ENTERING;
37
- exports.EXITED = EXITED;
38
- exports.EXITING = EXITING;
39
- exports.PRE_ENTER = PRE_ENTER;
40
- exports.PRE_EXIT = PRE_EXIT;
41
- exports.STATUS = STATUS;
42
- exports.UNMOUNTED = UNMOUNTED;
43
- exports.getEndStatus = getEndStatus;
44
- exports.getState = getState;
45
- exports.getTimeout = getTimeout;
46
- exports.nextTick = nextTick;
47
- exports.startOrEnd = startOrEnd;
@@ -1,111 +0,0 @@
1
- import { useState, useRef, useCallback } from 'react';
2
- import { getTimeout, getEndStatus, PRE_EXIT, nextTick, PRE_ENTER, EXITING, ENTERING, ENTERED, startOrEnd, getState } from './utils.mjs';
3
-
4
- const updateState = (key, status, setStateMap, latestStateMap, timeoutId, onChange) => {
5
- clearTimeout(timeoutId);
6
- const state = getState(status);
7
- const stateMap = new Map(latestStateMap.current);
8
- stateMap.set(key, state);
9
- setStateMap(stateMap);
10
- latestStateMap.current = stateMap;
11
- onChange && onChange({
12
- key,
13
- current: state
14
- });
15
- };
16
- const useTransitionMap = ({
17
- allowMultiple,
18
- enter = true,
19
- exit = true,
20
- preEnter,
21
- preExit,
22
- timeout,
23
- initialEntered,
24
- mountOnEnter,
25
- unmountOnExit,
26
- onStateChange: onChange
27
- } = {}) => {
28
- const [stateMap, setStateMap] = useState(new Map());
29
- const latestStateMap = useRef(stateMap);
30
- const configMap = useRef(new Map());
31
- const [enterTimeout, exitTimeout] = getTimeout(timeout);
32
- const setItem = useCallback((key, config) => {
33
- const {
34
- initialEntered: _initialEntered = initialEntered
35
- } = config || {};
36
- const status = _initialEntered ? ENTERED : startOrEnd(mountOnEnter);
37
- updateState(key, status, setStateMap, latestStateMap);
38
- configMap.current.set(key, {});
39
- }, [initialEntered, mountOnEnter]);
40
- const deleteItem = useCallback(key => {
41
- const newStateMap = new Map(latestStateMap.current);
42
- if (newStateMap.delete(key)) {
43
- setStateMap(newStateMap);
44
- latestStateMap.current = newStateMap;
45
- configMap.current.delete(key);
46
- return true;
47
- }
48
- return false;
49
- }, []);
50
- const endTransition = useCallback(key => {
51
- const stateObj = latestStateMap.current.get(key);
52
- if (!stateObj) {
53
- process.env.NODE_ENV !== 'production' && console.error(`[React-Transition-State] invalid key: ${key}`);
54
- return;
55
- }
56
- const {
57
- timeoutId
58
- } = configMap.current.get(key);
59
- const status = getEndStatus(stateObj._s, unmountOnExit);
60
- status && updateState(key, status, setStateMap, latestStateMap, timeoutId, onChange);
61
- }, [onChange, unmountOnExit]);
62
- const toggle = useCallback((key, toEnter) => {
63
- const stateObj = latestStateMap.current.get(key);
64
- if (!stateObj) {
65
- process.env.NODE_ENV !== 'production' && console.error(`[React-Transition-State] invalid key: ${key}`);
66
- return;
67
- }
68
- const config = configMap.current.get(key);
69
- const transitState = status => {
70
- updateState(key, status, setStateMap, latestStateMap, config.timeoutId, onChange);
71
- switch (status) {
72
- case ENTERING:
73
- if (enterTimeout >= 0) config.timeoutId = setTimeout(() => endTransition(key), enterTimeout);
74
- break;
75
- case EXITING:
76
- if (exitTimeout >= 0) config.timeoutId = setTimeout(() => endTransition(key), exitTimeout);
77
- break;
78
- case PRE_ENTER:
79
- case PRE_EXIT:
80
- config.timeoutId = nextTick(transitState, status);
81
- break;
82
- }
83
- };
84
- const enterStage = stateObj.isEnter;
85
- if (typeof toEnter !== 'boolean') toEnter = !enterStage;
86
- if (toEnter) {
87
- if (!enterStage) {
88
- transitState(enter ? preEnter ? PRE_ENTER : ENTERING : ENTERED);
89
- !allowMultiple && latestStateMap.current.forEach((_, _key) => _key !== key && toggle(_key, false));
90
- }
91
- } else {
92
- if (enterStage) {
93
- transitState(exit ? preExit ? PRE_EXIT : EXITING : startOrEnd(unmountOnExit));
94
- }
95
- }
96
- }, [onChange, endTransition, allowMultiple, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
97
- const toggleAll = useCallback(toEnter => {
98
- if (!allowMultiple && toEnter !== false) return;
99
- for (const key of latestStateMap.current.keys()) toggle(key, toEnter);
100
- }, [allowMultiple, toggle]);
101
- return {
102
- stateMap,
103
- toggle,
104
- toggleAll,
105
- endTransition,
106
- setItem,
107
- deleteItem
108
- };
109
- };
110
-
111
- export { useTransitionMap };
@@ -1,60 +0,0 @@
1
- import { useState, useRef, useCallback, useEffect } from 'react';
2
- import { getState, ENTERED, startOrEnd, getTimeout, getEndStatus, PRE_EXIT, nextTick, PRE_ENTER, EXITING, ENTERING } from './utils.mjs';
3
-
4
- const updateState = (status, setState, latestState, timeoutId, onChange) => {
5
- clearTimeout(timeoutId.current);
6
- const state = getState(status);
7
- setState(state);
8
- latestState.current = state;
9
- onChange && onChange({
10
- current: state
11
- });
12
- };
13
- const useTransitionState = ({
14
- enter = true,
15
- exit = true,
16
- preEnter,
17
- preExit,
18
- timeout,
19
- initialEntered,
20
- mountOnEnter,
21
- unmountOnExit,
22
- onStateChange: onChange
23
- } = {}) => {
24
- const [state, setState] = useState(() => getState(initialEntered ? ENTERED : startOrEnd(mountOnEnter)));
25
- const latestState = useRef(state);
26
- const timeoutId = useRef();
27
- const [enterTimeout, exitTimeout] = getTimeout(timeout);
28
- const endTransition = useCallback(() => {
29
- const status = getEndStatus(latestState.current._s, unmountOnExit);
30
- status && updateState(status, setState, latestState, timeoutId, onChange);
31
- }, [onChange, unmountOnExit]);
32
- const toggle = useCallback(toEnter => {
33
- const transitState = status => {
34
- updateState(status, setState, latestState, timeoutId, onChange);
35
- switch (status) {
36
- case ENTERING:
37
- if (enterTimeout >= 0) timeoutId.current = setTimeout(endTransition, enterTimeout);
38
- break;
39
- case EXITING:
40
- if (exitTimeout >= 0) timeoutId.current = setTimeout(endTransition, exitTimeout);
41
- break;
42
- case PRE_ENTER:
43
- case PRE_EXIT:
44
- timeoutId.current = nextTick(transitState, status);
45
- break;
46
- }
47
- };
48
- const enterStage = latestState.current.isEnter;
49
- if (typeof toEnter !== 'boolean') toEnter = !enterStage;
50
- if (toEnter) {
51
- !enterStage && transitState(enter ? preEnter ? PRE_ENTER : ENTERING : ENTERED);
52
- } else {
53
- enterStage && transitState(exit ? preExit ? PRE_EXIT : EXITING : startOrEnd(unmountOnExit));
54
- }
55
- }, [endTransition, onChange, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
56
- useEffect(() => () => clearTimeout(timeoutId.current), []);
57
- return [state, toggle, endTransition];
58
- };
59
-
60
- export { useTransitionState };
@@ -1,33 +0,0 @@
1
- const PRE_ENTER = 0;
2
- const ENTERING = 1;
3
- const ENTERED = 2;
4
- const PRE_EXIT = 3;
5
- const EXITING = 4;
6
- const EXITED = 5;
7
- const UNMOUNTED = 6;
8
- const STATUS = ['preEnter', 'entering', 'entered', 'preExit', 'exiting', 'exited', 'unmounted'];
9
- const getState = status => ({
10
- _s: status,
11
- status: STATUS[status],
12
- isEnter: status < PRE_EXIT,
13
- isMounted: status !== UNMOUNTED,
14
- isResolved: status === ENTERED || status > EXITING
15
- });
16
- const startOrEnd = unmounted => unmounted ? UNMOUNTED : EXITED;
17
- const getEndStatus = (status, unmountOnExit) => {
18
- switch (status) {
19
- case ENTERING:
20
- case PRE_ENTER:
21
- return ENTERED;
22
- case EXITING:
23
- case PRE_EXIT:
24
- return startOrEnd(unmountOnExit);
25
- }
26
- };
27
- const getTimeout = timeout => typeof timeout === 'object' ? [timeout.enter, timeout.exit] : [timeout, timeout];
28
- const nextTick = (transitState, status) => setTimeout(() => {
29
- // Reading document.body.offsetTop can force browser to repaint before transition to the next state
30
- isNaN(document.body.offsetTop) || transitState(status + 1);
31
- }, 0);
32
-
33
- export { ENTERED, ENTERING, EXITED, EXITING, PRE_ENTER, PRE_EXIT, STATUS, UNMOUNTED, getEndStatus, getState, getTimeout, nextTick, startOrEnd };