All good. Now for more fun.

This commit is contained in:
Yaro Kasear 2026-01-21 13:17:43 -06:00
parent ea1f43dcd3
commit d6bb3d8780
2 changed files with 99 additions and 6 deletions

View file

@ -32,8 +32,15 @@ export function createWidgetCore(env) {
// Document and shape lifecycle // Document and shape lifecycle
function loadDoc() { function loadDoc() {
try { return JSON.parse(localStorage.getItem(storageKey)) || structuredClone(DEFAULT_DOC); } try {
catch { return structuredClone(DEFAULT_DOC); } const raw = env.loadRaw
? env.loadRaw()
: localStorage.getItem(storageKey);
return raw ? JSON.parse(raw) : structuredClone(DEFAULT_DOC);
} catch {
return structuredClone(DEFAULT_DOC);
}
} }
function saveDoc(nextDoc = doc) { function saveDoc(nextDoc = doc) {
@ -42,7 +49,13 @@ export function createWidgetCore(env) {
shapes: stripCaches(Array.isArray(nextDoc.shapes) ? nextDoc.shapes : []) shapes: stripCaches(Array.isArray(nextDoc.shapes) ? nextDoc.shapes : [])
}; };
doc = safeDoc; doc = safeDoc;
try { localStorage.setItem(storageKey, JSON.stringify(safeDoc)); } catch { }
const raw = JSON.stringify(safeDoc);
try {
if (env.saveRaw) env.saveRaw(raw);
else localStorage.setItem(storageKey, raw);
} catch { }
} }
function setDoc(nextDoc) { function setDoc(nextDoc) {

View file

@ -1,5 +1,23 @@
import { encode, decode } from './encode-decode.js';
import { createWidgetCore, DEFAULT_DOC } from "./widget-core.js"; import { createWidgetCore, DEFAULT_DOC } from "./widget-core.js";
import { initWidgetEditor } from "./widget-editor.js"; import { initWidgetEditor } from "./widget-editor.js";
import { initWidgetViewer } from "./widget-viewer.js";
function readEmbeddedDoc(root, toastMessage) {
const el = root.querySelector('[data-grid-doc]');
if (!el) return null;
const raw = (el.textContent || '').trim();
if (!raw) return null;
try {
const parsed = JSON.parse(raw);
return decode(parsed);
} catch (err) {
toastMessage?.(`Failed to parse embedded grid JSON: ${err?.message || err}`, 'danger');
return null;
}
}
export function initGridWidget(root, opts = {}) { export function initGridWidget(root, opts = {}) {
const mode = opts.mode || 'editor'; const mode = opts.mode || 'editor';
@ -15,6 +33,12 @@ export function initGridWidget(root, opts = {}) {
const toastMessage = opts.toastMessage || (() => { }); const toastMessage = opts.toastMessage || (() => { });
let initialDoc = opts.doc ?? null;
if (!initialDoc && mode !== 'editor') {
initialDoc = readEmbeddedDoc(root, toastMessage);
}
const core = createWidgetCore({ const core = createWidgetCore({
root, root,
mode, mode,
@ -22,18 +46,67 @@ export function initGridWidget(root, opts = {}) {
gridEl, gridEl,
canvasEl, canvasEl,
viewerOffset: opts.viewerOffset || { x: 0, y: 0 }, viewerOffset: opts.viewerOffset || { x: 0, y: 0 },
doc: opts.doc, doc: initialDoc,
cellSize: opts.cellSize, cellSize: opts.cellSize,
shapes: opts.shapes shapes: opts.shapes,
loadRaw() {
if (mode !== 'editor') return null;
return localStorage.getItem(storageKey);
},
saveRaw(_rawInternalDoc) {
if (mode !== 'editor') return;
const payload = encode({
cellSize: core.cellSize,
shapes: core.shapes,
stripCaches: core.stripCaches,
SHAPE_DEFAULTS: core.SHAPE_DEFAULTS
});
localStorage.setItem(storageKey, JSON.stringify(payload));
}
}); });
const env = { root, gridEl, gridWrapEl, toastMessage, storageKey }; const env = { root, gridEl, gridWrapEl, toastMessage, storageKey };
if (mode === 'editor') {
const raw = localStorage.getItem(storageKey);
if (raw) {
try {
const decoded = decode(JSON.parse(raw));
core.setDoc(decoded);
} catch {
core.setDoc(DEFAULT_DOC);
}
} else {
const raw = root.dataset.doc;
if (raw) {
try {
const decoded = decode(JSON.parse(raw));
core.setDoc(decoded);
} catch {
core.setDoc(DEFAULT_DOC);
}
} else {
core.setDoc(DEFAULT_DOC);
}
}
} else {
const embedded = initialDoc ?? readEmbeddedDoc(root, toastMessage);
if (embedded) core.setDoc(embedded);
}
let editorApi = null; let editorApi = null;
if (mode === 'editor') { if (mode === 'editor') {
editorApi = initWidgetEditor(core, env); editorApi = initWidgetEditor(core, env);
} }
let viewerApi = null;
if (mode !== 'editor') {
viewerApi = initWidgetViewer(core, { core, gridEl, gridWrapEl });
}
const api = { const api = {
core, core,
mode, mode,
@ -52,5 +125,12 @@ export function initGridWidget(root, opts = {}) {
api.cancelStroke = editorApi.cancelStroke; api.cancelStroke = editorApi.cancelStroke;
} }
if (viewerApi) {
api.setDoc = viewerApi.setDoc;
api.redraw = viewerApi.redraw;
api.destroy = viewerApi.destroy;
api.decode = viewerApi.decode;
}
return api; return api;
} }