@hkdigital/lib-core 0.5.87 → 0.5.90
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.
- package/dist/state/classes/reactive-data-store/ReactiveDataStore.svelte.d.ts +152 -0
- package/dist/state/classes/reactive-data-store/ReactiveDataStore.svelte.js +300 -0
- package/dist/state/classes.d.ts +1 -0
- package/dist/state/classes.js +1 -0
- package/dist/state/machines/page-machine/PageMachine.svelte.d.ts +47 -102
- package/dist/state/machines/page-machine/PageMachine.svelte.js +76 -134
- package/dist/state/machines/page-machine/README.md +16 -8
- package/package.json +1 -1
- package/dist/state/classes/subscribers-count/index.d.ts +0 -1
- package/dist/state/classes/subscribers-count/index.js +0 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
export default class ReactiveDataStore {
|
|
2
|
+
/**
|
|
3
|
+
* Constructor
|
|
4
|
+
*
|
|
5
|
+
* @param {Object} [options]
|
|
6
|
+
* @param {Record<string, any>} [options.initialData={}]
|
|
7
|
+
* Initial key-value pairs
|
|
8
|
+
* @param {boolean} [options.strictMode=true]
|
|
9
|
+
* Throw error when accessing uninitialized keys
|
|
10
|
+
* @param {boolean} [options.productionGuard=false]
|
|
11
|
+
* Dev-only mode: no-op on SET, throw on GET in production
|
|
12
|
+
* @param {string} [options.errorPrefix='Data key']
|
|
13
|
+
* Prefix for error messages
|
|
14
|
+
*/
|
|
15
|
+
constructor({ initialData, strictMode, productionGuard, errorPrefix }?: {
|
|
16
|
+
initialData?: Record<string, any> | undefined;
|
|
17
|
+
strictMode?: boolean | undefined;
|
|
18
|
+
productionGuard?: boolean | undefined;
|
|
19
|
+
errorPrefix?: string | undefined;
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Set a data property value
|
|
23
|
+
*
|
|
24
|
+
* Automatically reactive - effects watching this key will re-run.
|
|
25
|
+
* Uses fine-grained reactivity via SvelteMap.
|
|
26
|
+
*
|
|
27
|
+
* With productionGuard: silent no-op in production (safe to call)
|
|
28
|
+
*
|
|
29
|
+
* @param {string} key - Property key
|
|
30
|
+
* @param {any} value - Property value
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```javascript
|
|
34
|
+
* store.set('score', 100);
|
|
35
|
+
* store.set('playerName', 'Alice');
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
set(key: string, value: any): void;
|
|
39
|
+
/**
|
|
40
|
+
* Get a data property value
|
|
41
|
+
*
|
|
42
|
+
* Automatically reactive - creates a dependency on this specific key.
|
|
43
|
+
* The effect will only re-run when THIS key changes.
|
|
44
|
+
*
|
|
45
|
+
* With strictMode: throws if key is not initialized
|
|
46
|
+
* With productionGuard: throws in production (programming error)
|
|
47
|
+
*
|
|
48
|
+
* @param {string} key - Property key
|
|
49
|
+
*
|
|
50
|
+
* @returns {any} Property value
|
|
51
|
+
*
|
|
52
|
+
* @throws {Error} If key not initialized (strictMode)
|
|
53
|
+
* @throws {Error} If accessed in production (productionGuard)
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```javascript
|
|
57
|
+
* // Reactive - re-runs only when 'score' changes
|
|
58
|
+
* $effect(() => {
|
|
59
|
+
* const score = store.get('score');
|
|
60
|
+
* console.log('Score:', score);
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
get(key: string): any;
|
|
65
|
+
/**
|
|
66
|
+
* Get all data properties as plain object
|
|
67
|
+
*
|
|
68
|
+
* Note: Returns a snapshot (plain object), not reactive.
|
|
69
|
+
* Use for serialization or inspection, not for reactive tracking.
|
|
70
|
+
*
|
|
71
|
+
* @returns {Record<string, any>} Plain object with all data
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```javascript
|
|
75
|
+
* const allData = store.getAll();
|
|
76
|
+
* await saveToServer(allData);
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
getAll(): Record<string, any>;
|
|
80
|
+
/**
|
|
81
|
+
* Update multiple data properties at once
|
|
82
|
+
*
|
|
83
|
+
* Each property update triggers fine-grained reactivity.
|
|
84
|
+
* Only effects watching the specific changed keys will re-run.
|
|
85
|
+
*
|
|
86
|
+
* @param {Record<string, any>} updates
|
|
87
|
+
* Object with key-value pairs to update
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```javascript
|
|
91
|
+
* store.update({
|
|
92
|
+
* score: 100,
|
|
93
|
+
* level: 5,
|
|
94
|
+
* completed: true
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
update(updates: Record<string, any>): void;
|
|
99
|
+
/**
|
|
100
|
+
* Delete a data property
|
|
101
|
+
*
|
|
102
|
+
* @param {string} key - Property key to delete
|
|
103
|
+
*
|
|
104
|
+
* @returns {boolean} True if the key existed and was deleted
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```javascript
|
|
108
|
+
* store.delete('temporaryFlag');
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
delete(key: string): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Check if data property exists
|
|
114
|
+
*
|
|
115
|
+
* With productionGuard: throws in production (same as get)
|
|
116
|
+
*
|
|
117
|
+
* @param {string} key - Property key to check
|
|
118
|
+
*
|
|
119
|
+
* @returns {boolean} True if the key exists
|
|
120
|
+
*
|
|
121
|
+
* @throws {Error} If accessed in production (productionGuard)
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```javascript
|
|
125
|
+
* if (store.has('tutorialSeen')) {
|
|
126
|
+
* // Skip tutorial
|
|
127
|
+
* }
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
has(key: string): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Clear all data properties
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```javascript
|
|
136
|
+
* store.clear(); // Reset all data
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
clear(): void;
|
|
140
|
+
/**
|
|
141
|
+
* Get number of data properties
|
|
142
|
+
*
|
|
143
|
+
* @returns {number} Number of data entries
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```javascript
|
|
147
|
+
* console.log(`Store has ${store.size} entries`);
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
get size(): number;
|
|
151
|
+
#private;
|
|
152
|
+
}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactive key-value data store with fine-grained reactivity
|
|
3
|
+
*
|
|
4
|
+
* Built on SvelteMap for fine-grained reactivity where effects only re-run
|
|
5
|
+
* when the specific keys they access change.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Fine-grained reactivity using SvelteMap
|
|
9
|
+
* - Strict mode: throws on access to uninitialized keys
|
|
10
|
+
* - Production guard: dev-only data throws on read in production
|
|
11
|
+
* - Initialization from plain object
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```javascript
|
|
15
|
+
* // Regular data store
|
|
16
|
+
* const store = new ReactiveDataStore({
|
|
17
|
+
* initialData: { score: 0, level: 1 }
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* store.set('score', 100);
|
|
21
|
+
* const score = store.get('score'); // Reactive access
|
|
22
|
+
*
|
|
23
|
+
* // Dev-only data store
|
|
24
|
+
* const devStore = new ReactiveDataStore({
|
|
25
|
+
* initialData: { autoNav: false },
|
|
26
|
+
* productionGuard: true,
|
|
27
|
+
* errorPrefix: 'Dev data key'
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* devStore.set('autoNav', true); // No-op in production
|
|
31
|
+
* devStore.get('autoNav'); // Throws in production
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import { SvelteMap } from 'svelte/reactivity';
|
|
36
|
+
import { dev } from '$app/environment';
|
|
37
|
+
|
|
38
|
+
export default class ReactiveDataStore {
|
|
39
|
+
/**
|
|
40
|
+
* Internal reactive map
|
|
41
|
+
* @type {SvelteMap<string, any>}
|
|
42
|
+
*/
|
|
43
|
+
#data;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Throw on access to uninitialized keys
|
|
47
|
+
* @type {boolean}
|
|
48
|
+
*/
|
|
49
|
+
#strictMode;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Guard against production access (for dev-only data)
|
|
53
|
+
* @type {boolean}
|
|
54
|
+
*/
|
|
55
|
+
#productionGuard;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Prefix for error messages
|
|
59
|
+
* @type {string}
|
|
60
|
+
*/
|
|
61
|
+
#errorPrefix;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Constructor
|
|
65
|
+
*
|
|
66
|
+
* @param {Object} [options]
|
|
67
|
+
* @param {Record<string, any>} [options.initialData={}]
|
|
68
|
+
* Initial key-value pairs
|
|
69
|
+
* @param {boolean} [options.strictMode=true]
|
|
70
|
+
* Throw error when accessing uninitialized keys
|
|
71
|
+
* @param {boolean} [options.productionGuard=false]
|
|
72
|
+
* Dev-only mode: no-op on SET, throw on GET in production
|
|
73
|
+
* @param {string} [options.errorPrefix='Data key']
|
|
74
|
+
* Prefix for error messages
|
|
75
|
+
*/
|
|
76
|
+
constructor({
|
|
77
|
+
initialData = {},
|
|
78
|
+
strictMode = true,
|
|
79
|
+
productionGuard = false,
|
|
80
|
+
errorPrefix = 'Data key'
|
|
81
|
+
} = {}) {
|
|
82
|
+
this.#strictMode = strictMode;
|
|
83
|
+
this.#productionGuard = productionGuard;
|
|
84
|
+
this.#errorPrefix = errorPrefix;
|
|
85
|
+
|
|
86
|
+
// Initialize map
|
|
87
|
+
this.#data = new SvelteMap();
|
|
88
|
+
|
|
89
|
+
// Only populate initial data in dev mode if guard is enabled
|
|
90
|
+
if (!productionGuard || dev) {
|
|
91
|
+
for (const [key, value] of Object.entries(initialData)) {
|
|
92
|
+
this.#data.set(key, value);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Set a data property value
|
|
99
|
+
*
|
|
100
|
+
* Automatically reactive - effects watching this key will re-run.
|
|
101
|
+
* Uses fine-grained reactivity via SvelteMap.
|
|
102
|
+
*
|
|
103
|
+
* With productionGuard: silent no-op in production (safe to call)
|
|
104
|
+
*
|
|
105
|
+
* @param {string} key - Property key
|
|
106
|
+
* @param {any} value - Property value
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```javascript
|
|
110
|
+
* store.set('score', 100);
|
|
111
|
+
* store.set('playerName', 'Alice');
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
set(key, value) {
|
|
115
|
+
// Production guard: no-op silently (safe to call conditionally)
|
|
116
|
+
if (this.#productionGuard && !dev) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.#data.set(key, value);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Get a data property value
|
|
125
|
+
*
|
|
126
|
+
* Automatically reactive - creates a dependency on this specific key.
|
|
127
|
+
* The effect will only re-run when THIS key changes.
|
|
128
|
+
*
|
|
129
|
+
* With strictMode: throws if key is not initialized
|
|
130
|
+
* With productionGuard: throws in production (programming error)
|
|
131
|
+
*
|
|
132
|
+
* @param {string} key - Property key
|
|
133
|
+
*
|
|
134
|
+
* @returns {any} Property value
|
|
135
|
+
*
|
|
136
|
+
* @throws {Error} If key not initialized (strictMode)
|
|
137
|
+
* @throws {Error} If accessed in production (productionGuard)
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```javascript
|
|
141
|
+
* // Reactive - re-runs only when 'score' changes
|
|
142
|
+
* $effect(() => {
|
|
143
|
+
* const score = store.get('score');
|
|
144
|
+
* console.log('Score:', score);
|
|
145
|
+
* });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
get(key) {
|
|
149
|
+
// Production guard: THROW on read in production
|
|
150
|
+
if (this.#productionGuard && !dev) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`${this.#errorPrefix} "${key}" accessed in production. ` +
|
|
153
|
+
`This data is only available in development mode.`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Strict mode: validate key exists
|
|
158
|
+
if (this.#strictMode && !this.#data.has(key)) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`${this.#errorPrefix} "${key}" is not initialized.`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return this.#data.get(key);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get all data properties as plain object
|
|
169
|
+
*
|
|
170
|
+
* Note: Returns a snapshot (plain object), not reactive.
|
|
171
|
+
* Use for serialization or inspection, not for reactive tracking.
|
|
172
|
+
*
|
|
173
|
+
* @returns {Record<string, any>} Plain object with all data
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```javascript
|
|
177
|
+
* const allData = store.getAll();
|
|
178
|
+
* await saveToServer(allData);
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
getAll() {
|
|
182
|
+
if (this.#productionGuard && !dev) {
|
|
183
|
+
return {};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return Object.fromEntries(this.#data);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Update multiple data properties at once
|
|
191
|
+
*
|
|
192
|
+
* Each property update triggers fine-grained reactivity.
|
|
193
|
+
* Only effects watching the specific changed keys will re-run.
|
|
194
|
+
*
|
|
195
|
+
* @param {Record<string, any>} updates
|
|
196
|
+
* Object with key-value pairs to update
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```javascript
|
|
200
|
+
* store.update({
|
|
201
|
+
* score: 100,
|
|
202
|
+
* level: 5,
|
|
203
|
+
* completed: true
|
|
204
|
+
* });
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
update(updates) {
|
|
208
|
+
if (this.#productionGuard && !dev) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
213
|
+
this.#data.set(key, value);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Delete a data property
|
|
219
|
+
*
|
|
220
|
+
* @param {string} key - Property key to delete
|
|
221
|
+
*
|
|
222
|
+
* @returns {boolean} True if the key existed and was deleted
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```javascript
|
|
226
|
+
* store.delete('temporaryFlag');
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
delete(key) {
|
|
230
|
+
if (this.#productionGuard && !dev) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return this.#data.delete(key);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Check if data property exists
|
|
239
|
+
*
|
|
240
|
+
* With productionGuard: throws in production (same as get)
|
|
241
|
+
*
|
|
242
|
+
* @param {string} key - Property key to check
|
|
243
|
+
*
|
|
244
|
+
* @returns {boolean} True if the key exists
|
|
245
|
+
*
|
|
246
|
+
* @throws {Error} If accessed in production (productionGuard)
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```javascript
|
|
250
|
+
* if (store.has('tutorialSeen')) {
|
|
251
|
+
* // Skip tutorial
|
|
252
|
+
* }
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
has(key) {
|
|
256
|
+
// Production guard: THROW on read in production
|
|
257
|
+
if (this.#productionGuard && !dev) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
`${this.#errorPrefix} "${key}" existence check in production. ` +
|
|
260
|
+
`This data is only available in development mode.`
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return this.#data.has(key);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Clear all data properties
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* ```javascript
|
|
272
|
+
* store.clear(); // Reset all data
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
clear() {
|
|
276
|
+
if (this.#productionGuard && !dev) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
this.#data.clear();
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Get number of data properties
|
|
285
|
+
*
|
|
286
|
+
* @returns {number} Number of data entries
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```javascript
|
|
290
|
+
* console.log(`Store has ${store.size} entries`);
|
|
291
|
+
* ```
|
|
292
|
+
*/
|
|
293
|
+
get size() {
|
|
294
|
+
if (this.#productionGuard && !dev) {
|
|
295
|
+
return 0;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return this.#data.size;
|
|
299
|
+
}
|
|
300
|
+
}
|
package/dist/state/classes.d.ts
CHANGED
package/dist/state/classes.js
CHANGED
|
@@ -9,6 +9,8 @@ export default class PageMachine {
|
|
|
9
9
|
* Optional list of valid routes (for validation/dev tools)
|
|
10
10
|
* @param {Record<string, any>} [config.initialData={}]
|
|
11
11
|
* Initial data properties (use KEY_ constants for keys)
|
|
12
|
+
* @param {Record<string, any>} [config.initialDevData={}]
|
|
13
|
+
* Initial dev data properties (use KEY_DEV_ constants for keys)
|
|
12
14
|
* @param {import('../../../logging/client.js').Logger} [config.logger]
|
|
13
15
|
* Logger instance (optional)
|
|
14
16
|
*
|
|
@@ -17,6 +19,7 @@ export default class PageMachine {
|
|
|
17
19
|
* const ROUTE_INTRO = '/intro/start';
|
|
18
20
|
* const KEY_INTRO_COMPLETED = 'intro-completed';
|
|
19
21
|
* const KEY_SCORE = 'score';
|
|
22
|
+
* const KEY_DEV_AUTO_NAVIGATION = 'dev-auto-navigation';
|
|
20
23
|
*
|
|
21
24
|
* const machine = new PageMachine({
|
|
22
25
|
* startPath: ROUTE_INTRO,
|
|
@@ -24,14 +27,18 @@ export default class PageMachine {
|
|
|
24
27
|
* initialData: {
|
|
25
28
|
* [KEY_INTRO_COMPLETED]: false,
|
|
26
29
|
* [KEY_SCORE]: 0
|
|
30
|
+
* },
|
|
31
|
+
* initialDevData: {
|
|
32
|
+
* [KEY_DEV_AUTO_NAVIGATION]: false
|
|
27
33
|
* }
|
|
28
34
|
* });
|
|
29
35
|
* ```
|
|
30
36
|
*/
|
|
31
|
-
constructor({ startPath, routes, initialData, logger }: {
|
|
37
|
+
constructor({ startPath, routes, initialData, initialDevData, logger }: {
|
|
32
38
|
startPath: string;
|
|
33
39
|
routes?: string[] | undefined;
|
|
34
40
|
initialData?: Record<string, any> | undefined;
|
|
41
|
+
initialDevData?: Record<string, any> | undefined;
|
|
35
42
|
logger?: import("../../../logging/client.js").Logger | undefined;
|
|
36
43
|
});
|
|
37
44
|
/**
|
|
@@ -63,132 +70,69 @@ export default class PageMachine {
|
|
|
63
70
|
*/
|
|
64
71
|
get routes(): string[];
|
|
65
72
|
/**
|
|
66
|
-
*
|
|
73
|
+
* Get the reactive data store
|
|
67
74
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* key will be triggered.
|
|
75
|
+
* Provides read-only access to the data store instance.
|
|
76
|
+
* Access all data methods through this property.
|
|
71
77
|
*
|
|
72
|
-
* @
|
|
73
|
-
* @param {any} value - Property value
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* ```javascript
|
|
77
|
-
* const KEY_HAS_STRONG_PROFILE = 'has-strong-profile';
|
|
78
|
-
* const KEY_PROFILE_SCORE = 'profile-score';
|
|
79
|
-
*
|
|
80
|
-
* machine.setData(KEY_HAS_STRONG_PROFILE, true);
|
|
81
|
-
* machine.setData(KEY_PROFILE_SCORE, 85);
|
|
82
|
-
* ```
|
|
83
|
-
*/
|
|
84
|
-
setData(key: string, value: any): void;
|
|
85
|
-
/**
|
|
86
|
-
* Get a data property value
|
|
87
|
-
*
|
|
88
|
-
* Automatically reactive - creates a dependency on this specific key.
|
|
89
|
-
* The effect will only re-run when THIS key changes, not when other
|
|
90
|
-
* keys change.
|
|
91
|
-
*
|
|
92
|
-
* @param {string} key - Property key (use KEY_ constant)
|
|
93
|
-
*
|
|
94
|
-
* @returns {any} Property value or undefined
|
|
78
|
+
* @returns {ReactiveDataStore} The data store
|
|
95
79
|
*
|
|
96
80
|
* @example
|
|
97
81
|
* ```javascript
|
|
98
82
|
* const KEY_SCORE = 'score';
|
|
99
83
|
*
|
|
100
|
-
* //
|
|
84
|
+
* // Set data
|
|
85
|
+
* machine.data.set(KEY_SCORE, 100);
|
|
86
|
+
*
|
|
87
|
+
* // Get data (reactive)
|
|
101
88
|
* $effect(() => {
|
|
102
|
-
* const score = machine.
|
|
89
|
+
* const score = machine.data.get(KEY_SCORE);
|
|
103
90
|
* console.log('Score:', score);
|
|
104
91
|
* });
|
|
105
|
-
* ```
|
|
106
|
-
*/
|
|
107
|
-
getData(key: string): any;
|
|
108
|
-
/**
|
|
109
|
-
* Get all data properties as plain object
|
|
110
|
-
*
|
|
111
|
-
* Note: This returns a snapshot (plain object), not a reactive map.
|
|
112
|
-
* Use this for serialization or server sync, not for reactive tracking.
|
|
113
92
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
93
|
+
* // Other operations
|
|
94
|
+
* machine.data.update({ [KEY_SCORE]: 200 });
|
|
95
|
+
* machine.data.has(KEY_SCORE);
|
|
96
|
+
* machine.data.delete(KEY_SCORE);
|
|
97
|
+
* machine.data.clear();
|
|
98
|
+
* console.log(machine.data.size);
|
|
120
99
|
* ```
|
|
121
100
|
*/
|
|
122
|
-
|
|
101
|
+
get data(): ReactiveDataStore;
|
|
123
102
|
/**
|
|
124
|
-
*
|
|
103
|
+
* Get the reactive dev data store
|
|
125
104
|
*
|
|
126
|
-
*
|
|
105
|
+
* Provides read-only access to the dev data store instance.
|
|
106
|
+
* Access all dev data methods through this property.
|
|
127
107
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
108
|
+
* Dev data is only available in development mode. In production:
|
|
109
|
+
* - SET operations are silent no-ops
|
|
110
|
+
* - GET/HAS operations throw errors (programming errors)
|
|
130
111
|
*
|
|
131
|
-
* @
|
|
132
|
-
* ```javascript
|
|
133
|
-
* const KEY_HAS_STRONG_PROFILE = 'has-strong-profile';
|
|
134
|
-
* const KEY_PROFILE_SCORE = 'profile-score';
|
|
135
|
-
* const KEY_MATCHED_SECTOR = 'matched-sector';
|
|
136
|
-
*
|
|
137
|
-
* machine.updateData({
|
|
138
|
-
* [KEY_HAS_STRONG_PROFILE]: true,
|
|
139
|
-
* [KEY_PROFILE_SCORE]: 85,
|
|
140
|
-
* [KEY_MATCHED_SECTOR]: 'technology'
|
|
141
|
-
* });
|
|
142
|
-
* ```
|
|
143
|
-
*/
|
|
144
|
-
updateData(dataUpdates: Record<string, any>): void;
|
|
145
|
-
/**
|
|
146
|
-
* Delete a data property
|
|
147
|
-
*
|
|
148
|
-
* @param {string} key - Property key to delete (use KEY_ constant)
|
|
149
|
-
*
|
|
150
|
-
* @returns {boolean} True if the key existed and was deleted
|
|
112
|
+
* @returns {ReactiveDataStore} The dev data store
|
|
151
113
|
*
|
|
152
114
|
* @example
|
|
153
115
|
* ```javascript
|
|
154
|
-
* const
|
|
116
|
+
* const KEY_DEV_AUTO_NAV = 'dev-auto-navigation';
|
|
155
117
|
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*/
|
|
159
|
-
deleteData(key: string): boolean;
|
|
160
|
-
/**
|
|
161
|
-
* Check if data property exists
|
|
162
|
-
*
|
|
163
|
-
* @param {string} key - Property key to check (use KEY_ constant)
|
|
164
|
-
*
|
|
165
|
-
* @returns {boolean} True if the key exists
|
|
166
|
-
*
|
|
167
|
-
* @example
|
|
168
|
-
* ```javascript
|
|
169
|
-
* const KEY_TUTORIAL_SEEN = 'tutorial-seen';
|
|
118
|
+
* // Set dev data (no-op in production)
|
|
119
|
+
* machine.devData.set(KEY_DEV_AUTO_NAV, true);
|
|
170
120
|
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
|
|
176
|
-
hasData(key: string): boolean;
|
|
177
|
-
/**
|
|
178
|
-
* Clear all data properties
|
|
121
|
+
* // Get dev data (throws in production)
|
|
122
|
+
* $effect(() => {
|
|
123
|
+
* const autoNav = machine.devData.get(KEY_DEV_AUTO_NAV);
|
|
124
|
+
* console.log('Auto-nav:', autoNav);
|
|
125
|
+
* });
|
|
179
126
|
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
* machine.
|
|
127
|
+
* // Other operations
|
|
128
|
+
* machine.devData.update({ [KEY_DEV_AUTO_NAV]: false });
|
|
129
|
+
* machine.devData.has(KEY_DEV_AUTO_NAV);
|
|
130
|
+
* machine.devData.delete(KEY_DEV_AUTO_NAV);
|
|
131
|
+
* machine.devData.clear();
|
|
132
|
+
* console.log(machine.devData.size);
|
|
183
133
|
* ```
|
|
184
134
|
*/
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Get number of data properties
|
|
188
|
-
*
|
|
189
|
-
* @returns {number} Number of data entries
|
|
190
|
-
*/
|
|
191
|
-
get dataSize(): number;
|
|
135
|
+
get devData(): ReactiveDataStore;
|
|
192
136
|
/**
|
|
193
137
|
* Check if a route has been visited
|
|
194
138
|
*
|
|
@@ -293,3 +237,4 @@ export default class PageMachine {
|
|
|
293
237
|
redirectToStartPath(): void;
|
|
294
238
|
#private;
|
|
295
239
|
}
|
|
240
|
+
import { ReactiveDataStore } from '../../classes.js';
|
|
@@ -8,12 +8,14 @@
|
|
|
8
8
|
* - Current route tracking and synchronization
|
|
9
9
|
* - Start path management
|
|
10
10
|
* - Data properties for business/domain state (using SvelteMap)
|
|
11
|
+
* - Dev data properties for dev-mode helpers (using SvelteMap)
|
|
11
12
|
* - Visited routes tracking (using SvelteSet)
|
|
12
13
|
* - Fine-grained reactivity without manual revision tracking
|
|
13
14
|
*
|
|
14
15
|
* Best practices:
|
|
15
16
|
* - Use constants for routes: `const ROUTE_INTRO = '/intro/start'`
|
|
16
17
|
* - Use KEY_ constants for data: `const KEY_SCORE = 'score'`
|
|
18
|
+
* - Use KEY_DEV_ constants for dev data: `const KEY_DEV_AUTO_NAV = 'dev-auto-navigation'`
|
|
17
19
|
*
|
|
18
20
|
* Basic usage:
|
|
19
21
|
* ```javascript
|
|
@@ -21,6 +23,7 @@
|
|
|
21
23
|
* const ROUTE_INTRO = '/intro/start';
|
|
22
24
|
* const KEY_SCORE = 'score';
|
|
23
25
|
* const KEY_TUTORIAL_SEEN = 'tutorial-seen';
|
|
26
|
+
* const KEY_DEV_AUTO_NAVIGATION = 'dev-auto-navigation';
|
|
24
27
|
*
|
|
25
28
|
* const machine = new PageMachine({
|
|
26
29
|
* startPath: ROUTE_INTRO,
|
|
@@ -48,6 +51,10 @@
|
|
|
48
51
|
* const score = machine.getData(KEY_SCORE);
|
|
49
52
|
* console.log('Score changed:', score);
|
|
50
53
|
* });
|
|
54
|
+
*
|
|
55
|
+
* // Dev-mode helpers (only available in dev)
|
|
56
|
+
* machine.setDevData(KEY_DEV_AUTO_NAVIGATION, true);
|
|
57
|
+
* const autoNavEnabled = machine.getDevData(KEY_DEV_AUTO_NAVIGATION);
|
|
51
58
|
* ```
|
|
52
59
|
*
|
|
53
60
|
* Animations and page-specific logic should use $effect in pages:
|
|
@@ -62,7 +69,8 @@
|
|
|
62
69
|
* });
|
|
63
70
|
* ```
|
|
64
71
|
*/
|
|
65
|
-
import {
|
|
72
|
+
import { SvelteSet } from 'svelte/reactivity';
|
|
73
|
+
import { ReactiveDataStore } from '../../classes.js';
|
|
66
74
|
|
|
67
75
|
export default class PageMachine {
|
|
68
76
|
/**
|
|
@@ -91,12 +99,17 @@ export default class PageMachine {
|
|
|
91
99
|
#routes = [];
|
|
92
100
|
|
|
93
101
|
/**
|
|
94
|
-
* Reactive
|
|
95
|
-
*
|
|
96
|
-
* @type {SvelteMap<string, any>}
|
|
102
|
+
* Reactive data store for business/domain data
|
|
103
|
+
* @type {ReactiveDataStore}
|
|
97
104
|
*/
|
|
98
105
|
#data;
|
|
99
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Reactive data store for dev-mode helper data
|
|
109
|
+
* @type {ReactiveDataStore}
|
|
110
|
+
*/
|
|
111
|
+
#devData;
|
|
112
|
+
|
|
100
113
|
/**
|
|
101
114
|
* Reactive set for visited routes
|
|
102
115
|
* Uses SvelteSet for automatic reactivity
|
|
@@ -114,6 +127,8 @@ export default class PageMachine {
|
|
|
114
127
|
* Optional list of valid routes (for validation/dev tools)
|
|
115
128
|
* @param {Record<string, any>} [config.initialData={}]
|
|
116
129
|
* Initial data properties (use KEY_ constants for keys)
|
|
130
|
+
* @param {Record<string, any>} [config.initialDevData={}]
|
|
131
|
+
* Initial dev data properties (use KEY_DEV_ constants for keys)
|
|
117
132
|
* @param {import('../../../logging/client.js').Logger} [config.logger]
|
|
118
133
|
* Logger instance (optional)
|
|
119
134
|
*
|
|
@@ -122,6 +137,7 @@ export default class PageMachine {
|
|
|
122
137
|
* const ROUTE_INTRO = '/intro/start';
|
|
123
138
|
* const KEY_INTRO_COMPLETED = 'intro-completed';
|
|
124
139
|
* const KEY_SCORE = 'score';
|
|
140
|
+
* const KEY_DEV_AUTO_NAVIGATION = 'dev-auto-navigation';
|
|
125
141
|
*
|
|
126
142
|
* const machine = new PageMachine({
|
|
127
143
|
* startPath: ROUTE_INTRO,
|
|
@@ -129,11 +145,14 @@ export default class PageMachine {
|
|
|
129
145
|
* initialData: {
|
|
130
146
|
* [KEY_INTRO_COMPLETED]: false,
|
|
131
147
|
* [KEY_SCORE]: 0
|
|
148
|
+
* },
|
|
149
|
+
* initialDevData: {
|
|
150
|
+
* [KEY_DEV_AUTO_NAVIGATION]: false
|
|
132
151
|
* }
|
|
133
152
|
* });
|
|
134
153
|
* ```
|
|
135
154
|
*/
|
|
136
|
-
constructor({ startPath, routes = [], initialData = {}, logger = null }) {
|
|
155
|
+
constructor({ startPath, routes = [], initialData = {}, initialDevData = {}, logger = null }) {
|
|
137
156
|
if (!startPath) {
|
|
138
157
|
throw new Error('PageMachine requires startPath parameter');
|
|
139
158
|
}
|
|
@@ -144,13 +163,17 @@ export default class PageMachine {
|
|
|
144
163
|
this.#current = startPath;
|
|
145
164
|
|
|
146
165
|
// Initialize reactive data structures
|
|
147
|
-
this.#data = new
|
|
148
|
-
|
|
166
|
+
this.#data = new ReactiveDataStore({
|
|
167
|
+
initialData
|
|
168
|
+
});
|
|
149
169
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
170
|
+
this.#devData = new ReactiveDataStore({
|
|
171
|
+
initialData: initialDevData,
|
|
172
|
+
productionGuard: true,
|
|
173
|
+
errorPrefix: 'Dev data key'
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
this.#visitedRoutes = new SvelteSet();
|
|
154
177
|
|
|
155
178
|
// Mark start path as visited
|
|
156
179
|
this.#visitedRoutes.add(startPath);
|
|
@@ -235,156 +258,75 @@ export default class PageMachine {
|
|
|
235
258
|
/* ===== Data Properties (Business/Domain State) ===== */
|
|
236
259
|
|
|
237
260
|
/**
|
|
238
|
-
*
|
|
261
|
+
* Get the reactive data store
|
|
239
262
|
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
* key will be triggered.
|
|
263
|
+
* Provides read-only access to the data store instance.
|
|
264
|
+
* Access all data methods through this property.
|
|
243
265
|
*
|
|
244
|
-
* @
|
|
245
|
-
* @param {any} value - Property value
|
|
246
|
-
*
|
|
247
|
-
* @example
|
|
248
|
-
* ```javascript
|
|
249
|
-
* const KEY_HAS_STRONG_PROFILE = 'has-strong-profile';
|
|
250
|
-
* const KEY_PROFILE_SCORE = 'profile-score';
|
|
251
|
-
*
|
|
252
|
-
* machine.setData(KEY_HAS_STRONG_PROFILE, true);
|
|
253
|
-
* machine.setData(KEY_PROFILE_SCORE, 85);
|
|
254
|
-
* ```
|
|
255
|
-
*/
|
|
256
|
-
setData(key, value) {
|
|
257
|
-
this.#data.set(key, value);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Get a data property value
|
|
262
|
-
*
|
|
263
|
-
* Automatically reactive - creates a dependency on this specific key.
|
|
264
|
-
* The effect will only re-run when THIS key changes, not when other
|
|
265
|
-
* keys change.
|
|
266
|
-
*
|
|
267
|
-
* @param {string} key - Property key (use KEY_ constant)
|
|
268
|
-
*
|
|
269
|
-
* @returns {any} Property value or undefined
|
|
266
|
+
* @returns {ReactiveDataStore} The data store
|
|
270
267
|
*
|
|
271
268
|
* @example
|
|
272
269
|
* ```javascript
|
|
273
270
|
* const KEY_SCORE = 'score';
|
|
274
271
|
*
|
|
275
|
-
* //
|
|
272
|
+
* // Set data
|
|
273
|
+
* machine.data.set(KEY_SCORE, 100);
|
|
274
|
+
*
|
|
275
|
+
* // Get data (reactive)
|
|
276
276
|
* $effect(() => {
|
|
277
|
-
* const score = machine.
|
|
277
|
+
* const score = machine.data.get(KEY_SCORE);
|
|
278
278
|
* console.log('Score:', score);
|
|
279
279
|
* });
|
|
280
|
-
* ```
|
|
281
|
-
*/
|
|
282
|
-
getData(key) {
|
|
283
|
-
return this.#data.get(key);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Get all data properties as plain object
|
|
288
|
-
*
|
|
289
|
-
* Note: This returns a snapshot (plain object), not a reactive map.
|
|
290
|
-
* Use this for serialization or server sync, not for reactive tracking.
|
|
291
280
|
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
*
|
|
281
|
+
* // Other operations
|
|
282
|
+
* machine.data.update({ [KEY_SCORE]: 200 });
|
|
283
|
+
* machine.data.has(KEY_SCORE);
|
|
284
|
+
* machine.data.delete(KEY_SCORE);
|
|
285
|
+
* machine.data.clear();
|
|
286
|
+
* console.log(machine.data.size);
|
|
298
287
|
* ```
|
|
299
288
|
*/
|
|
300
|
-
|
|
301
|
-
return
|
|
289
|
+
get data() {
|
|
290
|
+
return this.#data;
|
|
302
291
|
}
|
|
303
292
|
|
|
304
|
-
|
|
305
|
-
* Update multiple data properties at once
|
|
306
|
-
*
|
|
307
|
-
* Each property update triggers fine-grained reactivity.
|
|
308
|
-
*
|
|
309
|
-
* @param {Record<string, any>} dataUpdates
|
|
310
|
-
* Object with key-value pairs (use KEY_ constants for keys)
|
|
311
|
-
*
|
|
312
|
-
* @example
|
|
313
|
-
* ```javascript
|
|
314
|
-
* const KEY_HAS_STRONG_PROFILE = 'has-strong-profile';
|
|
315
|
-
* const KEY_PROFILE_SCORE = 'profile-score';
|
|
316
|
-
* const KEY_MATCHED_SECTOR = 'matched-sector';
|
|
317
|
-
*
|
|
318
|
-
* machine.updateData({
|
|
319
|
-
* [KEY_HAS_STRONG_PROFILE]: true,
|
|
320
|
-
* [KEY_PROFILE_SCORE]: 85,
|
|
321
|
-
* [KEY_MATCHED_SECTOR]: 'technology'
|
|
322
|
-
* });
|
|
323
|
-
* ```
|
|
324
|
-
*/
|
|
325
|
-
updateData(dataUpdates) {
|
|
326
|
-
for (const [key, value] of Object.entries(dataUpdates)) {
|
|
327
|
-
this.#data.set(key, value);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
293
|
+
/* ===== Dev Data Properties (Dev-Mode Helpers) ===== */
|
|
330
294
|
|
|
331
295
|
/**
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
* @param {string} key - Property key to delete (use KEY_ constant)
|
|
296
|
+
* Get the reactive dev data store
|
|
335
297
|
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
* @example
|
|
339
|
-
* ```javascript
|
|
340
|
-
* const KEY_TEMPORARY_FLAG = 'temporary-flag';
|
|
341
|
-
*
|
|
342
|
-
* machine.deleteData(KEY_TEMPORARY_FLAG);
|
|
343
|
-
* ```
|
|
344
|
-
*/
|
|
345
|
-
deleteData(key) {
|
|
346
|
-
return this.#data.delete(key);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* Check if data property exists
|
|
298
|
+
* Provides read-only access to the dev data store instance.
|
|
299
|
+
* Access all dev data methods through this property.
|
|
351
300
|
*
|
|
352
|
-
*
|
|
301
|
+
* Dev data is only available in development mode. In production:
|
|
302
|
+
* - SET operations are silent no-ops
|
|
303
|
+
* - GET/HAS operations throw errors (programming errors)
|
|
353
304
|
*
|
|
354
|
-
* @returns {
|
|
305
|
+
* @returns {ReactiveDataStore} The dev data store
|
|
355
306
|
*
|
|
356
307
|
* @example
|
|
357
308
|
* ```javascript
|
|
358
|
-
* const
|
|
309
|
+
* const KEY_DEV_AUTO_NAV = 'dev-auto-navigation';
|
|
359
310
|
*
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
* }
|
|
363
|
-
* ```
|
|
364
|
-
*/
|
|
365
|
-
hasData(key) {
|
|
366
|
-
return this.#data.has(key);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Clear all data properties
|
|
311
|
+
* // Set dev data (no-op in production)
|
|
312
|
+
* machine.devData.set(KEY_DEV_AUTO_NAV, true);
|
|
371
313
|
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
* machine.
|
|
375
|
-
*
|
|
376
|
-
|
|
377
|
-
clearData() {
|
|
378
|
-
this.#data.clear();
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Get number of data properties
|
|
314
|
+
* // Get dev data (throws in production)
|
|
315
|
+
* $effect(() => {
|
|
316
|
+
* const autoNav = machine.devData.get(KEY_DEV_AUTO_NAV);
|
|
317
|
+
* console.log('Auto-nav:', autoNav);
|
|
318
|
+
* });
|
|
383
319
|
*
|
|
384
|
-
*
|
|
320
|
+
* // Other operations
|
|
321
|
+
* machine.devData.update({ [KEY_DEV_AUTO_NAV]: false });
|
|
322
|
+
* machine.devData.has(KEY_DEV_AUTO_NAV);
|
|
323
|
+
* machine.devData.delete(KEY_DEV_AUTO_NAV);
|
|
324
|
+
* machine.devData.clear();
|
|
325
|
+
* console.log(machine.devData.size);
|
|
326
|
+
* ```
|
|
385
327
|
*/
|
|
386
|
-
get
|
|
387
|
-
return this.#
|
|
328
|
+
get devData() {
|
|
329
|
+
return this.#devData;
|
|
388
330
|
}
|
|
389
331
|
|
|
390
332
|
/* ===== Visited Routes Tracking ===== */
|
|
@@ -78,8 +78,12 @@ const KEY_TUTORIAL_SEEN = 'tutorial-seen';
|
|
|
78
78
|
const KEY_HIGHEST_LEVEL = 'highest-level';
|
|
79
79
|
const KEY_DIFFICULTY = 'difficulty';
|
|
80
80
|
|
|
81
|
+
// Dev data keys (use KEY_DEV_ prefix)
|
|
82
|
+
const KEY_DEV_AUTO_NAVIGATION = 'dev-auto-navigation';
|
|
83
|
+
const KEY_DEV_SKIP_ANIMATIONS = 'dev-skip-animations';
|
|
84
|
+
|
|
81
85
|
export class PuzzleState extends PageMachine {
|
|
82
|
-
#
|
|
86
|
+
#logic;
|
|
83
87
|
|
|
84
88
|
constructor() {
|
|
85
89
|
// Call PageMachine constructor with route config
|
|
@@ -96,14 +100,18 @@ export class PuzzleState extends PageMachine {
|
|
|
96
100
|
[KEY_TUTORIAL_SEEN]: false,
|
|
97
101
|
[KEY_HIGHEST_LEVEL]: 1,
|
|
98
102
|
[KEY_DIFFICULTY]: 'normal'
|
|
103
|
+
},
|
|
104
|
+
initialDevData: {
|
|
105
|
+
[KEY_DEV_AUTO_NAVIGATION]: false,
|
|
106
|
+
[KEY_DEV_SKIP_ANIMATIONS]: false
|
|
99
107
|
}
|
|
100
108
|
});
|
|
101
109
|
|
|
102
|
-
this.#
|
|
110
|
+
this.#logic = new PuzzleGameLogic();
|
|
103
111
|
}
|
|
104
112
|
|
|
105
|
-
get
|
|
106
|
-
return this.#
|
|
113
|
+
get logic() {
|
|
114
|
+
return this.#logic;
|
|
107
115
|
}
|
|
108
116
|
|
|
109
117
|
// Computed properties for convenience
|
|
@@ -161,7 +169,7 @@ export class PuzzleState extends PageMachine {
|
|
|
161
169
|
}
|
|
162
170
|
|
|
163
171
|
reset() {
|
|
164
|
-
this.#
|
|
172
|
+
this.#logic = new PuzzleGameLogic();
|
|
165
173
|
}
|
|
166
174
|
}
|
|
167
175
|
|
|
@@ -209,12 +217,12 @@ export const [createOrGetPuzzleState, createPuzzleState, getPuzzleState] =
|
|
|
209
217
|
{:else if puzzleState.isOnTutorial}
|
|
210
218
|
<TutorialView />
|
|
211
219
|
{:else if puzzleState.isOnLevel1}
|
|
212
|
-
<Level1View gameLogic={puzzleState.
|
|
220
|
+
<Level1View gameLogic={puzzleState.logic} />
|
|
213
221
|
{:else if puzzleState.isOnLevel2}
|
|
214
|
-
<Level2View gameLogic={puzzleState.
|
|
222
|
+
<Level2View gameLogic={puzzleState.logic} />
|
|
215
223
|
{:else if puzzleState.isComplete}
|
|
216
224
|
<CompleteView
|
|
217
|
-
score={puzzleState.
|
|
225
|
+
score={puzzleState.logic.score}
|
|
218
226
|
highestLevel={puzzleState.highestLevel} />
|
|
219
227
|
{/if}
|
|
220
228
|
```
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as SubScribersCount } from "./SubscribersCount.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as SubScribersCount } from './SubscribersCount.js';
|