@tramvai/state 2.70.0 → 2.72.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.
Files changed (67) hide show
  1. package/lib/connect/Provider.es.js +8 -0
  2. package/lib/connect/Provider.js +12 -0
  3. package/lib/connect/Subscription.es.js +37 -0
  4. package/lib/connect/Subscription.js +41 -0
  5. package/lib/connect/connectAdvanced.es.js +159 -0
  6. package/lib/connect/connectAdvanced.js +170 -0
  7. package/lib/connect/context.es.js +6 -0
  8. package/lib/connect/context.js +11 -0
  9. package/lib/connect/hooks/useActions.es.js +17 -0
  10. package/lib/connect/hooks/useActions.js +25 -0
  11. package/lib/connect/hooks/useConsumerContext.es.js +12 -0
  12. package/lib/connect/hooks/useConsumerContext.js +16 -0
  13. package/lib/connect/hooks/useSelector.es.js +53 -0
  14. package/lib/connect/hooks/useSelector.js +63 -0
  15. package/lib/connect/hooks/useStore.es.js +37 -0
  16. package/lib/connect/hooks/useStore.js +41 -0
  17. package/lib/connect/hooks/useStoreSelector.es.js +11 -0
  18. package/lib/connect/hooks/useStoreSelector.js +15 -0
  19. package/lib/connect/index.es.js +91 -0
  20. package/lib/connect/index.js +107 -0
  21. package/lib/connect/scheduling.es.js +12 -0
  22. package/lib/connect/scheduling.js +16 -0
  23. package/lib/connect/selectorFactory.es.js +95 -0
  24. package/lib/connect/selectorFactory.js +101 -0
  25. package/lib/connect/toProps/mapContextToProps.es.js +23 -0
  26. package/lib/connect/toProps/mapContextToProps.js +34 -0
  27. package/lib/connect/toProps/mapStateToProps.es.js +17 -0
  28. package/lib/connect/toProps/mapStateToProps.js +27 -0
  29. package/lib/connect/toProps/mergeProps.es.js +36 -0
  30. package/lib/connect/toProps/mergeProps.js +42 -0
  31. package/lib/connect/toProps/wrapMapToProps.es.js +73 -0
  32. package/lib/connect/toProps/wrapMapToProps.js +85 -0
  33. package/lib/connect/utils/verifyFunction.es.js +10 -0
  34. package/lib/connect/utils/verifyFunction.js +18 -0
  35. package/lib/connect/utils/verifyMapToProps.es.js +20 -0
  36. package/lib/connect/utils/verifyMapToProps.js +28 -0
  37. package/lib/connect/utils/verifyPlainObject.es.js +10 -0
  38. package/lib/connect/utils/verifyPlainObject.js +18 -0
  39. package/lib/createEvent/createEvent.es.js +22 -0
  40. package/lib/createEvent/createEvent.js +31 -0
  41. package/lib/createReducer/createReducer.es.js +60 -0
  42. package/lib/createReducer/createReducer.js +64 -0
  43. package/lib/devTools/constants.es.js +3 -0
  44. package/lib/devTools/constants.js +7 -0
  45. package/lib/{index_middleware.es.js → devTools/devTools.es.js} +2 -36
  46. package/lib/{index_middleware.js → devTools/devTools.js} +4 -40
  47. package/lib/devTools/index.es.js +21 -0
  48. package/lib/devTools/index.js +23 -0
  49. package/lib/devTools/middleware.es.js +37 -0
  50. package/lib/devTools/middleware.js +45 -0
  51. package/lib/dispatcher/childDispatcherContext.es.js +46 -0
  52. package/lib/dispatcher/childDispatcherContext.js +50 -0
  53. package/lib/dispatcher/dispatcher.es.js +105 -0
  54. package/lib/dispatcher/dispatcher.js +110 -0
  55. package/lib/dispatcher/dispatcherContext.es.js +279 -0
  56. package/lib/dispatcher/dispatcherContext.js +288 -0
  57. package/lib/dispatcher/storeSubscribe.es.js +8 -0
  58. package/lib/dispatcher/storeSubscribe.js +12 -0
  59. package/lib/index.es.js +16 -1246
  60. package/lib/index.js +36 -1281
  61. package/lib/logger.es.js +3 -0
  62. package/lib/logger.js +7 -0
  63. package/lib/stores/BaseStore.es.js +53 -0
  64. package/lib/stores/BaseStore.js +61 -0
  65. package/lib/stores/SimpleEmitter.es.js +30 -0
  66. package/lib/stores/SimpleEmitter.js +34 -0
  67. package/package.json +6 -7
package/lib/index.js CHANGED
@@ -2,1290 +2,45 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var compose = require('@tinkoff/utils/function/compose');
6
- var isString = require('@tinkoff/utils/is/string');
7
- var identity = require('@tinkoff/utils/function/identity');
8
- var pick = require('@tinkoff/utils/object/pick');
9
- var shallowEqual = require('@tinkoff/utils/is/shallowEqual');
10
- var strictEqual = require('@tinkoff/utils/is/strictEqual');
11
- var jsxRuntime = require('react/jsx-runtime');
12
- var noop = require('@tinkoff/utils/function/noop');
13
- var hoistStatics = require('hoist-non-react-statics');
14
- var invariant = require('invariant');
15
- var React = require('react');
16
- var reactIs = require('react-is');
17
- var shim = require('use-sync-external-store/shim');
18
- var isArray = require('@tinkoff/utils/is/array');
5
+ var index = require('./devTools/index.js');
6
+ var dispatcher = require('./dispatcher/dispatcher.js');
7
+ var dispatcherContext = require('./dispatcher/dispatcherContext.js');
8
+ var childDispatcherContext = require('./dispatcher/childDispatcherContext.js');
9
+ var createEvent = require('./createEvent/createEvent.js');
10
+ var createReducer = require('./createReducer/createReducer.js');
11
+ var BaseStore = require('./stores/BaseStore.js');
12
+ var index$1 = require('./connect/index.js');
13
+ var Subscription = require('./connect/Subscription.js');
14
+ var Provider = require('./connect/Provider.js');
15
+ var useConsumerContext = require('./connect/hooks/useConsumerContext.js');
16
+ var useActions = require('./connect/hooks/useActions.js');
17
+ var useStore = require('./connect/hooks/useStore.js');
18
+ var useSelector = require('./connect/hooks/useSelector.js');
19
+ var useStoreSelector = require('./connect/hooks/useStoreSelector.js');
19
20
  var reactHooks = require('@tinkoff/react-hooks');
20
- var toArray = require('@tinkoff/utils/array/toArray');
21
- var withSelector = require('use-sync-external-store/shim/with-selector');
22
- var always = require('@tinkoff/utils/function/always');
23
- var mapObject = require('@tinkoff/utils/object/map');
24
- var isPlainObject = require('@tinkoff/utils/is/plainObject');
25
- var isFunction = require('@tinkoff/utils/is/function');
26
21
 
27
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
28
22
 
29
- var compose__default = /*#__PURE__*/_interopDefaultLegacy(compose);
30
- var isString__default = /*#__PURE__*/_interopDefaultLegacy(isString);
31
- var identity__default = /*#__PURE__*/_interopDefaultLegacy(identity);
32
- var pick__default = /*#__PURE__*/_interopDefaultLegacy(pick);
33
- var shallowEqual__default = /*#__PURE__*/_interopDefaultLegacy(shallowEqual);
34
- var strictEqual__default = /*#__PURE__*/_interopDefaultLegacy(strictEqual);
35
- var noop__default = /*#__PURE__*/_interopDefaultLegacy(noop);
36
- var hoistStatics__default = /*#__PURE__*/_interopDefaultLegacy(hoistStatics);
37
- var invariant__default = /*#__PURE__*/_interopDefaultLegacy(invariant);
38
- var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
39
- var isArray__default = /*#__PURE__*/_interopDefaultLegacy(isArray);
40
- var toArray__default = /*#__PURE__*/_interopDefaultLegacy(toArray);
41
- var always__default = /*#__PURE__*/_interopDefaultLegacy(always);
42
- var mapObject__default = /*#__PURE__*/_interopDefaultLegacy(mapObject);
43
- var isPlainObject__default = /*#__PURE__*/_interopDefaultLegacy(isPlainObject);
44
- var isFunction__default = /*#__PURE__*/_interopDefaultLegacy(isFunction);
45
-
46
- /*
47
- ### TODO
48
-
49
- Монорепозиторий экосистемы [redux-devtools](https://github.com/reduxjs/redux-devtools)
50
-
51
- Пример кастомной [интеграции redux-devtools с mobx](https://github.com/zalmoxisus/mobx-remotedev/blob/master/src/monitorActions.js)
52
-
53
- Интегрированный в DevTools функционал:
54
-
55
- 1. Лог экшенов
56
- 2. Состояние стейта
57
- 3. Dispatch
58
- 4. ~~Time Traveling~~
59
- */
60
- // eslint-disable-next-line import/no-mutable-exports
61
- let middleware = () => () => (next) => (event) => next(event);
62
- if (process.env.NODE_ENV !== 'production') {
63
- middleware = require('./index_middleware.js').middleware;
64
- }
65
-
66
- var index = {
67
- __proto__: null,
68
- get middleware () { return middleware; }
69
- };
70
-
71
- const subscribe = (store, handler) => {
72
- // подписываемся на изменения
73
- store.on('change', handler);
74
- // вызываем сразу, чтобы заполнить начальное состояние
75
- handler();
76
- };
77
-
78
- class SimpleEmitter {
79
- constructor() {
80
- this.listeners = [];
81
- }
82
- emit(name) {
83
- this.listeners.forEach((listener) => {
84
- listener();
85
- });
86
- }
87
- addListener(event, fn) {
88
- this.listeners.push(fn);
89
- }
90
- on(event, fn) {
91
- this.addListener(event, fn);
92
- }
93
- removeListener(event, fn) {
94
- const listeners = [];
95
- for (let i = 0; i < this.listeners.length; i++) {
96
- if (this.listeners[i] !== fn) {
97
- listeners.push(this.listeners[i]);
98
- }
99
- }
100
- this.listeners = listeners;
101
- }
102
- off(event, fn) {
103
- this.removeListener(event, fn);
104
- }
105
- }
106
-
107
- const eventExecutor = (event, handlerFns) => {
108
- const keys = Object.keys(handlerFns);
109
- for (let index = 0; index < keys.length; index++) {
110
- const storeName = keys[index];
111
- const handlerFn = handlerFns[storeName];
112
- if (!handlerFn) {
113
- throw new Error(`${storeName} does not have a handler for action ${event.type}`);
114
- }
115
- handlerFn(event.payload, event.type);
116
- }
117
- };
118
- // Конвертация старого типа экшенов в новый
119
- const convertAction = (actionOrNameEvent, payload) => {
120
- if (typeof actionOrNameEvent === 'string') {
121
- return {
122
- payload,
123
- type: actionOrNameEvent,
124
- error: false,
125
- };
126
- }
127
- return actionOrNameEvent;
128
- };
129
- // Это форкнутый вариант dispatchr
130
- class DispatcherContext extends SimpleEmitter {
131
- /**
132
- * @param context The context to be used for store instances
133
- */
134
- constructor(dispatcher, context, initialState, middlewares) {
135
- super();
136
- this.applyDispatch = (event) => {
137
- const eventHandlers = this.dispatcher.handlers[event.type] || [];
138
- if (!eventHandlers.length) {
139
- if (process.env.NODE_ENV === 'development') {
140
- console.warn(`
141
- The event "${event.type}" has been dispatched, but no reducers for this event were registered.
142
- Have you forgot to register reducer or add event handler in existing reducer?
143
- `);
144
- }
145
- return event.payload;
146
- }
147
- this.applyHandlers(event, eventHandlers);
148
- return event.payload;
149
- };
150
- this.dispatcher = dispatcher;
151
- this.storeInstances = {};
152
- this.storeUnsubscribeCallbacks = {};
153
- this.context = context;
154
- this.dispatcherInterface = {
155
- getContext: () => this.context,
156
- getStore: this.getStore.bind(this),
157
- };
158
- this.rehydratedStoreState = {};
159
- this.fullState = {};
160
- // Заполняем стейт данными
161
- if (initialState) {
162
- this.rehydrate(initialState);
163
- }
164
- if (middlewares === null || middlewares === void 0 ? void 0 : middlewares.length) {
165
- this.applyDispatch = this.applyMiddlewares(middlewares);
166
- }
167
- // Инцииализируем уже имеющиеся сторы
168
- Object.keys(this.dispatcher.stores).forEach((store) => {
169
- this.getStore(store);
170
- });
171
- }
172
- applyMiddlewares(middlewares) {
173
- let dispatch = (...args) => {
174
- throw new Error('Dispatching while constructing your middleware is not allowed. Other middleware would not be applied to this dispatch.');
175
- };
176
- const api = {
177
- getState: this.getState.bind(this),
178
- subscribe: this.subscribe.bind(this),
179
- dispatch: (...args) => dispatch(...args),
180
- };
181
- dispatch = compose__default["default"](...middlewares.map((middleware) => middleware(api)))(this.applyDispatch);
182
- return dispatch;
183
- }
184
- storeSubscribe(storeName, storeInstance) {
185
- const subscribeHandler = () => {
186
- const newState = storeInstance.getState();
187
- if (newState !== this.fullState[storeName]) {
188
- this.fullState = {
189
- ...this.fullState,
190
- [storeName]: newState,
191
- };
192
- this.emit('change');
193
- }
194
- };
195
- subscribe(storeInstance, subscribeHandler);
196
- const unsubscribe = () => {
197
- storeInstance.off('change', subscribeHandler);
198
- };
199
- this.storeUnsubscribeCallbacks[storeName] = unsubscribe;
200
- }
201
- // eslint-disable-next-line max-statements
202
- getStore(storeClass) {
203
- let storeClassPrepared;
204
- let optional = false;
205
- if (typeof storeClass === 'object') {
206
- storeClassPrepared = storeClass.store;
207
- optional = storeClass.optional;
208
- }
209
- else {
210
- storeClassPrepared = storeClass;
211
- }
212
- const storeName = this.dispatcher.getStoreName(storeClassPrepared);
213
- if (!this.storeInstances[storeName]) {
214
- let Store = this.dispatcher.stores[storeName];
215
- if (!Store) {
216
- if (typeof storeClassPrepared === 'function') {
217
- this.dispatcher.registerStore(storeClassPrepared);
218
- Store = storeClassPrepared;
219
- }
220
- else {
221
- if (optional) {
222
- return null;
223
- }
224
- throw new Error(`Store ${storeName} was not registered.`);
225
- }
226
- }
227
- const storeInstance = new Store(this.dispatcherInterface);
228
- this.storeInstances[storeName] = storeInstance;
229
- if (this.rehydratedStoreState && this.rehydratedStoreState[storeName]) {
230
- const state = this.rehydratedStoreState[storeName];
231
- if (storeInstance.rehydrate) {
232
- storeInstance.rehydrate(state);
233
- }
234
- this.rehydratedStoreState[storeName] = null;
235
- }
236
- this.storeSubscribe(storeName, storeInstance);
237
- // TODO: убрать после того отпадёт надобность связывать сторы router и application
238
- if (Store.dependencies) {
239
- Store.dependencies.forEach((dependencyStoreClass) => {
240
- const dependency = this.getStore(dependencyStoreClass);
241
- subscribe(dependency, () => {
242
- storeInstance.emit('change');
243
- });
244
- });
245
- }
246
- }
247
- return this.storeInstances[storeName];
248
- }
249
- /**
250
- * Dispatches a new action or throws if one is already in progress
251
- * @param eventOrType Name of the event to be dispatched
252
- * @param payload Parameters to describe the action
253
- * @throws {Error} if store has handler registered that does not exist
254
- */
255
- dispatch(eventOrType, payload) {
256
- if (!eventOrType) {
257
- throw new Error(`eventOrType parameter ${eventOrType} is invalid.`);
258
- }
259
- // конвертим старый тип экшенов
260
- const event = convertAction(eventOrType, payload);
261
- return this.applyDispatch(event);
262
- }
263
- applyHandlers(action, handlers) {
264
- const handlerFns = {};
265
- const storeInstanceGet = (store) => {
266
- if (handlerFns[store.name]) {
267
- // Don't call the default if the store has an explicit action handler
268
- return;
269
- }
270
- const storeInstance = this.getStore(store.name);
271
- if (!storeInstance) {
272
- return;
273
- }
274
- if (typeof store.handler === 'function') {
275
- handlerFns[store.name] = store.handler.bind(storeInstance);
276
- }
277
- else {
278
- if (process.env.NODE_ENV !== 'production') {
279
- if (!storeInstance[store.handler]) {
280
- throw new Error(`${store.name} does not have a method called ${store.handler}`);
281
- }
282
- }
283
- handlerFns[store.name] = storeInstance[store.handler].bind(storeInstance);
284
- }
285
- };
286
- const handlersLength = handlers.length;
287
- for (let index = 0; index < handlersLength; index++) {
288
- storeInstanceGet(handlers[index]);
289
- }
290
- return eventExecutor(action, handlerFns);
291
- }
292
- /**
293
- * Returns a raw data object representation of the current state of the
294
- * dispatcher and all store instances. If the store implements a shouldDehdyrate
295
- * function, then it will be called and only dehydrate if the method returns `true`
296
- * @method dehydrate
297
- * @returns dehydrated dispatcher data
298
- */
299
- dehydrate() {
300
- const stores = {};
301
- const keys = Object.keys(this.storeInstances);
302
- for (let i = 0; i < keys.length; i++) {
303
- const storeName = keys[i];
304
- const store = this.storeInstances[storeName];
305
- if (!store.dehydrate()) {
306
- continue;
307
- }
308
- stores[storeName] = store.dehydrate();
309
- }
310
- return {
311
- stores,
312
- };
313
- }
314
- /**
315
- * Takes a raw data object and rehydrates the dispatcher and store instances
316
- * @method rehydrate
317
- * @param dispatcherState raw state typically retrieved from `dehydrate` method
318
- */
319
- rehydrate(dispatcherState) {
320
- if (dispatcherState.stores) {
321
- const keys = Object.keys(dispatcherState.stores);
322
- for (let index = 0; index < keys.length; index++) {
323
- const storeName = keys[index];
324
- this.rehydratedStoreState[storeName] = dispatcherState.stores[storeName];
325
- }
326
- }
327
- }
328
- subscribe(...args) {
329
- if ('storeName' in args[0]) {
330
- const reducer = args[0];
331
- const callback = args[1];
332
- const reducerInstance = this.getStore(reducer);
333
- const listener = () => {
334
- const state = this.getState(reducer);
335
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
336
- callback(state);
337
- };
338
- reducerInstance.on('change', listener);
339
- return () => {
340
- reducerInstance.off('change', listener);
341
- };
342
- }
343
- const callback = args[0];
344
- const listener = () => {
345
- const state = this.getState();
346
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
347
- callback(state);
348
- };
349
- this.on('change', listener);
350
- return () => {
351
- this.off('change', listener);
352
- };
353
- }
354
- getState(reducer) {
355
- if (reducer) {
356
- return this.fullState[reducer.storeName];
357
- }
358
- return this.fullState;
359
- }
360
- // Для отложенной инициализации контекста, в будующем нужно удалить
361
- setContext(context) {
362
- this.context = context;
363
- }
364
- hasStore(store) {
365
- return store.storeName in this.storeInstances && this.dispatcher.hasStore(store);
366
- }
367
- registerStore(store) {
368
- this.dispatcher.registerStore(store);
369
- this.getStore(store);
370
- }
371
- unregisterStore(store) {
372
- const { storeName } = store;
373
- this.dispatcher.unregisterStore(store);
374
- this.storeUnsubscribeCallbacks[storeName]();
375
- delete this.storeUnsubscribeCallbacks[storeName];
376
- delete this.rehydratedStoreState[storeName];
377
- delete this.storeInstances[storeName];
378
- }
379
- }
380
-
381
- class Dispatcher {
382
- /**
383
- * @class Dispatcher
384
- * @param options Dispatcher options
385
- * @param options.stores Array of stores to register
386
- * @constructor
387
- */
388
- constructor(options) {
389
- // eslint-disable-next-line no-param-reassign
390
- options = options || {};
391
- // eslint-disable-next-line no-param-reassign
392
- options.stores = options.stores || [];
393
- this.stores = {};
394
- this.handlers = {};
395
- options.stores.forEach((store) => {
396
- this.registerStore(store);
397
- });
398
- }
399
- createContext(context, initialState, middlewares) {
400
- return new DispatcherContext(this, context, initialState, middlewares);
401
- }
402
- hasStore(store) {
403
- return !!this.stores[store.storeName];
404
- }
405
- /**
406
- * Registers a store so that it can handle actions.ß
407
- * @param store A store class to be registered. The store should have a static
408
- * `storeName` property so that it can be loaded later.
409
- * @throws {Error} if store is invalid
410
- * @throws {Error} if store is already registered
411
- */
412
- registerStore(store) {
413
- const { storeName } = store;
414
- if (this.stores[storeName]) {
415
- if (this.stores[storeName] === store) {
416
- // Store is already registered, nothing to do
417
- return;
418
- }
419
- if (process.env.NODE_ENV !== 'production') {
420
- throw new Error(`Store with name '${storeName}' has already been registered.
421
- Make sure you do not have multiple copies of the store installed.
422
- exist ${this.stores[storeName]}
423
- try ${store}`);
424
- }
425
- }
426
- this.stores[storeName] = store;
427
- if (store.handlers) {
428
- Object.keys(store.handlers).forEach((action) => {
429
- const handler = store.handlers[action];
430
- this.registerHandler(action, storeName, handler);
431
- });
432
- }
433
- }
434
- unregisterStore(store) {
435
- const { storeName } = store;
436
- if (!this.stores[storeName]) {
437
- return;
438
- }
439
- delete this.stores[storeName];
440
- if (store.handlers) {
441
- Object.keys(store.handlers).forEach((action) => {
442
- const handler = store.handlers[action];
443
- this.unregisterHandler(action, storeName, handler);
444
- });
445
- }
446
- }
447
- /**
448
- * Gets a name from a store
449
- * @param {String|Object} store The store name or class from which to extract
450
- */
451
- // eslint-disable-next-line class-methods-use-this
452
- getStoreName(store) {
453
- if (typeof store === 'string') {
454
- return store;
455
- }
456
- return store.storeName;
457
- }
458
- /**
459
- * Adds a handler function to be called for the given action
460
- * @param action Name of the action
461
- * @param name Name of the store that handles the action
462
- * @param handler The function or name of the method that handles the action
463
- */
464
- registerHandler(action, name, handler) {
465
- this.handlers[action] = this.handlers[action] || [];
466
- this.handlers[action].push({
467
- name,
468
- handler,
469
- });
470
- }
471
- unregisterHandler(action, name, handler) {
472
- if (Array.isArray(this.handlers[action])) {
473
- this.handlers[action] = this.handlers[action].filter((actionHandlers) => {
474
- return !(actionHandlers.name === name && actionHandlers.handler === handler);
475
- });
476
- }
477
- }
478
- }
479
- function createDispatcher(options) {
480
- return new Dispatcher(options);
481
- }
482
-
483
- class ChildDispatcherContext extends DispatcherContext {
484
- /**
485
- * @param context The context to be used for store instances
486
- */
487
- constructor({ dispatcher, context, initialState, parentDispatcherContext, middlewares, parentAllowedStores, }) {
488
- super(dispatcher, context, initialState, middlewares);
489
- this.allowedParentStores = new Set();
490
- this.parentDispatcherContext = parentDispatcherContext;
491
- parentAllowedStores === null || parentAllowedStores === void 0 ? void 0 : parentAllowedStores.forEach((store) => {
492
- const storeName = this.dispatcher.getStoreName(typeof store === 'object' ? store.store : store);
493
- this.allowedParentStores.add(storeName);
494
- // use just storeName to prevent store initialization on the root-app side
495
- this.getStore({ store: storeName, optional: true });
496
- });
497
- }
498
- getStore(storeClass) {
499
- let storeClassPrepared;
500
- if (typeof storeClass === 'object') {
501
- storeClassPrepared = storeClass.store;
502
- }
503
- else {
504
- storeClassPrepared = storeClass;
505
- }
506
- const storeName = this.dispatcher.getStoreName(storeClassPrepared);
507
- if (this.dispatcher.stores[storeName]) {
508
- return super.getStore(storeClass);
509
- }
510
- if (this.allowedParentStores.has(storeName)) {
511
- // use just storeName to prevent store initialization on the root-app side
512
- const storeInstance = this.parentDispatcherContext.getStore({
513
- store: storeName,
514
- optional: true,
515
- });
516
- if (!storeInstance) {
517
- return null;
518
- }
519
- this.storeSubscribe(storeName, storeInstance);
520
- return storeInstance;
521
- }
522
- return super.getStore(storeClass);
523
- }
524
- }
525
-
526
- function createEvent(eventName, payloadCreator = identity__default["default"]) {
527
- if (process.env.NODE_ENV !== 'production') {
528
- if (!isString__default["default"](eventName) || !eventName.length) {
529
- throw new Error(`eventName should be not empty string, got '${eventName}'`);
530
- }
531
- }
532
- const type = eventName;
533
- const eventCreator = (...args) => {
534
- return {
535
- type,
536
- payload: payloadCreator(...args),
537
- };
538
- };
539
- eventCreator.getType = () => type;
540
- eventCreator.toString = () => type;
541
- return eventCreator;
542
- }
543
-
544
- function createReducer(name, initialState) {
545
- var _a;
546
- const reducers = {};
547
- return _a = class ReducerStore extends SimpleEmitter {
548
- constructor() {
549
- super();
550
- this.state = initialState;
551
- }
552
- static createEvents(model) {
553
- const eventNames = Object.keys(model);
554
- const events = {};
555
- eventNames.forEach((eventName) => {
556
- const handler = model[eventName];
557
- const eventCreator = createEvent(`${eventName}`);
558
- events[eventName] = eventCreator;
559
- ReducerStore.on(eventCreator, handler);
560
- });
561
- return events;
562
- }
563
- static on(eventOrType, reducer) {
564
- if (Array.isArray(eventOrType)) {
565
- eventOrType.forEach((event) => ReducerStore.on(event, reducer));
566
- return ReducerStore;
567
- }
568
- const type = eventOrType.toString();
569
- ReducerStore.handlers[type] = 'handle';
570
- reducers[type] = reducer;
571
- return ReducerStore;
572
- }
573
- getState() {
574
- return this.state;
575
- }
576
- setState(state) {
577
- this.state = state;
578
- // обновление необходимо, иначе state-manager не пересчитает состояние
579
- this.emit('change');
580
- }
581
- dehydrate() {
582
- return this.state;
583
- }
584
- rehydrate(state) {
585
- this.state = state;
586
- }
587
- handle(payload, eventName) {
588
- const reducer = reducers[eventName];
589
- if (reducer) {
590
- this.state = reducer(this.state, payload);
591
- this.emit('change');
592
- }
593
- }
594
- },
595
- _a.storeName = name,
596
- _a.handlers = {},
597
- _a;
598
- }
599
-
600
- /**
601
- * @deprecated метод устарел, в замен этого API используй createReducer, который новее и лучше маштабируется
602
- */
603
- class BaseStore extends SimpleEmitter {
604
- constructor() {
605
- super(...arguments);
606
- this.state = Object.create(null);
607
- this.hydrateKeys = Object.create(null);
608
- }
609
- getState() {
610
- return this.state;
611
- }
612
- dehydrate() {
613
- return pick__default["default"](Object.keys(this.hydrateKeys), this.state);
614
- }
615
- rehydrate(state) {
616
- this.setStateSilently(state);
617
- }
618
- writeHydrateKeys(state) {
619
- Object.keys(state).forEach((key) => {
620
- this.hydrateKeys[key] = true;
621
- });
622
- }
623
- // eslint-disable-next-line class-methods-use-this
624
- shouldStateUpdate(nextState) {
625
- return !!Object.keys(nextState).length;
626
- }
627
- setState(state, force = false) {
628
- if (force || this.shouldStateUpdate(state)) {
629
- this.setStateSilently(state);
630
- this.emit('change');
631
- }
632
- }
633
- setStateSilently(state) {
634
- this.state = { ...this.state, ...state };
635
- this.writeHydrateKeys(state);
636
- }
637
- replaceState(state) {
638
- this.replaceStateSilently(state);
639
- this.emit('change');
640
- }
641
- // @deprecated нужно использовать replaceState
642
- replaceStateSilently(state) {
643
- this.state = state;
644
- this.hydrateKeys = Object.create(null);
645
- this.writeHydrateKeys(state);
646
- }
647
- }
648
-
649
- // encapsulates the subscription logic for connecting a component to the redux store, as
650
- // well as nesting subscriptions of descendant components, so that we can ensure the
651
- // ancestor components re-render before descendants
652
- class Subscription {
653
- constructor(stores) {
654
- this.handleStateChange = () => {
655
- this.onStateChange && this.onStateChange();
656
- };
657
- this.stores = stores;
658
- this.unsubscribe = undefined;
659
- }
660
- isSubscribed() {
661
- return Boolean(this.unsubscribe);
662
- }
663
- setOnStateChange(onStateChange) {
664
- this.onStateChange = onStateChange;
665
- }
666
- trySubscribe() {
667
- if (!this.unsubscribe) {
668
- this.unsubscribe = this.stores.filter(Boolean).map((store) => {
669
- store.on('change', this.handleStateChange);
670
- return () => {
671
- store.removeListener('change', this.handleStateChange);
672
- };
673
- });
674
- }
675
- }
676
- tryUnsubscribe() {
677
- if (this.unsubscribe) {
678
- this.unsubscribe.forEach((f) => f());
679
- this.unsubscribe = undefined;
680
- }
681
- this.onStateChange = undefined;
682
- }
683
- }
684
-
685
- const ConnectContext = /* #__PURE__*/ React.createContext(null);
686
- const ServerStateContext = /* #__PURE__*/ React.createContext(null);
687
-
688
- const useConsumerContext = () => {
689
- const context = React.useContext(ConnectContext);
690
- if (!context) {
691
- throw new Error('CONSUMER_CONTEXT not found, have you added "@tramvai/module-common"?');
692
- }
693
- return context;
694
- };
695
-
696
- function useActions(actions) {
697
- const context = useConsumerContext();
698
- const actionsRef = reactHooks.useShallowEqual(actions);
699
- return React.useMemo(() => {
700
- if (isArray__default["default"](actionsRef)) {
701
- return actionsRef.map((action) => context.executeAction.bind(context, action));
702
- }
703
- return context.executeAction.bind(context, actionsRef);
704
- }, [actionsRef, context]);
705
- }
706
-
707
- function useStore(reducer) {
708
- const context = useConsumerContext();
709
- const serverState = React.useContext(ServerStateContext);
710
- const reducerRef = React.useRef(reducer);
711
- const addedReducerRef = React.useRef(null);
712
- // если текущий редьюсер не зарегистрирован в диспетчере,
713
- // регистрируем его вручную, что бы гарантировать работоспособность `context.getState(reducer)`,
714
- // и сохраняем в `addedReducerRef`, что бы удалить при unmount
715
- if (!context.hasStore(reducer)) {
716
- context.registerStore(reducer);
717
- addedReducerRef.current = reducer.storeName;
718
- }
719
- const subscribe = React.useCallback((reactUpdate) => {
720
- const unsubscribe = context.subscribe(reducer, reactUpdate);
721
- // заменяем текущий редьюсер
722
- reducerRef.current = reducer;
723
- return () => {
724
- // гарантируем отписку от обновлений текущего редьюсера,
725
- // при анмаунте компонента
726
- unsubscribe();
727
- // если текущий редьюсер был зарегистрирован в диспетчере в этом хуке,
728
- // удаляем его из диспетчера
729
- if (addedReducerRef.current) {
730
- context.unregisterStore(reducerRef.current);
731
- addedReducerRef.current = null;
732
- }
733
- };
734
- }, [reducer, context]);
735
- return shim.useSyncExternalStore(subscribe, () => context.getState(reducer), serverState ? () => serverState[reducer.storeName] : () => context.getState(reducer));
736
- }
737
-
738
- const contextExecution = typeof window !== 'undefined' ? window : global;
739
- function scheduling() {
740
- if ('requestAnimationFrame' in contextExecution) {
741
- return requestAnimationFrame;
742
- }
743
- if ('setImmediate' in contextExecution) {
744
- return contextExecution.setImmediate;
745
- }
746
- return setTimeout;
747
- }
748
-
749
- const schedule = /* #__PURE__*/ scheduling();
750
- function useSelector(storesOrStore, selector, equalityFn = shallowEqual__default["default"]) {
751
- invariant__default["default"](selector, `You must pass a selector to useSelectors`);
752
- const context = useConsumerContext();
753
- const serverState = React.useContext(ServerStateContext);
754
- const renderIsScheduled = React.useRef(false);
755
- const storesRef = reactHooks.useShallowEqual(storesOrStore);
756
- const subscription = React.useMemo(() => new Subscription(toArray__default["default"](storesRef).map(context.getStore)), [storesRef, context]);
757
- const latestSubscriptionCallbackError = React.useRef();
758
- const subscribe = React.useCallback((reactUpdate) => {
759
- subscription.setOnStateChange(() => {
760
- if (!renderIsScheduled.current) {
761
- renderIsScheduled.current = true;
762
- schedule(() => {
763
- reactUpdate();
764
- renderIsScheduled.current = false;
765
- });
766
- }
767
- });
768
- subscription.trySubscribe();
769
- return () => {
770
- return subscription.tryUnsubscribe();
771
- };
772
- }, [subscription]);
773
- let selectedState;
774
- try {
775
- selectedState = withSelector.useSyncExternalStoreWithSelector(subscribe, context.getState, serverState ? () => serverState : context.getState, selector, equalityFn);
776
- }
777
- catch (err) {
778
- let errorMessage = `An error occured while selecting the store state: ${err.message}.`;
779
- if (latestSubscriptionCallbackError.current) {
780
- errorMessage += `\nThe error may be correlated with this previous error:\n${latestSubscriptionCallbackError.current.stack}\n\nOriginal stack trace:`;
781
- }
782
- throw new Error(errorMessage);
783
- }
784
- reactHooks.useIsomorphicLayoutEffect(() => {
785
- latestSubscriptionCallbackError.current = undefined;
786
- });
787
- return selectedState;
788
- }
789
-
790
- const useStoreSelector = (store, selector) => {
791
- const memoizedSelector = React.useCallback((stores) => {
792
- return selector(stores[store.storeName]);
793
- }, [store, selector]);
794
- return useSelector(store, memoizedSelector);
795
- };
796
-
797
- const stringifyComponent = (Comp) => {
798
- try {
799
- return JSON.stringify(Comp);
800
- }
801
- catch (err) {
802
- return String(Comp);
803
- }
804
- };
805
- /**
806
- * @deprecated
807
- */
808
- function connectAdvanced(
809
- /*
810
- selectorFactory is a func that is responsible for returning the selector function used to
811
- compute new props from state, props, and dispatch. For example:
812
- export default connectAdvanced((dispatch, options) => (state, props) => ({
813
- thing: state.things[props.thingId],
814
- saveThing: fields => dispatch(actionCreators.saveThing(props.thingId, fields)),
815
- }))(YourComponent)
816
- Access to dispatch is provided to the factory so selectorFactories can bind actionCreators
817
- outside of their selector as an optimization. Options passed to connectAdvanced are passed to
818
- the selectorFactory, along with displayName and WrappedComponent, as the second argument.
819
- Note that selectorFactory is responsible for all caching/memoization of inbound and outbound
820
- props. Do not use connectAdvanced directly without memoizing results between calls to your
821
- selector, otherwise the Connect component will re-render on every state or props change.
822
- */
823
- selectorFactory,
824
- // options object:
825
- {
826
- // the func used to compute this HOC's displayName from the wrapped component's displayName.
827
- // probably overridden by wrapper functions such as connect()
828
- getDisplayName = (name) => `ConnectAdvanced(${name})`,
829
- // shown in error messages
830
- // probably overridden by wrapper functions such as connect()
831
- methodName = 'connectAdvanced',
832
- // stores to connect to
833
- stores = [],
834
- // determines whether this HOC subscribes to store changes
835
- shouldHandleStateChanges = true,
836
- // use React's forwardRef to expose a ref of the wrapped component
837
- forwardRef = false,
838
- // function used to schedule updates
839
- schedule = (fn) => fn(),
840
- // is component and all toProps functions are pure, so they can be memoized
841
- pure = true,
842
- // additional options are passed through to the selectorFactory
843
- ...connectOptions } = {}) {
844
- return function wrapWithConnect(WrappedComponent) {
845
- if (process.env.NODE_ENV !== 'production') {
846
- invariant__default["default"](reactIs.isValidElementType(WrappedComponent), `You must pass a component to the function returned by ` +
847
- `${methodName}. Instead received ${stringifyComponent(WrappedComponent)}`);
848
- }
849
- const wrappedComponentName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
850
- const displayName = getDisplayName(wrappedComponentName);
851
- const selectorFactoryOptions = {
852
- ...connectOptions,
853
- pure,
854
- getDisplayName,
855
- methodName,
856
- shouldHandleStateChanges,
857
- displayName,
858
- wrappedComponentName,
859
- WrappedComponent,
860
- };
861
- const ConnectFunction = (props) => {
862
- const [forwardedRef, wrapperProps] = React.useMemo(() => {
863
- // Distinguish between actual "data" props that were passed to the wrapper component,
864
- // and values needed to control behavior (forwarded refs, alternate context instances).
865
- // To maintain the wrapperProps object reference, memoize this destructuring.
866
- // eslint-disable-next-line no-shadow
867
- const { forwardedRef, ...wrapperProps } = props;
868
- return [forwardedRef, wrapperProps];
869
- }, [props]);
870
- // Retrieve the store and ancestor subscription via context, if available
871
- const contextValue = useConsumerContext();
872
- const serverState = React.useContext(ServerStateContext);
873
- invariant__default["default"](Boolean(contextValue), `Could not find context in ` +
874
- `"${displayName}". Either wrap the root component in a <Provider>, ` +
875
- `or pass a custom React context provider to <Provider> and the corresponding ` +
876
- `React context consumer to ${displayName} in connect options.`);
877
- const childPropsSelector = React.useMemo(() => {
878
- // The child props selector needs the store reference as an input.
879
- // Re-create this selector whenever the store changes.
880
- return selectorFactory(contextValue, selectorFactoryOptions);
881
- }, [contextValue]);
882
- const subscription = React.useMemo(() => {
883
- if (!shouldHandleStateChanges)
884
- return null;
885
- return new Subscription(stores.map((store) => contextValue.getStore(store)));
886
- }, [contextValue]);
887
- React.useMemo(() => {
888
- if (subscription && typeof window !== 'undefined') {
889
- subscription.trySubscribe();
890
- }
891
- }, [subscription]);
892
- const renderIsScheduled = React.useRef(false);
893
- const actualChildPropsSelector = React.useCallback(() => {
894
- return childPropsSelector(contextValue.getState(), wrapperProps);
895
- }, [contextValue, wrapperProps, childPropsSelector]);
896
- // Our re-subscribe logic only runs when the store/subscription setup changes
897
- const subscribe = React.useCallback((reactUpdate) => {
898
- if (!subscription) {
899
- return noop__default["default"];
900
- }
901
- subscription.setOnStateChange(() => {
902
- if (!renderIsScheduled.current) {
903
- renderIsScheduled.current = true;
904
- schedule(() => {
905
- reactUpdate();
906
- renderIsScheduled.current = false;
907
- });
908
- }
909
- });
910
- return () => {
911
- return subscription.tryUnsubscribe();
912
- };
913
- }, [subscription]);
914
- const actualChildProps = shim.useSyncExternalStore(subscribe, actualChildPropsSelector, serverState ? () => childPropsSelector(serverState, wrapperProps) : actualChildPropsSelector);
915
- // Now that all that's done, we can finally try to actually render the child component.
916
- // We memoize the elements for the rendered child component as an optimization.
917
- const renderedWrappedComponent = React.useMemo(
918
- // eslint-disable-next-line react/jsx-props-no-spreading
919
- () => jsxRuntime.jsx(WrappedComponent, { ...actualChildProps, ref: forwardedRef }), [forwardedRef, actualChildProps]);
920
- return renderedWrappedComponent;
921
- };
922
- // If we're in "pure" mode, ensure our wrapper component only re-renders when incoming props have changed.
923
- const Connect = pure ? React__default["default"].memo(ConnectFunction) : ConnectFunction;
924
- Connect.WrappedComponent = WrappedComponent;
925
- Connect.displayName = displayName;
926
- if (forwardRef) {
927
- const forwarded = React__default["default"].forwardRef(function forwardConnectRef(props, ref) {
928
- // eslint-disable-next-line react/jsx-props-no-spreading
929
- return jsxRuntime.jsx(Connect, { ...props, forwardedRef: ref });
930
- });
931
- forwarded.displayName = displayName;
932
- forwarded.WrappedComponent = WrappedComponent;
933
- return hoistStatics__default["default"](forwarded, WrappedComponent);
934
- }
935
- return hoistStatics__default["default"](Connect, WrappedComponent);
936
- };
937
- }
938
-
939
- const getLogger = () => console;
940
-
941
- function verifyPlainObject(value, displayName, methodName) {
942
- if (!isPlainObject__default["default"](value)) {
943
- getLogger().debug(`${methodName}() in ${displayName} must return a plain object. Instead received ${value}.`);
944
- }
945
- }
946
-
947
- function verifyFunction(value, displayName, methodName) {
948
- if (!isFunction__default["default"](value)) {
949
- getLogger().debug(`${methodName}() in ${displayName} must be a function. Instead received ${JSON.stringify(value)}.`);
950
- }
951
- }
952
-
953
- function wrapMapToPropsConstant(getConstant) {
954
- return function initConstantSelector(context, options) {
955
- const constantSelector = always__default["default"](getConstant(context, options));
956
- constantSelector.dependsOnOwnProps = false;
957
- return constantSelector;
958
- };
959
- }
960
- // dependsOnOwnProps is used by createMapToPropsProxy to determine whether to pass props as args
961
- // to the mapToProps function being wrapped. It is also used by makePurePropsSelector to determine
962
- // whether mapToProps needs to be invoked when props have changed.
963
- //
964
- // A length of one signals that mapToProps does not depend on props from the parent component.
965
- // A length of zero is assumed to mean mapToProps is getting args via arguments or ...args and
966
- // therefore not reporting its length accurately..
967
- function getDependsOnOwnProps(mapToProps) {
968
- return mapToProps.dependsOnOwnProps !== null && mapToProps.dependsOnOwnProps !== undefined
969
- ? Boolean(mapToProps.dependsOnOwnProps)
970
- : mapToProps.length !== 1;
971
- }
972
- // Used by whenMapStateToPropsIsFunction and whenMapDispatchToPropsIsFunction,
973
- // this function wraps mapToProps in a proxy function which does several things:
974
- //
975
- // * Detects whether the mapToProps function being called depends on props, which
976
- // is used by selectorFactory to decide if it should reinvoke on props changes.
977
- //
978
- // * On first call, handles mapToProps if returns another function, and treats that
979
- // new function as the true mapToProps for subsequent calls.
980
- //
981
- // * On first call, verifies the first result is a plain object, in order to warn
982
- // the developer that their mapToProps function is not returning a valid result.
983
- //
984
- function wrapMapToPropsFunc(mapToProps, methodName) {
985
- return function initProxySelector(context, { displayName }) {
986
- const proxy = (stateOrContext, ownProps) => proxy.dependsOnOwnProps
987
- ? proxy.mapToProps(stateOrContext, ownProps)
988
- : proxy.mapToProps(stateOrContext, undefined);
989
- // allow detectFactoryAndVerify to get ownProps
990
- proxy.dependsOnOwnProps = true;
991
- proxy.mapToProps = function detectFactoryAndVerify(stateOrContext, ownProps) {
992
- proxy.mapToProps = mapToProps;
993
- proxy.dependsOnOwnProps = getDependsOnOwnProps(mapToProps);
994
- let props = proxy(stateOrContext, ownProps);
995
- if (typeof props === 'function') {
996
- proxy.mapToProps = props;
997
- proxy.dependsOnOwnProps = getDependsOnOwnProps(props);
998
- props = proxy(stateOrContext, ownProps);
999
- }
1000
- if (process.env.NODE_ENV !== 'production') {
1001
- verifyPlainObject(props, displayName, methodName);
1002
- }
1003
- return props;
1004
- };
1005
- return proxy;
1006
- };
1007
- }
1008
- function wrapMapToPropsObject(actionsObject) {
1009
- function getConstant({ executeAction }, { displayName }) {
1010
- return mapObject__default["default"]((action, actionName) => {
1011
- if (process.env.NODE_ENV !== 'production') {
1012
- verifyFunction(action, displayName, actionName);
1013
- }
1014
- return (params) => executeAction(action, params);
1015
- }, actionsObject);
1016
- }
1017
- return wrapMapToPropsConstant(getConstant);
1018
- }
1019
-
1020
- function whenMapContextToPropsIsFunction(mapContextToProps) {
1021
- return typeof mapContextToProps === 'function'
1022
- ? wrapMapToPropsFunc(mapContextToProps, 'mapContextToProps')
1023
- : undefined;
1024
- }
1025
- function whenMapContextToPropsIsMissing(mapContextToProps) {
1026
- return !mapContextToProps ? wrapMapToPropsConstant(always__default["default"]({})) : undefined;
1027
- }
1028
- function whenMapContextToPropsIsObject(mapContextToProps) {
1029
- return typeof mapContextToProps === 'object' && mapContextToProps !== null
1030
- ? wrapMapToPropsObject(mapContextToProps)
1031
- : undefined;
1032
- }
1033
- const mapContextToPropsFactories = [
1034
- whenMapContextToPropsIsObject,
1035
- whenMapContextToPropsIsFunction,
1036
- whenMapContextToPropsIsMissing,
1037
- ];
1038
-
1039
- function whenMapStateToPropsIsFunction(mapStateToProps) {
1040
- return typeof mapStateToProps === 'function'
1041
- ? wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps')
1042
- : undefined;
1043
- }
1044
- function whenMapStateToPropsIsMissing(mapStateToProps) {
1045
- return !mapStateToProps ? wrapMapToPropsConstant(always__default["default"]({})) : undefined;
1046
- }
1047
- const mapStateToPropsFactories = [
1048
- whenMapStateToPropsIsFunction,
1049
- whenMapStateToPropsIsMissing,
1050
- ];
1051
-
1052
- const defaultMergeProps = (stateProps, contextProps, ownProps) => {
1053
- return { ...ownProps, ...stateProps, ...contextProps };
1054
- };
1055
- function wrapMergePropsFunc(mergeProps) {
1056
- return function initMergePropsProxy(context, { displayName, pure, areMergedPropsEqual }) {
1057
- let hasRunOnce = false;
1058
- let mergedProps;
1059
- return function mergePropsProxy(stateProps, contextProps, ownProps) {
1060
- const nextMergedProps = mergeProps(stateProps, contextProps, ownProps);
1061
- if (hasRunOnce) {
1062
- if (!pure || !areMergedPropsEqual(nextMergedProps, mergedProps)) {
1063
- mergedProps = nextMergedProps;
1064
- }
1065
- }
1066
- else {
1067
- hasRunOnce = true;
1068
- mergedProps = nextMergedProps;
1069
- if (process.env.NODE_ENV !== 'production') {
1070
- verifyPlainObject(mergedProps, displayName, 'mergeProps');
1071
- }
1072
- }
1073
- return mergedProps;
1074
- };
1075
- };
1076
- }
1077
- function whenMergePropsIsFunction(mergeProps) {
1078
- return typeof mergeProps === 'function' ? wrapMergePropsFunc(mergeProps) : undefined;
1079
- }
1080
- function whenMergePropsIsOmitted(mergeProps) {
1081
- return !mergeProps ? () => defaultMergeProps : undefined;
1082
- }
1083
- const mergePropsFactories = [whenMergePropsIsFunction, whenMergePropsIsOmitted];
1084
-
1085
- const verifyMapToProps = (mapStateToProps, name) => {
1086
- function verify(state, props) {
1087
- const firstStateProps = mapStateToProps(state, props);
1088
- const secondStateProps = mapStateToProps(state, props);
1089
- if (!shallowEqual__default["default"](firstStateProps, secondStateProps)) {
1090
- getLogger().warn('Component "%s" recreate equal props %s', name, Object.keys(firstStateProps)
1091
- .filter((key) => firstStateProps[key] !== secondStateProps[key])
1092
- .map((key) => `"${key}"`)
1093
- .join(', '));
1094
- }
1095
- verify.dependsOnOwnProps = mapStateToProps.dependsOnOwnProps;
1096
- return secondStateProps;
1097
- }
1098
- return verify;
1099
- };
1100
-
1101
- function impureFinalPropsSelectorFactory(mapStateToProps, mapContextToProps, mergeProps, context) {
1102
- return function impureFinalPropsSelector(state, ownProps) {
1103
- return mergeProps(mapStateToProps(state, ownProps), mapContextToProps(context, ownProps), ownProps);
1104
- };
1105
- }
1106
- // eslint-disable-next-line max-params
1107
- function pureFinalPropsSelectorFactory(mapStateToProps, mapContextToProps, mergeProps, context, { areStatesEqual, areOwnPropsEqual, areStatePropsEqual, WrappedComponent: { defaultProps } }) {
1108
- let hasRunAtLeastOnce = false;
1109
- let state;
1110
- let ownProps;
1111
- let ownPropsWithDefault;
1112
- let stateProps;
1113
- let contextProps;
1114
- let mergedProps;
1115
- function handleFirstCall(firstState, firstOwnProps) {
1116
- state = firstState;
1117
- ownProps = firstOwnProps;
1118
- ownPropsWithDefault = { ...defaultProps, ...firstOwnProps }; // TODO проверить зачем мержить пропсы с defaultProps, взято из старого connect, иначе падают некоторые тесты
1119
- stateProps = mapStateToProps(state, ownPropsWithDefault);
1120
- contextProps = mapContextToProps(context, ownPropsWithDefault);
1121
- mergedProps = mergeProps(stateProps, contextProps, ownProps);
1122
- hasRunAtLeastOnce = true;
1123
- return mergedProps;
1124
- }
1125
- function handleNewPropsAndNewState() {
1126
- stateProps = mapStateToProps(state, ownPropsWithDefault);
1127
- if (mapContextToProps.dependsOnOwnProps) {
1128
- contextProps = mapContextToProps(context, ownPropsWithDefault);
1129
- }
1130
- mergedProps = mergeProps(stateProps, contextProps, ownProps);
1131
- return mergedProps;
1132
- }
1133
- function handleNewProps() {
1134
- if (mapStateToProps.dependsOnOwnProps) {
1135
- stateProps = mapStateToProps(state, ownPropsWithDefault);
1136
- }
1137
- if (mapContextToProps.dependsOnOwnProps) {
1138
- contextProps = mapContextToProps(context, ownPropsWithDefault);
1139
- }
1140
- mergedProps = mergeProps(stateProps, contextProps, ownProps);
1141
- return mergedProps;
1142
- }
1143
- function handleNewState() {
1144
- const nextStateProps = mapStateToProps(state, ownPropsWithDefault);
1145
- const statePropsChanged = !areStatePropsEqual(nextStateProps, stateProps);
1146
- stateProps = nextStateProps;
1147
- if (statePropsChanged) {
1148
- mergedProps = mergeProps(stateProps, contextProps, ownProps);
1149
- }
1150
- return mergedProps;
1151
- }
1152
- function handleSubsequentCalls(nextState, nextOwnProps) {
1153
- const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps);
1154
- const stateChanged = !areStatesEqual(nextState, state);
1155
- state = nextState;
1156
- ownProps = nextOwnProps;
1157
- ownPropsWithDefault = { ...defaultProps, ...nextOwnProps };
1158
- if (propsChanged && stateChanged) {
1159
- return handleNewPropsAndNewState();
1160
- }
1161
- if (propsChanged) {
1162
- return handleNewProps();
1163
- }
1164
- if (stateChanged) {
1165
- return handleNewState();
1166
- }
1167
- return mergedProps;
1168
- }
1169
- return function pureFinalPropsSelector(nextState, nextOwnProps) {
1170
- return hasRunAtLeastOnce
1171
- ? handleSubsequentCalls(nextState, nextOwnProps)
1172
- : handleFirstCall(nextState, nextOwnProps);
1173
- };
1174
- }
1175
- // TODO: Add more comments
1176
- // If pure is true, the selector returned by selectorFactory will memoize its results,
1177
- // allowing connectAdvanced's shouldComponentUpdate to return false if final
1178
- // props have not changed. If false, the selector will always return a new
1179
- // object and shouldComponentUpdate will always return true.
1180
- function finalPropsSelectorFactory(context, { initMapStateToProps, initMapContextToProps, initMergeProps, ...options }) {
1181
- let mapStateToProps = initMapStateToProps(context, options);
1182
- const mapContextToProps = initMapContextToProps(context, options);
1183
- const mergeProps = initMergeProps(context, options);
1184
- if (process.env.NODE_ENV !== 'production') {
1185
- mapStateToProps = verifyMapToProps(mapStateToProps, options.WrappedComponent.name);
1186
- }
1187
- const selectorFactory = options.pure
1188
- ? pureFinalPropsSelectorFactory
1189
- : impureFinalPropsSelectorFactory;
1190
- return selectorFactory(mapStateToProps, mapContextToProps, mergeProps, context, options);
1191
- }
1192
-
1193
- const Provider = ({ context, children, serverState, }) => {
1194
- return (jsxRuntime.jsx(ConnectContext.Provider, { value: context, children: jsxRuntime.jsx(ServerStateContext.Provider, { value: serverState, children: children }) }));
1195
- };
1196
-
1197
- /*
1198
- connect is a facade over connectAdvanced. It turns its args into a compatible
1199
- selectorFactory, which has the signature:
1200
- (dispatch, options) => (nextState, nextOwnProps) => nextFinalProps
1201
-
1202
- connect passes its args to connectAdvanced as options, which will in turn pass them to
1203
- selectorFactory each time a Connect component instance is instantiated or hot reloaded.
1204
- selectorFactory returns a final props selector from its mapStateToProps,
1205
- mapStateToPropsFactories, mapContextToProps, mapContextToPropsFactories, mergeProps,
1206
- mergePropsFactories, and pure args.
1207
- The resulting final props selector is called by the Connect component instance whenever
1208
- it receives new props or store state.
1209
- */
1210
- function match(arg, factories, name) {
1211
- for (let i = factories.length - 1; i >= 0; i--) {
1212
- const result = factories[i](arg);
1213
- if (result) {
1214
- return result;
1215
- }
1216
- }
1217
- return (context, options) => {
1218
- throw new Error(`Invalid value of type ${typeof arg} for ${name} argument when connecting component ${options.wrappedComponentName}.`);
1219
- };
1220
- }
1221
- // createConnect with default args builds the 'official' connect behavior. Calling it with
1222
- // different options opens up some testing and extensibility scenarios
1223
- /**
1224
- * @deprecated
1225
- */
1226
- function createConnect({ connectHOC = connectAdvanced, mapStateToPropsFactories: mapStateToPropsFactories$1 = mapStateToPropsFactories, mapContextToPropsFactories: mapContextToPropsFactories$1 = mapContextToPropsFactories, mergePropsFactories: mergePropsFactories$1 = mergePropsFactories, selectorFactory = finalPropsSelectorFactory, schedule = scheduling(), } = {}) {
1227
- return (stores, mapStateToProps, mapContextToProps, mergeProps, { pure = true, areStatesEqual = strictEqual__default["default"], areOwnPropsEqual = shallowEqual__default["default"], areStatePropsEqual = shallowEqual__default["default"], areMergedPropsEqual = shallowEqual__default["default"], ...extraOptions } = {}
1228
- // eslint-disable-next-line max-params
1229
- ) => {
1230
- // @ts-ignore
1231
- const initMapStateToProps = match(mapStateToProps, mapStateToPropsFactories$1, 'mapStateToProps');
1232
- // @ts-ignore
1233
- const initMapContextToProps = match(mapContextToProps,
1234
- // @ts-ignore
1235
- mapContextToPropsFactories$1, 'mapContextToProps');
1236
- // @ts-ignore
1237
- const initMergeProps = match(mergeProps, mergePropsFactories$1, 'mergeProps');
1238
- return connectHOC(selectorFactory, {
1239
- // @ts-ignore
1240
- stores,
1241
- // passed through to selectorFactory 2
1242
- // @ts-ignore
1243
- initMapStateToProps,
1244
- initMapContextToProps,
1245
- initMergeProps,
1246
- pure,
1247
- areStatesEqual,
1248
- areOwnPropsEqual,
1249
- areStatePropsEqual,
1250
- areMergedPropsEqual,
1251
- schedule,
1252
- // used in error messages
1253
- methodName: 'connect',
1254
- // used to compute Connect's displayName from the wrapped component's displayName.
1255
- getDisplayName: (name) => `Connect(${name})`,
1256
- // if mapStateToProps is falsy, the Connect component doesn't subscribe to store state changes
1257
- shouldHandleStateChanges: stores && stores.length > 0,
1258
- // any extra options args can override defaults of connect or connectAdvanced
1259
- ...extraOptions,
1260
- });
1261
- };
1262
- }
1263
- /**
1264
- * @deprecated
1265
- */
1266
- const connect = /* @__PURE__ */ createConnect();
1267
- const { Consumer } = ConnectContext;
1268
23
 
24
+ exports.devTools = index;
25
+ exports.Dispatcher = dispatcher.Dispatcher;
26
+ exports.createDispatcher = dispatcher.createDispatcher;
27
+ exports.DispatcherContext = dispatcherContext.DispatcherContext;
28
+ exports.convertAction = dispatcherContext.convertAction;
29
+ exports.ChildDispatcherContext = childDispatcherContext.ChildDispatcherContext;
30
+ exports.createEvent = createEvent.createEvent;
31
+ exports.createReducer = createReducer.createReducer;
32
+ exports.BaseStore = BaseStore.BaseStore;
33
+ exports.Consumer = index$1.Consumer;
34
+ exports.connect = index$1["default"];
35
+ exports.createConnect = index$1.createConnect;
36
+ exports.Subscription = Subscription.Subscription;
37
+ exports.Provider = Provider.Provider;
38
+ exports.useConsumerContext = useConsumerContext.useConsumerContext;
39
+ exports.useActions = useActions.useActions;
40
+ exports.useStore = useStore.useStore;
41
+ exports.useSelector = useSelector.useSelector;
42
+ exports.useStoreSelector = useStoreSelector.useStoreSelector;
1269
43
  Object.defineProperty(exports, 'useIsomorphicLayoutEffect', {
1270
- enumerable: true,
1271
- get: function () { return reactHooks.useIsomorphicLayoutEffect; }
44
+ enumerable: true,
45
+ get: function () { return reactHooks.useIsomorphicLayoutEffect; }
1272
46
  });
1273
- exports.BaseStore = BaseStore;
1274
- exports.ChildDispatcherContext = ChildDispatcherContext;
1275
- exports.Consumer = Consumer;
1276
- exports.Dispatcher = Dispatcher;
1277
- exports.DispatcherContext = DispatcherContext;
1278
- exports.Provider = Provider;
1279
- exports.Subscription = Subscription;
1280
- exports.connect = connect;
1281
- exports.convertAction = convertAction;
1282
- exports.createConnect = createConnect;
1283
- exports.createDispatcher = createDispatcher;
1284
- exports.createEvent = createEvent;
1285
- exports.createReducer = createReducer;
1286
- exports.devTools = index;
1287
- exports.useActions = useActions;
1288
- exports.useConsumerContext = useConsumerContext;
1289
- exports.useSelector = useSelector;
1290
- exports.useStore = useStore;
1291
- exports.useStoreSelector = useStoreSelector;