@hkdigital/lib-core 0.5.90 → 0.5.92
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/README.md +445 -0
- package/dist/state/machines/page-machine/README.md +71 -20
- package/dist/ui/CHANGES-COMPONENT-PROPS.md +121 -0
- package/dist/ui/components/game-box/GameBox.svelte +10 -7
- package/dist/ui/components/game-box/GameBox.svelte.d.ts +2 -0
- package/dist/ui/components/game-box/ScaledContainer.svelte +12 -9
- package/dist/ui/components/grid-layers/GridLayers.svelte +9 -7
- package/dist/ui/components/grid-layers/GridLayers.svelte.d.ts +2 -0
- package/dist/ui/components/image-box/ImageBox.svelte +9 -7
- package/dist/ui/components/image-box/ImageBox.svelte.d.ts +2 -0
- package/dist/ui/components/presenter/Presenter.svelte +5 -3
- package/dist/ui/components/presenter/Presenter.svelte.d.ts +2 -0
- package/dist/ui/primitives/buttons/button/Button.svelte +9 -7
- package/dist/ui/primitives/buttons/button/Button.svelte.d.ts +2 -0
- package/dist/ui/primitives/icons/SteezeIcon.svelte +7 -5
- package/dist/ui/primitives/icons/SteezeIcon.svelte.d.ts +2 -0
- package/dist/ui/primitives/panels/panel/Panel.svelte +9 -7
- package/dist/ui/primitives/panels/panel/Panel.svelte.d.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
# ReactiveDataStore
|
|
2
|
+
|
|
3
|
+
Reactive key-value data store with fine-grained reactivity built on Svelte 5's
|
|
4
|
+
`SvelteMap`.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- **Fine-grained reactivity**: Effects only re-run when specific keys change
|
|
9
|
+
- **Strict mode**: Throws errors on uninitialized key access
|
|
10
|
+
- **Production guard**: Dev-only data mode for development helpers
|
|
11
|
+
- **Full CRUD API**: Set, get, update, delete, check existence, clear
|
|
12
|
+
- **Type-safe**: Use constants for keys to get autocomplete and typo prevention
|
|
13
|
+
|
|
14
|
+
## Basic Usage
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
import { ReactiveDataStore } from '$lib/state/classes.js';
|
|
18
|
+
|
|
19
|
+
// Create a store
|
|
20
|
+
const store = new ReactiveDataStore({
|
|
21
|
+
initialData: {
|
|
22
|
+
score: 0,
|
|
23
|
+
level: 1,
|
|
24
|
+
playerName: 'Alice'
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Set data
|
|
29
|
+
store.set('score', 100);
|
|
30
|
+
|
|
31
|
+
// Get data (reactive)
|
|
32
|
+
$effect(() => {
|
|
33
|
+
const score = store.get('score');
|
|
34
|
+
console.log('Score changed:', score);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Update multiple values
|
|
38
|
+
store.update({
|
|
39
|
+
score: 200,
|
|
40
|
+
level: 5
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Check existence
|
|
44
|
+
if (store.has('score')) {
|
|
45
|
+
// ...
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Get all data (snapshot)
|
|
49
|
+
const allData = store.getAll();
|
|
50
|
+
|
|
51
|
+
// Delete
|
|
52
|
+
store.delete('temporaryFlag');
|
|
53
|
+
|
|
54
|
+
// Clear all
|
|
55
|
+
store.clear();
|
|
56
|
+
|
|
57
|
+
// Get size
|
|
58
|
+
console.log(`Store has ${store.size} entries`);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Options
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
const store = new ReactiveDataStore({
|
|
65
|
+
// Initial key-value pairs
|
|
66
|
+
initialData: {},
|
|
67
|
+
|
|
68
|
+
// Throw on uninitialized key access (default: true)
|
|
69
|
+
strictMode: true,
|
|
70
|
+
|
|
71
|
+
// Dev-only mode (default: false)
|
|
72
|
+
productionGuard: false,
|
|
73
|
+
|
|
74
|
+
// Custom error message prefix (default: 'Data key')
|
|
75
|
+
errorPrefix: 'Custom prefix'
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Fine-Grained Reactivity
|
|
80
|
+
|
|
81
|
+
ReactiveDataStore uses `SvelteMap` internally, providing fine-grained
|
|
82
|
+
reactivity where effects only re-run when the specific keys they access change.
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
const store = new ReactiveDataStore({
|
|
86
|
+
initialData: { score: 0, lives: 3 }
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Effect 1: Only re-runs when 'score' changes
|
|
90
|
+
$effect(() => {
|
|
91
|
+
const score = store.get('score');
|
|
92
|
+
console.log('Score:', score);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Effect 2: Only re-runs when 'lives' changes
|
|
96
|
+
$effect(() => {
|
|
97
|
+
const lives = store.get('lives');
|
|
98
|
+
console.log('Lives:', lives);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// This only triggers Effect 1, not Effect 2
|
|
102
|
+
store.set('score', 100);
|
|
103
|
+
|
|
104
|
+
// This only triggers Effect 2, not Effect 1
|
|
105
|
+
store.set('lives', 2);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Strict Mode (Default)
|
|
109
|
+
|
|
110
|
+
By default, ReactiveDataStore throws errors when accessing uninitialized keys.
|
|
111
|
+
This helps catch typos and ensures data is properly initialized.
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
const store = new ReactiveDataStore();
|
|
115
|
+
|
|
116
|
+
// ❌ Throws: "Data key "score" is not initialized."
|
|
117
|
+
store.get('score');
|
|
118
|
+
|
|
119
|
+
// ✅ Initialize first
|
|
120
|
+
store.set('score', 0);
|
|
121
|
+
store.get('score'); // Works
|
|
122
|
+
|
|
123
|
+
// Or initialize via constructor
|
|
124
|
+
const store2 = new ReactiveDataStore({
|
|
125
|
+
initialData: { score: 0 }
|
|
126
|
+
});
|
|
127
|
+
store2.get('score'); // Works
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Disabling Strict Mode
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
const store = new ReactiveDataStore({
|
|
134
|
+
strictMode: false
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Returns undefined instead of throwing
|
|
138
|
+
const score = store.get('nonexistent'); // undefined
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Production Guard (Dev-Only Data)
|
|
142
|
+
|
|
143
|
+
Use `productionGuard: true` for development-only data that should not be
|
|
144
|
+
accessed in production.
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
const devStore = new ReactiveDataStore({
|
|
148
|
+
initialData: {
|
|
149
|
+
autoNavigation: false,
|
|
150
|
+
skipAnimations: false,
|
|
151
|
+
mockApi: 'localhost'
|
|
152
|
+
},
|
|
153
|
+
productionGuard: true,
|
|
154
|
+
errorPrefix: 'Dev data key'
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// In development mode:
|
|
158
|
+
devStore.set('autoNavigation', true); // ✅ Works
|
|
159
|
+
const value = devStore.get('autoNavigation'); // ✅ Works
|
|
160
|
+
|
|
161
|
+
// In production:
|
|
162
|
+
devStore.set('autoNavigation', true); // ✅ Silent no-op (safe)
|
|
163
|
+
devStore.get('autoNavigation'); // ❌ Throws error (programming bug!)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Why this design?**
|
|
167
|
+
|
|
168
|
+
- **SET operations**: Safe to call conditionally in production (no-op)
|
|
169
|
+
- **GET/HAS operations**: Reading dev data in production is a programming
|
|
170
|
+
error that should fail fast
|
|
171
|
+
|
|
172
|
+
## Using with PageMachine
|
|
173
|
+
|
|
174
|
+
ReactiveDataStore is used internally by PageMachine for data management:
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
import { PageMachine } from '$lib/state/machines.js';
|
|
178
|
+
|
|
179
|
+
const machine = new PageMachine({
|
|
180
|
+
startPath: '/intro',
|
|
181
|
+
initialData: {
|
|
182
|
+
score: 0,
|
|
183
|
+
tutorialSeen: false
|
|
184
|
+
},
|
|
185
|
+
initialDevData: {
|
|
186
|
+
autoNav: false,
|
|
187
|
+
skipAnimations: false
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Access via read-only getters
|
|
192
|
+
machine.data.set('score', 100);
|
|
193
|
+
machine.data.get('score');
|
|
194
|
+
|
|
195
|
+
machine.devData.set('autoNav', true);
|
|
196
|
+
machine.devData.get('autoNav');
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Best Practices
|
|
200
|
+
|
|
201
|
+
### 1. Use Constants for Keys
|
|
202
|
+
|
|
203
|
+
Avoid magic strings - use constants for autocomplete and typo prevention:
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
// ✅ Good - use constants
|
|
207
|
+
const KEY_SCORE = 'score';
|
|
208
|
+
const KEY_PLAYER_NAME = 'player-name';
|
|
209
|
+
const KEY_TUTORIAL_SEEN = 'tutorial-seen';
|
|
210
|
+
|
|
211
|
+
store.set(KEY_SCORE, 100);
|
|
212
|
+
const score = store.get(KEY_SCORE);
|
|
213
|
+
|
|
214
|
+
// ❌ Avoid - magic strings
|
|
215
|
+
store.set('score', 100);
|
|
216
|
+
const score = store.get('scroe'); // Typo! No error until runtime
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### 2. Initialize Data in Constructor
|
|
220
|
+
|
|
221
|
+
Always initialize expected keys in the constructor for strict mode:
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
// ✅ Good
|
|
225
|
+
const store = new ReactiveDataStore({
|
|
226
|
+
initialData: {
|
|
227
|
+
score: 0,
|
|
228
|
+
lives: 3,
|
|
229
|
+
playerName: ''
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// ❌ Avoid - uninitialized keys
|
|
234
|
+
const store = new ReactiveDataStore();
|
|
235
|
+
store.get('score'); // Throws error
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### 3. Use Dev Data for Development Helpers
|
|
239
|
+
|
|
240
|
+
Keep development-only flags separate with production guard:
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
// Regular data
|
|
244
|
+
const data = new ReactiveDataStore({
|
|
245
|
+
initialData: {
|
|
246
|
+
score: 0,
|
|
247
|
+
level: 1
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Dev-only data
|
|
252
|
+
const devData = new ReactiveDataStore({
|
|
253
|
+
initialData: {
|
|
254
|
+
autoNavigation: false,
|
|
255
|
+
skipAnimations: false,
|
|
256
|
+
debugMode: false
|
|
257
|
+
},
|
|
258
|
+
productionGuard: true,
|
|
259
|
+
errorPrefix: 'Dev data key'
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### 4. Use getAll() for Serialization Only
|
|
264
|
+
|
|
265
|
+
`getAll()` returns a snapshot (plain object), not a reactive value. Use it for
|
|
266
|
+
serialization or inspection, not for reactive tracking:
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
// ✅ Good - serialization
|
|
270
|
+
const snapshot = store.getAll();
|
|
271
|
+
await saveToServer(snapshot);
|
|
272
|
+
|
|
273
|
+
// ✅ Good - inspection
|
|
274
|
+
console.log('Current state:', store.getAll());
|
|
275
|
+
|
|
276
|
+
// ❌ Avoid - for reactivity
|
|
277
|
+
$effect(() => {
|
|
278
|
+
const data = store.getAll(); // Re-runs on ANY key change
|
|
279
|
+
console.log(data.score); // Use store.get('score') instead
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## API Reference
|
|
284
|
+
|
|
285
|
+
### Constructor
|
|
286
|
+
|
|
287
|
+
```javascript
|
|
288
|
+
new ReactiveDataStore(options)
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**Options:**
|
|
292
|
+
- `initialData` (object): Initial key-value pairs
|
|
293
|
+
- `strictMode` (boolean): Throw on uninitialized keys (default: `true`)
|
|
294
|
+
- `productionGuard` (boolean): Dev-only mode (default: `false`)
|
|
295
|
+
- `errorPrefix` (string): Error message prefix (default: `'Data key'`)
|
|
296
|
+
|
|
297
|
+
### Methods
|
|
298
|
+
|
|
299
|
+
#### `set(key, value)`
|
|
300
|
+
|
|
301
|
+
Set a data property value. Triggers reactivity for this key.
|
|
302
|
+
|
|
303
|
+
```javascript
|
|
304
|
+
store.set('score', 100);
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
#### `get(key)`
|
|
308
|
+
|
|
309
|
+
Get a data property value. Creates a reactive dependency on this key.
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
const score = store.get('score');
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
**Throws:** Error if key not initialized (strict mode)
|
|
316
|
+
|
|
317
|
+
#### `getAll()`
|
|
318
|
+
|
|
319
|
+
Get all data as a plain object snapshot (not reactive).
|
|
320
|
+
|
|
321
|
+
```javascript
|
|
322
|
+
const snapshot = store.getAll();
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
#### `update(updates)`
|
|
326
|
+
|
|
327
|
+
Update multiple properties at once.
|
|
328
|
+
|
|
329
|
+
```javascript
|
|
330
|
+
store.update({
|
|
331
|
+
score: 100,
|
|
332
|
+
level: 5,
|
|
333
|
+
lives: 2
|
|
334
|
+
});
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
#### `has(key)`
|
|
338
|
+
|
|
339
|
+
Check if a key exists.
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
if (store.has('score')) {
|
|
343
|
+
// Key exists
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
#### `delete(key)`
|
|
348
|
+
|
|
349
|
+
Delete a property.
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
const deleted = store.delete('temporaryFlag');
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Returns:** `true` if key existed and was deleted
|
|
356
|
+
|
|
357
|
+
#### `clear()`
|
|
358
|
+
|
|
359
|
+
Clear all data properties.
|
|
360
|
+
|
|
361
|
+
```javascript
|
|
362
|
+
store.clear();
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### `size` (getter)
|
|
366
|
+
|
|
367
|
+
Get the number of data entries.
|
|
368
|
+
|
|
369
|
+
```javascript
|
|
370
|
+
console.log(`Store has ${store.size} entries`);
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Common Patterns
|
|
374
|
+
|
|
375
|
+
### Persisting to Server
|
|
376
|
+
|
|
377
|
+
```javascript
|
|
378
|
+
const store = new ReactiveDataStore({
|
|
379
|
+
initialData: {
|
|
380
|
+
score: 0,
|
|
381
|
+
level: 1,
|
|
382
|
+
preferences: {}
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// Save snapshot to server
|
|
387
|
+
async function saveProgress() {
|
|
388
|
+
const data = store.getAll();
|
|
389
|
+
await fetch('/api/save', {
|
|
390
|
+
method: 'POST',
|
|
391
|
+
body: JSON.stringify(data)
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Load from server
|
|
396
|
+
async function loadProgress() {
|
|
397
|
+
const response = await fetch('/api/load');
|
|
398
|
+
const data = await response.json();
|
|
399
|
+
store.update(data);
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Computed Values
|
|
404
|
+
|
|
405
|
+
```javascript
|
|
406
|
+
const store = new ReactiveDataStore({
|
|
407
|
+
initialData: {
|
|
408
|
+
score: 0,
|
|
409
|
+
multiplier: 1
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
// Computed value based on store data
|
|
414
|
+
const totalScore = $derived(
|
|
415
|
+
store.get('score') * store.get('multiplier')
|
|
416
|
+
);
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Conditional Effects
|
|
420
|
+
|
|
421
|
+
```javascript
|
|
422
|
+
const store = new ReactiveDataStore({
|
|
423
|
+
initialData: {
|
|
424
|
+
level: 1,
|
|
425
|
+
lives: 3
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// Effect only runs when level changes and lives > 0
|
|
430
|
+
$effect(() => {
|
|
431
|
+
const level = store.get('level');
|
|
432
|
+
const lives = store.get('lives');
|
|
433
|
+
|
|
434
|
+
if (lives > 0) {
|
|
435
|
+
console.log(`Playing level ${level}`);
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
## See Also
|
|
441
|
+
|
|
442
|
+
- [PageMachine](../../machines/page-machine/README.md) - Uses ReactiveDataStore
|
|
443
|
+
for route-aware data management
|
|
444
|
+
- [SubscribersCount](../subscribers-count/SubscribersCount.js) - Another state
|
|
445
|
+
utility class
|
|
@@ -135,32 +135,32 @@ export class PuzzleState extends PageMachine {
|
|
|
135
135
|
return this.current === ROUTE_COMPLETE;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
// Persistent settings/progress (use
|
|
138
|
+
// Persistent settings/progress (use machine.data)
|
|
139
139
|
get hasSeenTutorial() {
|
|
140
|
-
return this.
|
|
140
|
+
return this.data.get(KEY_TUTORIAL_SEEN) || false;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
markTutorialComplete() {
|
|
144
|
-
this.
|
|
144
|
+
this.data.set(KEY_TUTORIAL_SEEN, true);
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
get highestLevel() {
|
|
148
|
-
return this.
|
|
148
|
+
return this.data.get(KEY_HIGHEST_LEVEL) || 1;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
updateHighestLevel(level) {
|
|
152
152
|
const current = this.highestLevel;
|
|
153
153
|
if (level > current) {
|
|
154
|
-
this.
|
|
154
|
+
this.data.set(KEY_HIGHEST_LEVEL, level);
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
get difficulty() {
|
|
159
|
-
return this.
|
|
159
|
+
return this.data.get(KEY_DIFFICULTY) || 'normal';
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
setDifficulty(level) {
|
|
163
|
-
this.
|
|
163
|
+
this.data.set(KEY_DIFFICULTY, level);
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
// Optional: Lifecycle methods
|
|
@@ -273,11 +273,25 @@ puzzleState.isStartPath(path) // Check if path is start path
|
|
|
273
273
|
puzzleState.isOnStartPath // Check if on start path
|
|
274
274
|
puzzleState.redirectToStartPath() // Navigate to start path
|
|
275
275
|
|
|
276
|
-
// Persistent data properties
|
|
277
|
-
puzzleState.
|
|
278
|
-
puzzleState.
|
|
279
|
-
puzzleState.
|
|
280
|
-
puzzleState.
|
|
276
|
+
// Persistent data properties (via ReactiveDataStore)
|
|
277
|
+
puzzleState.data.set(KEY_NAME, value)
|
|
278
|
+
puzzleState.data.get(KEY_NAME)
|
|
279
|
+
puzzleState.data.getAll()
|
|
280
|
+
puzzleState.data.update({ KEY1: val1, KEY2: val2 })
|
|
281
|
+
puzzleState.data.has(KEY_NAME)
|
|
282
|
+
puzzleState.data.delete(KEY_NAME)
|
|
283
|
+
puzzleState.data.clear()
|
|
284
|
+
puzzleState.data.size
|
|
285
|
+
|
|
286
|
+
// Dev data properties (dev-only, via ReactiveDataStore)
|
|
287
|
+
puzzleState.devData.set(KEY_DEV_NAME, value)
|
|
288
|
+
puzzleState.devData.get(KEY_DEV_NAME)
|
|
289
|
+
puzzleState.devData.getAll()
|
|
290
|
+
puzzleState.devData.update({ KEY1: val1 })
|
|
291
|
+
puzzleState.devData.has(KEY_DEV_NAME)
|
|
292
|
+
puzzleState.devData.delete(KEY_DEV_NAME)
|
|
293
|
+
puzzleState.devData.clear()
|
|
294
|
+
puzzleState.devData.size
|
|
281
295
|
|
|
282
296
|
// Visited routes tracking
|
|
283
297
|
puzzleState.hasVisited(route) // e.g., hasVisited('/puzzle/intro')
|
|
@@ -296,9 +310,9 @@ puzzleState.hasSeenTutorial
|
|
|
296
310
|
|
|
297
311
|
## Data Storage Guidelines
|
|
298
312
|
|
|
299
|
-
### When to use `
|
|
313
|
+
### When to use `machine.data` (ReactiveDataStore)
|
|
300
314
|
|
|
301
|
-
Use PageMachine's data
|
|
315
|
+
Use PageMachine's data store for **persistent settings and progress**:
|
|
302
316
|
|
|
303
317
|
- ✅ Tutorial completion flags
|
|
304
318
|
- ✅ User preferences (difficulty, language, sound)
|
|
@@ -319,13 +333,39 @@ const KEY_DIFFICULTY = 'difficulty';
|
|
|
319
333
|
const KEY_HIGHEST_LEVEL = 'highest-level';
|
|
320
334
|
|
|
321
335
|
// Use constants (not strings!)
|
|
322
|
-
pageMachine.
|
|
323
|
-
pageMachine.
|
|
324
|
-
pageMachine.
|
|
336
|
+
pageMachine.data.set(KEY_TUTORIAL_SEEN, true); // ✅ Good
|
|
337
|
+
pageMachine.data.set(KEY_DIFFICULTY, 'hard'); // ✅ Good
|
|
338
|
+
pageMachine.data.set(KEY_HIGHEST_LEVEL, 5); // ✅ Good
|
|
325
339
|
|
|
326
340
|
// DON'T use magic strings
|
|
327
|
-
pageMachine.
|
|
328
|
-
pageMachine.
|
|
341
|
+
pageMachine.data.set('tutorial-seen', true); // ❌ Avoid
|
|
342
|
+
pageMachine.data.set('TUTORIAL_SEEN', true); // ❌ Avoid
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### When to use `machine.devData` (Dev-only ReactiveDataStore)
|
|
346
|
+
|
|
347
|
+
Use PageMachine's devData store for **development helpers**:
|
|
348
|
+
|
|
349
|
+
- ✅ Auto-navigation flags
|
|
350
|
+
- ✅ Skip animations/delays
|
|
351
|
+
- ✅ Mock API endpoints
|
|
352
|
+
- ✅ Debug mode flags
|
|
353
|
+
- ✅ Development-only settings
|
|
354
|
+
|
|
355
|
+
**IMPORTANT**: Use KEY_DEV_ prefix for dev data constants:
|
|
356
|
+
|
|
357
|
+
```javascript
|
|
358
|
+
// Define constants (at top of file)
|
|
359
|
+
const KEY_DEV_AUTO_NAVIGATION = 'dev-auto-navigation';
|
|
360
|
+
const KEY_DEV_SKIP_ANIMATIONS = 'dev-skip-animations';
|
|
361
|
+
const KEY_DEV_MOCK_API = 'dev-mock-api';
|
|
362
|
+
|
|
363
|
+
// Use in development (no-op in production)
|
|
364
|
+
pageMachine.devData.set(KEY_DEV_AUTO_NAVIGATION, true); // ✅ Good
|
|
365
|
+
pageMachine.devData.set(KEY_DEV_SKIP_ANIMATIONS, false); // ✅ Good
|
|
366
|
+
|
|
367
|
+
// Reading in production throws error (programming bug)
|
|
368
|
+
const autoNav = pageMachine.devData.get(KEY_DEV_AUTO_NAVIGATION);
|
|
329
369
|
```
|
|
330
370
|
|
|
331
371
|
### When to use GameLogic with `$state`
|
|
@@ -358,6 +398,17 @@ export class PuzzleGameLogic {
|
|
|
358
398
|
- Routes are the source of truth (no state abstraction layer)
|
|
359
399
|
- Use route constants for clarity and maintainability
|
|
360
400
|
- Always sync in `$effect` watching `$page.url.pathname`
|
|
361
|
-
- Use constants for data keys (e.g., `KEY_TUTORIAL_SEEN`)
|
|
401
|
+
- Use constants for data keys (e.g., `KEY_TUTORIAL_SEEN`, `KEY_DEV_AUTO_NAV`)
|
|
362
402
|
- Separate persistent data (PageMachine) from reactive state (GameLogic)
|
|
363
403
|
- Handle animations in pages using `$effect` or `onMount`
|
|
404
|
+
- Data and devData use [ReactiveDataStore](../../classes/reactive-data-store/README.md)
|
|
405
|
+
for fine-grained reactivity
|
|
406
|
+
- Access data via read-only getters: `machine.data.get()`, `machine.devData.set()`
|
|
407
|
+
|
|
408
|
+
## See Also
|
|
409
|
+
|
|
410
|
+
- [ReactiveDataStore](../../classes/reactive-data-store/README.md) - The
|
|
411
|
+
underlying reactive data storage implementation
|
|
412
|
+
- [FiniteStateMachine](../finite-state-machine/README.md) - For enforced state
|
|
413
|
+
transitions
|
|
414
|
+
- [State Context](../../context/README.md) - For providing state to components
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# UI Component Changes
|
|
2
|
+
|
|
3
|
+
## Property Name Changes (2026-01)
|
|
4
|
+
|
|
5
|
+
### Background
|
|
6
|
+
Skeleton.dev has updated their component API standards, and we follow
|
|
7
|
+
skeleton standards for consistency across the ecosystem.
|
|
8
|
+
|
|
9
|
+
### Changes
|
|
10
|
+
|
|
11
|
+
#### `classes` → `class`
|
|
12
|
+
All UI components now accept `class` instead of `classes` for CSS
|
|
13
|
+
class names.
|
|
14
|
+
|
|
15
|
+
#### `base` → removed
|
|
16
|
+
The `base` property has been deprecated. Use `class` instead.
|
|
17
|
+
|
|
18
|
+
#### `bg` → removed
|
|
19
|
+
The `bg` property has been deprecated. Use `class` instead.
|
|
20
|
+
|
|
21
|
+
### Migration Guide
|
|
22
|
+
|
|
23
|
+
**Before:**
|
|
24
|
+
```svelte
|
|
25
|
+
<SteezeIcon
|
|
26
|
+
base="icon-base"
|
|
27
|
+
classes="text-primary-500"
|
|
28
|
+
src={icon}
|
|
29
|
+
/>
|
|
30
|
+
|
|
31
|
+
<GameBox
|
|
32
|
+
base="box-base"
|
|
33
|
+
bg="bg-surface-100"
|
|
34
|
+
classes="rounded-md"
|
|
35
|
+
/>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**After:**
|
|
39
|
+
```svelte
|
|
40
|
+
<SteezeIcon
|
|
41
|
+
class="icon-base text-primary-500"
|
|
42
|
+
src={icon}
|
|
43
|
+
/>
|
|
44
|
+
|
|
45
|
+
<GameBox
|
|
46
|
+
class="box-base bg-surface-100 rounded-md"
|
|
47
|
+
/>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Implementation Pattern
|
|
51
|
+
|
|
52
|
+
All components follow this exact pattern for backward compatibility:
|
|
53
|
+
|
|
54
|
+
**JSDoc Type:**
|
|
55
|
+
```javascript
|
|
56
|
+
/**
|
|
57
|
+
* @type {{
|
|
58
|
+
* class?: string,
|
|
59
|
+
* base?: string, // Deprecated: use 'class' instead
|
|
60
|
+
* bg?: string, // Deprecated: use 'class' instead (if applicable)
|
|
61
|
+
* classes?: string, // Deprecated: use 'class' instead
|
|
62
|
+
* // ... other props
|
|
63
|
+
* }}
|
|
64
|
+
*/
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Props Destructuring:**
|
|
68
|
+
```javascript
|
|
69
|
+
const {
|
|
70
|
+
class: className,
|
|
71
|
+
base, // Deprecated: kept for backward compatibility
|
|
72
|
+
bg, // Deprecated: kept for backward compatibility (if applicable)
|
|
73
|
+
classes, // Deprecated: kept for backward compatibility
|
|
74
|
+
// ... other props
|
|
75
|
+
} = $props();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Class Attribute Usage:**
|
|
79
|
+
```svelte
|
|
80
|
+
<!-- With bg prop -->
|
|
81
|
+
<div class="{base ?? ''} {bg ?? ''} {className ?? classes ?? ''}"></div>
|
|
82
|
+
|
|
83
|
+
<!-- Without bg prop -->
|
|
84
|
+
<div class="{base ?? ''} {className ?? classes ?? ''}"></div>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Priority Order:**
|
|
88
|
+
1. `base` - applied first if provided
|
|
89
|
+
2. `bg` - applied second if provided and component supports it
|
|
90
|
+
3. `className` - from new `class` prop, applied if `classes` not provided
|
|
91
|
+
4. `classes` - deprecated fallback, applied if `className` not provided
|
|
92
|
+
|
|
93
|
+
### Backward Compatibility
|
|
94
|
+
|
|
95
|
+
During the transition period, components accept both old and new
|
|
96
|
+
property names:
|
|
97
|
+
|
|
98
|
+
- `class` - new standard (recommended)
|
|
99
|
+
- `classes` - deprecated, still works
|
|
100
|
+
- `base` - deprecated, still works
|
|
101
|
+
- `bg` - deprecated, still works (GameBox only)
|
|
102
|
+
|
|
103
|
+
All properties will be merged if provided together, allowing gradual
|
|
104
|
+
migration without breaking existing code.
|
|
105
|
+
|
|
106
|
+
### Timeline
|
|
107
|
+
|
|
108
|
+
- **Now**: Both old and new properties supported
|
|
109
|
+
- **Future**: `base`, `bg`, and `classes` will be removed in a future
|
|
110
|
+
major version
|
|
111
|
+
|
|
112
|
+
### Affected Components
|
|
113
|
+
|
|
114
|
+
- `SteezeIcon.svelte`
|
|
115
|
+
- `GameBox.svelte`
|
|
116
|
+
- `ImageBox.svelte`
|
|
117
|
+
- `Presenter.svelte`
|
|
118
|
+
- `GridLayers.svelte`
|
|
119
|
+
- `Panel.svelte`
|
|
120
|
+
- `Button.svelte`
|
|
121
|
+
- More components will be updated following this pattern
|
|
@@ -26,9 +26,10 @@
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* @type {{
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
29
|
+
* class?: string,
|
|
30
|
+
* base?: string, // Deprecated: use 'class' instead
|
|
31
|
+
* bg?: string, // Deprecated: use 'class' instead
|
|
32
|
+
* classes?: string, // Deprecated: use 'class' instead
|
|
32
33
|
* style?: string,
|
|
33
34
|
* aspectOnLandscape?: number,
|
|
34
35
|
* aspectOnPortrait?: number,
|
|
@@ -57,9 +58,10 @@
|
|
|
57
58
|
*/
|
|
58
59
|
const {
|
|
59
60
|
// > Style
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
class: className,
|
|
62
|
+
base, // Deprecated: kept for backward compatibility
|
|
63
|
+
bg, // Deprecated: kept for backward compatibility
|
|
64
|
+
classes, // Deprecated: kept for backward compatibility
|
|
63
65
|
style = '',
|
|
64
66
|
|
|
65
67
|
// > Functional properties
|
|
@@ -468,8 +470,9 @@
|
|
|
468
470
|
<div
|
|
469
471
|
data-component="game-box"
|
|
470
472
|
data-orientation={isLandscape ? 'landscape' : 'portrait'}
|
|
471
|
-
class="{base} {bg} {classes}"
|
|
473
|
+
class="{base ?? ''} {bg ?? ''} {className ?? classes ?? ''}"
|
|
472
474
|
class:isMobile
|
|
475
|
+
style:position="relative"
|
|
473
476
|
style:width="{gameWidth}px"
|
|
474
477
|
style:height="{gameHeight}px"
|
|
475
478
|
style:--game-width={gameWidth}
|
|
@@ -3,6 +3,7 @@ type GameBox = {
|
|
|
3
3
|
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
4
|
$set?(props: Partial<{
|
|
5
5
|
[attr: string]: any;
|
|
6
|
+
class?: string | undefined;
|
|
6
7
|
base?: string | undefined;
|
|
7
8
|
bg?: string | undefined;
|
|
8
9
|
classes?: string | undefined;
|
|
@@ -51,6 +52,7 @@ type GameBox = {
|
|
|
51
52
|
};
|
|
52
53
|
declare const GameBox: import("svelte").Component<{
|
|
53
54
|
[attr: string]: any;
|
|
55
|
+
class?: string;
|
|
54
56
|
base?: string;
|
|
55
57
|
bg?: string;
|
|
56
58
|
classes?: string;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
// import { onMount } from 'svelte';
|
|
3
|
+
|
|
2
4
|
import { enableContainerScaling } from '../../../design/index.js';
|
|
3
5
|
|
|
6
|
+
// onMount( () => {
|
|
7
|
+
// console.debug('[ScaledContainer] mounted');
|
|
8
|
+
// } );
|
|
9
|
+
|
|
4
10
|
/**
|
|
5
11
|
* Wrapper component that applies container scaling to its children
|
|
6
12
|
*
|
|
@@ -41,8 +47,8 @@
|
|
|
41
47
|
!width ||
|
|
42
48
|
!height ||
|
|
43
49
|
!design ||
|
|
44
|
-
!clamping
|
|
45
|
-
hidden
|
|
50
|
+
!clamping
|
|
51
|
+
|| hidden
|
|
46
52
|
) {
|
|
47
53
|
return;
|
|
48
54
|
}
|
|
@@ -62,16 +68,13 @@
|
|
|
62
68
|
<div
|
|
63
69
|
data-component="scaled-container"
|
|
64
70
|
bind:this={container}
|
|
65
|
-
|
|
71
|
+
style:position="absolute"
|
|
72
|
+
style:top="0"
|
|
73
|
+
style:left="0"
|
|
66
74
|
style:width="{width}px"
|
|
67
75
|
style:height="{height}px"
|
|
76
|
+
style:display={hidden ? "none" : "block"}
|
|
68
77
|
>
|
|
69
78
|
{@render snippet(snippetParams)}
|
|
70
79
|
</div>
|
|
71
80
|
{/if}
|
|
72
|
-
|
|
73
|
-
<style>
|
|
74
|
-
.hidden {
|
|
75
|
-
visibility: hidden;
|
|
76
|
-
}
|
|
77
|
-
</style>
|
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
* enabling layered layouts with natural height behavior.
|
|
7
7
|
*
|
|
8
8
|
* @type {{
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* class?: string,
|
|
10
|
+
* base?: string, // Deprecated: use 'class' instead
|
|
11
|
+
* bg?: string, // Deprecated: use 'class' instead
|
|
11
12
|
* padding?: string,
|
|
12
13
|
* margin?: string,
|
|
13
|
-
* classes?: string,
|
|
14
|
+
* classes?: string, // Deprecated: use 'class' instead
|
|
14
15
|
* style?: string,
|
|
15
16
|
* overflow?: string,
|
|
16
17
|
* children: import('svelte').Snippet,
|
|
@@ -19,11 +20,12 @@
|
|
|
19
20
|
*/
|
|
20
21
|
const {
|
|
21
22
|
// Container styles
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
class: className,
|
|
24
|
+
base, // Deprecated: kept for backward compatibility
|
|
25
|
+
bg, // Deprecated: kept for backward compatibility
|
|
24
26
|
padding = '',
|
|
25
27
|
margin = '',
|
|
26
|
-
classes
|
|
28
|
+
classes, // Deprecated: kept for backward compatibility
|
|
27
29
|
style = '',
|
|
28
30
|
overflow = '',
|
|
29
31
|
|
|
@@ -48,7 +50,7 @@
|
|
|
48
50
|
|
|
49
51
|
<div
|
|
50
52
|
data-component="grid-layers"
|
|
51
|
-
class="grid {base} {bg} {classes} {margin} {padding} {overflow}"
|
|
53
|
+
class="grid {base ?? ''} {bg ?? ''} {className ?? classes ?? ''} {margin} {padding} {overflow}"
|
|
52
54
|
style={containerStyle}
|
|
53
55
|
{...attrs}
|
|
54
56
|
>
|
|
@@ -3,6 +3,7 @@ type GridLayers = {
|
|
|
3
3
|
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
4
|
$set?(props: Partial<{
|
|
5
5
|
[attr: string]: any;
|
|
6
|
+
class?: string | undefined;
|
|
6
7
|
base?: string | undefined;
|
|
7
8
|
bg?: string | undefined;
|
|
8
9
|
padding?: string | undefined;
|
|
@@ -15,6 +16,7 @@ type GridLayers = {
|
|
|
15
16
|
};
|
|
16
17
|
declare const GridLayers: import("svelte").Component<{
|
|
17
18
|
[attr: string]: any;
|
|
19
|
+
class?: string;
|
|
18
20
|
base?: string;
|
|
19
21
|
bg?: string;
|
|
20
22
|
padding?: string;
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @type {{
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* class?: string,
|
|
8
|
+
* base?: string, // Deprecated: use 'class' instead
|
|
9
|
+
* bg?: string, // Deprecated: use 'class' instead
|
|
10
|
+
* classes?: string, // Deprecated: use 'class' instead
|
|
10
11
|
* width?: string,
|
|
11
12
|
* height?: string,
|
|
12
13
|
* aspect?: string,
|
|
@@ -23,9 +24,10 @@
|
|
|
23
24
|
*/
|
|
24
25
|
let {
|
|
25
26
|
// Style
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
class: className,
|
|
28
|
+
base, // Deprecated: kept for backward compatibility
|
|
29
|
+
bg, // Deprecated: kept for backward compatibility
|
|
30
|
+
classes, // Deprecated: kept for backward compatibility
|
|
29
31
|
width,
|
|
30
32
|
height,
|
|
31
33
|
aspect,
|
|
@@ -172,7 +174,7 @@
|
|
|
172
174
|
<div
|
|
173
175
|
data-component="image-box"
|
|
174
176
|
bind:this={containerElem}
|
|
175
|
-
class="{base} {bg} {aspect} {overflow} {width} {height} {classes}"
|
|
177
|
+
class="{base ?? ''} {bg ?? ''} {aspect} {overflow} {width} {height} {className ?? classes ?? ''}"
|
|
176
178
|
style:--fit={fit}
|
|
177
179
|
style:--pos={position}
|
|
178
180
|
style:width={width || (height && aspect) ? undefined : '100%'}
|
|
@@ -3,6 +3,7 @@ type ImageBox = {
|
|
|
3
3
|
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
4
|
$set?(props: Partial<{
|
|
5
5
|
[attr: string]: any;
|
|
6
|
+
class?: string | undefined;
|
|
6
7
|
base?: string | undefined;
|
|
7
8
|
bg?: string | undefined;
|
|
8
9
|
classes?: string | undefined;
|
|
@@ -21,6 +22,7 @@ type ImageBox = {
|
|
|
21
22
|
};
|
|
22
23
|
declare const ImageBox: import("svelte").Component<{
|
|
23
24
|
[attr: string]: any;
|
|
25
|
+
class?: string;
|
|
24
26
|
base?: string;
|
|
25
27
|
bg?: string;
|
|
26
28
|
classes?: string;
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @type {{
|
|
19
|
-
*
|
|
19
|
+
* class?: string,
|
|
20
|
+
* classes?: string, // Deprecated: use 'class' instead
|
|
20
21
|
* slides?: import("./typedef.js").Slide[],
|
|
21
22
|
* presenterRef?: import('./Presenter.state.svelte.js').PresenterRef,
|
|
22
23
|
* layoutSnippet: import('svelte').Snippet<[Slide|null, Layer]>,
|
|
@@ -25,7 +26,8 @@
|
|
|
25
26
|
*/
|
|
26
27
|
let {
|
|
27
28
|
// > Style
|
|
28
|
-
|
|
29
|
+
class: className,
|
|
30
|
+
classes, // Deprecated: kept for backward compatibility
|
|
29
31
|
|
|
30
32
|
// > Functional
|
|
31
33
|
slides,
|
|
@@ -109,7 +111,7 @@
|
|
|
109
111
|
});
|
|
110
112
|
</script>
|
|
111
113
|
|
|
112
|
-
<GridLayers data-feature="presenter" {classes}>
|
|
114
|
+
<GridLayers data-feature="presenter" class={className ?? classes ?? ''}>
|
|
113
115
|
<div
|
|
114
116
|
data-layer="layer1"
|
|
115
117
|
style:z-index={presenter.layerA.z}
|
|
@@ -2,6 +2,7 @@ export default Presenter;
|
|
|
2
2
|
type Presenter = {
|
|
3
3
|
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
4
|
$set?(props: Partial<{
|
|
5
|
+
class?: string | undefined;
|
|
5
6
|
classes?: string | undefined;
|
|
6
7
|
slides?: Slide[] | undefined;
|
|
7
8
|
presenterRef?: PresenterRef | undefined;
|
|
@@ -10,6 +11,7 @@ type Presenter = {
|
|
|
10
11
|
}>): void;
|
|
11
12
|
};
|
|
12
13
|
declare const Presenter: import("svelte").Component<{
|
|
14
|
+
class?: string;
|
|
13
15
|
classes?: string;
|
|
14
16
|
slides?: import("./typedef.js").Slide[];
|
|
15
17
|
presenterRef?: import("./Presenter.state.svelte.js").PresenterRef;
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @type {{
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* class?: string,
|
|
7
|
+
* base?: string, // Deprecated: use 'class' instead
|
|
8
|
+
* bg?: string, // Deprecated: use 'class' instead
|
|
9
|
+
* classes?: string, // Deprecated: use 'class' instead
|
|
9
10
|
* type?: string,
|
|
10
11
|
* role?: 'primary' | 'secondary' | 'tertiary' | 'custom',
|
|
11
12
|
* size?: 'sm' | 'md' | 'lg',
|
|
@@ -25,9 +26,10 @@
|
|
|
25
26
|
*/
|
|
26
27
|
const {
|
|
27
28
|
// Style
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
class: className,
|
|
30
|
+
base, // Deprecated: kept for backward compatibility
|
|
31
|
+
bg, // Deprecated: kept for backward compatibility
|
|
32
|
+
classes, // Deprecated: kept for backward compatibility
|
|
31
33
|
|
|
32
34
|
type = '',
|
|
33
35
|
role = 'primary',
|
|
@@ -66,7 +68,7 @@
|
|
|
66
68
|
data-variant={variant}
|
|
67
69
|
data-mode={mode}
|
|
68
70
|
type={buttonType}
|
|
69
|
-
class="{base} {bg} {classes} {stateClasses}"
|
|
71
|
+
class="{base ?? ''} {bg ?? ''} {className ?? classes ?? ''} {stateClasses}"
|
|
70
72
|
disabled={disabled || loading}
|
|
71
73
|
aria-busy={loading}
|
|
72
74
|
aria-pressed={selected}
|
|
@@ -3,6 +3,7 @@ type Button = {
|
|
|
3
3
|
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
4
|
$set?(props: Partial<{
|
|
5
5
|
[key: string]: any;
|
|
6
|
+
class?: string | undefined;
|
|
6
7
|
base?: string | undefined;
|
|
7
8
|
bg?: string | undefined;
|
|
8
9
|
classes?: string | undefined;
|
|
@@ -24,6 +25,7 @@ type Button = {
|
|
|
24
25
|
};
|
|
25
26
|
declare const Button: import("svelte").Component<{
|
|
26
27
|
[key: string]: any;
|
|
28
|
+
class?: string;
|
|
27
29
|
base?: string;
|
|
28
30
|
bg?: string;
|
|
29
31
|
classes?: string;
|
|
@@ -23,8 +23,9 @@
|
|
|
23
23
|
* theme - name of the icon theme (e.g. 'solid' or 'outline')
|
|
24
24
|
*
|
|
25
25
|
* @type {{
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* class?: string,
|
|
27
|
+
* base?: string, // Deprecated: use 'class' instead
|
|
28
|
+
* classes?: string, // Deprecated: use 'class' instead
|
|
28
29
|
* size?: string,
|
|
29
30
|
* variant?: string,
|
|
30
31
|
* src: import('./typedef.js').IconSource,
|
|
@@ -33,8 +34,9 @@
|
|
|
33
34
|
*/
|
|
34
35
|
let {
|
|
35
36
|
// Style
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
class: className,
|
|
38
|
+
base, // Deprecated: kept for backward compatibility
|
|
39
|
+
classes, // Deprecated: kept for backward compatibility
|
|
38
40
|
|
|
39
41
|
size = 'md',
|
|
40
42
|
variant = '',
|
|
@@ -72,7 +74,7 @@
|
|
|
72
74
|
data-variant={variant}
|
|
73
75
|
{...icon.a}
|
|
74
76
|
xmlns="http://www.w3.org/2000/svg"
|
|
75
|
-
class="{base} {classes}"
|
|
77
|
+
class="{base ?? ''} {className ?? classes ?? ''}"
|
|
76
78
|
{...attrs}
|
|
77
79
|
>
|
|
78
80
|
{#each icon.path ?? [] as a}
|
|
@@ -2,6 +2,7 @@ export default SteezeIcon;
|
|
|
2
2
|
type SteezeIcon = {
|
|
3
3
|
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
4
|
$set?(props: Partial<{
|
|
5
|
+
class?: string | undefined;
|
|
5
6
|
base?: string | undefined;
|
|
6
7
|
classes?: string | undefined;
|
|
7
8
|
size?: string | undefined;
|
|
@@ -13,6 +14,7 @@ type SteezeIcon = {
|
|
|
13
14
|
}>): void;
|
|
14
15
|
};
|
|
15
16
|
declare const SteezeIcon: import("svelte").Component<{
|
|
17
|
+
class?: string;
|
|
16
18
|
base?: string;
|
|
17
19
|
classes?: string;
|
|
18
20
|
size?: string;
|
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @type {{
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* class?: string,
|
|
11
|
+
* base?: string, // Deprecated: use 'class' instead
|
|
12
|
+
* bg?: string, // Deprecated: use 'class' instead
|
|
13
|
+
* classes?: string, // Deprecated: use 'class' instead
|
|
13
14
|
* width?: 'sm' | 'md' | 'lg',
|
|
14
15
|
* variant?: string,
|
|
15
16
|
* children?: import('svelte').Snippet,
|
|
@@ -17,9 +18,10 @@
|
|
|
17
18
|
*/
|
|
18
19
|
const {
|
|
19
20
|
// Style
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
class: className,
|
|
22
|
+
base, // Deprecated: kept for backward compatibility
|
|
23
|
+
bg, // Deprecated: kept for backward compatibility
|
|
24
|
+
classes, // Deprecated: kept for backward compatibility
|
|
23
25
|
|
|
24
26
|
width = 'md',
|
|
25
27
|
variant = 'light',
|
|
@@ -36,7 +38,7 @@
|
|
|
36
38
|
data-component="panel"
|
|
37
39
|
data-width={width}
|
|
38
40
|
data-variant={variant}
|
|
39
|
-
class="{base} {bg} {classes}"
|
|
41
|
+
class="{base ?? ''} {bg ?? ''} {className ?? classes ?? ''}"
|
|
40
42
|
{...attrs}
|
|
41
43
|
>
|
|
42
44
|
{@render children()}
|
|
@@ -2,6 +2,7 @@ export default Panel;
|
|
|
2
2
|
type Panel = {
|
|
3
3
|
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
4
|
$set?(props: Partial<{
|
|
5
|
+
class?: string | undefined;
|
|
5
6
|
base?: string | undefined;
|
|
6
7
|
bg?: string | undefined;
|
|
7
8
|
classes?: string | undefined;
|
|
@@ -13,6 +14,7 @@ type Panel = {
|
|
|
13
14
|
}>): void;
|
|
14
15
|
};
|
|
15
16
|
declare const Panel: import("svelte").Component<{
|
|
17
|
+
class?: string;
|
|
16
18
|
base?: string;
|
|
17
19
|
bg?: string;
|
|
18
20
|
classes?: string;
|