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 CHANGED
@@ -1,9 +1,6 @@
1
1
  # React-Transition-State
2
2
 
3
- [![NPM](https://img.shields.io/npm/v/react-transition-state.svg)](https://www.npmjs.com/package/react-transition-state)
4
- [![NPM](https://img.shields.io/npm/dm/react-transition-state)](https://www.npmjs.com/package/react-transition-state)
5
- [![NPM](https://img.shields.io/bundlephobia/minzip/react-transition-state)](https://bundlephobia.com/package/react-transition-state)
6
- [![Known Vulnerabilities](https://snyk.io/test/github/szhsin/react-transition-state/badge.svg)](https://snyk.io/test/github/szhsin/react-transition-state)
3
+ [![NPM](https://img.shields.io/npm/v/react-transition-state.svg)](https://www.npmjs.com/package/react-transition-state) [![NPM](https://img.shields.io/npm/dm/react-transition-state)](https://www.npmjs.com/package/react-transition-state) [![NPM](https://img.shields.io/bundlephobia/minzip/react-transition-state)](https://bundlephobia.com/package/react-transition-state) [![Known Vulnerabilities](https://snyk.io/test/github/szhsin/react-transition-state/badge.svg)](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: [~0.7KB](https://bundlephobia.com/package/react-transition-state) and no dependencies, ideal for both component libraries and applications.
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
- ![state-diagram](https://user-images.githubusercontent.com/41896553/142855447-cb8d8730-f8fb-4296-a3db-d1523b0fa2d9.png)
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
+ ![state-diagram](https://user-images.githubusercontent.com/41896553/142855447-cb8d8730-f8fb-4296-a3db-d1523b0fa2d9.png) 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
- ${({ state }) =>
92
- (state === 'preEnter' || state === 'exiting') &&
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 [state, toggle] = useTransition({
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
- {showButton && <button onClick={() => toggle(true)}>Show Message</button>}
111
- {!showButton && (
112
- <Box state={state}>
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
- | | React Transition Group | This library |
151
- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
152
- | 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 |
153
- | 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. |
154
- | 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` |
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) | _Pure_ – rendering based on [transition state](https://codesandbox.io/s/react-transition-state-vs-group-p45iy?file=/src/App.js:2140-2325) |
156
- | 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_ |
157
- | Bundle size | [![NPM](https://img.shields.io/bundlephobia/minzip/react-transition-group)](https://bundlephobia.com/package/react-transition-group) | ✅ [![NPM](https://img.shields.io/bundlephobia/minzip/react-transition-state)](https://bundlephobia.com/package/react-transition-state) |
158
- | Dependency count | [![NPM](https://badgen.net/bundlephobia/dependency-count/react-transition-group)](https://www.npmjs.com/package/react-transition-group?activeTab=dependencies) | ✅ [![NPM](https://badgen.net/bundlephobia/dependency-count/react-transition-state)](https://www.npmjs.com/package/react-transition-state?activeTab=dependencies) |
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 | [![NPM](https://img.shields.io/bundlephobia/minzip/react-transition-group)](https://bundlephobia.com/package/react-transition-group) | ✅ [![NPM](https://img.shields.io/bundlephobia/minzip/react-transition-state)](https://bundlephobia.com/package/react-transition-state) |
153
+ | Dependency count | [![NPM](https://badgen.net/bundlephobia/dependency-count/react-transition-group)](https://www.npmjs.com/package/react-transition-group?activeTab=dependencies) | ✅ [![NPM](https://badgen.net/bundlephobia/dependency-count/react-transition-state)](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 | Type | Default | Description |
177
- | ---------------- | -------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
178
- | `enter` | boolean | true | Enable or disable enter phase transitions |
179
- | `exit` | boolean | true | Enable or disable exit phase transitions |
180
- | `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). |
181
- | `preExit` | boolean | | Add a 'preExit' state immediately before 'exiting' |
182
- | `initialEntered` | boolean | | Beginning from 'entered' state |
183
- | `mountOnEnter` | boolean | | State will be 'unmounted' until hit enter phase for the first time. It allows you to create lazily mounted component. |
184
- | `unmountOnExit` | boolean | | State will become 'unmounted' after 'exiting' finishes. It allows you to transition component out of DOM. |
185
- | `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. |
186
- | `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._ |
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 an array of values in the following order:
185
+ The `useTransition` Hook returns a tuple of values in the following order:
191
186
 
192
- 1. state: 'preEnter' | 'entering' | 'entered' | 'preExit' | 'exiting' | 'exited' | 'unmounted'
193
- 2. toggle: (toEnter?: boolean) => void
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 STATES = ['preEnter', 'entering', 'entered', 'preExit', 'exiting', 'exited', 'unmounted'];
15
- var getFullState = function getFullState(_state) {
14
+ var STATUS = ['preEnter', 'entering', 'entered', 'preExit', 'exiting', 'exited', 'unmounted'];
15
+ var getState = function getState(_status) {
16
16
  return {
17
- _state: _state,
18
- state: STATES[_state],
19
- isEnter: _state < PRE_EXIT,
20
- isMounted: _state !== UNMOUNTED,
21
- isResolved: _state === ENTERED || _state > EXITING
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 getEndState = function getEndState(state, unmountOnExit) {
28
- switch (state) {
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(state, setState, latestState, timeoutId, onChange) {
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
- state: STATES[state]
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.onChange;
64
+ onChange = _ref.onStateChange;
64
65
 
65
- var _useState = react.useState(initialEntered ? ENTERED : startOrEnd(mountOnEnter)),
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 newState = getEndState(latestState.current, unmountOnExit);
78
- newState && updateState$1(newState, setState, latestState, timeoutId, onChange);
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(newState) {
82
- updateState$1(newState, setState, latestState, timeoutId, onChange);
84
+ var transitState = function transitState(status) {
85
+ updateState$1(status, setState, latestState, timeoutId, onChange);
83
86
 
84
- switch (newState) {
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(newState + 1);
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 [STATES[state], toggle, endTransition];
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
- _state = _ref.newState,
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 = getFullState(_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
- singleEnter = _ref2.singleEnter,
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 newState = _initialEntered ? ENTERED : startOrEnd(mountOnEnter);
175
+ var status = _initialEntered ? ENTERED : startOrEnd(mountOnEnter);
173
176
  updateState({
174
177
  key: key,
175
- newState: newState,
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 newState = getEndState(stateObj._state, unmountOnExit);
205
- newState && updateState({
207
+ var status = getEndStatus(stateObj._status, unmountOnExit);
208
+ status && updateState({
206
209
  key: key,
207
- newState: newState,
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(newState) {
227
+ var transitState = function transitState(status) {
225
228
  updateState({
226
229
  key: key,
227
- newState: newState,
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 (newState) {
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(newState + 1);
253
+ return transitState(status + 1);
251
254
  }, 0);
252
255
  break;
253
256
  }
254
257
  };
255
258
 
256
- var enterStage = stateObj._state <= ENTERED;
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
- singleEnter && latestStateMap.current.forEach(function (_, _key) {
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, singleEnter, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
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, getEndState, PRE_EXIT, EXITING, STATES, PRE_ENTER, ENTERING } from './utils.js';
2
+ import { getState, ENTERED, startOrEnd, getTimeout, getEndStatus, PRE_EXIT, EXITING, PRE_ENTER, ENTERING } from './utils.js';
3
3
 
4
- var updateState = function updateState(state, setState, latestState, timeoutId, onChange) {
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
- state: STATES[state]
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.onChange;
26
+ onChange = _ref.onStateChange;
26
27
 
27
- var _useState = useState(initialEntered ? ENTERED : startOrEnd(mountOnEnter)),
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 newState = getEndState(latestState.current, unmountOnExit);
40
- newState && updateState(newState, setState, latestState, timeoutId, onChange);
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(newState) {
44
- updateState(newState, setState, latestState, timeoutId, onChange);
46
+ var transitState = function transitState(status) {
47
+ updateState(status, setState, latestState, timeoutId, onChange);
45
48
 
46
- switch (newState) {
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(newState + 1);
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 [STATES[state], toggle, endTransition];
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, getEndState, PRE_EXIT, EXITING, PRE_ENTER, ENTERING, getFullState } from './utils.js';
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
- _state = _ref.newState,
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 = getFullState(_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
- singleEnter = _ref2.singleEnter,
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 newState = _initialEntered ? ENTERED : startOrEnd(mountOnEnter);
57
+ var status = _initialEntered ? ENTERED : startOrEnd(mountOnEnter);
58
58
  updateState({
59
59
  key: key,
60
- newState: newState,
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 newState = getEndState(stateObj._state, unmountOnExit);
90
- newState && updateState({
89
+ var status = getEndStatus(stateObj._status, unmountOnExit);
90
+ status && updateState({
91
91
  key: key,
92
- newState: newState,
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(newState) {
109
+ var transitState = function transitState(status) {
110
110
  updateState({
111
111
  key: key,
112
- newState: newState,
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 (newState) {
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(newState + 1);
135
+ return transitState(status + 1);
136
136
  }, 0);
137
137
  break;
138
138
  }
139
139
  };
140
140
 
141
- var enterStage = stateObj._state <= ENTERED;
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
- singleEnter && latestStateMap.current.forEach(function (_, _key) {
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, singleEnter, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
156
+ }, [onChange, endTransition, allowMultiple, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
157
157
  return {
158
158
  stateMap: stateMap,
159
159
  toggle: toggle,
@@ -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 STATES = ['preEnter', 'entering', 'entered', 'preExit', 'exiting', 'exited', 'unmounted'];
9
- var getFullState = function getFullState(_state) {
8
+ var STATUS = ['preEnter', 'entering', 'entered', 'preExit', 'exiting', 'exited', 'unmounted'];
9
+ var getState = function getState(_status) {
10
10
  return {
11
- _state: _state,
12
- state: STATES[_state],
13
- isEnter: _state < PRE_EXIT,
14
- isMounted: _state !== UNMOUNTED,
15
- isResolved: _state === ENTERED || _state > EXITING
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 getEndState = function getEndState(state, unmountOnExit) {
22
- switch (state) {
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, STATES, UNMOUNTED, getEndState, getFullState, getTimeout, startOrEnd };
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": "1.2.0-alpha.5",
4
- "description": "Zero dependency, 0.7KB react-transition-group alternative.",
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.17.9",
44
- "@babel/preset-env": "^7.16.11",
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-hooks": "^7.0.2",
47
- "@types/jest": "^27.4.1",
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.12.0",
51
+ "eslint": "^8.22.0",
51
52
  "eslint-config-prettier": "^8.5.0",
52
- "eslint-plugin-jest": "^26.1.3",
53
- "eslint-plugin-react-hooks": "^4.4.0",
54
- "jest": "^27.5.1",
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.6.2",
57
- "react": "^17.0.2",
58
- "react-dom": "^17.0.2",
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.70.1",
61
- "typescript": "^4.6.3"
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 TransitionState =
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 interface State {
11
- state: TransitionState;
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
- onChange?: (event: { state: TransitionState }) => void;
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, 'onChange'> {
34
- singleEnter?: boolean;
35
- onStateChange?: (event: { key: K; current: State }) => void;
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: Omit<Map<K, State>, 'clear' | 'delete' | 'set'>;
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;