@bitstillery/mithril 3.4.0 → 3.4.1
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/package.json +1 -1
- package/render/ssrState.ts +4 -2
- package/store.ts +36 -12
package/package.json
CHANGED
package/render/ssrState.ts
CHANGED
|
@@ -100,8 +100,10 @@ export function serializeStore(state: State<any>): any {
|
|
|
100
100
|
continue
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
// For nested states, only serialize keys that belong to this state (not parent keys)
|
|
104
|
-
|
|
103
|
+
// For nested states, only serialize keys that belong to this state (not parent keys).
|
|
104
|
+
// When originalKeys is empty (e.g. lookup: {}), include all keys so dynamically
|
|
105
|
+
// added entries (e.g. $s.lookup[path] = data) are serialized.
|
|
106
|
+
if (nestedOriginalKeys && nestedOriginalKeys.size > 0 && !nestedOriginalKeys.has(key)) {
|
|
105
107
|
continue
|
|
106
108
|
}
|
|
107
109
|
|
package/store.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {state, State, updateStateRegistry} from './state'
|
|
2
2
|
import {serializeStore, deserializeStore} from './render/ssrState'
|
|
3
|
-
import {ComputedSignal} from './signal'
|
|
4
3
|
|
|
5
4
|
// Helper function to restore computed properties (same as in ssrState.ts)
|
|
6
5
|
function restoreComputedProperties(state: State<any>, initial: any): void {
|
|
@@ -374,22 +373,26 @@ export class Store<T extends Record<string, any> = Record<string, any>> {
|
|
|
374
373
|
return
|
|
375
374
|
}
|
|
376
375
|
|
|
377
|
-
// Default to
|
|
378
|
-
const
|
|
379
|
-
const
|
|
380
|
-
const
|
|
376
|
+
// Default: write to localStorage and sessionStorage when no options; session is opt-in
|
|
377
|
+
const writeLocalStorage = options?.saved ?? options === undefined
|
|
378
|
+
const writeSessionStorage = options?.tab ?? options === undefined
|
|
379
|
+
const writeSessionApi = options?.session === true
|
|
381
380
|
|
|
382
|
-
// Use SSR serialization which properly handles State objects and skips ComputedSignal properties
|
|
383
|
-
// This is the same mechanism used for SSR, ensuring consistency
|
|
384
381
|
const statePlain = serializeStore(this.stateInstance)
|
|
385
382
|
|
|
386
|
-
//
|
|
387
|
-
if (
|
|
383
|
+
// Write to localStorage (persistent across browser restarts)
|
|
384
|
+
if (writeLocalStorage && this.templates.saved) {
|
|
388
385
|
this.set(this.storageKey, this.blueprint(statePlain, copy_object(this.templates.saved)))
|
|
389
386
|
}
|
|
390
387
|
|
|
391
|
-
//
|
|
392
|
-
|
|
388
|
+
// Lookup is always persisted to localStorage when present, regardless of writeLocalStorage.
|
|
389
|
+
// This ensures cached values (e.g. filter/sort state) are never lost when save() is called.
|
|
390
|
+
if ((statePlain as any).lookup) {
|
|
391
|
+
this.persist_lookup_to_local_storage(statePlain)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Write to sessionStorage (tab-scoped, cleared when tab closes)
|
|
395
|
+
if (writeSessionStorage && this.templates.tab) {
|
|
393
396
|
const tabState = (this.stateInstance as any).tab
|
|
394
397
|
if (tabState) {
|
|
395
398
|
// Get the tab template - unwrap if it's nested under a 'tab' key
|
|
@@ -420,7 +423,7 @@ export class Store<T extends Record<string, any> = Record<string, any>> {
|
|
|
420
423
|
// Save to session API (session state) - async by nature
|
|
421
424
|
// Only save session on client side (not during SSR)
|
|
422
425
|
if (
|
|
423
|
-
|
|
426
|
+
writeSessionApi &&
|
|
424
427
|
this.templates.session &&
|
|
425
428
|
Object.keys(this.templates.session).length > 0 &&
|
|
426
429
|
typeof window !== 'undefined'
|
|
@@ -441,6 +444,27 @@ export class Store<T extends Record<string, any> = Record<string, any>> {
|
|
|
441
444
|
}
|
|
442
445
|
}
|
|
443
446
|
|
|
447
|
+
/**
|
|
448
|
+
* Merge lookup from state into localStorage and write. Ensures lookup is always persisted
|
|
449
|
+
* whenever save() is called and state contains lookup.
|
|
450
|
+
*/
|
|
451
|
+
private persist_lookup_to_local_storage(statePlain: Record<string, any>): void {
|
|
452
|
+
if (typeof window === 'undefined') return
|
|
453
|
+
try {
|
|
454
|
+
const existing = this.get(this.storageKey)
|
|
455
|
+
let storeData: Record<string, any> = {}
|
|
456
|
+
try {
|
|
457
|
+
storeData = JSON.parse(existing) || {}
|
|
458
|
+
} catch {
|
|
459
|
+
storeData = {}
|
|
460
|
+
}
|
|
461
|
+
storeData.lookup = copy_object(statePlain.lookup || {})
|
|
462
|
+
window.localStorage.setItem(this.storageKey, JSON.stringify(storeData))
|
|
463
|
+
} catch (err) {
|
|
464
|
+
console.error('Cannot persist lookup to Local Storage; continue without.', err)
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
444
468
|
set(key: string, item: object): void {
|
|
445
469
|
if (typeof window === 'undefined') return
|
|
446
470
|
try {
|