synstate 0.1.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 (268) hide show
  1. package/README.md +878 -0
  2. package/dist/core/class/child-observable-class.d.mts +37 -0
  3. package/dist/core/class/child-observable-class.d.mts.map +1 -0
  4. package/dist/core/class/child-observable-class.mjs +134 -0
  5. package/dist/core/class/child-observable-class.mjs.map +1 -0
  6. package/dist/core/class/index.d.mts +4 -0
  7. package/dist/core/class/index.d.mts.map +1 -0
  8. package/dist/core/class/index.mjs +4 -0
  9. package/dist/core/class/index.mjs.map +1 -0
  10. package/dist/core/class/observable-base-class.d.mts +28 -0
  11. package/dist/core/class/observable-base-class.d.mts.map +1 -0
  12. package/dist/core/class/observable-base-class.mjs +116 -0
  13. package/dist/core/class/observable-base-class.mjs.map +1 -0
  14. package/dist/core/class/root-observable-class.d.mts +12 -0
  15. package/dist/core/class/root-observable-class.d.mts.map +1 -0
  16. package/dist/core/class/root-observable-class.mjs +35 -0
  17. package/dist/core/class/root-observable-class.mjs.map +1 -0
  18. package/dist/core/combine/combine.d.mts +35 -0
  19. package/dist/core/combine/combine.d.mts.map +1 -0
  20. package/dist/core/combine/combine.mjs +94 -0
  21. package/dist/core/combine/combine.mjs.map +1 -0
  22. package/dist/core/combine/index.d.mts +4 -0
  23. package/dist/core/combine/index.d.mts.map +1 -0
  24. package/dist/core/combine/index.mjs +4 -0
  25. package/dist/core/combine/index.mjs.map +1 -0
  26. package/dist/core/combine/merge.d.mts +28 -0
  27. package/dist/core/combine/merge.d.mts.map +1 -0
  28. package/dist/core/combine/merge.mjs +52 -0
  29. package/dist/core/combine/merge.mjs.map +1 -0
  30. package/dist/core/combine/zip.d.mts +26 -0
  31. package/dist/core/combine/zip.d.mts.map +1 -0
  32. package/dist/core/combine/zip.mjs +63 -0
  33. package/dist/core/combine/zip.mjs.map +1 -0
  34. package/dist/core/create/from-array.d.mts +21 -0
  35. package/dist/core/create/from-array.d.mts.map +1 -0
  36. package/dist/core/create/from-array.mjs +47 -0
  37. package/dist/core/create/from-array.mjs.map +1 -0
  38. package/dist/core/create/from-promise.d.mts +25 -0
  39. package/dist/core/create/from-promise.d.mts.map +1 -0
  40. package/dist/core/create/from-promise.mjs +51 -0
  41. package/dist/core/create/from-promise.mjs.map +1 -0
  42. package/dist/core/create/from-subscribable.d.mts +3 -0
  43. package/dist/core/create/from-subscribable.d.mts.map +1 -0
  44. package/dist/core/create/from-subscribable.mjs +22 -0
  45. package/dist/core/create/from-subscribable.mjs.map +1 -0
  46. package/dist/core/create/index.d.mts +8 -0
  47. package/dist/core/create/index.d.mts.map +1 -0
  48. package/dist/core/create/index.mjs +8 -0
  49. package/dist/core/create/index.mjs.map +1 -0
  50. package/dist/core/create/interval.d.mts +21 -0
  51. package/dist/core/create/interval.d.mts.map +1 -0
  52. package/dist/core/create/interval.mjs +74 -0
  53. package/dist/core/create/interval.mjs.map +1 -0
  54. package/dist/core/create/of.d.mts +20 -0
  55. package/dist/core/create/of.d.mts.map +1 -0
  56. package/dist/core/create/of.mjs +44 -0
  57. package/dist/core/create/of.mjs.map +1 -0
  58. package/dist/core/create/source.d.mts +29 -0
  59. package/dist/core/create/source.d.mts.map +1 -0
  60. package/dist/core/create/source.mjs +29 -0
  61. package/dist/core/create/source.mjs.map +1 -0
  62. package/dist/core/create/timer.d.mts +20 -0
  63. package/dist/core/create/timer.d.mts.map +1 -0
  64. package/dist/core/create/timer.mjs +64 -0
  65. package/dist/core/create/timer.mjs.map +1 -0
  66. package/dist/core/index.d.mts +7 -0
  67. package/dist/core/index.d.mts.map +1 -0
  68. package/dist/core/index.mjs +37 -0
  69. package/dist/core/index.mjs.map +1 -0
  70. package/dist/core/operators/audit-time.d.mts +3 -0
  71. package/dist/core/operators/audit-time.d.mts.map +1 -0
  72. package/dist/core/operators/audit-time.mjs +50 -0
  73. package/dist/core/operators/audit-time.mjs.map +1 -0
  74. package/dist/core/operators/debounce-time.d.mts +31 -0
  75. package/dist/core/operators/debounce-time.d.mts.map +1 -0
  76. package/dist/core/operators/debounce-time.mjs +73 -0
  77. package/dist/core/operators/debounce-time.mjs.map +1 -0
  78. package/dist/core/operators/filter.d.mts +28 -0
  79. package/dist/core/operators/filter.d.mts.map +1 -0
  80. package/dist/core/operators/filter.mjs +38 -0
  81. package/dist/core/operators/filter.mjs.map +1 -0
  82. package/dist/core/operators/index.d.mts +18 -0
  83. package/dist/core/operators/index.d.mts.map +1 -0
  84. package/dist/core/operators/index.mjs +18 -0
  85. package/dist/core/operators/index.mjs.map +1 -0
  86. package/dist/core/operators/map-with-index.d.mts +39 -0
  87. package/dist/core/operators/map-with-index.d.mts.map +1 -0
  88. package/dist/core/operators/map-with-index.mjs +73 -0
  89. package/dist/core/operators/map-with-index.mjs.map +1 -0
  90. package/dist/core/operators/merge-map.d.mts +34 -0
  91. package/dist/core/operators/merge-map.d.mts.map +1 -0
  92. package/dist/core/operators/merge-map.mjs +75 -0
  93. package/dist/core/operators/merge-map.mjs.map +1 -0
  94. package/dist/core/operators/pairwise.d.mts +27 -0
  95. package/dist/core/operators/pairwise.d.mts.map +1 -0
  96. package/dist/core/operators/pairwise.mjs +59 -0
  97. package/dist/core/operators/pairwise.mjs.map +1 -0
  98. package/dist/core/operators/scan.d.mts +30 -0
  99. package/dist/core/operators/scan.d.mts.map +1 -0
  100. package/dist/core/operators/scan.mjs +56 -0
  101. package/dist/core/operators/scan.mjs.map +1 -0
  102. package/dist/core/operators/skip-if-no-change.d.mts +33 -0
  103. package/dist/core/operators/skip-if-no-change.d.mts.map +1 -0
  104. package/dist/core/operators/skip-if-no-change.mjs +68 -0
  105. package/dist/core/operators/skip-if-no-change.mjs.map +1 -0
  106. package/dist/core/operators/skip-until.d.mts +3 -0
  107. package/dist/core/operators/skip-until.d.mts.map +1 -0
  108. package/dist/core/operators/skip-until.mjs +33 -0
  109. package/dist/core/operators/skip-until.mjs.map +1 -0
  110. package/dist/core/operators/skip-while.d.mts +4 -0
  111. package/dist/core/operators/skip-while.d.mts.map +1 -0
  112. package/dist/core/operators/skip-while.mjs +40 -0
  113. package/dist/core/operators/skip-while.mjs.map +1 -0
  114. package/dist/core/operators/switch-map.d.mts +31 -0
  115. package/dist/core/operators/switch-map.d.mts.map +1 -0
  116. package/dist/core/operators/switch-map.mjs +70 -0
  117. package/dist/core/operators/switch-map.mjs.map +1 -0
  118. package/dist/core/operators/take-until.d.mts +32 -0
  119. package/dist/core/operators/take-until.d.mts.map +1 -0
  120. package/dist/core/operators/take-until.mjs +60 -0
  121. package/dist/core/operators/take-until.mjs.map +1 -0
  122. package/dist/core/operators/take-while.d.mts +4 -0
  123. package/dist/core/operators/take-while.d.mts.map +1 -0
  124. package/dist/core/operators/take-while.mjs +42 -0
  125. package/dist/core/operators/take-while.mjs.map +1 -0
  126. package/dist/core/operators/throttle-time.d.mts +23 -0
  127. package/dist/core/operators/throttle-time.d.mts.map +1 -0
  128. package/dist/core/operators/throttle-time.mjs +68 -0
  129. package/dist/core/operators/throttle-time.mjs.map +1 -0
  130. package/dist/core/operators/with-buffered-from.d.mts +4 -0
  131. package/dist/core/operators/with-buffered-from.d.mts.map +1 -0
  132. package/dist/core/operators/with-buffered-from.mjs +45 -0
  133. package/dist/core/operators/with-buffered-from.mjs.map +1 -0
  134. package/dist/core/operators/with-current-value-from.d.mts +4 -0
  135. package/dist/core/operators/with-current-value-from.d.mts.map +1 -0
  136. package/dist/core/operators/with-current-value-from.mjs +37 -0
  137. package/dist/core/operators/with-current-value-from.mjs.map +1 -0
  138. package/dist/core/operators/with-initial-value.d.mts +26 -0
  139. package/dist/core/operators/with-initial-value.d.mts.map +1 -0
  140. package/dist/core/operators/with-initial-value.mjs +47 -0
  141. package/dist/core/operators/with-initial-value.mjs.map +1 -0
  142. package/dist/core/types/id.d.mts +4 -0
  143. package/dist/core/types/id.d.mts.map +1 -0
  144. package/dist/core/types/id.mjs +2 -0
  145. package/dist/core/types/id.mjs.map +1 -0
  146. package/dist/core/types/index.d.mts +6 -0
  147. package/dist/core/types/index.d.mts.map +1 -0
  148. package/dist/core/types/index.mjs +3 -0
  149. package/dist/core/types/index.mjs.map +1 -0
  150. package/dist/core/types/observable-family.d.mts +68 -0
  151. package/dist/core/types/observable-family.d.mts.map +1 -0
  152. package/dist/core/types/observable-family.mjs +2 -0
  153. package/dist/core/types/observable-family.mjs.map +1 -0
  154. package/dist/core/types/observable-kind.d.mts +4 -0
  155. package/dist/core/types/observable-kind.d.mts.map +1 -0
  156. package/dist/core/types/observable-kind.mjs +2 -0
  157. package/dist/core/types/observable-kind.mjs.map +1 -0
  158. package/dist/core/types/observable.d.mts +83 -0
  159. package/dist/core/types/observable.d.mts.map +1 -0
  160. package/dist/core/types/observable.mjs +10 -0
  161. package/dist/core/types/observable.mjs.map +1 -0
  162. package/dist/core/types/types.d.mts +16 -0
  163. package/dist/core/types/types.d.mts.map +1 -0
  164. package/dist/core/types/types.mjs +2 -0
  165. package/dist/core/types/types.mjs.map +1 -0
  166. package/dist/core/utils/id-maker.d.mts +5 -0
  167. package/dist/core/utils/id-maker.d.mts.map +1 -0
  168. package/dist/core/utils/id-maker.mjs +17 -0
  169. package/dist/core/utils/id-maker.mjs.map +1 -0
  170. package/dist/core/utils/index.d.mts +5 -0
  171. package/dist/core/utils/index.d.mts.map +1 -0
  172. package/dist/core/utils/index.mjs +5 -0
  173. package/dist/core/utils/index.mjs.map +1 -0
  174. package/dist/core/utils/max-depth.d.mts +3 -0
  175. package/dist/core/utils/max-depth.d.mts.map +1 -0
  176. package/dist/core/utils/max-depth.mjs +8 -0
  177. package/dist/core/utils/max-depth.mjs.map +1 -0
  178. package/dist/core/utils/observable-utils.d.mts +3 -0
  179. package/dist/core/utils/observable-utils.d.mts.map +1 -0
  180. package/dist/core/utils/observable-utils.mjs +7 -0
  181. package/dist/core/utils/observable-utils.mjs.map +1 -0
  182. package/dist/core/utils/utils.d.mts +4 -0
  183. package/dist/core/utils/utils.d.mts.map +1 -0
  184. package/dist/core/utils/utils.mjs +38 -0
  185. package/dist/core/utils/utils.mjs.map +1 -0
  186. package/dist/entry-point.d.mts +2 -0
  187. package/dist/entry-point.d.mts.map +1 -0
  188. package/dist/entry-point.mjs +40 -0
  189. package/dist/entry-point.mjs.map +1 -0
  190. package/dist/globals.d.mts +4 -0
  191. package/dist/index.d.mts +3 -0
  192. package/dist/index.d.mts.map +1 -0
  193. package/dist/index.mjs +40 -0
  194. package/dist/index.mjs.map +1 -0
  195. package/dist/tsconfig.json +1 -0
  196. package/dist/types.d.mts +2 -0
  197. package/dist/utils/create-event-emitter.d.mts +39 -0
  198. package/dist/utils/create-event-emitter.d.mts.map +1 -0
  199. package/dist/utils/create-event-emitter.mjs +57 -0
  200. package/dist/utils/create-event-emitter.mjs.map +1 -0
  201. package/dist/utils/create-reducer.d.mts +34 -0
  202. package/dist/utils/create-reducer.d.mts.map +1 -0
  203. package/dist/utils/create-reducer.mjs +49 -0
  204. package/dist/utils/create-reducer.mjs.map +1 -0
  205. package/dist/utils/create-state.d.mts +61 -0
  206. package/dist/utils/create-state.d.mts.map +1 -0
  207. package/dist/utils/create-state.mjs +92 -0
  208. package/dist/utils/create-state.mjs.map +1 -0
  209. package/dist/utils/index.d.mts +4 -0
  210. package/dist/utils/index.d.mts.map +1 -0
  211. package/dist/utils/index.mjs +4 -0
  212. package/dist/utils/index.mjs.map +1 -0
  213. package/package.json +71 -0
  214. package/src/core/class/child-observable-class.mts +232 -0
  215. package/src/core/class/index.mts +3 -0
  216. package/src/core/class/observable-base-class.mts +186 -0
  217. package/src/core/class/observable.class.test.mts +89 -0
  218. package/src/core/class/root-observable-class.mts +68 -0
  219. package/src/core/combine/combine.mts +144 -0
  220. package/src/core/combine/index.mts +3 -0
  221. package/src/core/combine/merge.mts +84 -0
  222. package/src/core/combine/zip.mts +149 -0
  223. package/src/core/create/from-array.mts +58 -0
  224. package/src/core/create/from-promise.mts +58 -0
  225. package/src/core/create/from-subscribable.mts +37 -0
  226. package/src/core/create/index.mts +7 -0
  227. package/src/core/create/interval.mts +99 -0
  228. package/src/core/create/of.mts +54 -0
  229. package/src/core/create/source.mts +59 -0
  230. package/src/core/create/timer.mts +84 -0
  231. package/src/core/index.mts +6 -0
  232. package/src/core/operators/audit-time.mts +77 -0
  233. package/src/core/operators/debounce-time.mts +96 -0
  234. package/src/core/operators/filter.mts +125 -0
  235. package/src/core/operators/index.mts +17 -0
  236. package/src/core/operators/map-with-index.mts +168 -0
  237. package/src/core/operators/merge-map.mts +108 -0
  238. package/src/core/operators/pairwise.mts +77 -0
  239. package/src/core/operators/scan.mts +81 -0
  240. package/src/core/operators/skip-if-no-change.mts +91 -0
  241. package/src/core/operators/skip-until.mts +54 -0
  242. package/src/core/operators/skip-while.mts +77 -0
  243. package/src/core/operators/switch-map.mts +101 -0
  244. package/src/core/operators/take-until.mts +80 -0
  245. package/src/core/operators/take-while.mts +103 -0
  246. package/src/core/operators/throttle-time.mts +95 -0
  247. package/src/core/operators/with-buffered-from.mts +68 -0
  248. package/src/core/operators/with-current-value-from.mts +58 -0
  249. package/src/core/operators/with-initial-value.mts +76 -0
  250. package/src/core/types/id.mts +5 -0
  251. package/src/core/types/index.mts +5 -0
  252. package/src/core/types/observable-family.mts +259 -0
  253. package/src/core/types/observable-kind.mts +5 -0
  254. package/src/core/types/observable.mts +218 -0
  255. package/src/core/types/types.mts +40 -0
  256. package/src/core/utils/id-maker.mts +31 -0
  257. package/src/core/utils/index.mts +4 -0
  258. package/src/core/utils/max-depth.mts +7 -0
  259. package/src/core/utils/observable-utils.mts +10 -0
  260. package/src/core/utils/utils.mts +51 -0
  261. package/src/core/utils/utils.test.mts +88 -0
  262. package/src/entry-point.mts +1 -0
  263. package/src/globals.d.mts +4 -0
  264. package/src/index.mts +2 -0
  265. package/src/utils/create-event-emitter.mts +62 -0
  266. package/src/utils/create-reducer.mts +55 -0
  267. package/src/utils/create-state.mts +138 -0
  268. package/src/utils/index.mts +3 -0
@@ -0,0 +1,88 @@
1
+ import { asSafeInt } from 'ts-data-forge';
2
+ import { binarySearch, halfInt } from './utils.mjs';
3
+
4
+ describe(halfInt, () => {
5
+ test('case: even number', () => {
6
+ expect(halfInt(asSafeInt(2))).toBe(1);
7
+ });
8
+
9
+ test('case: odd positive number', () => {
10
+ expect(halfInt(asSafeInt(3))).toBe(1);
11
+ });
12
+
13
+ test('case: odd negative number', () => {
14
+ expect(halfInt(asSafeInt(-3))).toBe(-1);
15
+ });
16
+ });
17
+
18
+ describe(binarySearch, () => {
19
+ test('empty array', () => {
20
+ expect(binarySearch([], 0)).toBe(0);
21
+ });
22
+
23
+ test('1 element array (1)', () => {
24
+ expect(binarySearch([1], 0)).toBe(0);
25
+ });
26
+
27
+ test('1 element array (2)', () => {
28
+ expect(binarySearch([-1], 0)).toBe(1);
29
+ });
30
+
31
+ test('2 element array (1)', () => {
32
+ expect(binarySearch([-1, 1], 0)).toBe(1);
33
+ });
34
+
35
+ test('2 element array (2)', () => {
36
+ expect(binarySearch([1, 2], 0)).toBe(0);
37
+ });
38
+
39
+ test('2 element array (3)', () => {
40
+ expect(binarySearch([-2, -1], 0)).toBe(2);
41
+ });
42
+
43
+ test('array with same value (1)', () => {
44
+ expect([0, 1]).toContain(binarySearch([0], 0));
45
+ });
46
+
47
+ test('array with same value (2)', () => {
48
+ expect([0, 1, 2]).toContain(binarySearch([0, 0], 0));
49
+ });
50
+
51
+ test('array with same value (3)', () => {
52
+ expect([0, 1, 2, 3]).toContain(binarySearch([0, 0, 0], 0));
53
+ });
54
+
55
+ test('complicated example 1', () => {
56
+ expect([2, 3]).toContain(binarySearch([1, 3, 4, 6, 7, 8], 4));
57
+ });
58
+
59
+ test('complicated example 2', () => {
60
+ expect([2, 3, 4]).toContain(binarySearch([1, 3, 4, 4, 6, 7, 8], 4));
61
+ });
62
+
63
+ test('complicated example 3', () => {
64
+ expect(binarySearch([1, 3, 4, 4, 6, 7, 8], 0)).toBe(0);
65
+ });
66
+
67
+ test('complicated example 4', () => {
68
+ expect([0, 1]).toContain(binarySearch([1, 3, 4, 4, 6, 7, 8], 1));
69
+ });
70
+
71
+ test('complicated example 5', () => {
72
+ expect([0, 1, 2, 3]).toContain(
73
+ binarySearch([1, 1, 1, 3, 4, 4, 6, 7, 8], 1),
74
+ );
75
+ });
76
+
77
+ test('complicated example 6', () => {
78
+ expect([5, 6]).toContain(binarySearch([1, 3, 4, 4, 6, 7, 8], 7));
79
+ });
80
+
81
+ test('complicated example 7', () => {
82
+ expect([6, 7]).toContain(binarySearch([1, 3, 4, 4, 6, 7, 8], 8));
83
+ });
84
+
85
+ test('complicated example 8', () => {
86
+ expect(binarySearch([1, 3, 4, 4, 6, 7, 8], 9)).toBe(7);
87
+ });
88
+ });
@@ -0,0 +1 @@
1
+ export * from './index.mjs';
@@ -0,0 +1,4 @@
1
+ /// <reference types="ts-type-forge" />
2
+
3
+ // Timer types for Node.js/Browser compatibility
4
+ type TimerId = ReturnType<typeof setTimeout>;
package/src/index.mts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './core/index.mjs';
2
+ export * from './utils/index.mjs';
@@ -0,0 +1,62 @@
1
+ import { source, type Observable } from '../core/index.mjs';
2
+
3
+ /**
4
+ * Creates an event emitter for void events (events without payload).
5
+ * Returns a tuple of [observable, emitter function].
6
+ *
7
+ * @returns A tuple containing the observable and the emitter function
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const [click$, emitClick] = createEventEmitter();
12
+ *
13
+ * click$.subscribe(() => {
14
+ * console.log('Clicked!');
15
+ * });
16
+ *
17
+ * emitClick(); // logs: Clicked!
18
+ * ```
19
+ */
20
+ export const createEventEmitter = (): readonly [
21
+ Observable<void>,
22
+ () => void,
23
+ ] => {
24
+ const src$ = source<undefined>();
25
+
26
+ const emitter = (): void => {
27
+ src$.next(undefined);
28
+ };
29
+
30
+ return [src$, emitter];
31
+ };
32
+
33
+ /**
34
+ * Creates an event emitter with typed payload.
35
+ * Returns a tuple of [observable, emitter function].
36
+ *
37
+ * @template A - The type of the event payload
38
+ * @returns A tuple containing the observable and the emitter function
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const [message$, emitMessage] = createValueEmitter<string>();
43
+ *
44
+ * message$.subscribe((msg) => {
45
+ * console.log(msg);
46
+ * });
47
+ *
48
+ * emitMessage('Hello'); // logs: Hello
49
+ * ```
50
+ */
51
+ export const createValueEmitter = <A,>(): readonly [
52
+ Observable<A>,
53
+ (value: A) => void,
54
+ ] => {
55
+ const src$ = source<A>();
56
+
57
+ const emitter = (value: A): void => {
58
+ src$.next(value);
59
+ };
60
+
61
+ return [src$, emitter];
62
+ };
@@ -0,0 +1,55 @@
1
+ import { source, type InitializedObservable } from '../core/index.mjs';
2
+
3
+ /**
4
+ * Creates a reducer-based state management container following the Redux pattern.
5
+ * Actions are dispatched to update the state according to the reducer function.
6
+ *
7
+ * @template S - The type of the state
8
+ * @template A - The type of actions
9
+ * @param reducer - A pure function that takes current state and action, returns new state
10
+ * @param initialState - The initial value of the state
11
+ * @returns An object containing the state observable, dispatch function, and snapshot getter
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const [state, dispatch] = createReducer(
16
+ * (s, action: Readonly<{ type: 'increment' } | { type: 'decrement' }>) => {
17
+ * switch (action.type) {
18
+ * case 'increment':
19
+ * return s + 1;
20
+ * case 'decrement':
21
+ * return s - 1;
22
+ * }
23
+ * },
24
+ * 0,
25
+ * );
26
+ *
27
+ * state.subscribe((value: number) => {
28
+ * console.log(value);
29
+ * });
30
+ *
31
+ * dispatch({ type: 'increment' }); // logs: 1
32
+ * ```
33
+ */
34
+ export const createReducer = <S, A>(
35
+ reducer: Reducer<S, A>,
36
+ initialState: S,
37
+ ): readonly [
38
+ state: InitializedObservable<S>,
39
+ dispatch: (action: A) => S,
40
+ getSnapshot: () => S,
41
+ ] => {
42
+ const state = source<S>(initialState);
43
+
44
+ const dispatch = (action: A): S => {
45
+ const nextState = reducer(state.getSnapshot().value, action);
46
+
47
+ state.next(nextState);
48
+
49
+ return nextState;
50
+ };
51
+
52
+ const getSnapshot = (): S => state.getSnapshot().value;
53
+
54
+ return [state, dispatch, getSnapshot] as const;
55
+ };
@@ -0,0 +1,138 @@
1
+ import { type InitializedObservable } from '../core/index.mjs';
2
+ import { createReducer } from './create-reducer.mjs';
3
+
4
+ type Action<S> = Readonly<
5
+ | {
6
+ type: 'set';
7
+ nextState: S;
8
+ }
9
+ | {
10
+ type: 'update';
11
+ updateFn: (a: S) => S;
12
+ }
13
+ >;
14
+
15
+ const reducer = <S,>(state: S, action: Action<S>): S => {
16
+ switch (action.type) {
17
+ case 'set':
18
+ return action.nextState;
19
+
20
+ case 'update':
21
+ return action.updateFn(state);
22
+ }
23
+ };
24
+
25
+ /**
26
+ * Creates a reactive state container with getter and setter methods.
27
+ * Provides a simple state management solution with observable state.
28
+ *
29
+ * @template S - The type of the state
30
+ * @param initialState - The initial value of the state
31
+ * @returns An object containing the state observable and methods to manipulate it
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const [state, setState, { updateState, resetState }] = createState(0);
36
+ *
37
+ * state.subscribe((value: number) => {
38
+ * console.log(value);
39
+ * }); // logs: 0
40
+ *
41
+ * setState(10); // logs: 10
42
+ *
43
+ * updateState((prev: number) => prev + 1); // logs: 11
44
+ *
45
+ * resetState(); // logs: 0
46
+ * ```
47
+ */
48
+ export const createState = <S,>(
49
+ initialState: S,
50
+ ): readonly [
51
+ state: InitializedObservable<S>,
52
+ setState: (v: S) => S,
53
+ Readonly<{
54
+ updateState: (updateFn: (prev: S) => S) => S;
55
+ resetState: () => S;
56
+ getSnapshot: () => S;
57
+ }>,
58
+ ] => {
59
+ const [state, dispatch, getSnapshot] = createReducer<S, Action<S>>(
60
+ reducer,
61
+ initialState,
62
+ );
63
+
64
+ const updateState = (updateFn: (prev: S) => S): S =>
65
+ dispatch({ type: 'update', updateFn });
66
+
67
+ const setState = (nextState: S): S => dispatch({ type: 'set', nextState });
68
+
69
+ const resetState = (): S =>
70
+ dispatch({ type: 'set', nextState: initialState });
71
+
72
+ return [
73
+ state,
74
+ setState,
75
+ {
76
+ updateState,
77
+ resetState,
78
+ getSnapshot,
79
+ },
80
+ ] as const;
81
+ };
82
+
83
+ /**
84
+ * Creates a reactive boolean state with convenient methods for boolean operations.
85
+ * Extends `createState` with boolean-specific helpers like `toggle`, `setTrue`, and `setFalse`.
86
+ *
87
+ * @param initialState - The initial boolean value
88
+ * @returns An object with the state observable and boolean-specific methods
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * const [state, { setTrue, toggle }] = createBooleanState(false);
93
+ *
94
+ * state.subscribe((value: boolean) => {
95
+ * console.log(value);
96
+ * }); // logs: false
97
+ *
98
+ * setTrue(); // logs: true
99
+ *
100
+ * toggle(); // logs: false
101
+ *
102
+ * toggle(); // logs: true
103
+ * ```
104
+ */
105
+ export const createBooleanState = (
106
+ initialState: boolean,
107
+ ): readonly [
108
+ state: InitializedObservable<boolean>,
109
+ Readonly<{
110
+ setTrue: () => void;
111
+ setFalse: () => void;
112
+ setState: (next: boolean) => boolean;
113
+ toggle: () => boolean;
114
+ updateState: (updateFn: (prev: boolean) => boolean) => boolean;
115
+ resetState: () => boolean;
116
+ getSnapshot: () => boolean;
117
+ }>,
118
+ ] => {
119
+ const [state, setState, { updateState, resetState, getSnapshot }] =
120
+ createState(initialState);
121
+
122
+ return [
123
+ state,
124
+ {
125
+ setTrue: () => {
126
+ setState(true);
127
+ },
128
+ setFalse: () => {
129
+ setState(false);
130
+ },
131
+ toggle: () => updateState((s) => !s),
132
+ setState,
133
+ updateState,
134
+ resetState,
135
+ getSnapshot,
136
+ },
137
+ ] as const;
138
+ };
@@ -0,0 +1,3 @@
1
+ export * from './create-event-emitter.mjs';
2
+ export * from './create-reducer.mjs';
3
+ export * from './create-state.mjs';