@uistate/examples 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.md +40 -0
  2. package/cssState/.gitkeep +0 -0
  3. package/eventState/001-counter/README.md +44 -0
  4. package/eventState/001-counter/index.html +33 -0
  5. package/eventState/002-counter-improved/README.md +44 -0
  6. package/eventState/002-counter-improved/index.html +47 -0
  7. package/eventState/003-input-reactive/README.md +44 -0
  8. package/eventState/003-input-reactive/index.html +33 -0
  9. package/eventState/004-computed-state/README.md +45 -0
  10. package/eventState/004-computed-state/index.html +65 -0
  11. package/eventState/005-conditional-rendering/README.md +42 -0
  12. package/eventState/005-conditional-rendering/index.html +39 -0
  13. package/eventState/006-list-rendering/README.md +49 -0
  14. package/eventState/006-list-rendering/index.html +63 -0
  15. package/eventState/007-form-validation/README.md +52 -0
  16. package/eventState/007-form-validation/index.html +102 -0
  17. package/eventState/008-undo-redo/README.md +70 -0
  18. package/eventState/008-undo-redo/index.html +108 -0
  19. package/eventState/009-localStorage-side-effects/README.md +72 -0
  20. package/eventState/009-localStorage-side-effects/index.html +57 -0
  21. package/eventState/010-decoupled-components/README.md +74 -0
  22. package/eventState/010-decoupled-components/index.html +93 -0
  23. package/eventState/011-async-patterns/README.md +98 -0
  24. package/eventState/011-async-patterns/index.html +132 -0
  25. package/eventState/028-counter-improved-eventTest/LICENSE +55 -0
  26. package/eventState/028-counter-improved-eventTest/README.md +131 -0
  27. package/eventState/028-counter-improved-eventTest/app/store.js +9 -0
  28. package/eventState/028-counter-improved-eventTest/index.html +49 -0
  29. package/eventState/028-counter-improved-eventTest/runtime/core/behaviors.runtime.js +282 -0
  30. package/eventState/028-counter-improved-eventTest/runtime/core/eventState.js +100 -0
  31. package/eventState/028-counter-improved-eventTest/runtime/core/eventStateNew.js +149 -0
  32. package/eventState/028-counter-improved-eventTest/runtime/core/helpers.js +212 -0
  33. package/eventState/028-counter-improved-eventTest/runtime/core/router.js +271 -0
  34. package/eventState/028-counter-improved-eventTest/store.d.ts +8 -0
  35. package/eventState/028-counter-improved-eventTest/style.css +170 -0
  36. package/eventState/028-counter-improved-eventTest/tests/README.md +208 -0
  37. package/eventState/028-counter-improved-eventTest/tests/counter.test.js +116 -0
  38. package/eventState/028-counter-improved-eventTest/tests/eventTest.js +176 -0
  39. package/eventState/028-counter-improved-eventTest/tests/generateTypes.js +168 -0
  40. package/eventState/028-counter-improved-eventTest/tests/run.js +20 -0
  41. package/eventState/030-todo-app-with-eventTest/LICENSE +55 -0
  42. package/eventState/030-todo-app-with-eventTest/README.md +121 -0
  43. package/eventState/030-todo-app-with-eventTest/app/router.js +25 -0
  44. package/eventState/030-todo-app-with-eventTest/app/store.js +16 -0
  45. package/eventState/030-todo-app-with-eventTest/app/views/home.js +11 -0
  46. package/eventState/030-todo-app-with-eventTest/app/views/todoDemo.js +88 -0
  47. package/eventState/030-todo-app-with-eventTest/index.html +65 -0
  48. package/eventState/030-todo-app-with-eventTest/runtime/core/behaviors.runtime.js +282 -0
  49. package/eventState/030-todo-app-with-eventTest/runtime/core/eventState.js +100 -0
  50. package/eventState/030-todo-app-with-eventTest/runtime/core/eventStateNew.js +149 -0
  51. package/eventState/030-todo-app-with-eventTest/runtime/core/helpers.js +212 -0
  52. package/eventState/030-todo-app-with-eventTest/runtime/core/router.js +271 -0
  53. package/eventState/030-todo-app-with-eventTest/store.d.ts +18 -0
  54. package/eventState/030-todo-app-with-eventTest/style.css +170 -0
  55. package/eventState/030-todo-app-with-eventTest/tests/README.md +208 -0
  56. package/eventState/030-todo-app-with-eventTest/tests/eventTest.js +176 -0
  57. package/eventState/030-todo-app-with-eventTest/tests/generateTypes.js +189 -0
  58. package/eventState/030-todo-app-with-eventTest/tests/run.js +20 -0
  59. package/eventState/030-todo-app-with-eventTest/tests/todos.test.js +167 -0
  60. package/eventState/031-todo-app-with-eventTest/LICENSE +55 -0
  61. package/eventState/031-todo-app-with-eventTest/README.md +54 -0
  62. package/eventState/031-todo-app-with-eventTest/TUTORIAL.md +390 -0
  63. package/eventState/031-todo-app-with-eventTest/WHY_EVENTSTATE.md +777 -0
  64. package/eventState/031-todo-app-with-eventTest/app/bridges.js +113 -0
  65. package/eventState/031-todo-app-with-eventTest/app/router.js +26 -0
  66. package/eventState/031-todo-app-with-eventTest/app/store.js +15 -0
  67. package/eventState/031-todo-app-with-eventTest/app/views/home.js +46 -0
  68. package/eventState/031-todo-app-with-eventTest/app/views/todoDemo.js +69 -0
  69. package/eventState/031-todo-app-with-eventTest/devtools/dock.js +41 -0
  70. package/eventState/031-todo-app-with-eventTest/devtools/stateTracker.dock.js +10 -0
  71. package/eventState/031-todo-app-with-eventTest/devtools/stateTracker.js +246 -0
  72. package/eventState/031-todo-app-with-eventTest/devtools/telemetry.js +104 -0
  73. package/eventState/031-todo-app-with-eventTest/devtools/typeGenerator.js +339 -0
  74. package/eventState/031-todo-app-with-eventTest/index.html +103 -0
  75. package/eventState/031-todo-app-with-eventTest/package-lock.json +2184 -0
  76. package/eventState/031-todo-app-with-eventTest/package.json +24 -0
  77. package/eventState/031-todo-app-with-eventTest/runtime/core/behaviors.runtime.js +282 -0
  78. package/eventState/031-todo-app-with-eventTest/runtime/core/eventState.js +100 -0
  79. package/eventState/031-todo-app-with-eventTest/runtime/core/eventStateNew.js +149 -0
  80. package/eventState/031-todo-app-with-eventTest/runtime/core/helpers.js +212 -0
  81. package/eventState/031-todo-app-with-eventTest/runtime/core/router.js +271 -0
  82. package/eventState/031-todo-app-with-eventTest/runtime/extensions/boundary.js +36 -0
  83. package/eventState/031-todo-app-with-eventTest/runtime/extensions/converge.js +63 -0
  84. package/eventState/031-todo-app-with-eventTest/runtime/extensions/eventState.plus.js +210 -0
  85. package/eventState/031-todo-app-with-eventTest/runtime/extensions/hydrate.js +157 -0
  86. package/eventState/031-todo-app-with-eventTest/runtime/extensions/queryBinding.js +69 -0
  87. package/eventState/031-todo-app-with-eventTest/runtime/forms/computed.js +78 -0
  88. package/eventState/031-todo-app-with-eventTest/runtime/forms/meta.js +51 -0
  89. package/eventState/031-todo-app-with-eventTest/runtime/forms/submitWithBoundary.js +28 -0
  90. package/eventState/031-todo-app-with-eventTest/runtime/forms/validators.js +55 -0
  91. package/eventState/031-todo-app-with-eventTest/store.d.ts +23 -0
  92. package/eventState/031-todo-app-with-eventTest/style.css +170 -0
  93. package/eventState/031-todo-app-with-eventTest/tests/README.md +208 -0
  94. package/eventState/031-todo-app-with-eventTest/tests/eventTest.js +176 -0
  95. package/eventState/031-todo-app-with-eventTest/tests/generateTypes.js +191 -0
  96. package/eventState/031-todo-app-with-eventTest/tests/run.js +20 -0
  97. package/eventState/031-todo-app-with-eventTest/tests/todos.test.js +192 -0
  98. package/eventState/032-todo-app-with-eventTest/LICENSE +55 -0
  99. package/eventState/032-todo-app-with-eventTest/README.md +54 -0
  100. package/eventState/032-todo-app-with-eventTest/TUTORIAL.md +390 -0
  101. package/eventState/032-todo-app-with-eventTest/WHY_EVENTSTATE.md +777 -0
  102. package/eventState/032-todo-app-with-eventTest/app/actions/index.js +153 -0
  103. package/eventState/032-todo-app-with-eventTest/app/bridges.js +113 -0
  104. package/eventState/032-todo-app-with-eventTest/app/router.js +26 -0
  105. package/eventState/032-todo-app-with-eventTest/app/store.js +15 -0
  106. package/eventState/032-todo-app-with-eventTest/app/views/home.js +46 -0
  107. package/eventState/032-todo-app-with-eventTest/app/views/todoDemo.js +69 -0
  108. package/eventState/032-todo-app-with-eventTest/devtools/dock.js +41 -0
  109. package/eventState/032-todo-app-with-eventTest/devtools/stateTracker.dock.js +10 -0
  110. package/eventState/032-todo-app-with-eventTest/devtools/stateTracker.js +246 -0
  111. package/eventState/032-todo-app-with-eventTest/devtools/telemetry.js +104 -0
  112. package/eventState/032-todo-app-with-eventTest/devtools/typeGenerator.js +339 -0
  113. package/eventState/032-todo-app-with-eventTest/index.html +87 -0
  114. package/eventState/032-todo-app-with-eventTest/package-lock.json +2184 -0
  115. package/eventState/032-todo-app-with-eventTest/package.json +24 -0
  116. package/eventState/032-todo-app-with-eventTest/runtime/core/behaviors.runtime.js +282 -0
  117. package/eventState/032-todo-app-with-eventTest/runtime/core/eventState.js +100 -0
  118. package/eventState/032-todo-app-with-eventTest/runtime/core/eventStateNew.js +149 -0
  119. package/eventState/032-todo-app-with-eventTest/runtime/core/helpers.js +212 -0
  120. package/eventState/032-todo-app-with-eventTest/runtime/core/router.js +271 -0
  121. package/eventState/032-todo-app-with-eventTest/runtime/extensions/boundary.js +36 -0
  122. package/eventState/032-todo-app-with-eventTest/runtime/extensions/converge.js +63 -0
  123. package/eventState/032-todo-app-with-eventTest/runtime/extensions/eventState.plus.js +210 -0
  124. package/eventState/032-todo-app-with-eventTest/runtime/extensions/hydrate.js +157 -0
  125. package/eventState/032-todo-app-with-eventTest/runtime/extensions/queryBinding.js +69 -0
  126. package/eventState/032-todo-app-with-eventTest/runtime/forms/computed.js +78 -0
  127. package/eventState/032-todo-app-with-eventTest/runtime/forms/meta.js +51 -0
  128. package/eventState/032-todo-app-with-eventTest/runtime/forms/submitWithBoundary.js +28 -0
  129. package/eventState/032-todo-app-with-eventTest/runtime/forms/validators.js +55 -0
  130. package/eventState/032-todo-app-with-eventTest/store.d.ts +23 -0
  131. package/eventState/032-todo-app-with-eventTest/style.css +170 -0
  132. package/eventState/032-todo-app-with-eventTest/tests/README.md +208 -0
  133. package/eventState/032-todo-app-with-eventTest/tests/eventTest.js +176 -0
  134. package/eventState/032-todo-app-with-eventTest/tests/generateTypes.js +191 -0
  135. package/eventState/032-todo-app-with-eventTest/tests/run.js +20 -0
  136. package/eventState/032-todo-app-with-eventTest/tests/todos.test.js +192 -0
  137. package/package.json +27 -0
@@ -0,0 +1,390 @@
1
+ # EventState Tutorial
2
+
3
+ Learn how to build reactive web applications with EventState's fine-grained state management.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Core Concepts](#core-concepts)
8
+ 2. [Getting Started](#getting-started)
9
+ 3. [Architecture Patterns](#architecture-patterns)
10
+ 4. [Advanced Features](#advanced-features)
11
+ 5. [Comparison with Other Frameworks](#comparison)
12
+
13
+ ---
14
+
15
+ ## Core Concepts
16
+
17
+ ### 1. Fine-Grained Reactivity
18
+
19
+ EventState uses **path-based subscriptions** for surgical DOM updates:
20
+
21
+ ```javascript
22
+ // Subscribe to specific paths
23
+ store.subscribe('domain.todos.items', render); // Only updates when todos change
24
+ store.subscribe('ui.theme', updateTheme); // Only updates when theme changes
25
+ ```
26
+
27
+ **Key differences from other frameworks:**
28
+ - ❌ No virtual DOM diffing
29
+ - ❌ No component-level re-renders
30
+ - ✅ Direct path → handler mapping
31
+ - ✅ Update only what changed
32
+
33
+ ### 2. Intent-Based Architecture
34
+
35
+ EventState separates **what happened** (intent) from **what to do** (bridge):
36
+
37
+ ```
38
+ UI Event → intent.* → Bridge → domain.* → View Update
39
+ ```
40
+
41
+ **Benefits:**
42
+ - ✅ Unidirectional data flow (like Redux)
43
+ - ✅ No boilerplate (unlike Redux)
44
+ - ✅ Testable business logic (bridges are pure functions)
45
+ - ✅ Decoupled UI from domain logic
46
+
47
+ ### 3. Progressive API
48
+
49
+ Start simple, add complexity only when needed:
50
+
51
+ **Declarative** (for simple interactions):
52
+ ```html
53
+ <button data-on="click: addTodo()">Add</button>
54
+ ```
55
+
56
+ **Imperative** (for complex views):
57
+ ```javascript
58
+ store.subscribe('domain.todos.items', (items) => {
59
+ // Custom rendering logic
60
+ });
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Getting Started
66
+
67
+
68
+ ### Quick Start
69
+
70
+ **1. Create a store:**
71
+ ```javascript
72
+ import { createEventState } from './runtime/core/eventState.js';
73
+
74
+ const store = createEventState({
75
+ ui: { count: 0 },
76
+ domain: { todos: [] }
77
+ });
78
+ ```
79
+
80
+ **2. Subscribe to changes:**
81
+ ```javascript
82
+ store.subscribe('ui.count', (count) => {
83
+ document.getElementById('count').textContent = count;
84
+ });
85
+ ```
86
+
87
+ **3. Update state:**
88
+ ```javascript
89
+ button.onclick = () => {
90
+ store.set('ui.count', store.get('ui.count') + 1);
91
+ };
92
+ ```
93
+
94
+ That's it! No build step, no framework, just reactive data.
95
+
96
+ ---
97
+
98
+ ## Architecture Patterns
99
+
100
+ ### The Intent-Bridge-Domain Pattern
101
+
102
+ **Step 1: UI fires an intent**
103
+ ```javascript
104
+ // User clicks "Add Todo"
105
+ store.set('intent.todo.add', { text: 'Buy milk' });
106
+ ```
107
+
108
+ **Step 2: Bridge handles the intent**
109
+ ```javascript
110
+ // app/bridges.js
111
+ store.subscribe('intent.todo.add', ({ text }) => {
112
+ const items = store.get('domain.todos.items') || [];
113
+ store.set('domain.todos.items', [...items, { id: Date.now(), text }]);
114
+ });
115
+ ```
116
+
117
+ **Step 3: View reacts to domain change**
118
+ ```javascript
119
+ // app/views/todoDemo.js
120
+ store.subscribe('domain.todos.items', (items) => {
121
+ renderTodoList(items);
122
+ });
123
+ ```
124
+
125
+ **Why this pattern?**
126
+ - ✅ Testable (test bridges in isolation)
127
+ - ✅ Auditable (log all intents)
128
+ - ✅ Flexible (change behavior without touching UI)
129
+
130
+ ---
131
+
132
+ ## Advanced Features
133
+
134
+ ### 1. Wildcard Subscriptions
135
+
136
+ ```javascript
137
+ // Listen to all state changes
138
+ store.subscribe('**', (value, path) => {
139
+ console.log(`[state] ${path}`, value);
140
+ });
141
+
142
+ // Listen to all intents
143
+ store.subscribe('intent.**', (value, path) => {
144
+ console.log(`[intent] ${path}`, value);
145
+ });
146
+ ```
147
+
148
+ ### 2. Batch Updates
149
+
150
+ ```javascript
151
+ import { upgradeEventState } from './runtime/extensions/eventState.plus.js';
152
+
153
+ const storePlus = upgradeEventState(store);
154
+
155
+ storePlus.setMany({
156
+ 'ui.loading': false,
157
+ 'domain.user': userData,
158
+ 'ui.error': null
159
+ });
160
+ ```
161
+
162
+ ### 3. Router Integration
163
+
164
+ ```javascript
165
+ import { createRouter } from './runtime/core/router.js';
166
+
167
+ const router = createRouter({
168
+ routes: [
169
+ { path: '/', view: 'home', component: Home },
170
+ { path: '/todos', view: 'todos', component: TodoList }
171
+ ],
172
+ store,
173
+ rootSelector: '[data-route-root]'
174
+ });
175
+
176
+ router.start();
177
+ ```
178
+
179
+ ### 4. Built-in Telemetry
180
+
181
+ ```javascript
182
+ // All state changes are automatically logged in dev mode
183
+ // Click "Console" button in dev dock to copy logs
184
+
185
+ // Or access programmatically:
186
+ window.__telemetry.get(); // Get all logs
187
+ window.__telemetry.copy(); // Copy to clipboard
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Comparison
193
+
194
+ ### Why Choose EventState?
195
+
196
+ #### 1. No Common React Bugs
197
+
198
+ **Stale Closures**
199
+ ```javascript
200
+ // React problem:
201
+ const [count, setCount] = useState(0);
202
+ setTimeout(() => console.log(count), 1000); // Stale!
203
+
204
+ // EventState framework:
205
+ store.subscribe('ui.count', (val) => console.log(val)); // Always fresh
206
+ ```
207
+
208
+ **Dependency Arrays**
209
+ ```javascript
210
+ // React:
211
+ useEffect(() => { /* ... */ }, [dep1, dep2, dep3]); // Miss one? Bug!
212
+
213
+ // EventState framework:
214
+ store.subscribe('path.to.dep', handler); // Explicit, no guessing
215
+ ```
216
+
217
+ **Prop Drilling**
218
+ ```javascript
219
+ // React: <A> → <B> → <C> → <D> (pass props 4 levels)
220
+ // EventState framework: Any component reads store.get('shared.data')
221
+ ```
222
+
223
+ **Re-render Debugging**
224
+ ```javascript
225
+ // EventState: Only subscribed handlers run
226
+ store.subscribe('ui.count', updateCount); // Only this runs when count changes
227
+
228
+ // React: Entire component tree may re-render
229
+ // Need React DevTools to debug why
230
+ ```
231
+
232
+ #### 2. Performance by Default
233
+
234
+ **Other frameworks require optimization:**
235
+ ```javascript
236
+ // React: Manual memoization
237
+ const MemoizedComponent = memo(Component);
238
+ const memoizedValue = useMemo(() => compute(a, b), [a, b]);
239
+ const memoizedCallback = useCallback(() => {}, [deps]);
240
+
241
+ // Angular: Change detection strategy
242
+ @Component({ changeDetection: ChangeDetectionStrategy.OnPush })
243
+ ```
244
+
245
+ **EventState: Fast by default**
246
+ ```javascript
247
+ // Direct DOM updates, no virtual DOM
248
+ // Only subscribed handlers run
249
+ // No manual optimization needed
250
+ store.subscribe('ui.count', (val) => el.textContent = val);
251
+ ```
252
+
253
+ #### 3. Less Boilerplate
254
+
255
+ **Redux:**
256
+ ```javascript
257
+ // actions.js
258
+ export const ADD_TODO = 'ADD_TODO';
259
+ export const addTodo = (text) => ({ type: ADD_TODO, text });
260
+
261
+ // reducers.js
262
+ export default function todos(state = [], action) {
263
+ switch (action.type) {
264
+ case ADD_TODO:
265
+ return [...state, { id: Date.now(), text: action.text }];
266
+ default:
267
+ return state;
268
+ }
269
+ }
270
+
271
+ // component.js
272
+ const mapStateToProps = (state) => ({ todos: state.todos });
273
+ const mapDispatchToProps = { addTodo };
274
+ export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
275
+ ```
276
+
277
+ **EventState:**
278
+ ```javascript
279
+ // bridges.js
280
+ store.subscribe('intent.todo.add', ({ text }) => {
281
+ const items = store.get('domain.todos.items') || [];
282
+ store.set('domain.todos.items', [...items, { id: Date.now(), text }]);
283
+ });
284
+ ```
285
+
286
+ **3 files vs 1 function.**
287
+
288
+ #### 4. Built-in Observability
289
+
290
+ ```javascript
291
+ // See every state change (one line)
292
+ store.subscribe('**', (val, path) => console.log('[state]', path, val));
293
+
294
+ // Time-travel debugging
295
+ const history = [];
296
+ store.subscribe('**', (val, path) => history.push({ path, val }));
297
+ history.forEach(({ path, val }) => store.set(path, val)); // Replay
298
+
299
+ // State snapshot
300
+ const snapshot = store.get(''); // Entire state tree
301
+ ```
302
+
303
+ **No browser extensions needed** - everything is built-in.
304
+
305
+ #### 5. Framework-Agnostic
306
+
307
+ ```javascript
308
+ // Works in vanilla JS
309
+ store.set('count', 1);
310
+
311
+ // Works with React
312
+ function Counter() {
313
+ const [count, setCount] = useState(store.get('count'));
314
+ useEffect(() => store.subscribe('count', setCount), []);
315
+ return <div>{count}</div>;
316
+ }
317
+
318
+ // Works with Web Components
319
+ class MyCounter extends HTMLElement {
320
+ connectedCallback() {
321
+ this.unsub = store.subscribe('count', (val) => {
322
+ this.textContent = val;
323
+ });
324
+ }
325
+ }
326
+
327
+ // Works with any build tool (or none)
328
+ ```
329
+
330
+ ---
331
+
332
+ ## Feature Comparison
333
+
334
+ | Feature | React | Redux | Vue | Solid | EventState |
335
+ |---------|-------|-------|-----|-------|------------|
336
+ | Fine-grained updates | ❌ | ❌ | ⚠️ | ✅ | ✅ |
337
+ | No boilerplate | ⚠️ | ❌ | ⚠️ | ✅ | ✅ |
338
+ | Framework-agnostic | ❌ | ⚠️ | ❌ | ⚠️ | ✅ |
339
+ | Built-in time-travel | ❌ | ✅ | ❌ | ❌ | ✅ |
340
+ | Wildcard subscriptions | ❌ | ❌ | ❌ | ❌ | ✅ |
341
+ | Bundle size | 45KB | 3KB | 34KB | 7KB | <1KB |
342
+ | Learning curve | High | Very High | Medium | Medium | Low |
343
+
344
+ ---
345
+
346
+ ## What's Next
347
+
348
+ ### Current Status
349
+
350
+ **What EventState has today:**
351
+ - ✅ Solid reactivity primitive (~200 lines)
352
+ - ✅ Clean architecture (intent → bridge → domain)
353
+ - ✅ Low complexity (no build step required)
354
+ - ✅ Good performance (fine-grained updates)
355
+ - ✅ Generic router (`runtime/core/router.js`)
356
+ - ✅ Form utilities (`runtime/forms/`)
357
+ - ✅ Dev tools (telemetry, state tracker)
358
+
359
+ ### Roadmap
360
+
361
+ **In Development:**
362
+ - TypeScript definitions
363
+ - Component abstraction layer
364
+ - Comprehensive test suite
365
+ - npm package (`@uistate/core`)
366
+
367
+ **Planned:**
368
+ - Separate packages (`@uistate/router`, `@uistate/forms`)
369
+ - VS Code extension (path autocomplete)
370
+ - Documentation site
371
+ - SSR adapter
372
+
373
+ ---
374
+
375
+ ## Learn More
376
+
377
+ - **[WHY_EVENTSTATE.md](./WHY_EVENTSTATE.md)** - Philosophy and comparisons
378
+ - **[runtime/core/eventState.js](./runtime/core/eventState.js)** - Source code (~200 lines)
379
+ - **[app/bridges.js](./app/bridges.js)** - Real-world patterns
380
+ - **[runtime/core/router.js](./runtime/core/router.js)** - Generic SPA router
381
+
382
+ ---
383
+
384
+ ## Contributing
385
+
386
+ EventState is in active development. Feedback, issues, and contributions are welcome!
387
+
388
+ ---
389
+
390
+ *EventState: Fine-grained reactivity without the complexity.*