@veams/status-quo 1.5.0 → 1.6.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 (126) hide show
  1. package/.turbo/turbo-build.log +12 -0
  2. package/.turbo/turbo-check$colon$types.log +4 -0
  3. package/.turbo/turbo-docs$colon$build.log +14 -0
  4. package/.turbo/turbo-lint.log +8 -0
  5. package/.turbo/turbo-test.log +15 -0
  6. package/CHANGELOG.md +24 -3
  7. package/README.md +217 -41
  8. package/dist/config/status-quo-config.d.ts +13 -0
  9. package/dist/config/status-quo-config.js +14 -0
  10. package/dist/config/status-quo-config.js.map +1 -1
  11. package/dist/hooks/__tests__/state-provider.spec.d.ts +4 -0
  12. package/dist/hooks/__tests__/state-provider.spec.js +179 -0
  13. package/dist/hooks/__tests__/state-provider.spec.js.map +1 -0
  14. package/dist/hooks/__tests__/state-selector.spec.js +11 -12
  15. package/dist/hooks/__tests__/state-selector.spec.js.map +1 -1
  16. package/dist/hooks/__tests__/state-singleton.spec.js +10 -11
  17. package/dist/hooks/__tests__/state-singleton.spec.js.map +1 -1
  18. package/dist/hooks/index.d.ts +1 -0
  19. package/dist/hooks/index.js +1 -0
  20. package/dist/hooks/index.js.map +1 -1
  21. package/dist/hooks/state-factory.js.map +1 -1
  22. package/dist/hooks/state-provider.d.ts +14 -0
  23. package/dist/hooks/state-provider.js +24 -0
  24. package/dist/hooks/state-provider.js.map +1 -0
  25. package/dist/hooks/state-subscription-selector.js +6 -2
  26. package/dist/hooks/state-subscription-selector.js.map +1 -1
  27. package/dist/hooks/state-subscription.js +1 -1
  28. package/dist/hooks/state-subscription.js.map +1 -1
  29. package/dist/index.d.ts +4 -5
  30. package/dist/index.js +2 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/react/hooks/__tests__/state-provider.spec.d.ts +4 -0
  33. package/dist/react/hooks/__tests__/state-provider.spec.js +179 -0
  34. package/dist/react/hooks/__tests__/state-provider.spec.js.map +1 -0
  35. package/dist/react/hooks/__tests__/state-selector.spec.d.ts +4 -0
  36. package/dist/react/hooks/__tests__/state-selector.spec.js +499 -0
  37. package/dist/react/hooks/__tests__/state-selector.spec.js.map +1 -0
  38. package/dist/react/hooks/__tests__/state-singleton.spec.d.ts +4 -0
  39. package/dist/react/hooks/__tests__/state-singleton.spec.js +96 -0
  40. package/dist/react/hooks/__tests__/state-singleton.spec.js.map +1 -0
  41. package/{src/hooks/index.ts → dist/react/hooks/index.d.ts} +1 -0
  42. package/dist/react/hooks/index.js +7 -0
  43. package/dist/react/hooks/index.js.map +1 -0
  44. package/dist/react/hooks/state-actions.d.ts +2 -0
  45. package/dist/react/hooks/state-actions.js +5 -0
  46. package/dist/react/hooks/state-actions.js.map +1 -0
  47. package/dist/react/hooks/state-factory.d.ts +7 -0
  48. package/dist/react/hooks/state-factory.js +13 -0
  49. package/dist/react/hooks/state-factory.js.map +1 -0
  50. package/dist/react/hooks/state-handler.d.ts +2 -0
  51. package/dist/react/hooks/state-handler.js +9 -0
  52. package/dist/react/hooks/state-handler.js.map +1 -0
  53. package/dist/react/hooks/state-provider.d.ts +14 -0
  54. package/dist/react/hooks/state-provider.js +24 -0
  55. package/dist/react/hooks/state-provider.js.map +1 -0
  56. package/dist/react/hooks/state-singleton.d.ts +6 -0
  57. package/dist/react/hooks/state-singleton.js +7 -0
  58. package/dist/react/hooks/state-singleton.js.map +1 -0
  59. package/dist/react/hooks/state-subscription-selector.d.ts +3 -0
  60. package/dist/react/hooks/state-subscription-selector.js +63 -0
  61. package/dist/react/hooks/state-subscription-selector.js.map +1 -0
  62. package/dist/react/hooks/state-subscription.d.ts +9 -0
  63. package/dist/react/hooks/state-subscription.js +53 -0
  64. package/dist/react/hooks/state-subscription.js.map +1 -0
  65. package/dist/react/index.d.ts +1 -0
  66. package/dist/react/index.js +2 -0
  67. package/dist/react/index.js.map +1 -0
  68. package/dist/store/__tests__/observable-state-handler.spec.js +66 -11
  69. package/dist/store/__tests__/observable-state-handler.spec.js.map +1 -1
  70. package/dist/store/__tests__/signal-state-handler.spec.js.map +1 -1
  71. package/dist/store/base-state-handler.d.ts +4 -6
  72. package/dist/store/base-state-handler.js +10 -9
  73. package/dist/store/base-state-handler.js.map +1 -1
  74. package/dist/store/dev-tools.js +0 -3
  75. package/dist/store/dev-tools.js.map +1 -1
  76. package/dist/store/observable-state-handler.d.ts +4 -10
  77. package/dist/store/observable-state-handler.js +4 -11
  78. package/dist/store/observable-state-handler.js.map +1 -1
  79. package/dist/store/signal-state-handler.d.ts +2 -5
  80. package/dist/store/signal-state-handler.js +3 -2
  81. package/dist/store/signal-state-handler.js.map +1 -1
  82. package/dist/store/state-singleton.js +1 -1
  83. package/dist/store/state-singleton.js.map +1 -1
  84. package/eslint.config.mjs +75 -0
  85. package/package.json +18 -18
  86. package/src/config/status-quo-config.ts +31 -1
  87. package/src/index.ts +11 -15
  88. package/src/react/hooks/__tests__/state-provider.spec.tsx +286 -0
  89. package/src/{hooks → react/hooks}/__tests__/state-selector.spec.tsx +52 -44
  90. package/src/{hooks → react/hooks}/__tests__/state-singleton.spec.tsx +21 -20
  91. package/src/react/hooks/index.ts +11 -0
  92. package/src/{hooks → react/hooks}/state-actions.tsx +1 -1
  93. package/src/{hooks → react/hooks}/state-factory.tsx +2 -2
  94. package/src/{hooks → react/hooks}/state-handler.tsx +1 -1
  95. package/src/react/hooks/state-provider.tsx +56 -0
  96. package/src/{hooks → react/hooks}/state-singleton.tsx +1 -1
  97. package/src/{hooks → react/hooks}/state-subscription-selector.tsx +15 -6
  98. package/src/{hooks → react/hooks}/state-subscription.tsx +5 -9
  99. package/src/react/index.ts +1 -0
  100. package/src/store/__tests__/observable-state-handler.spec.ts +92 -13
  101. package/src/store/__tests__/signal-state-handler.spec.ts +5 -1
  102. package/src/store/base-state-handler.ts +17 -24
  103. package/src/store/dev-tools.ts +3 -3
  104. package/src/store/observable-state-handler.ts +12 -22
  105. package/src/store/signal-state-handler.ts +11 -8
  106. package/src/store/state-singleton.ts +1 -1
  107. package/tsconfig.json +2 -3
  108. package/.eslintrc.cjs +0 -132
  109. package/.github/workflows/pages.yml +0 -46
  110. package/.github/workflows/release.yml +0 -33
  111. package/.nvmrc +0 -1
  112. package/.prettierrc +0 -7
  113. package/docs/assets/index-BBmpszOW.css +0 -1
  114. package/docs/assets/index-Cf8El_RO.js +0 -194
  115. package/docs/assets/statusquo-logo-8GVRbxpc.png +0 -0
  116. package/docs/index.html +0 -13
  117. package/playground/index.html +0 -12
  118. package/playground/src/App.tsx +0 -699
  119. package/playground/src/assets/philosophy-agnostic.svg +0 -18
  120. package/playground/src/assets/philosophy-separation.svg +0 -13
  121. package/playground/src/assets/philosophy-swap.svg +0 -17
  122. package/playground/src/assets/statusquo-logo.png +0 -0
  123. package/playground/src/main.tsx +0 -19
  124. package/playground/src/styles.css +0 -534
  125. package/playground/tsconfig.json +0 -12
  126. package/playground/vite.config.ts +0 -18
@@ -0,0 +1,499 @@
1
+ import React, { act } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { makeStateSingleton } from '../../../store/state-singleton.js';
4
+ import { useStateActions } from '../state-actions.js';
5
+ import { useStateFactory } from '../state-factory.js';
6
+ import { useStateHandler } from '../state-handler.js';
7
+ import { useStateSingleton } from '../state-singleton.js';
8
+ import { useStateSubscription } from '../state-subscription.js';
9
+ class TestStateHandler {
10
+ initialState;
11
+ state;
12
+ listeners = new Set();
13
+ destroy = jest.fn();
14
+ constructor(initialState) {
15
+ this.initialState = initialState;
16
+ this.state = initialState;
17
+ }
18
+ subscribe(listener) {
19
+ const typedListener = listener;
20
+ this.listeners.add(typedListener);
21
+ return () => {
22
+ this.listeners.delete(typedListener);
23
+ };
24
+ }
25
+ getSnapshot = () => {
26
+ return this.state;
27
+ };
28
+ getInitialState = () => {
29
+ return this.initialState;
30
+ };
31
+ getActions = () => {
32
+ return {
33
+ setName: (name) => {
34
+ this.state = {
35
+ ...this.state,
36
+ user: {
37
+ ...this.state.user,
38
+ name,
39
+ },
40
+ };
41
+ this.emitStateChange();
42
+ },
43
+ increment: () => {
44
+ this.state = {
45
+ ...this.state,
46
+ counter: this.state.counter + 1,
47
+ };
48
+ this.emitStateChange();
49
+ },
50
+ };
51
+ };
52
+ emitStateChange() {
53
+ const nextState = this.state;
54
+ this.listeners.forEach((listener) => listener(nextState));
55
+ }
56
+ }
57
+ class CounterStateHandler {
58
+ initialState;
59
+ state;
60
+ listeners = new Set();
61
+ destroy = jest.fn();
62
+ constructor(initialCount = 0) {
63
+ this.initialState = { count: initialCount };
64
+ this.state = this.initialState;
65
+ }
66
+ subscribe(listener) {
67
+ const typedListener = listener;
68
+ this.listeners.add(typedListener);
69
+ return () => {
70
+ this.listeners.delete(typedListener);
71
+ };
72
+ }
73
+ getSnapshot = () => {
74
+ return this.state;
75
+ };
76
+ getInitialState = () => {
77
+ return this.initialState;
78
+ };
79
+ getActions = () => {
80
+ return {
81
+ increment: () => {
82
+ this.state = {
83
+ count: this.state.count + 1,
84
+ };
85
+ const nextState = this.state;
86
+ this.listeners.forEach((listener) => listener(nextState));
87
+ },
88
+ };
89
+ };
90
+ }
91
+ class CounterMirrorStateHandler {
92
+ initialState;
93
+ state;
94
+ listeners = new Set();
95
+ unsubscribeFromCounter;
96
+ destroy = jest.fn(() => {
97
+ this.unsubscribeFromCounter();
98
+ this.listeners.clear();
99
+ });
100
+ constructor(counterSingleton) {
101
+ const counterStateHandler = counterSingleton.getInstance();
102
+ const initialCounterState = counterStateHandler.getSnapshot();
103
+ this.initialState = {
104
+ mirroredCount: initialCounterState.count,
105
+ };
106
+ this.state = this.initialState;
107
+ this.unsubscribeFromCounter = counterStateHandler.subscribe((nextCounterState) => {
108
+ this.state = {
109
+ mirroredCount: nextCounterState.count,
110
+ };
111
+ const nextMirrorState = this.state;
112
+ this.listeners.forEach((listener) => listener(nextMirrorState));
113
+ });
114
+ }
115
+ subscribe(listener) {
116
+ const typedListener = listener;
117
+ this.listeners.add(typedListener);
118
+ return () => {
119
+ this.listeners.delete(typedListener);
120
+ };
121
+ }
122
+ getSnapshot = () => {
123
+ return this.state;
124
+ };
125
+ getInitialState = () => {
126
+ return this.initialState;
127
+ };
128
+ getActions = () => {
129
+ return {
130
+ noop: () => undefined,
131
+ };
132
+ };
133
+ }
134
+ const ComposedHooksConsumer = ({ createStateHandler, onStateRender, onActionsReady, }) => {
135
+ const stateHandler = useStateHandler(createStateHandler, []);
136
+ const actions = useStateActions(stateHandler);
137
+ const [userName] = useStateSubscription(stateHandler, (state) => state.user.name);
138
+ onActionsReady(actions);
139
+ onStateRender(userName);
140
+ return React.createElement("span", null, userName);
141
+ };
142
+ const ActionsOnlyConsumer = ({ createStateHandler, onRender, onActionsReady, }) => {
143
+ const stateHandler = useStateHandler(createStateHandler, []);
144
+ const actions = useStateActions(stateHandler);
145
+ onRender();
146
+ onActionsReady(actions);
147
+ return React.createElement("span", null, "actions-only");
148
+ };
149
+ const FactoryShortcutConsumer = ({ createStateHandler, onRender, }) => {
150
+ const [userName] = useStateFactory(createStateHandler, (state) => state.user.name, Object.is, []);
151
+ onRender(userName);
152
+ return React.createElement("span", null, userName);
153
+ };
154
+ const FactoryShortcutWithoutEqualityConsumer = ({ createStateHandler, onRender, }) => {
155
+ const [userName] = useStateFactory(createStateHandler, (state) => state.user.name, []);
156
+ onRender(userName);
157
+ return React.createElement("span", null, userName);
158
+ };
159
+ const SingletonShortcutConsumer = ({ singleton, onRender }) => {
160
+ const [userName] = useStateSingleton(singleton, (state) => state.user.name);
161
+ onRender(userName);
162
+ return React.createElement("span", null, userName);
163
+ };
164
+ const SingletonSubscriptionConsumer = ({ singleton, onRender, onActionsReady, }) => {
165
+ const [name, actions] = useStateSubscription(singleton, (state) => state.user.name);
166
+ onRender(name);
167
+ onActionsReady(actions);
168
+ return React.createElement("span", null, name);
169
+ };
170
+ const FullSubscriptionConsumer = ({ createStateHandler, onRender, onActionsReady, }) => {
171
+ const stateHandler = useStateHandler(createStateHandler, []);
172
+ const [state, actions] = useStateSubscription(stateHandler);
173
+ onRender(state);
174
+ onActionsReady(actions);
175
+ return React.createElement("span", null, state.user.name);
176
+ };
177
+ const StrictModeMirrorFactoryConsumer = ({ createStateHandler, onRender, }) => {
178
+ const [count] = useStateFactory(createStateHandler, (state) => state.mirroredCount, []);
179
+ onRender(count);
180
+ return React.createElement("span", null, count);
181
+ };
182
+ describe('Selector hooks', () => {
183
+ let container;
184
+ let root;
185
+ beforeAll(() => {
186
+ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
187
+ });
188
+ beforeEach(() => {
189
+ container = document.createElement('div');
190
+ document.body.appendChild(container);
191
+ root = createRoot(container);
192
+ });
193
+ afterEach(() => {
194
+ act(() => {
195
+ root.unmount();
196
+ });
197
+ container.remove();
198
+ });
199
+ afterAll(() => {
200
+ globalThis.IS_REACT_ACT_ENVIRONMENT = false;
201
+ });
202
+ it('useStateFactory selector should only rerender when selected state changes', async () => {
203
+ let stateHandler = null;
204
+ const createStateHandler = jest.fn(() => {
205
+ if (!stateHandler) {
206
+ stateHandler = new TestStateHandler({
207
+ user: { name: 'Ada' },
208
+ counter: 0,
209
+ });
210
+ }
211
+ return stateHandler;
212
+ });
213
+ const renderSpy = jest.fn();
214
+ act(() => {
215
+ root.render(React.createElement(FactoryShortcutConsumer, { createStateHandler: createStateHandler, onRender: renderSpy }));
216
+ });
217
+ expect(stateHandler).not.toBeNull();
218
+ expect(renderSpy).toHaveBeenCalledTimes(1);
219
+ expect(renderSpy).toHaveBeenLastCalledWith('Ada');
220
+ act(() => {
221
+ stateHandler.getActions().increment();
222
+ });
223
+ expect(renderSpy).toHaveBeenCalledTimes(1);
224
+ act(() => {
225
+ stateHandler.getActions().setName('Grace');
226
+ });
227
+ expect(renderSpy).toHaveBeenCalledTimes(2);
228
+ expect(renderSpy).toHaveBeenLastCalledWith('Grace');
229
+ expect(createStateHandler).toHaveBeenCalledTimes(1);
230
+ act(() => {
231
+ root.render(React.createElement(React.Fragment, null));
232
+ });
233
+ await act(async () => {
234
+ await new Promise((resolve) => {
235
+ setTimeout(resolve, 0);
236
+ });
237
+ });
238
+ expect(stateHandler.destroy).toHaveBeenCalledTimes(1);
239
+ });
240
+ it('composed hook interface should support selector subscription and actions', () => {
241
+ let stateHandler = null;
242
+ const createStateHandler = jest.fn(() => {
243
+ if (!stateHandler) {
244
+ stateHandler = new TestStateHandler({
245
+ user: { name: 'Ada' },
246
+ counter: 0,
247
+ });
248
+ }
249
+ return stateHandler;
250
+ });
251
+ const stateRenderSpy = jest.fn();
252
+ const actionsReadySpy = jest.fn();
253
+ act(() => {
254
+ root.render(React.createElement(ComposedHooksConsumer, { createStateHandler: createStateHandler, onStateRender: stateRenderSpy, onActionsReady: actionsReadySpy }));
255
+ });
256
+ expect(stateRenderSpy).toHaveBeenCalledTimes(1);
257
+ expect(stateRenderSpy).toHaveBeenLastCalledWith('Ada');
258
+ expect(actionsReadySpy).toHaveBeenCalledTimes(1);
259
+ act(() => {
260
+ stateHandler.getActions().increment();
261
+ });
262
+ expect(stateRenderSpy).toHaveBeenCalledTimes(1);
263
+ act(() => {
264
+ stateHandler.getActions().setName('Grace');
265
+ });
266
+ expect(stateRenderSpy).toHaveBeenCalledTimes(2);
267
+ expect(stateRenderSpy).toHaveBeenLastCalledWith('Grace');
268
+ expect(actionsReadySpy).toHaveBeenCalledTimes(2);
269
+ expect(createStateHandler).toHaveBeenCalledTimes(1);
270
+ });
271
+ it('useStateActions should not subscribe when used without useStateSubscription', () => {
272
+ let stateHandler = null;
273
+ const createStateHandler = jest.fn(() => {
274
+ if (!stateHandler) {
275
+ stateHandler = new TestStateHandler({
276
+ user: { name: 'Ada' },
277
+ counter: 0,
278
+ });
279
+ }
280
+ return stateHandler;
281
+ });
282
+ const renderSpy = jest.fn();
283
+ const actionsReadySpy = jest.fn();
284
+ act(() => {
285
+ root.render(React.createElement(ActionsOnlyConsumer, { createStateHandler: createStateHandler, onRender: renderSpy, onActionsReady: actionsReadySpy }));
286
+ });
287
+ const [[actions]] = actionsReadySpy.mock.calls;
288
+ act(() => {
289
+ actions.increment();
290
+ actions.setName('Grace');
291
+ });
292
+ expect(renderSpy).toHaveBeenCalledTimes(1);
293
+ expect(createStateHandler).toHaveBeenCalledTimes(1);
294
+ });
295
+ it('useStateFactory shortcut should support selector, equality and params as last argument', () => {
296
+ let stateHandler = null;
297
+ const createStateHandler = jest.fn(() => {
298
+ if (!stateHandler) {
299
+ stateHandler = new TestStateHandler({
300
+ user: { name: 'Ada' },
301
+ counter: 0,
302
+ });
303
+ }
304
+ return stateHandler;
305
+ });
306
+ const renderSpy = jest.fn();
307
+ act(() => {
308
+ root.render(React.createElement(FactoryShortcutConsumer, { createStateHandler: createStateHandler, onRender: renderSpy }));
309
+ });
310
+ act(() => {
311
+ stateHandler.getActions().increment();
312
+ });
313
+ expect(renderSpy).toHaveBeenCalledTimes(1);
314
+ expect(createStateHandler).toHaveBeenCalledTimes(1);
315
+ });
316
+ it('useStateFactory should support selector and params without custom equality', () => {
317
+ let stateHandler = null;
318
+ const createStateHandler = jest.fn(() => {
319
+ if (!stateHandler) {
320
+ stateHandler = new TestStateHandler({
321
+ user: { name: 'Ada' },
322
+ counter: 0,
323
+ });
324
+ }
325
+ return stateHandler;
326
+ });
327
+ const renderSpy = jest.fn();
328
+ act(() => {
329
+ root.render(React.createElement(FactoryShortcutWithoutEqualityConsumer, { createStateHandler: createStateHandler, onRender: renderSpy }));
330
+ });
331
+ act(() => {
332
+ stateHandler.getActions().increment();
333
+ });
334
+ expect(renderSpy).toHaveBeenCalledTimes(1);
335
+ act(() => {
336
+ stateHandler.getActions().setName('Grace');
337
+ });
338
+ expect(renderSpy).toHaveBeenCalledTimes(2);
339
+ });
340
+ it('useStateSubscription should return full snapshot when no selector is provided', () => {
341
+ let stateHandler = null;
342
+ const createStateHandler = jest.fn(() => {
343
+ if (!stateHandler) {
344
+ stateHandler = new TestStateHandler({
345
+ user: { name: 'Ada' },
346
+ counter: 0,
347
+ });
348
+ }
349
+ return stateHandler;
350
+ });
351
+ const renderSpy = jest.fn();
352
+ const actionsReadySpy = jest.fn();
353
+ act(() => {
354
+ root.render(React.createElement(FullSubscriptionConsumer, { createStateHandler: createStateHandler, onRender: renderSpy, onActionsReady: actionsReadySpy }));
355
+ });
356
+ expect(renderSpy).toHaveBeenLastCalledWith({
357
+ user: { name: 'Ada' },
358
+ counter: 0,
359
+ });
360
+ const [[actions]] = actionsReadySpy.mock.calls;
361
+ act(() => {
362
+ actions.increment();
363
+ });
364
+ expect(renderSpy).toHaveBeenLastCalledWith({
365
+ user: { name: 'Ada' },
366
+ counter: 1,
367
+ });
368
+ });
369
+ it('useStateSingleton selector should keep singleton alive while consumers exist', () => {
370
+ const stateHandler = new TestStateHandler({
371
+ user: { name: 'Ada' },
372
+ counter: 0,
373
+ });
374
+ const singleton = makeStateSingleton(() => stateHandler, {
375
+ destroyOnNoConsumers: true,
376
+ });
377
+ const firstRenderSpy = jest.fn();
378
+ const secondRenderSpy = jest.fn();
379
+ act(() => {
380
+ root.render(React.createElement(React.Fragment, null,
381
+ React.createElement(SingletonShortcutConsumer, { singleton: singleton, onRender: firstRenderSpy }),
382
+ React.createElement(SingletonShortcutConsumer, { singleton: singleton, onRender: secondRenderSpy })));
383
+ });
384
+ act(() => {
385
+ stateHandler.getActions().increment();
386
+ });
387
+ expect(firstRenderSpy).toHaveBeenCalledTimes(1);
388
+ expect(secondRenderSpy).toHaveBeenCalledTimes(1);
389
+ act(() => {
390
+ stateHandler.getActions().setName('Linus');
391
+ });
392
+ expect(firstRenderSpy).toHaveBeenCalledTimes(2);
393
+ expect(secondRenderSpy).toHaveBeenCalledTimes(2);
394
+ act(() => {
395
+ root.render(React.createElement(SingletonShortcutConsumer, { singleton: singleton, onRender: firstRenderSpy }));
396
+ });
397
+ expect(stateHandler.destroy).not.toHaveBeenCalled();
398
+ act(() => {
399
+ root.render(React.createElement(React.Fragment, null));
400
+ });
401
+ expect(stateHandler.destroy).toHaveBeenCalledTimes(1);
402
+ });
403
+ it('useStateSingleton shortcut should support selector without rerender fanout', () => {
404
+ const stateHandler = new TestStateHandler({
405
+ user: { name: 'Ada' },
406
+ counter: 0,
407
+ });
408
+ const singleton = makeStateSingleton(() => stateHandler);
409
+ const renderSpy = jest.fn();
410
+ act(() => {
411
+ root.render(React.createElement(SingletonShortcutConsumer, { singleton: singleton, onRender: renderSpy }));
412
+ });
413
+ act(() => {
414
+ stateHandler.getActions().increment();
415
+ });
416
+ expect(renderSpy).toHaveBeenCalledTimes(1);
417
+ act(() => {
418
+ stateHandler.getActions().setName('Grace');
419
+ });
420
+ expect(renderSpy).toHaveBeenCalledTimes(2);
421
+ });
422
+ it('useStateSubscription should accept singleton sources directly', () => {
423
+ const stateHandler = new TestStateHandler({
424
+ user: { name: 'Ada' },
425
+ counter: 0,
426
+ });
427
+ const singleton = makeStateSingleton(() => stateHandler);
428
+ const renderSpy = jest.fn();
429
+ const actionsReadySpy = jest.fn();
430
+ act(() => {
431
+ root.render(React.createElement(SingletonSubscriptionConsumer, { singleton: singleton, onRender: renderSpy, onActionsReady: actionsReadySpy }));
432
+ });
433
+ const [[actions]] = actionsReadySpy.mock.calls;
434
+ act(() => {
435
+ actions.increment();
436
+ });
437
+ expect(renderSpy).toHaveBeenCalledTimes(1);
438
+ act(() => {
439
+ actions.setName('Grace');
440
+ });
441
+ expect(renderSpy).toHaveBeenCalledTimes(2);
442
+ });
443
+ it('useStateSingleton selector should keep the singleton instance alive by default', () => {
444
+ const firstHandler = new TestStateHandler({
445
+ user: { name: 'Ada' },
446
+ counter: 0,
447
+ });
448
+ const secondHandler = new TestStateHandler({
449
+ user: { name: 'Grace' },
450
+ counter: 0,
451
+ });
452
+ const createStateHandler = jest
453
+ .fn(() => firstHandler)
454
+ .mockReturnValueOnce(firstHandler)
455
+ .mockReturnValueOnce(secondHandler);
456
+ const singleton = makeStateSingleton(createStateHandler);
457
+ const renderSpy = jest.fn();
458
+ act(() => {
459
+ root.render(React.createElement(SingletonShortcutConsumer, { singleton: singleton, onRender: renderSpy }));
460
+ });
461
+ act(() => {
462
+ root.render(React.createElement(React.Fragment, null));
463
+ });
464
+ expect(firstHandler.destroy).not.toHaveBeenCalled();
465
+ act(() => {
466
+ root.render(React.createElement(SingletonShortcutConsumer, { singleton: singleton, onRender: renderSpy }));
467
+ });
468
+ expect(createStateHandler).toHaveBeenCalledTimes(1);
469
+ expect(renderSpy).toHaveBeenLastCalledWith('Ada');
470
+ });
471
+ it('useStateFactory should keep bridge handler alive through StrictMode subscribe re-check', () => {
472
+ const counterStateHandler = new CounterStateHandler(0);
473
+ const counterSingleton = makeStateSingleton(() => counterStateHandler, {
474
+ destroyOnNoConsumers: false,
475
+ });
476
+ let counterMirrorStateHandler = null;
477
+ const createStateHandler = jest.fn(() => {
478
+ if (!counterMirrorStateHandler) {
479
+ counterMirrorStateHandler = new CounterMirrorStateHandler(counterSingleton);
480
+ }
481
+ return counterMirrorStateHandler;
482
+ });
483
+ const renderSpy = jest.fn();
484
+ act(() => {
485
+ root.render(React.createElement(React.StrictMode, null,
486
+ React.createElement(StrictModeMirrorFactoryConsumer, { createStateHandler: createStateHandler, onRender: renderSpy })));
487
+ });
488
+ act(() => {
489
+ counterStateHandler.getActions().increment();
490
+ });
491
+ act(() => {
492
+ counterStateHandler.getActions().increment();
493
+ });
494
+ expect(createStateHandler).toHaveBeenCalledTimes(1);
495
+ expect(renderSpy).toHaveBeenLastCalledWith(2);
496
+ expect(counterMirrorStateHandler.destroy).not.toHaveBeenCalled();
497
+ });
498
+ });
499
+ //# sourceMappingURL=state-selector.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-selector.spec.js","sourceRoot":"","sources":["../../../../src/react/hooks/__tests__/state-selector.spec.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ declare global {
2
+ var IS_REACT_ACT_ENVIRONMENT: boolean;
3
+ }
4
+ export {};
@@ -0,0 +1,96 @@
1
+ import React, { act } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { makeStateSingleton } from '../../../store';
4
+ import { useStateSingleton } from '../state-singleton.js';
5
+ const createStateHandler = (value) => {
6
+ const snapshot = { value };
7
+ const actions = { noop: jest.fn() };
8
+ return {
9
+ subscribe: (_listener) => () => undefined,
10
+ getSnapshot: () => snapshot,
11
+ getInitialState: () => snapshot,
12
+ getActions: () => actions,
13
+ destroy: jest.fn(),
14
+ };
15
+ };
16
+ const SingletonConsumer = ({ singleton, }) => {
17
+ useStateSingleton(singleton);
18
+ return null;
19
+ };
20
+ describe('useStateSingleton', () => {
21
+ let container;
22
+ let root;
23
+ beforeAll(() => {
24
+ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
25
+ });
26
+ beforeEach(() => {
27
+ container = document.createElement('div');
28
+ document.body.appendChild(container);
29
+ root = createRoot(container);
30
+ });
31
+ afterEach(() => {
32
+ act(() => {
33
+ root.unmount();
34
+ });
35
+ container.remove();
36
+ });
37
+ afterAll(() => {
38
+ globalThis.IS_REACT_ACT_ENVIRONMENT = false;
39
+ });
40
+ it('should keep singleton alive while at least one consumer is mounted', () => {
41
+ const firstHandler = createStateHandler(1);
42
+ const singleton = makeStateSingleton(() => firstHandler);
43
+ act(() => {
44
+ root.render(React.createElement(React.Fragment, null,
45
+ React.createElement(SingletonConsumer, { singleton: singleton }),
46
+ React.createElement(SingletonConsumer, { singleton: singleton })));
47
+ });
48
+ act(() => {
49
+ root.render(React.createElement(SingletonConsumer, { singleton: singleton }));
50
+ });
51
+ expect(firstHandler.destroy).not.toHaveBeenCalled();
52
+ act(() => {
53
+ root.render(React.createElement(React.Fragment, null));
54
+ });
55
+ expect(firstHandler.destroy).not.toHaveBeenCalled();
56
+ });
57
+ it('should create a new singleton instance after all consumers unmount when destroyOnNoConsumers is true', () => {
58
+ const firstHandler = createStateHandler(1);
59
+ const secondHandler = createStateHandler(2);
60
+ const factory = jest.fn(() => firstHandler);
61
+ factory.mockReturnValueOnce(firstHandler).mockReturnValueOnce(secondHandler);
62
+ const singleton = makeStateSingleton(factory, {
63
+ destroyOnNoConsumers: true,
64
+ });
65
+ act(() => {
66
+ root.render(React.createElement(SingletonConsumer, { singleton: singleton }));
67
+ });
68
+ act(() => {
69
+ root.render(React.createElement(React.Fragment, null));
70
+ });
71
+ expect(firstHandler.destroy).toHaveBeenCalledTimes(1);
72
+ act(() => {
73
+ root.render(React.createElement(SingletonConsumer, { singleton: singleton }));
74
+ });
75
+ expect(factory).toHaveBeenCalledTimes(2);
76
+ expect(singleton.getInstance().getSnapshot()).toStrictEqual({ value: 2 });
77
+ });
78
+ it('should keep singleton instance alive by default', () => {
79
+ const firstHandler = createStateHandler(1);
80
+ const factory = jest.fn(() => firstHandler);
81
+ const singleton = makeStateSingleton(factory);
82
+ act(() => {
83
+ root.render(React.createElement(SingletonConsumer, { singleton: singleton }));
84
+ });
85
+ act(() => {
86
+ root.render(React.createElement(React.Fragment, null));
87
+ });
88
+ expect(firstHandler.destroy).not.toHaveBeenCalled();
89
+ act(() => {
90
+ root.render(React.createElement(SingletonConsumer, { singleton: singleton }));
91
+ });
92
+ expect(factory).toHaveBeenCalledTimes(1);
93
+ expect(singleton.getInstance().getSnapshot()).toStrictEqual({ value: 1 });
94
+ });
95
+ });
96
+ //# sourceMappingURL=state-singleton.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-singleton.spec.js","sourceRoot":"","sources":["../../../../src/react/hooks/__tests__/state-singleton.spec.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  export { useStateActions } from './state-actions.js';
2
2
  export { useStateFactory } from './state-factory.js';
3
3
  export { useStateHandler } from './state-handler.js';
4
+ export { StateProvider, useProvidedStateActions, useProvidedStateHandler, useProvidedStateSubscription, } from './state-provider.js';
4
5
  export { useStateSingleton } from './state-singleton.js';
5
6
  export { useStateSubscription } from './state-subscription.js';
@@ -0,0 +1,7 @@
1
+ export { useStateActions } from './state-actions.js';
2
+ export { useStateFactory } from './state-factory.js';
3
+ export { useStateHandler } from './state-handler.js';
4
+ export { StateProvider, useProvidedStateActions, useProvidedStateHandler, useProvidedStateSubscription, } from './state-provider.js';
5
+ export { useStateSingleton } from './state-singleton.js';
6
+ export { useStateSubscription } from './state-subscription.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,uBAAuB,EACvB,4BAA4B,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { StateSubscriptionHandler } from '../../types/types.js';
2
+ export declare function useStateActions<V, A>(stateSubscriptionHandler: StateSubscriptionHandler<V, A>): A;