react-transition-state 2.1.3 → 2.3.0
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.
- package/README.md +11 -12
- package/dist/cjs/hooks/useTransitionMap.cjs +113 -0
- package/dist/cjs/hooks/useTransitionState.cjs +62 -0
- package/dist/cjs/hooks/utils.cjs +47 -0
- package/dist/cjs/index.cjs +13 -0
- package/dist/{es/hooks/useTransitionMap.js → esm/hooks/useTransitionMap.mjs} +1 -1
- package/dist/{es/hooks/useTransition.js → esm/hooks/useTransitionState.mjs} +3 -3
- package/dist/esm/index.mjs +2 -0
- package/package.json +34 -24
- package/types/index.d.ts +12 -2
- package/dist/cjs/index.js +0 -204
- package/dist/es/index.js +0 -2
- /package/dist/{es/hooks/utils.js → esm/hooks/utils.mjs} +0 -0
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Inspired by the [React Transition Group](https://github.com/reactjs/react-transi
|
|
|
22
22
|
|
|
23
23
|
## State diagram
|
|
24
24
|
|
|
25
|
-
 The `initialEntered` and `mountOnEnter` props are omitted from the diagram to keep it less convoluted. [Please read more details at the API section](#
|
|
25
|
+
 The `initialEntered` and `mountOnEnter` props are omitted from the diagram to keep it less convoluted. [Please read more details at the API section](#usetransitionstate-hook).
|
|
26
26
|
|
|
27
27
|
<br/>
|
|
28
28
|
|
|
@@ -43,11 +43,10 @@ yarn add react-transition-state
|
|
|
43
43
|
### CSS example
|
|
44
44
|
|
|
45
45
|
```jsx
|
|
46
|
-
import {
|
|
47
|
-
/* or import useTransition from 'react-transition-state'; */
|
|
46
|
+
import { useTransitionState } from 'react-transition-state';
|
|
48
47
|
|
|
49
48
|
function Example() {
|
|
50
|
-
const [state, toggle] =
|
|
49
|
+
const [state, toggle] = useTransitionState({ timeout: 750, preEnter: true });
|
|
51
50
|
return (
|
|
52
51
|
<div>
|
|
53
52
|
<button onClick={() => toggle()}>toggle</button>
|
|
@@ -83,7 +82,7 @@ export default Example;
|
|
|
83
82
|
|
|
84
83
|
```jsx
|
|
85
84
|
import styled from 'styled-components';
|
|
86
|
-
import {
|
|
85
|
+
import { useTransitionState } from 'react-transition-state';
|
|
87
86
|
|
|
88
87
|
const Box = styled.div`
|
|
89
88
|
transition: all 500ms;
|
|
@@ -97,7 +96,7 @@ const Box = styled.div`
|
|
|
97
96
|
`;
|
|
98
97
|
|
|
99
98
|
function StyledExample() {
|
|
100
|
-
const [{ status, isMounted }, toggle] =
|
|
99
|
+
const [{ status, isMounted }, toggle] = useTransitionState({
|
|
101
100
|
timeout: 500,
|
|
102
101
|
mountOnEnter: true,
|
|
103
102
|
unmountOnExit: true,
|
|
@@ -134,7 +133,7 @@ export default StyledExample;
|
|
|
134
133
|
|
|
135
134
|
You can create switch transition effects using one of the provided hooks,
|
|
136
135
|
|
|
137
|
-
- `
|
|
136
|
+
- `useTransitionState` if the number of elements participating in the switch transition is static.
|
|
138
137
|
- `useTransitionMap` if the number of elements participating in the switch transition is dynamic and only known at runtime.
|
|
139
138
|
|
|
140
139
|
**[Edit on CodeSandbox](https://codesandbox.io/p/sandbox/react-switch-transition-x87jt8)**
|
|
@@ -173,10 +172,10 @@ This [CodeSandbox example](https://codesandbox.io/s/react-transition-state-vs-gr
|
|
|
173
172
|
|
|
174
173
|
## API
|
|
175
174
|
|
|
176
|
-
### `
|
|
175
|
+
### `useTransitionState` Hook
|
|
177
176
|
|
|
178
177
|
```typescript
|
|
179
|
-
function
|
|
178
|
+
function useTransitionState(
|
|
180
179
|
options?: TransitionOptions
|
|
181
180
|
): [TransitionState, (toEnter?: boolean) => void, () => void];
|
|
182
181
|
```
|
|
@@ -197,7 +196,7 @@ function useTransition(
|
|
|
197
196
|
|
|
198
197
|
#### Return value
|
|
199
198
|
|
|
200
|
-
The `
|
|
199
|
+
The `useTransitionState` Hook returns a tuple of values in the following order:
|
|
201
200
|
|
|
202
201
|
1. state:
|
|
203
202
|
|
|
@@ -231,11 +230,11 @@ The `useTransition` Hook returns a tuple of values in the following order:
|
|
|
231
230
|
|
|
232
231
|
### `useTransitionMap` Hook
|
|
233
232
|
|
|
234
|
-
It's similar to the `
|
|
233
|
+
It's similar to the `useTransitionState` Hook except that it manages multiple states in a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) structure instead of a single state.
|
|
235
234
|
|
|
236
235
|
#### Options
|
|
237
236
|
|
|
238
|
-
It accepts all options as `
|
|
237
|
+
It accepts all options as `useTransitionState` and the following ones:
|
|
239
238
|
|
|
240
239
|
| Name | Type | Default | Description |
|
|
241
240
|
| --- | --- | --- | --- |
|
|
@@ -0,0 +1,113 @@
|
|
|
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;
|
|
@@ -0,0 +1,62 @@
|
|
|
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;
|
|
@@ -0,0 +1,47 @@
|
|
|
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;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
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;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, useRef, useCallback } from 'react';
|
|
2
|
-
import { getTimeout, getEndStatus, PRE_EXIT, nextTick, PRE_ENTER, EXITING, ENTERING, ENTERED, startOrEnd, getState } from './utils.
|
|
2
|
+
import { getTimeout, getEndStatus, PRE_EXIT, nextTick, PRE_ENTER, EXITING, ENTERING, ENTERED, startOrEnd, getState } from './utils.mjs';
|
|
3
3
|
|
|
4
4
|
const updateState = (key, status, setStateMap, latestStateMap, timeoutId, onChange) => {
|
|
5
5
|
clearTimeout(timeoutId);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
2
|
-
import { getState, ENTERED, startOrEnd, getTimeout, getEndStatus, PRE_EXIT, nextTick, PRE_ENTER, EXITING, ENTERING } from './utils.
|
|
2
|
+
import { getState, ENTERED, startOrEnd, getTimeout, getEndStatus, PRE_EXIT, nextTick, PRE_ENTER, EXITING, ENTERING } from './utils.mjs';
|
|
3
3
|
|
|
4
4
|
const updateState = (status, setState, latestState, timeoutId, onChange) => {
|
|
5
5
|
clearTimeout(timeoutId.current);
|
|
@@ -10,7 +10,7 @@ const updateState = (status, setState, latestState, timeoutId, onChange) => {
|
|
|
10
10
|
current: state
|
|
11
11
|
});
|
|
12
12
|
};
|
|
13
|
-
const
|
|
13
|
+
const useTransitionState = ({
|
|
14
14
|
enter = true,
|
|
15
15
|
exit = true,
|
|
16
16
|
preEnter,
|
|
@@ -57,4 +57,4 @@ const useTransition = ({
|
|
|
57
57
|
return [state, toggle, endTransition];
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
-
export {
|
|
60
|
+
export { useTransitionState };
|
package/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-transition-state",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Zero dependency React transition state machine.",
|
|
5
5
|
"author": "Zheng Song",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"repository":
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/szhsin/react-transition-state.git"
|
|
10
|
+
},
|
|
8
11
|
"homepage": "https://szhsin.github.io/react-transition-state/",
|
|
9
|
-
"main": "dist/cjs/index.
|
|
10
|
-
"module": "dist/
|
|
11
|
-
"types": "types/index.d.ts",
|
|
12
|
+
"main": "./dist/cjs/index.cjs",
|
|
13
|
+
"module": "./dist/esm/index.mjs",
|
|
14
|
+
"types": "./types/index.d.ts",
|
|
12
15
|
"sideEffects": false,
|
|
13
16
|
"files": [
|
|
14
17
|
"dist/",
|
|
@@ -35,37 +38,44 @@
|
|
|
35
38
|
"pret:fix": "prettier -w .",
|
|
36
39
|
"build": "run-s pret clean lint types bundle"
|
|
37
40
|
},
|
|
41
|
+
"exports": {
|
|
42
|
+
".": {
|
|
43
|
+
"types": "./types/index.d.ts",
|
|
44
|
+
"require": "./dist/cjs/index.cjs",
|
|
45
|
+
"default": "./dist/esm/index.mjs"
|
|
46
|
+
},
|
|
47
|
+
"./package.json": "./package.json"
|
|
48
|
+
},
|
|
38
49
|
"peerDependencies": {
|
|
39
50
|
"react": ">=16.8.0",
|
|
40
51
|
"react-dom": ">=16.8.0"
|
|
41
52
|
},
|
|
42
53
|
"devDependencies": {
|
|
43
|
-
"@babel/core": "^7.
|
|
44
|
-
"@babel/preset-env": "^7.
|
|
45
|
-
"@eslint/compat": "^1.1.1",
|
|
54
|
+
"@babel/core": "^7.26.7",
|
|
55
|
+
"@babel/preset-env": "^7.26.7",
|
|
46
56
|
"@rollup/plugin-babel": "^6.0.4",
|
|
47
|
-
"@testing-library/react": "^16.0
|
|
48
|
-
"@types/jest": "^29.5.
|
|
57
|
+
"@testing-library/react": "^16.2.0",
|
|
58
|
+
"@types/jest": "^29.5.14",
|
|
49
59
|
"babel-plugin-pure-annotations": "^0.1.2",
|
|
50
|
-
"eslint": "^9.
|
|
51
|
-
"eslint-config-prettier": "^
|
|
52
|
-
"eslint-plugin-jest": "^28.
|
|
53
|
-
"eslint-plugin-react": "^7.37.
|
|
54
|
-
"eslint-plugin-react-hooks": "^
|
|
55
|
-
"eslint-plugin-react-hooks-addons": "^0.
|
|
56
|
-
"globals": "^15.
|
|
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",
|
|
57
67
|
"jest": "^29.7.0",
|
|
58
68
|
"jest-environment-jsdom": "^29.7.0",
|
|
59
69
|
"npm-run-all": "^4.1.5",
|
|
60
|
-
"prettier": "^3.
|
|
61
|
-
"react": "^
|
|
62
|
-
"react-dom": "^
|
|
63
|
-
"rollup": "^4.
|
|
64
|
-
"typescript": "^5.
|
|
70
|
+
"prettier": "^3.4.2",
|
|
71
|
+
"react": "^19",
|
|
72
|
+
"react-dom": "^19",
|
|
73
|
+
"rollup": "^4.32.1",
|
|
74
|
+
"typescript": "^5.7.3"
|
|
65
75
|
},
|
|
66
76
|
"overrides": {
|
|
67
|
-
"
|
|
68
|
-
"
|
|
77
|
+
"whatwg-url@11.0.0": {
|
|
78
|
+
"tr46": "^4"
|
|
69
79
|
}
|
|
70
80
|
}
|
|
71
81
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -46,8 +46,18 @@ export interface TransitionMapResult<K> {
|
|
|
46
46
|
deleteItem: (key: K) => boolean;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export const
|
|
49
|
+
export const useTransitionState: (options?: TransitionOptions) => TransitionResult;
|
|
50
50
|
|
|
51
51
|
export const useTransitionMap: <K>(options?: TransitionMapOptions<K>) => TransitionMapResult<K>;
|
|
52
52
|
|
|
53
|
-
export
|
|
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
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @deprecated The default export will be removed in v3.0.0. Use the named export `useTransitionState` instead.
|
|
62
|
+
*/
|
|
63
|
+
export default useTransitionState;
|
package/dist/cjs/index.js
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var react = require('react');
|
|
6
|
-
|
|
7
|
-
const PRE_ENTER = 0;
|
|
8
|
-
const ENTERING = 1;
|
|
9
|
-
const ENTERED = 2;
|
|
10
|
-
const PRE_EXIT = 3;
|
|
11
|
-
const EXITING = 4;
|
|
12
|
-
const EXITED = 5;
|
|
13
|
-
const UNMOUNTED = 6;
|
|
14
|
-
const STATUS = ['preEnter', 'entering', 'entered', 'preExit', 'exiting', 'exited', 'unmounted'];
|
|
15
|
-
const getState = status => ({
|
|
16
|
-
_s: status,
|
|
17
|
-
status: STATUS[status],
|
|
18
|
-
isEnter: status < PRE_EXIT,
|
|
19
|
-
isMounted: status !== UNMOUNTED,
|
|
20
|
-
isResolved: status === ENTERED || status > EXITING
|
|
21
|
-
});
|
|
22
|
-
const startOrEnd = unmounted => unmounted ? UNMOUNTED : EXITED;
|
|
23
|
-
const getEndStatus = (status, unmountOnExit) => {
|
|
24
|
-
switch (status) {
|
|
25
|
-
case ENTERING:
|
|
26
|
-
case PRE_ENTER:
|
|
27
|
-
return ENTERED;
|
|
28
|
-
case EXITING:
|
|
29
|
-
case PRE_EXIT:
|
|
30
|
-
return startOrEnd(unmountOnExit);
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
const getTimeout = timeout => typeof timeout === 'object' ? [timeout.enter, timeout.exit] : [timeout, timeout];
|
|
34
|
-
const nextTick = (transitState, status) => setTimeout(() => {
|
|
35
|
-
// Reading document.body.offsetTop can force browser to repaint before transition to the next state
|
|
36
|
-
isNaN(document.body.offsetTop) || transitState(status + 1);
|
|
37
|
-
}, 0);
|
|
38
|
-
|
|
39
|
-
const updateState$1 = (status, setState, latestState, timeoutId, onChange) => {
|
|
40
|
-
clearTimeout(timeoutId.current);
|
|
41
|
-
const state = getState(status);
|
|
42
|
-
setState(state);
|
|
43
|
-
latestState.current = state;
|
|
44
|
-
onChange && onChange({
|
|
45
|
-
current: state
|
|
46
|
-
});
|
|
47
|
-
};
|
|
48
|
-
const useTransition = ({
|
|
49
|
-
enter = true,
|
|
50
|
-
exit = true,
|
|
51
|
-
preEnter,
|
|
52
|
-
preExit,
|
|
53
|
-
timeout,
|
|
54
|
-
initialEntered,
|
|
55
|
-
mountOnEnter,
|
|
56
|
-
unmountOnExit,
|
|
57
|
-
onStateChange: onChange
|
|
58
|
-
} = {}) => {
|
|
59
|
-
const [state, setState] = react.useState(() => getState(initialEntered ? ENTERED : startOrEnd(mountOnEnter)));
|
|
60
|
-
const latestState = react.useRef(state);
|
|
61
|
-
const timeoutId = react.useRef();
|
|
62
|
-
const [enterTimeout, exitTimeout] = getTimeout(timeout);
|
|
63
|
-
const endTransition = react.useCallback(() => {
|
|
64
|
-
const status = getEndStatus(latestState.current._s, unmountOnExit);
|
|
65
|
-
status && updateState$1(status, setState, latestState, timeoutId, onChange);
|
|
66
|
-
}, [onChange, unmountOnExit]);
|
|
67
|
-
const toggle = react.useCallback(toEnter => {
|
|
68
|
-
const transitState = status => {
|
|
69
|
-
updateState$1(status, setState, latestState, timeoutId, onChange);
|
|
70
|
-
switch (status) {
|
|
71
|
-
case ENTERING:
|
|
72
|
-
if (enterTimeout >= 0) timeoutId.current = setTimeout(endTransition, enterTimeout);
|
|
73
|
-
break;
|
|
74
|
-
case EXITING:
|
|
75
|
-
if (exitTimeout >= 0) timeoutId.current = setTimeout(endTransition, exitTimeout);
|
|
76
|
-
break;
|
|
77
|
-
case PRE_ENTER:
|
|
78
|
-
case PRE_EXIT:
|
|
79
|
-
timeoutId.current = nextTick(transitState, status);
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
const enterStage = latestState.current.isEnter;
|
|
84
|
-
if (typeof toEnter !== 'boolean') toEnter = !enterStage;
|
|
85
|
-
if (toEnter) {
|
|
86
|
-
!enterStage && transitState(enter ? preEnter ? PRE_ENTER : ENTERING : ENTERED);
|
|
87
|
-
} else {
|
|
88
|
-
enterStage && transitState(exit ? preExit ? PRE_EXIT : EXITING : startOrEnd(unmountOnExit));
|
|
89
|
-
}
|
|
90
|
-
}, [endTransition, onChange, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
|
|
91
|
-
react.useEffect(() => () => clearTimeout(timeoutId.current), []);
|
|
92
|
-
return [state, toggle, endTransition];
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const updateState = (key, status, setStateMap, latestStateMap, timeoutId, onChange) => {
|
|
96
|
-
clearTimeout(timeoutId);
|
|
97
|
-
const state = getState(status);
|
|
98
|
-
const stateMap = new Map(latestStateMap.current);
|
|
99
|
-
stateMap.set(key, state);
|
|
100
|
-
setStateMap(stateMap);
|
|
101
|
-
latestStateMap.current = stateMap;
|
|
102
|
-
onChange && onChange({
|
|
103
|
-
key,
|
|
104
|
-
current: state
|
|
105
|
-
});
|
|
106
|
-
};
|
|
107
|
-
const useTransitionMap = ({
|
|
108
|
-
allowMultiple,
|
|
109
|
-
enter = true,
|
|
110
|
-
exit = true,
|
|
111
|
-
preEnter,
|
|
112
|
-
preExit,
|
|
113
|
-
timeout,
|
|
114
|
-
initialEntered,
|
|
115
|
-
mountOnEnter,
|
|
116
|
-
unmountOnExit,
|
|
117
|
-
onStateChange: onChange
|
|
118
|
-
} = {}) => {
|
|
119
|
-
const [stateMap, setStateMap] = react.useState(new Map());
|
|
120
|
-
const latestStateMap = react.useRef(stateMap);
|
|
121
|
-
const configMap = react.useRef(new Map());
|
|
122
|
-
const [enterTimeout, exitTimeout] = getTimeout(timeout);
|
|
123
|
-
const setItem = react.useCallback((key, config) => {
|
|
124
|
-
const {
|
|
125
|
-
initialEntered: _initialEntered = initialEntered
|
|
126
|
-
} = config || {};
|
|
127
|
-
const status = _initialEntered ? ENTERED : startOrEnd(mountOnEnter);
|
|
128
|
-
updateState(key, status, setStateMap, latestStateMap);
|
|
129
|
-
configMap.current.set(key, {});
|
|
130
|
-
}, [initialEntered, mountOnEnter]);
|
|
131
|
-
const deleteItem = react.useCallback(key => {
|
|
132
|
-
const newStateMap = new Map(latestStateMap.current);
|
|
133
|
-
if (newStateMap.delete(key)) {
|
|
134
|
-
setStateMap(newStateMap);
|
|
135
|
-
latestStateMap.current = newStateMap;
|
|
136
|
-
configMap.current.delete(key);
|
|
137
|
-
return true;
|
|
138
|
-
}
|
|
139
|
-
return false;
|
|
140
|
-
}, []);
|
|
141
|
-
const endTransition = react.useCallback(key => {
|
|
142
|
-
const stateObj = latestStateMap.current.get(key);
|
|
143
|
-
if (!stateObj) {
|
|
144
|
-
process.env.NODE_ENV !== 'production' && console.error(`[React-Transition-State] invalid key: ${key}`);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
const {
|
|
148
|
-
timeoutId
|
|
149
|
-
} = configMap.current.get(key);
|
|
150
|
-
const status = getEndStatus(stateObj._s, unmountOnExit);
|
|
151
|
-
status && updateState(key, status, setStateMap, latestStateMap, timeoutId, onChange);
|
|
152
|
-
}, [onChange, unmountOnExit]);
|
|
153
|
-
const toggle = react.useCallback((key, toEnter) => {
|
|
154
|
-
const stateObj = latestStateMap.current.get(key);
|
|
155
|
-
if (!stateObj) {
|
|
156
|
-
process.env.NODE_ENV !== 'production' && console.error(`[React-Transition-State] invalid key: ${key}`);
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
const config = configMap.current.get(key);
|
|
160
|
-
const transitState = status => {
|
|
161
|
-
updateState(key, status, setStateMap, latestStateMap, config.timeoutId, onChange);
|
|
162
|
-
switch (status) {
|
|
163
|
-
case ENTERING:
|
|
164
|
-
if (enterTimeout >= 0) config.timeoutId = setTimeout(() => endTransition(key), enterTimeout);
|
|
165
|
-
break;
|
|
166
|
-
case EXITING:
|
|
167
|
-
if (exitTimeout >= 0) config.timeoutId = setTimeout(() => endTransition(key), exitTimeout);
|
|
168
|
-
break;
|
|
169
|
-
case PRE_ENTER:
|
|
170
|
-
case PRE_EXIT:
|
|
171
|
-
config.timeoutId = nextTick(transitState, status);
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
const enterStage = stateObj.isEnter;
|
|
176
|
-
if (typeof toEnter !== 'boolean') toEnter = !enterStage;
|
|
177
|
-
if (toEnter) {
|
|
178
|
-
if (!enterStage) {
|
|
179
|
-
transitState(enter ? preEnter ? PRE_ENTER : ENTERING : ENTERED);
|
|
180
|
-
!allowMultiple && latestStateMap.current.forEach((_, _key) => _key !== key && toggle(_key, false));
|
|
181
|
-
}
|
|
182
|
-
} else {
|
|
183
|
-
if (enterStage) {
|
|
184
|
-
transitState(exit ? preExit ? PRE_EXIT : EXITING : startOrEnd(unmountOnExit));
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}, [onChange, endTransition, allowMultiple, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
|
|
188
|
-
const toggleAll = react.useCallback(toEnter => {
|
|
189
|
-
if (!allowMultiple && toEnter !== false) return;
|
|
190
|
-
for (const key of latestStateMap.current.keys()) toggle(key, toEnter);
|
|
191
|
-
}, [allowMultiple, toggle]);
|
|
192
|
-
return {
|
|
193
|
-
stateMap,
|
|
194
|
-
toggle,
|
|
195
|
-
toggleAll,
|
|
196
|
-
endTransition,
|
|
197
|
-
setItem,
|
|
198
|
-
deleteItem
|
|
199
|
-
};
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
exports.default = useTransition;
|
|
203
|
-
exports.useTransition = useTransition;
|
|
204
|
-
exports.useTransitionMap = useTransitionMap;
|
package/dist/es/index.js
DELETED
|
File without changes
|