@uistate/core 5.0.2 → 5.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 (38) hide show
  1. package/eventStateNew.js +149 -0
  2. package/eventTest.js +1 -1
  3. package/examples/002-counter-improved/index.html +4 -1
  4. package/examples/003-input-reactive/index.html +4 -1
  5. package/examples/004-computed-state/index.html +9 -6
  6. package/examples/005-conditional-rendering/index.html +7 -4
  7. package/examples/006-list-rendering/index.html +8 -5
  8. package/examples/007-form-validation/index.html +11 -8
  9. package/examples/008-undo-redo/index.html +15 -12
  10. package/examples/009-localStorage-side-effects/index.html +7 -4
  11. package/examples/010-decoupled-components/index.html +6 -3
  12. package/examples/011-async-patterns/index.html +19 -16
  13. package/examples/028-counter-improved-eventTest/app/store.js +1 -1
  14. package/examples/028-counter-improved-eventTest/runtime/core/eventStateNew.js +149 -0
  15. package/examples/028-counter-improved-eventTest/tests/eventTest.js +1 -1
  16. package/examples/030-todo-app-with-eventTest/app/store.js +1 -1
  17. package/examples/030-todo-app-with-eventTest/runtime/core/eventStateNew.js +149 -0
  18. package/examples/030-todo-app-with-eventTest/tests/eventTest.js +1 -1
  19. package/examples/031-todo-app-with-eventTest/app/store.js +1 -1
  20. package/examples/031-todo-app-with-eventTest/runtime/core/eventStateNew.js +149 -0
  21. package/examples/031-todo-app-with-eventTest/runtime/extensions/eventState.plus.js +1 -1
  22. package/examples/031-todo-app-with-eventTest/tests/eventTest.js +1 -1
  23. package/examples/032-todo-app-with-eventTest/app/store.js +1 -1
  24. package/examples/032-todo-app-with-eventTest/runtime/core/eventStateNew.js +149 -0
  25. package/examples/032-todo-app-with-eventTest/runtime/extensions/eventState.plus.js +1 -1
  26. package/examples/032-todo-app-with-eventTest/tests/eventTest.js +1 -1
  27. package/index.js +2 -2
  28. package/package.json +3 -1
  29. package/examples/002-counter-improved/eventState.js +0 -86
  30. package/examples/003-input-reactive/eventState.js +0 -86
  31. package/examples/004-computed-state/eventState.js +0 -86
  32. package/examples/005-conditional-rendering/eventState.js +0 -86
  33. package/examples/006-list-rendering/eventState.js +0 -86
  34. package/examples/007-form-validation/eventState.js +0 -86
  35. package/examples/008-undo-redo/eventState.js +0 -86
  36. package/examples/009-localStorage-side-effects/eventState.js +0 -86
  37. package/examples/010-decoupled-components/eventState.js +0 -86
  38. package/examples/011-async-patterns/eventState.js +0 -86
@@ -1,86 +0,0 @@
1
- const createEventState = (initial = {}) => {
2
- const store = JSON.parse(JSON.stringify(initial));
3
-
4
- const bus = new EventTarget();
5
- let destroyed = false;
6
-
7
- return {
8
- get: (path) => {
9
- if (destroyed) throw new Error('Cannot get from destroyed store');
10
- if (!path) return store;
11
-
12
- // Parse dot-paths: 'items.0' → ['items', '0']
13
- const parts = path.split('.').flatMap(part => {
14
- const match = part.match(/([^\[]+)\[(\d+)\]/);
15
- return match ? [match[1], match[2]] : part;
16
- });
17
-
18
- return parts.reduce(
19
- (obj, prop) => (obj && obj[prop] !== undefined ? obj[prop] : undefined),
20
- store
21
- );
22
- },
23
- set: (path, value) => {
24
- if (destroyed) throw new Error('Cannot set on destroyed store');
25
- if (!path) return;
26
- const parts = path.split('.');
27
- const last = parts.pop();
28
- let target = store;
29
-
30
- for (const key of parts) {
31
- // create intermediate objects as needed
32
- if (typeof target[key] !== 'object' || target[key] === null) {
33
- target[key] = {};
34
- }
35
- target = target[key];
36
- }
37
-
38
- target[last] = value;
39
-
40
- if (!destroyed) {
41
- // exact path
42
- bus.dispatchEvent(new CustomEvent(path, { detail: value }));
43
-
44
- // parent wildcards: a, a.b -> 'a.*', 'a.b.*'
45
- for (let i = 1; i <= parts.length; i++) {
46
- const parent = parts.slice(0, i).join('.');
47
- bus.dispatchEvent(new CustomEvent(`${parent}.*`, { detail: { path, value } }));
48
- }
49
-
50
- // root wildcard
51
- bus.dispatchEvent(new CustomEvent('*', { detail: { path, value } }));
52
- }
53
-
54
- return value;
55
- },
56
- subscribe(path, handler) {
57
- if (destroyed) throw new Error('store destroyed');
58
- if (!path || typeof handler !== 'function') {
59
- throw new TypeError('subscribe(path, handler) requires a string path and function handler');
60
- }
61
- const onEvent = (evt) => handler(evt.detail, evt);
62
- bus.addEventListener(path, onEvent);
63
-
64
- return function unsubscribe() {
65
- bus.removeEventListener(path, onEvent);
66
- };
67
- },
68
- off(unsubscribe) {
69
- if (typeof unsubscribe !== 'function') {
70
- throw new TypeError('off(unsubscribe) requires a function returned by subscribe');
71
- }
72
- return unsubscribe();
73
- },
74
-
75
- destroy() {
76
- if (!destroyed) {
77
- destroyed = true;
78
- // EventTarget has no parentNode - just mark as destroyed
79
- // Future sets/subscribes will be blocked by destroyed flag
80
- }
81
- }
82
- };
83
- }
84
-
85
- export default createEventState;
86
- export { createEventState };
@@ -1,86 +0,0 @@
1
- const createEventState = (initial = {}) => {
2
- const store = JSON.parse(JSON.stringify(initial));
3
-
4
- const bus = new EventTarget();
5
- let destroyed = false;
6
-
7
- return {
8
- get: (path) => {
9
- if (destroyed) throw new Error('Cannot get from destroyed store');
10
- if (!path) return store;
11
-
12
- // Parse dot-paths: 'items.0' → ['items', '0']
13
- const parts = path.split('.').flatMap(part => {
14
- const match = part.match(/([^\[]+)\[(\d+)\]/);
15
- return match ? [match[1], match[2]] : part;
16
- });
17
-
18
- return parts.reduce(
19
- (obj, prop) => (obj && obj[prop] !== undefined ? obj[prop] : undefined),
20
- store
21
- );
22
- },
23
- set: (path, value) => {
24
- if (destroyed) throw new Error('Cannot set on destroyed store');
25
- if (!path) return;
26
- const parts = path.split('.');
27
- const last = parts.pop();
28
- let target = store;
29
-
30
- for (const key of parts) {
31
- // create intermediate objects as needed
32
- if (typeof target[key] !== 'object' || target[key] === null) {
33
- target[key] = {};
34
- }
35
- target = target[key];
36
- }
37
-
38
- target[last] = value;
39
-
40
- if (!destroyed) {
41
- // exact path
42
- bus.dispatchEvent(new CustomEvent(path, { detail: value }));
43
-
44
- // parent wildcards: a, a.b -> 'a.*', 'a.b.*'
45
- for (let i = 1; i <= parts.length; i++) {
46
- const parent = parts.slice(0, i).join('.');
47
- bus.dispatchEvent(new CustomEvent(`${parent}.*`, { detail: { path, value } }));
48
- }
49
-
50
- // root wildcard
51
- bus.dispatchEvent(new CustomEvent('*', { detail: { path, value } }));
52
- }
53
-
54
- return value;
55
- },
56
- subscribe(path, handler) {
57
- if (destroyed) throw new Error('store destroyed');
58
- if (!path || typeof handler !== 'function') {
59
- throw new TypeError('subscribe(path, handler) requires a string path and function handler');
60
- }
61
- const onEvent = (evt) => handler(evt.detail, evt);
62
- bus.addEventListener(path, onEvent);
63
-
64
- return function unsubscribe() {
65
- bus.removeEventListener(path, onEvent);
66
- };
67
- },
68
- off(unsubscribe) {
69
- if (typeof unsubscribe !== 'function') {
70
- throw new TypeError('off(unsubscribe) requires a function returned by subscribe');
71
- }
72
- return unsubscribe();
73
- },
74
-
75
- destroy() {
76
- if (!destroyed) {
77
- destroyed = true;
78
- // EventTarget has no parentNode - just mark as destroyed
79
- // Future sets/subscribes will be blocked by destroyed flag
80
- }
81
- }
82
- };
83
- }
84
-
85
- export default createEventState;
86
- export { createEventState };
@@ -1,86 +0,0 @@
1
- const createEventState = (initial = {}) => {
2
- const store = JSON.parse(JSON.stringify(initial));
3
-
4
- const bus = new EventTarget();
5
- let destroyed = false;
6
-
7
- return {
8
- get: (path) => {
9
- if (destroyed) throw new Error('Cannot get from destroyed store');
10
- if (!path) return store;
11
-
12
- // Parse dot-paths: 'items.0' → ['items', '0']
13
- const parts = path.split('.').flatMap(part => {
14
- const match = part.match(/([^\[]+)\[(\d+)\]/);
15
- return match ? [match[1], match[2]] : part;
16
- });
17
-
18
- return parts.reduce(
19
- (obj, prop) => (obj && obj[prop] !== undefined ? obj[prop] : undefined),
20
- store
21
- );
22
- },
23
- set: (path, value) => {
24
- if (destroyed) throw new Error('Cannot set on destroyed store');
25
- if (!path) return;
26
- const parts = path.split('.');
27
- const last = parts.pop();
28
- let target = store;
29
-
30
- for (const key of parts) {
31
- // create intermediate objects as needed
32
- if (typeof target[key] !== 'object' || target[key] === null) {
33
- target[key] = {};
34
- }
35
- target = target[key];
36
- }
37
-
38
- target[last] = value;
39
-
40
- if (!destroyed) {
41
- // exact path
42
- bus.dispatchEvent(new CustomEvent(path, { detail: value }));
43
-
44
- // parent wildcards: a, a.b -> 'a.*', 'a.b.*'
45
- for (let i = 1; i <= parts.length; i++) {
46
- const parent = parts.slice(0, i).join('.');
47
- bus.dispatchEvent(new CustomEvent(`${parent}.*`, { detail: { path, value } }));
48
- }
49
-
50
- // root wildcard
51
- bus.dispatchEvent(new CustomEvent('*', { detail: { path, value } }));
52
- }
53
-
54
- return value;
55
- },
56
- subscribe(path, handler) {
57
- if (destroyed) throw new Error('store destroyed');
58
- if (!path || typeof handler !== 'function') {
59
- throw new TypeError('subscribe(path, handler) requires a string path and function handler');
60
- }
61
- const onEvent = (evt) => handler(evt.detail, evt);
62
- bus.addEventListener(path, onEvent);
63
-
64
- return function unsubscribe() {
65
- bus.removeEventListener(path, onEvent);
66
- };
67
- },
68
- off(unsubscribe) {
69
- if (typeof unsubscribe !== 'function') {
70
- throw new TypeError('off(unsubscribe) requires a function returned by subscribe');
71
- }
72
- return unsubscribe();
73
- },
74
-
75
- destroy() {
76
- if (!destroyed) {
77
- destroyed = true;
78
- // EventTarget has no parentNode - just mark as destroyed
79
- // Future sets/subscribes will be blocked by destroyed flag
80
- }
81
- }
82
- };
83
- }
84
-
85
- export default createEventState;
86
- export { createEventState };