diff --git a/shared/static/scripts/sx-browser.js b/shared/static/scripts/sx-browser.js index b9012d9..84a0355 100644 --- a/shared/static/scripts/sx-browser.js +++ b/shared/static/scripts/sx-browser.js @@ -14,7 +14,7 @@ // ========================================================================= var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } }); - var SX_VERSION = "2026-03-14T22:48:39Z"; + var SX_VERSION = "2026-03-14T23:27:46Z"; function isNil(x) { return x === NIL || x === null || x === undefined; } function isSxTruthy(x) { return x !== false && !isNil(x); } @@ -7019,6 +7019,9 @@ PRIMITIVES["resource"] = resource; function localStorageRemove(key) { try { localStorage.removeItem(key); } catch (e) {} } + PRIMITIVES["local-storage-get"] = localStorageGet; + PRIMITIVES["local-storage-set"] = localStorageSet; + PRIMITIVES["local-storage-remove"] = localStorageRemove; // --- Cookies --- diff --git a/shared/sx/ref/platform_js.py b/shared/sx/ref/platform_js.py index 1a1c032..5f1ffff 100644 --- a/shared/sx/ref/platform_js.py +++ b/shared/sx/ref/platform_js.py @@ -2912,6 +2912,9 @@ PLATFORM_BOOT_JS = """ function localStorageRemove(key) { try { localStorage.removeItem(key); } catch (e) {} } + PRIMITIVES["local-storage-get"] = localStorageGet; + PRIMITIVES["local-storage-set"] = localStorageSet; + PRIMITIVES["local-storage-remove"] = localStorageRemove; // --- Cookies --- diff --git a/sx/sx/home-stepper.sx b/sx/sx/home-stepper.sx index a7a6ff2..6fe77b7 100644 --- a/sx/sx/home-stepper.sx +++ b/sx/sx/home-stepper.sx @@ -174,7 +174,8 @@ (when (and parent rendered) (dom-append parent rendered))))) (swap! step-idx inc) - (update-code-highlight)))) + (update-code-highlight) + (local-storage-set "sx-home-stepper" (freeze-to-sx "home-stepper"))))) (do-back (fn () (when (> (deref step-idx) 0) (let ((target (- (deref step-idx) 1)) @@ -182,7 +183,18 @@ (when container (dom-set-prop container "innerHTML" "")) (set-stack (list (get-preview))) (reset! step-idx 0) - (for-each (fn (_) (do-step)) (slice (deref steps) 0 target))))))) + (for-each (fn (_) (do-step)) (slice (deref steps) 0 target)) + (local-storage-set "sx-home-stepper" (freeze-to-sx "home-stepper"))))))) + ;; Freeze scope for persistence + (freeze-scope "home-stepper" (fn () + (freeze-signal "step" step-idx))) + ;; Restore from localStorage on mount + (let ((saved (local-storage-get "sx-home-stepper"))) + (when saved + (thaw-from-sx saved) + ;; Validate — reset to default if out of range + (when (or (< (deref step-idx) 0) (> (deref step-idx) 16)) + (reset! step-idx 9)))) ;; Auto-parse via effect (effect (fn () (let ((parsed (sx-parse source))) @@ -198,7 +210,9 @@ ;; Defer code DOM build until lake exists (schedule-idle (fn () (build-code-dom) - ;; Replay to initial step-idx + ;; Clear preview and replay to initial step-idx + (let ((preview (get-preview))) + (when preview (dom-set-prop preview "innerHTML" ""))) (let ((target (deref step-idx))) (reset! step-idx 0) (set-stack (list (get-preview))) @@ -213,7 +227,7 @@ ;; Controls (div :class "flex items-center justify-center gap-2 md:gap-3" (button :on-click (fn (e) (do-back)) - :class (str "px-2 py-1 rounded text-lg " + :class (str "px-2 py-1 rounded text-3xl " (if (> (deref step-idx) 0) "text-stone-600 hover:text-stone-800 hover:bg-stone-100" "text-stone-300 cursor-not-allowed")) @@ -221,7 +235,7 @@ (span :class "text-sm text-stone-500 font-mono tabular-nums" (deref step-idx) " / " (len (deref steps))) (button :on-click (fn (e) (do-step)) - :class (str "px-2 py-1 rounded text-lg " + :class (str "px-2 py-1 rounded text-3xl " (if (< (deref step-idx) (len (deref steps))) "text-violet-600 hover:text-violet-800 hover:bg-violet-50" "text-violet-300 cursor-not-allowed"))