UNPKG

7.7 kBJavaScriptView Raw
1import { __assign, __spreadArray, __read, __rest } from './_virtual/_tslib.js';
2import { EMPTY_ACTIVITY_MAP } from './constants.js';
3import { isString, matchesState, warn } from './utils.js';
4import { getMeta, nextEvents } from './stateUtils.js';
5import { initEvent } from './actions.js';
6import { IS_PRODUCTION } from './environment.js';
7
8function stateValuesEqual(a, b) {
9 if (a === b) {
10 return true;
11 }
12
13 if (a === undefined || b === undefined) {
14 return false;
15 }
16
17 if (isString(a) || isString(b)) {
18 return a === b;
19 }
20
21 var aKeys = Object.keys(a);
22 var bKeys = Object.keys(b);
23 return aKeys.length === bKeys.length && aKeys.every(function (key) {
24 return stateValuesEqual(a[key], b[key]);
25 });
26}
27function isStateConfig(state) {
28 if (typeof state !== 'object' || state === null) {
29 return false;
30 }
31
32 return 'value' in state && '_event' in state;
33}
34/**
35 * @deprecated Use `isStateConfig(object)` or `state instanceof State` instead.
36 */
37
38var isState = isStateConfig;
39function bindActionToState(action, state) {
40 var exec = action.exec;
41
42 var boundAction = __assign(__assign({}, action), {
43 exec: exec !== undefined ? function () {
44 return exec(state.context, state.event, {
45 action: action,
46 state: state,
47 _event: state._event
48 });
49 } : undefined
50 });
51
52 return boundAction;
53}
54
55var State =
56/*#__PURE__*/
57
58/** @class */
59function () {
60 /**
61 * Creates a new State instance.
62 * @param value The state value
63 * @param context The extended state
64 * @param historyValue The tree representing historical values of the state nodes
65 * @param history The previous state
66 * @param actions An array of action objects to execute as side-effects
67 * @param activities A mapping of activities and whether they are started (`true`) or stopped (`false`).
68 * @param meta
69 * @param events Internal event queue. Should be empty with run-to-completion semantics.
70 * @param configuration
71 */
72 function State(config) {
73 var _this = this;
74
75 var _a;
76
77 this.actions = [];
78 this.activities = EMPTY_ACTIVITY_MAP;
79 this.meta = {};
80 this.events = [];
81 this.value = config.value;
82 this.context = config.context;
83 this._event = config._event;
84 this._sessionid = config._sessionid;
85 this.event = this._event.data;
86 this.historyValue = config.historyValue;
87 this.history = config.history;
88 this.actions = config.actions || [];
89 this.activities = config.activities || EMPTY_ACTIVITY_MAP;
90 this.meta = getMeta(config.configuration);
91 this.events = config.events || [];
92 this.matches = this.matches.bind(this);
93 this.toStrings = this.toStrings.bind(this);
94 this.configuration = config.configuration;
95 this.transitions = config.transitions;
96 this.children = config.children;
97 this.done = !!config.done;
98 this.tags = (_a = Array.isArray(config.tags) ? new Set(config.tags) : config.tags) !== null && _a !== void 0 ? _a : new Set();
99 this.machine = config.machine;
100 Object.defineProperty(this, 'nextEvents', {
101 get: function () {
102 return nextEvents(_this.configuration);
103 }
104 });
105 }
106 /**
107 * Creates a new State instance for the given `stateValue` and `context`.
108 * @param stateValue
109 * @param context
110 */
111
112
113 State.from = function (stateValue, context) {
114 if (stateValue instanceof State) {
115 if (stateValue.context !== context) {
116 return new State({
117 value: stateValue.value,
118 context: context,
119 _event: stateValue._event,
120 _sessionid: null,
121 historyValue: stateValue.historyValue,
122 history: stateValue.history,
123 actions: [],
124 activities: stateValue.activities,
125 meta: {},
126 events: [],
127 configuration: [],
128 transitions: [],
129 children: {}
130 });
131 }
132
133 return stateValue;
134 }
135
136 var _event = initEvent;
137 return new State({
138 value: stateValue,
139 context: context,
140 _event: _event,
141 _sessionid: null,
142 historyValue: undefined,
143 history: undefined,
144 actions: [],
145 activities: undefined,
146 meta: undefined,
147 events: [],
148 configuration: [],
149 transitions: [],
150 children: {}
151 });
152 };
153 /**
154 * Creates a new State instance for the given `config`.
155 * @param config The state config
156 */
157
158
159 State.create = function (config) {
160 return new State(config);
161 };
162 /**
163 * Creates a new `State` instance for the given `stateValue` and `context` with no actions (side-effects).
164 * @param stateValue
165 * @param context
166 */
167
168
169 State.inert = function (stateValue, context) {
170 if (stateValue instanceof State) {
171 if (!stateValue.actions.length) {
172 return stateValue;
173 }
174
175 var _event = initEvent;
176 return new State({
177 value: stateValue.value,
178 context: context,
179 _event: _event,
180 _sessionid: null,
181 historyValue: stateValue.historyValue,
182 history: stateValue.history,
183 activities: stateValue.activities,
184 configuration: stateValue.configuration,
185 transitions: [],
186 children: {}
187 });
188 }
189
190 return State.from(stateValue, context);
191 };
192 /**
193 * Returns an array of all the string leaf state node paths.
194 * @param stateValue
195 * @param delimiter The character(s) that separate each subpath in the string state node path.
196 */
197
198
199 State.prototype.toStrings = function (stateValue, delimiter) {
200 var _this = this;
201
202 if (stateValue === void 0) {
203 stateValue = this.value;
204 }
205
206 if (delimiter === void 0) {
207 delimiter = '.';
208 }
209
210 if (isString(stateValue)) {
211 return [stateValue];
212 }
213
214 var valueKeys = Object.keys(stateValue);
215 return valueKeys.concat.apply(valueKeys, __spreadArray([], __read(valueKeys.map(function (key) {
216 return _this.toStrings(stateValue[key], delimiter).map(function (s) {
217 return key + delimiter + s;
218 });
219 })), false));
220 };
221
222 State.prototype.toJSON = function () {
223 var _a = this;
224 _a.configuration;
225 _a.transitions;
226 var tags = _a.tags;
227 _a.machine;
228 var jsonValues = __rest(_a, ["configuration", "transitions", "tags", "machine"]);
229
230 return __assign(__assign({}, jsonValues), {
231 tags: Array.from(tags)
232 });
233 };
234
235 State.prototype.matches = function (parentStateValue) {
236 return matchesState(parentStateValue, this.value);
237 };
238 /**
239 * Whether the current state configuration has a state node with the specified `tag`.
240 * @param tag
241 */
242
243
244 State.prototype.hasTag = function (tag) {
245 return this.tags.has(tag);
246 };
247 /**
248 * Determines whether sending the `event` will cause a non-forbidden transition
249 * to be selected, even if the transitions have no actions nor
250 * change the state value.
251 *
252 * @param event The event to test
253 * @returns Whether the event will cause a transition
254 */
255
256
257 State.prototype.can = function (event) {
258 var _a;
259
260 if (IS_PRODUCTION) {
261 warn(!!this.machine, "state.can(...) used outside of a machine-created State object; this will always return false.");
262 }
263
264 var transitionData = (_a = this.machine) === null || _a === void 0 ? void 0 : _a.getTransitionData(this, event);
265 return !!(transitionData === null || transitionData === void 0 ? void 0 : transitionData.transitions.length) && // Check that at least one transition is not forbidden
266 transitionData.transitions.some(function (t) {
267 return t.target !== undefined || t.actions.length;
268 });
269 };
270
271 return State;
272}();
273
274export { State, bindActionToState, isState, isStateConfig, stateValuesEqual };