react-transition-state 1.2.0-alpha.5 → 2.0.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 +78 -39
- package/dist/cjs/index.js +39 -36
- package/dist/es/hooks/useTransition.js +16 -13
- package/dist/es/hooks/useTransitionMap.js +16 -16
- package/dist/es/hooks/utils.js +10 -10
- package/package.json +18 -16
- package/types/index.d.ts +9 -9
package/README.md
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
# React-Transition-State
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/react-transition-state)
|
|
4
|
-
[](https://www.npmjs.com/package/react-transition-state)
|
|
5
|
-
[](https://bundlephobia.com/package/react-transition-state)
|
|
6
|
-
[](https://snyk.io/test/github/szhsin/react-transition-state)
|
|
3
|
+
[](https://www.npmjs.com/package/react-transition-state) [](https://www.npmjs.com/package/react-transition-state) [](https://bundlephobia.com/package/react-transition-state) [](https://snyk.io/test/github/szhsin/react-transition-state)
|
|
7
4
|
|
|
8
5
|
## Features
|
|
9
6
|
|
|
@@ -13,7 +10,7 @@ Inspired by the [React Transition Group](https://github.com/reactjs/react-transi
|
|
|
13
10
|
- 🔄 Moving React components in and out of DOM seamlessly.
|
|
14
11
|
- 🚫 Using no [derived state](https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html).
|
|
15
12
|
- 🚀 Efficient: each state transition results in at most one extract render for consuming component.
|
|
16
|
-
- 🤏 Tiny: [~
|
|
13
|
+
- 🤏 Tiny: [~1KB](https://bundlephobia.com/package/react-transition-state)(post-treeshaking) and no dependencies, ideal for both component libraries and applications.
|
|
17
14
|
|
|
18
15
|
🤔 Not convinced? [See a comparison with _React Transition Group_](#comparisons-with-react-transition-group)
|
|
19
16
|
|
|
@@ -21,8 +18,7 @@ Inspired by the [React Transition Group](https://github.com/reactjs/react-transi
|
|
|
21
18
|
|
|
22
19
|
## State diagram
|
|
23
20
|
|
|
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](#usetransition-hook).
|
|
21
|
+
 The `initialEntered` and `mountOnEnter` props are omitted from the diagram to keep it less convoluted. [Please read more details at the API section](#usetransition-hook).
|
|
26
22
|
|
|
27
23
|
<br/>
|
|
28
24
|
|
|
@@ -51,7 +47,7 @@ function Example() {
|
|
|
51
47
|
return (
|
|
52
48
|
<div>
|
|
53
49
|
<button onClick={() => toggle()}>toggle</button>
|
|
54
|
-
<div className={`example ${state}`}>React transition state</div>
|
|
50
|
+
<div className={`example ${state.status}`}>React transition state</div>
|
|
55
51
|
</div>
|
|
56
52
|
);
|
|
57
53
|
}
|
|
@@ -88,8 +84,8 @@ import { useTransition } from 'react-transition-state';
|
|
|
88
84
|
const Box = styled.div`
|
|
89
85
|
transition: all 500ms;
|
|
90
86
|
|
|
91
|
-
${({
|
|
92
|
-
(
|
|
87
|
+
${({ status }) =>
|
|
88
|
+
(status === 'preEnter' || status === 'exiting') &&
|
|
93
89
|
`
|
|
94
90
|
opacity: 0;
|
|
95
91
|
transform: scale(0.9);
|
|
@@ -97,19 +93,18 @@ const Box = styled.div`
|
|
|
97
93
|
`;
|
|
98
94
|
|
|
99
95
|
function StyledExample() {
|
|
100
|
-
const [
|
|
96
|
+
const [{ status, isMounted }, toggle] = useTransition({
|
|
101
97
|
timeout: 500,
|
|
102
98
|
mountOnEnter: true,
|
|
103
99
|
unmountOnExit: true,
|
|
104
100
|
preEnter: true
|
|
105
101
|
});
|
|
106
102
|
|
|
107
|
-
const showButton = state === 'unmounted';
|
|
108
103
|
return (
|
|
109
104
|
<div>
|
|
110
|
-
{
|
|
111
|
-
{
|
|
112
|
-
<Box
|
|
105
|
+
{!isMounted && <button onClick={() => toggle(true)}>Show Message</button>}
|
|
106
|
+
{isMounted && (
|
|
107
|
+
<Box status={status}>
|
|
113
108
|
<p>This message is being transitioned in and out of the DOM.</p>
|
|
114
109
|
<button onClick={() => toggle(false)}>Close</button>
|
|
115
110
|
</Box>
|
|
@@ -147,15 +142,15 @@ useEffect(() => {
|
|
|
147
142
|
|
|
148
143
|
## Comparisons with _React Transition Group_
|
|
149
144
|
|
|
150
|
-
|
|
|
151
|
-
|
|
|
152
|
-
| Use derived state
|
|
153
|
-
| Controlled
|
|
154
|
-
| DOM updates
|
|
155
|
-
| Render something in response to state updates | _Resort to side effects_ – rendering based on [state update events](https://codesandbox.io/s/react-transition-state-vs-group-p45iy?file=/src/App.js:1007-1188)
|
|
156
|
-
| Working with _styled-components_
|
|
157
|
-
| Bundle size
|
|
158
|
-
| Dependency count
|
|
145
|
+
| | React Transition Group | This library |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| Use derived state | _Yes_ – use an `in` prop to trigger changes in a derived transition state | _No_ – there is only a single state which is triggered by a toggle function |
|
|
148
|
+
| Controlled | _No_ – <br/>Transition state is managed internally.<br/>Resort to callback events to read the internal state. | _Yes_ – <br/>Transition state is _lifted_ up into the consuming component.<br/>You have direct access to the transition state. |
|
|
149
|
+
| DOM updates | _Imperative_ – [commit changes into DOM imperatively](https://github.com/reactjs/react-transition-group/blob/5aa3fd2d7e3354a7e42505d55af605ff44f74e2e/src/CSSTransition.js#L10) to update `classes` | _Declarative_ – you declare [what the `classes` look like](https://github.com/szhsin/react-transition-state/blob/2ab44c12ac5d5283ec3bb997bfc1d5ef6dffb0ce/example/src/components/BasicExample.js#L31) and DOM updates are taken care of by `ReactDOM` |
|
|
150
|
+
| Render something in response to state updates | _Resort to side effects_ – rendering based on [state update events](https://codesandbox.io/s/react-transition-state-vs-group-p45iy?file=/src/App.js:1007-1188) | _Pure_ – rendering based on [transition state](https://codesandbox.io/s/react-transition-state-vs-group-p45iy?file=/src/App.js:2140-2325) |
|
|
151
|
+
| Working with _styled-components_ | Your code looks like – <br/>`&.box-exit-active { opacity: 0; }`<br/>`&.box-enter-active { opacity: 1; }` | Your code looks like – <br/>`opacity: ${({ state }) => (state === 'exiting' ? '0' : '1')};` <br/> It's the way how you normally use the _styled-components_ |
|
|
152
|
+
| Bundle size | [](https://bundlephobia.com/package/react-transition-group) | ✅ [](https://bundlephobia.com/package/react-transition-state) |
|
|
153
|
+
| Dependency count | [](https://www.npmjs.com/package/react-transition-group?activeTab=dependencies) | ✅ [](https://www.npmjs.com/package/react-transition-state?activeTab=dependencies) |
|
|
159
154
|
|
|
160
155
|
This [CodeSandbox example](https://codesandbox.io/s/react-transition-state-vs-group-p45iy) demonstrates how the same transition can be implemented in a simpler, more declarative, and controllable manner than _React Transition Group_.
|
|
161
156
|
|
|
@@ -173,29 +168,45 @@ function useTransition(
|
|
|
173
168
|
|
|
174
169
|
#### Options
|
|
175
170
|
|
|
176
|
-
| Name
|
|
177
|
-
|
|
|
178
|
-
| `enter`
|
|
179
|
-
| `exit`
|
|
180
|
-
| `preEnter`
|
|
181
|
-
| `preExit`
|
|
182
|
-
| `initialEntered` | boolean
|
|
183
|
-
| `mountOnEnter`
|
|
184
|
-
| `unmountOnExit`
|
|
185
|
-
| `timeout`
|
|
186
|
-
| `onChange`
|
|
171
|
+
| Name | Type | Default | Description |
|
|
172
|
+
| --- | --- | --- | --- |
|
|
173
|
+
| `enter` | boolean | true | Enable or disable enter phase transitions |
|
|
174
|
+
| `exit` | boolean | true | Enable or disable exit phase transitions |
|
|
175
|
+
| `preEnter` | boolean | | Add a 'preEnter' state immediately before 'entering', which is necessary to change DOM elements from unmounted or `display: none` with CSS transition (not necessary for CSS animation). |
|
|
176
|
+
| `preExit` | boolean | | Add a 'preExit' state immediately before 'exiting' |
|
|
177
|
+
| `initialEntered` | boolean | | Beginning from 'entered' state |
|
|
178
|
+
| `mountOnEnter` | boolean | | State will be 'unmounted' until hit enter phase for the first time. It allows you to create lazily mounted component. |
|
|
179
|
+
| `unmountOnExit` | boolean | | State will become 'unmounted' after 'exiting' finishes. It allows you to transition component out of DOM. |
|
|
180
|
+
| `timeout` | number \| <br />{ enter?: number; exit?: number; } | | Set timeout in **ms** for transitions; you can set a single value or different values for enter and exit transitions. |
|
|
181
|
+
| `onChange` | (event: { state: string }) => void | | Event fired when state has changed. <br/><br/>Prefer to read state from the hook function return value directly unless you want to perform some side effects in response to state changes. <br/><br/>_Note: create an event handler with `useCallback` if you need to keep `toggle` or `endTransition` function's identity stable across re-renders._ |
|
|
187
182
|
|
|
188
183
|
#### Return value
|
|
189
184
|
|
|
190
|
-
The `useTransition` Hook returns
|
|
185
|
+
The `useTransition` Hook returns a tuple of values in the following order:
|
|
191
186
|
|
|
192
|
-
1. state:
|
|
193
|
-
|
|
187
|
+
1. state:
|
|
188
|
+
|
|
189
|
+
```js
|
|
190
|
+
{
|
|
191
|
+
status: 'preEnter' |
|
|
192
|
+
'entering' |
|
|
193
|
+
'entered' |
|
|
194
|
+
'preExit' |
|
|
195
|
+
'exiting' |
|
|
196
|
+
'exited' |
|
|
197
|
+
'unmounted';
|
|
198
|
+
isMounted: boolean;
|
|
199
|
+
isEnter: boolean;
|
|
200
|
+
isResolved: boolean;
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
2. toggle: `(toEnter?: boolean) => void`
|
|
194
205
|
|
|
195
206
|
- If no parameter is supplied, this function will toggle state between enter and exit phases.
|
|
196
207
|
- You can set a boolean parameter to explicitly switch into one of the two phases.
|
|
197
208
|
|
|
198
|
-
3. endTransition: () => void
|
|
209
|
+
3. endTransition: `() => void`
|
|
199
210
|
|
|
200
211
|
- Call this function to stop transition which will turn state into 'entered' or 'exited'.
|
|
201
212
|
- You will normally call this function in the `onAnimationEnd` or `onTransitionEnd` event.
|
|
@@ -203,6 +214,34 @@ The `useTransition` Hook returns an array of values in the following order:
|
|
|
203
214
|
|
|
204
215
|
<br/>
|
|
205
216
|
|
|
217
|
+
### `useTransitionMap` Hook
|
|
218
|
+
|
|
219
|
+
It's similar to the `useTransition` 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.
|
|
220
|
+
|
|
221
|
+
#### Options
|
|
222
|
+
|
|
223
|
+
It accepts all options as `useTransition` and the following ones:
|
|
224
|
+
|
|
225
|
+
| Name | Type | Default | Description |
|
|
226
|
+
| --- | --- | --- | --- |
|
|
227
|
+
| `allowMultiple` | boolean | | Allow multiple items to be in the enter phase at the same time. |
|
|
228
|
+
|
|
229
|
+
#### Return value
|
|
230
|
+
|
|
231
|
+
The Hook returns an object of shape:
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
interface TransitionMapResult<K> {
|
|
235
|
+
stateMap: ReadonlyMap<K, TransitionState>;
|
|
236
|
+
toggle: (key: K, toEnter?: boolean) => void;
|
|
237
|
+
endTransition: (key: K) => void;
|
|
238
|
+
setItem: (key: K, options?: TransitionItemOptions) => void;
|
|
239
|
+
deleteItem: (key: K) => boolean;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`setItem` and `deleteItem` are used to add and remove items from the state map.
|
|
244
|
+
|
|
206
245
|
## License
|
|
207
246
|
|
|
208
247
|
[MIT](https://github.com/szhsin/react-transition-state/blob/master/LICENSE) Licensed.
|
package/dist/cjs/index.js
CHANGED
|
@@ -11,21 +11,21 @@ var PRE_EXIT = 3;
|
|
|
11
11
|
var EXITING = 4;
|
|
12
12
|
var EXITED = 5;
|
|
13
13
|
var UNMOUNTED = 6;
|
|
14
|
-
var
|
|
15
|
-
var
|
|
14
|
+
var STATUS = ['preEnter', 'entering', 'entered', 'preExit', 'exiting', 'exited', 'unmounted'];
|
|
15
|
+
var getState = function getState(_status) {
|
|
16
16
|
return {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
isEnter:
|
|
20
|
-
isMounted:
|
|
21
|
-
isResolved:
|
|
17
|
+
_status: _status,
|
|
18
|
+
status: STATUS[_status],
|
|
19
|
+
isEnter: _status < PRE_EXIT,
|
|
20
|
+
isMounted: _status !== UNMOUNTED,
|
|
21
|
+
isResolved: _status === ENTERED || _status > EXITING
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
var startOrEnd = function startOrEnd(unmounted) {
|
|
25
25
|
return unmounted ? UNMOUNTED : EXITED;
|
|
26
26
|
};
|
|
27
|
-
var
|
|
28
|
-
switch (
|
|
27
|
+
var getEndStatus = function getEndStatus(status, unmountOnExit) {
|
|
28
|
+
switch (status) {
|
|
29
29
|
case ENTERING:
|
|
30
30
|
case PRE_ENTER:
|
|
31
31
|
return ENTERED;
|
|
@@ -39,12 +39,13 @@ var getTimeout = function getTimeout(timeout) {
|
|
|
39
39
|
return typeof timeout === 'object' ? [timeout.enter, timeout.exit] : [timeout, timeout];
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
var updateState$1 = function updateState(
|
|
42
|
+
var updateState$1 = function updateState(status, setState, latestState, timeoutId, onChange) {
|
|
43
43
|
clearTimeout(timeoutId.current);
|
|
44
|
+
var state = getState(status);
|
|
44
45
|
setState(state);
|
|
45
46
|
latestState.current = state;
|
|
46
47
|
onChange && onChange({
|
|
47
|
-
|
|
48
|
+
current: state
|
|
48
49
|
});
|
|
49
50
|
};
|
|
50
51
|
|
|
@@ -60,9 +61,11 @@ var useTransition = function useTransition(_temp) {
|
|
|
60
61
|
initialEntered = _ref.initialEntered,
|
|
61
62
|
mountOnEnter = _ref.mountOnEnter,
|
|
62
63
|
unmountOnExit = _ref.unmountOnExit,
|
|
63
|
-
onChange = _ref.
|
|
64
|
+
onChange = _ref.onStateChange;
|
|
64
65
|
|
|
65
|
-
var _useState = react.useState(
|
|
66
|
+
var _useState = react.useState(function () {
|
|
67
|
+
return getState(initialEntered ? ENTERED : startOrEnd(mountOnEnter));
|
|
68
|
+
}),
|
|
66
69
|
state = _useState[0],
|
|
67
70
|
setState = _useState[1];
|
|
68
71
|
|
|
@@ -74,14 +77,14 @@ var useTransition = function useTransition(_temp) {
|
|
|
74
77
|
exitTimeout = _getTimeout[1];
|
|
75
78
|
|
|
76
79
|
var endTransition = react.useCallback(function () {
|
|
77
|
-
var
|
|
78
|
-
|
|
80
|
+
var status = getEndStatus(latestState.current._status, unmountOnExit);
|
|
81
|
+
status && updateState$1(status, setState, latestState, timeoutId, onChange);
|
|
79
82
|
}, [onChange, unmountOnExit]);
|
|
80
83
|
var toggle = react.useCallback(function (toEnter) {
|
|
81
|
-
var transitState = function transitState(
|
|
82
|
-
updateState$1(
|
|
84
|
+
var transitState = function transitState(status) {
|
|
85
|
+
updateState$1(status, setState, latestState, timeoutId, onChange);
|
|
83
86
|
|
|
84
|
-
switch (
|
|
87
|
+
switch (status) {
|
|
85
88
|
case ENTERING:
|
|
86
89
|
if (enterTimeout >= 0) timeoutId.current = setTimeout(endTransition, enterTimeout);
|
|
87
90
|
break;
|
|
@@ -93,13 +96,13 @@ var useTransition = function useTransition(_temp) {
|
|
|
93
96
|
case PRE_ENTER:
|
|
94
97
|
case PRE_EXIT:
|
|
95
98
|
timeoutId.current = setTimeout(function () {
|
|
96
|
-
return transitState(
|
|
99
|
+
return transitState(status + 1);
|
|
97
100
|
}, 0);
|
|
98
101
|
break;
|
|
99
102
|
}
|
|
100
103
|
};
|
|
101
104
|
|
|
102
|
-
var enterStage = latestState.current <= ENTERED;
|
|
105
|
+
var enterStage = latestState.current._status <= ENTERED;
|
|
103
106
|
if (typeof toEnter !== 'boolean') toEnter = !enterStage;
|
|
104
107
|
|
|
105
108
|
if (toEnter) {
|
|
@@ -113,7 +116,7 @@ var useTransition = function useTransition(_temp) {
|
|
|
113
116
|
return clearTimeout(timeoutId.current);
|
|
114
117
|
};
|
|
115
118
|
}, []);
|
|
116
|
-
return [
|
|
119
|
+
return [state, toggle, endTransition];
|
|
117
120
|
};
|
|
118
121
|
|
|
119
122
|
var initialStateMap = new Map();
|
|
@@ -121,13 +124,13 @@ var initialConfigMap = new Map();
|
|
|
121
124
|
|
|
122
125
|
var updateState = function updateState(_ref) {
|
|
123
126
|
var key = _ref.key,
|
|
124
|
-
|
|
127
|
+
status = _ref.status,
|
|
125
128
|
setStateMap = _ref.setStateMap,
|
|
126
129
|
latestStateMap = _ref.latestStateMap,
|
|
127
130
|
timeoutId = _ref.timeoutId,
|
|
128
131
|
onChange = _ref.onChange;
|
|
129
132
|
clearTimeout(timeoutId);
|
|
130
|
-
var state =
|
|
133
|
+
var state = getState(status);
|
|
131
134
|
var stateMap = new Map(latestStateMap.current);
|
|
132
135
|
stateMap.set(key, state);
|
|
133
136
|
setStateMap(stateMap);
|
|
@@ -140,7 +143,7 @@ var updateState = function updateState(_ref) {
|
|
|
140
143
|
|
|
141
144
|
var useTransitionMap = function useTransitionMap(_temp) {
|
|
142
145
|
var _ref2 = _temp === void 0 ? {} : _temp,
|
|
143
|
-
|
|
146
|
+
allowMultiple = _ref2.allowMultiple,
|
|
144
147
|
_ref2$enter = _ref2.enter,
|
|
145
148
|
enter = _ref2$enter === void 0 ? true : _ref2$enter,
|
|
146
149
|
_ref2$exit = _ref2.exit,
|
|
@@ -169,10 +172,10 @@ var useTransitionMap = function useTransitionMap(_temp) {
|
|
|
169
172
|
_ref3$initialEntered = _ref3.initialEntered,
|
|
170
173
|
_initialEntered = _ref3$initialEntered === void 0 ? initialEntered : _ref3$initialEntered;
|
|
171
174
|
|
|
172
|
-
var
|
|
175
|
+
var status = _initialEntered ? ENTERED : startOrEnd(mountOnEnter);
|
|
173
176
|
updateState({
|
|
174
177
|
key: key,
|
|
175
|
-
|
|
178
|
+
status: status,
|
|
176
179
|
setStateMap: setStateMap,
|
|
177
180
|
latestStateMap: latestStateMap
|
|
178
181
|
});
|
|
@@ -201,10 +204,10 @@ var useTransitionMap = function useTransitionMap(_temp) {
|
|
|
201
204
|
var _configMap$current$ge = configMap.current.get(key),
|
|
202
205
|
timeoutId = _configMap$current$ge.timeoutId;
|
|
203
206
|
|
|
204
|
-
var
|
|
205
|
-
|
|
207
|
+
var status = getEndStatus(stateObj._status, unmountOnExit);
|
|
208
|
+
status && updateState({
|
|
206
209
|
key: key,
|
|
207
|
-
|
|
210
|
+
status: status,
|
|
208
211
|
setStateMap: setStateMap,
|
|
209
212
|
latestStateMap: latestStateMap,
|
|
210
213
|
timeoutId: timeoutId,
|
|
@@ -221,17 +224,17 @@ var useTransitionMap = function useTransitionMap(_temp) {
|
|
|
221
224
|
|
|
222
225
|
var config = configMap.current.get(key);
|
|
223
226
|
|
|
224
|
-
var transitState = function transitState(
|
|
227
|
+
var transitState = function transitState(status) {
|
|
225
228
|
updateState({
|
|
226
229
|
key: key,
|
|
227
|
-
|
|
230
|
+
status: status,
|
|
228
231
|
setStateMap: setStateMap,
|
|
229
232
|
latestStateMap: latestStateMap,
|
|
230
233
|
timeoutId: config.timeoutId,
|
|
231
234
|
onChange: onChange
|
|
232
235
|
});
|
|
233
236
|
|
|
234
|
-
switch (
|
|
237
|
+
switch (status) {
|
|
235
238
|
case ENTERING:
|
|
236
239
|
if (enterTimeout >= 0) config.timeoutId = setTimeout(function () {
|
|
237
240
|
return endTransition(key);
|
|
@@ -247,19 +250,19 @@ var useTransitionMap = function useTransitionMap(_temp) {
|
|
|
247
250
|
case PRE_ENTER:
|
|
248
251
|
case PRE_EXIT:
|
|
249
252
|
config.timeoutId = setTimeout(function () {
|
|
250
|
-
return transitState(
|
|
253
|
+
return transitState(status + 1);
|
|
251
254
|
}, 0);
|
|
252
255
|
break;
|
|
253
256
|
}
|
|
254
257
|
};
|
|
255
258
|
|
|
256
|
-
var enterStage = stateObj.
|
|
259
|
+
var enterStage = stateObj._status <= ENTERED;
|
|
257
260
|
if (typeof toEnter !== 'boolean') toEnter = !enterStage;
|
|
258
261
|
|
|
259
262
|
if (toEnter) {
|
|
260
263
|
if (!enterStage) {
|
|
261
264
|
transitState(enter ? preEnter ? PRE_ENTER : ENTERING : ENTERED);
|
|
262
|
-
|
|
265
|
+
!allowMultiple && latestStateMap.current.forEach(function (_, _key) {
|
|
263
266
|
return _key !== key && toggle(_key, false);
|
|
264
267
|
});
|
|
265
268
|
}
|
|
@@ -268,7 +271,7 @@ var useTransitionMap = function useTransitionMap(_temp) {
|
|
|
268
271
|
transitState(exit ? preExit ? PRE_EXIT : EXITING : startOrEnd(unmountOnExit));
|
|
269
272
|
}
|
|
270
273
|
}
|
|
271
|
-
}, [onChange, endTransition,
|
|
274
|
+
}, [onChange, endTransition, allowMultiple, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
|
|
272
275
|
return {
|
|
273
276
|
stateMap: stateMap,
|
|
274
277
|
toggle: toggle,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
2
|
-
import { ENTERED, startOrEnd, getTimeout,
|
|
2
|
+
import { getState, ENTERED, startOrEnd, getTimeout, getEndStatus, PRE_EXIT, EXITING, PRE_ENTER, ENTERING } from './utils.js';
|
|
3
3
|
|
|
4
|
-
var updateState = function updateState(
|
|
4
|
+
var updateState = function updateState(status, setState, latestState, timeoutId, onChange) {
|
|
5
5
|
clearTimeout(timeoutId.current);
|
|
6
|
+
var state = getState(status);
|
|
6
7
|
setState(state);
|
|
7
8
|
latestState.current = state;
|
|
8
9
|
onChange && onChange({
|
|
9
|
-
|
|
10
|
+
current: state
|
|
10
11
|
});
|
|
11
12
|
};
|
|
12
13
|
|
|
@@ -22,9 +23,11 @@ var useTransition = function useTransition(_temp) {
|
|
|
22
23
|
initialEntered = _ref.initialEntered,
|
|
23
24
|
mountOnEnter = _ref.mountOnEnter,
|
|
24
25
|
unmountOnExit = _ref.unmountOnExit,
|
|
25
|
-
onChange = _ref.
|
|
26
|
+
onChange = _ref.onStateChange;
|
|
26
27
|
|
|
27
|
-
var _useState = useState(
|
|
28
|
+
var _useState = useState(function () {
|
|
29
|
+
return getState(initialEntered ? ENTERED : startOrEnd(mountOnEnter));
|
|
30
|
+
}),
|
|
28
31
|
state = _useState[0],
|
|
29
32
|
setState = _useState[1];
|
|
30
33
|
|
|
@@ -36,14 +39,14 @@ var useTransition = function useTransition(_temp) {
|
|
|
36
39
|
exitTimeout = _getTimeout[1];
|
|
37
40
|
|
|
38
41
|
var endTransition = useCallback(function () {
|
|
39
|
-
var
|
|
40
|
-
|
|
42
|
+
var status = getEndStatus(latestState.current._status, unmountOnExit);
|
|
43
|
+
status && updateState(status, setState, latestState, timeoutId, onChange);
|
|
41
44
|
}, [onChange, unmountOnExit]);
|
|
42
45
|
var toggle = useCallback(function (toEnter) {
|
|
43
|
-
var transitState = function transitState(
|
|
44
|
-
updateState(
|
|
46
|
+
var transitState = function transitState(status) {
|
|
47
|
+
updateState(status, setState, latestState, timeoutId, onChange);
|
|
45
48
|
|
|
46
|
-
switch (
|
|
49
|
+
switch (status) {
|
|
47
50
|
case ENTERING:
|
|
48
51
|
if (enterTimeout >= 0) timeoutId.current = setTimeout(endTransition, enterTimeout);
|
|
49
52
|
break;
|
|
@@ -55,13 +58,13 @@ var useTransition = function useTransition(_temp) {
|
|
|
55
58
|
case PRE_ENTER:
|
|
56
59
|
case PRE_EXIT:
|
|
57
60
|
timeoutId.current = setTimeout(function () {
|
|
58
|
-
return transitState(
|
|
61
|
+
return transitState(status + 1);
|
|
59
62
|
}, 0);
|
|
60
63
|
break;
|
|
61
64
|
}
|
|
62
65
|
};
|
|
63
66
|
|
|
64
|
-
var enterStage = latestState.current <= ENTERED;
|
|
67
|
+
var enterStage = latestState.current._status <= ENTERED;
|
|
65
68
|
if (typeof toEnter !== 'boolean') toEnter = !enterStage;
|
|
66
69
|
|
|
67
70
|
if (toEnter) {
|
|
@@ -75,7 +78,7 @@ var useTransition = function useTransition(_temp) {
|
|
|
75
78
|
return clearTimeout(timeoutId.current);
|
|
76
79
|
};
|
|
77
80
|
}, []);
|
|
78
|
-
return [
|
|
81
|
+
return [state, toggle, endTransition];
|
|
79
82
|
};
|
|
80
83
|
|
|
81
84
|
export { useTransition };
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { useState, useRef, useCallback } from 'react';
|
|
2
|
-
import { getTimeout, ENTERED, startOrEnd,
|
|
2
|
+
import { getTimeout, ENTERED, startOrEnd, getEndStatus, PRE_EXIT, EXITING, PRE_ENTER, ENTERING, getState } from './utils.js';
|
|
3
3
|
|
|
4
4
|
var initialStateMap = new Map();
|
|
5
5
|
var initialConfigMap = new Map();
|
|
6
6
|
|
|
7
7
|
var updateState = function updateState(_ref) {
|
|
8
8
|
var key = _ref.key,
|
|
9
|
-
|
|
9
|
+
status = _ref.status,
|
|
10
10
|
setStateMap = _ref.setStateMap,
|
|
11
11
|
latestStateMap = _ref.latestStateMap,
|
|
12
12
|
timeoutId = _ref.timeoutId,
|
|
13
13
|
onChange = _ref.onChange;
|
|
14
14
|
clearTimeout(timeoutId);
|
|
15
|
-
var state =
|
|
15
|
+
var state = getState(status);
|
|
16
16
|
var stateMap = new Map(latestStateMap.current);
|
|
17
17
|
stateMap.set(key, state);
|
|
18
18
|
setStateMap(stateMap);
|
|
@@ -25,7 +25,7 @@ var updateState = function updateState(_ref) {
|
|
|
25
25
|
|
|
26
26
|
var useTransitionMap = function useTransitionMap(_temp) {
|
|
27
27
|
var _ref2 = _temp === void 0 ? {} : _temp,
|
|
28
|
-
|
|
28
|
+
allowMultiple = _ref2.allowMultiple,
|
|
29
29
|
_ref2$enter = _ref2.enter,
|
|
30
30
|
enter = _ref2$enter === void 0 ? true : _ref2$enter,
|
|
31
31
|
_ref2$exit = _ref2.exit,
|
|
@@ -54,10 +54,10 @@ var useTransitionMap = function useTransitionMap(_temp) {
|
|
|
54
54
|
_ref3$initialEntered = _ref3.initialEntered,
|
|
55
55
|
_initialEntered = _ref3$initialEntered === void 0 ? initialEntered : _ref3$initialEntered;
|
|
56
56
|
|
|
57
|
-
var
|
|
57
|
+
var status = _initialEntered ? ENTERED : startOrEnd(mountOnEnter);
|
|
58
58
|
updateState({
|
|
59
59
|
key: key,
|
|
60
|
-
|
|
60
|
+
status: status,
|
|
61
61
|
setStateMap: setStateMap,
|
|
62
62
|
latestStateMap: latestStateMap
|
|
63
63
|
});
|
|
@@ -86,10 +86,10 @@ var useTransitionMap = function useTransitionMap(_temp) {
|
|
|
86
86
|
var _configMap$current$ge = configMap.current.get(key),
|
|
87
87
|
timeoutId = _configMap$current$ge.timeoutId;
|
|
88
88
|
|
|
89
|
-
var
|
|
90
|
-
|
|
89
|
+
var status = getEndStatus(stateObj._status, unmountOnExit);
|
|
90
|
+
status && updateState({
|
|
91
91
|
key: key,
|
|
92
|
-
|
|
92
|
+
status: status,
|
|
93
93
|
setStateMap: setStateMap,
|
|
94
94
|
latestStateMap: latestStateMap,
|
|
95
95
|
timeoutId: timeoutId,
|
|
@@ -106,17 +106,17 @@ var useTransitionMap = function useTransitionMap(_temp) {
|
|
|
106
106
|
|
|
107
107
|
var config = configMap.current.get(key);
|
|
108
108
|
|
|
109
|
-
var transitState = function transitState(
|
|
109
|
+
var transitState = function transitState(status) {
|
|
110
110
|
updateState({
|
|
111
111
|
key: key,
|
|
112
|
-
|
|
112
|
+
status: status,
|
|
113
113
|
setStateMap: setStateMap,
|
|
114
114
|
latestStateMap: latestStateMap,
|
|
115
115
|
timeoutId: config.timeoutId,
|
|
116
116
|
onChange: onChange
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
switch (
|
|
119
|
+
switch (status) {
|
|
120
120
|
case ENTERING:
|
|
121
121
|
if (enterTimeout >= 0) config.timeoutId = setTimeout(function () {
|
|
122
122
|
return endTransition(key);
|
|
@@ -132,19 +132,19 @@ var useTransitionMap = function useTransitionMap(_temp) {
|
|
|
132
132
|
case PRE_ENTER:
|
|
133
133
|
case PRE_EXIT:
|
|
134
134
|
config.timeoutId = setTimeout(function () {
|
|
135
|
-
return transitState(
|
|
135
|
+
return transitState(status + 1);
|
|
136
136
|
}, 0);
|
|
137
137
|
break;
|
|
138
138
|
}
|
|
139
139
|
};
|
|
140
140
|
|
|
141
|
-
var enterStage = stateObj.
|
|
141
|
+
var enterStage = stateObj._status <= ENTERED;
|
|
142
142
|
if (typeof toEnter !== 'boolean') toEnter = !enterStage;
|
|
143
143
|
|
|
144
144
|
if (toEnter) {
|
|
145
145
|
if (!enterStage) {
|
|
146
146
|
transitState(enter ? preEnter ? PRE_ENTER : ENTERING : ENTERED);
|
|
147
|
-
|
|
147
|
+
!allowMultiple && latestStateMap.current.forEach(function (_, _key) {
|
|
148
148
|
return _key !== key && toggle(_key, false);
|
|
149
149
|
});
|
|
150
150
|
}
|
|
@@ -153,7 +153,7 @@ var useTransitionMap = function useTransitionMap(_temp) {
|
|
|
153
153
|
transitState(exit ? preExit ? PRE_EXIT : EXITING : startOrEnd(unmountOnExit));
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
|
-
}, [onChange, endTransition,
|
|
156
|
+
}, [onChange, endTransition, allowMultiple, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
|
|
157
157
|
return {
|
|
158
158
|
stateMap: stateMap,
|
|
159
159
|
toggle: toggle,
|
package/dist/es/hooks/utils.js
CHANGED
|
@@ -5,21 +5,21 @@ var PRE_EXIT = 3;
|
|
|
5
5
|
var EXITING = 4;
|
|
6
6
|
var EXITED = 5;
|
|
7
7
|
var UNMOUNTED = 6;
|
|
8
|
-
var
|
|
9
|
-
var
|
|
8
|
+
var STATUS = ['preEnter', 'entering', 'entered', 'preExit', 'exiting', 'exited', 'unmounted'];
|
|
9
|
+
var getState = function getState(_status) {
|
|
10
10
|
return {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
isEnter:
|
|
14
|
-
isMounted:
|
|
15
|
-
isResolved:
|
|
11
|
+
_status: _status,
|
|
12
|
+
status: STATUS[_status],
|
|
13
|
+
isEnter: _status < PRE_EXIT,
|
|
14
|
+
isMounted: _status !== UNMOUNTED,
|
|
15
|
+
isResolved: _status === ENTERED || _status > EXITING
|
|
16
16
|
};
|
|
17
17
|
};
|
|
18
18
|
var startOrEnd = function startOrEnd(unmounted) {
|
|
19
19
|
return unmounted ? UNMOUNTED : EXITED;
|
|
20
20
|
};
|
|
21
|
-
var
|
|
22
|
-
switch (
|
|
21
|
+
var getEndStatus = function getEndStatus(status, unmountOnExit) {
|
|
22
|
+
switch (status) {
|
|
23
23
|
case ENTERING:
|
|
24
24
|
case PRE_ENTER:
|
|
25
25
|
return ENTERED;
|
|
@@ -33,4 +33,4 @@ var getTimeout = function getTimeout(timeout) {
|
|
|
33
33
|
return typeof timeout === 'object' ? [timeout.enter, timeout.exit] : [timeout, timeout];
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
export { ENTERED, ENTERING, EXITED, EXITING, PRE_ENTER, PRE_EXIT,
|
|
36
|
+
export { ENTERED, ENTERING, EXITED, EXITING, PRE_ENTER, PRE_EXIT, STATUS, UNMOUNTED, getEndStatus, getState, getTimeout, startOrEnd };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-transition-state",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Zero dependency
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Zero dependency React transition state machine.",
|
|
5
5
|
"author": "Zheng Song",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": "szhsin/react-transition-state",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"transition",
|
|
20
20
|
"animation",
|
|
21
21
|
"component",
|
|
22
|
-
"hook"
|
|
22
|
+
"hook",
|
|
23
|
+
"state machine"
|
|
23
24
|
],
|
|
24
25
|
"scripts": {
|
|
25
26
|
"start": "rollup -c -w",
|
|
@@ -40,24 +41,25 @@
|
|
|
40
41
|
"react-dom": ">=16.8.0"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
|
-
"@babel/core": "^7.
|
|
44
|
-
"@babel/preset-env": "^7.
|
|
44
|
+
"@babel/core": "^7.18.10",
|
|
45
|
+
"@babel/preset-env": "^7.18.10",
|
|
45
46
|
"@rollup/plugin-babel": "^5.3.1",
|
|
46
|
-
"@testing-library/react
|
|
47
|
-
"@types/jest": "^
|
|
47
|
+
"@testing-library/react": "^13.3.0",
|
|
48
|
+
"@types/jest": "^28.1.7",
|
|
48
49
|
"babel-plugin-pure-annotations": "^0.1.2",
|
|
49
50
|
"dtslint": "^4.1.6",
|
|
50
|
-
"eslint": "^8.
|
|
51
|
+
"eslint": "^8.22.0",
|
|
51
52
|
"eslint-config-prettier": "^8.5.0",
|
|
52
|
-
"eslint-plugin-jest": "^26.
|
|
53
|
-
"eslint-plugin-react-hooks": "^4.
|
|
54
|
-
"jest": "^
|
|
53
|
+
"eslint-plugin-jest": "^26.8.3",
|
|
54
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
55
|
+
"jest": "^28.1.3",
|
|
56
|
+
"jest-environment-jsdom": "^28.1.3",
|
|
55
57
|
"npm-run-all": "^4.1.5",
|
|
56
|
-
"prettier": "^2.
|
|
57
|
-
"react": "^
|
|
58
|
-
"react-dom": "^
|
|
58
|
+
"prettier": "^2.7.1",
|
|
59
|
+
"react": "^18.2.0",
|
|
60
|
+
"react-dom": "^18.2.0",
|
|
59
61
|
"regenerator-runtime": "^0.13.9",
|
|
60
|
-
"rollup": "^2.
|
|
61
|
-
"typescript": "^4.
|
|
62
|
+
"rollup": "^2.77.2",
|
|
63
|
+
"typescript": "^4.7.4"
|
|
62
64
|
}
|
|
63
65
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type TransitionStatus =
|
|
2
2
|
| 'preEnter'
|
|
3
3
|
| 'entering'
|
|
4
4
|
| 'entered'
|
|
@@ -7,12 +7,12 @@ export type TransitionState =
|
|
|
7
7
|
| 'exited'
|
|
8
8
|
| 'unmounted';
|
|
9
9
|
|
|
10
|
-
export
|
|
11
|
-
|
|
10
|
+
export type TransitionState = Readonly<{
|
|
11
|
+
status: TransitionStatus;
|
|
12
12
|
isMounted: boolean;
|
|
13
13
|
isEnter: boolean;
|
|
14
14
|
isResolved: boolean;
|
|
15
|
-
}
|
|
15
|
+
}>;
|
|
16
16
|
|
|
17
17
|
export interface TransitionOptions {
|
|
18
18
|
initialEntered?: boolean;
|
|
@@ -23,22 +23,22 @@ export interface TransitionOptions {
|
|
|
23
23
|
enter?: boolean;
|
|
24
24
|
exit?: boolean;
|
|
25
25
|
timeout?: number | { enter?: number; exit?: number };
|
|
26
|
-
|
|
26
|
+
onStateChange?: (event: { current: TransitionState }) => void;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export interface TransitionItemOptions {
|
|
30
30
|
initialEntered?: boolean;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export interface TransitionMapOptions<K> extends Omit<TransitionOptions, '
|
|
34
|
-
|
|
35
|
-
onStateChange?: (event: { key: K; current:
|
|
33
|
+
export interface TransitionMapOptions<K> extends Omit<TransitionOptions, 'onStateChange'> {
|
|
34
|
+
allowMultiple?: boolean;
|
|
35
|
+
onStateChange?: (event: { key: K; current: TransitionState }) => void;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export type TransitionResult = [TransitionState, (toEnter?: boolean) => void, () => void];
|
|
39
39
|
|
|
40
40
|
export interface TransitionMapResult<K> {
|
|
41
|
-
stateMap:
|
|
41
|
+
stateMap: ReadonlyMap<K, TransitionState>;
|
|
42
42
|
toggle: (key: K, toEnter?: boolean) => void;
|
|
43
43
|
endTransition: (key: K) => void;
|
|
44
44
|
setItem: (key: K, options?: TransitionItemOptions) => void;
|