Add snippet metadata panel, duplicate, and immediate-load preview (M4.5)

This commit is contained in:
2026-06-06 23:54:59 +03:00
parent 3e89d9a531
commit 80bedd2a8d
13 changed files with 785 additions and 51 deletions
+16 -2
View File
@@ -78,6 +78,14 @@ export function LivePreview() {
// Datasets feed reference resolution (spec §04 step 1). Re-rendering on a
// dataset change keeps a referencing chart live as its data is edited.
const datasets = useDatasetStore(useShallow((s) => s.datasets));
// A programmatic buffer load (select/create/revert/hydrate — `bufferEpoch`) or a
// Draft/Published switch (`editorView`) must render *immediately*, not after the
// typing debounce (spec §03C). Keystrokes change only `shownText`, so when these
// two are unchanged the change is typing and the debounce applies.
const bufferEpoch = useSnippetStore((s) => s.bufferEpoch);
const editorView = useSnippetStore((s) => s.editorView);
// Seed with a sentinel epoch so the very first paint counts as a load (immediate).
const lastLoadRef = useRef({ bufferEpoch: -1, editorView });
const error = usePreviewStore((s) => s.error);
const setError = usePreviewStore((s) => s.setError);
@@ -90,6 +98,12 @@ export function LivePreview() {
if (!node) return;
const text = shownText.trim();
// Immediate on snippet load / view switch (spec §03C), debounced while typing.
const prevLoad = lastLoadRef.current;
const immediate = bufferEpoch !== prevLoad.bufferEpoch || editorView !== prevLoad.editorView;
lastLoadRef.current = { bufferEpoch, editorView };
const delay = immediate ? 0 : RENDER_DEBOUNCE_MS;
// The debounced body is async; wrap in a void IIFE so the timer callback
// returns void (it handles its own errors internally — nothing awaits it).
const timer = setTimeout(() => {
@@ -148,10 +162,10 @@ export function LivePreview() {
}
}
})();
}, RENDER_DEBOUNCE_MS);
}, delay);
return () => clearTimeout(timer);
}, [shownText, fitMode, uiTheme, datasets, setError]);
}, [shownText, fitMode, uiTheme, datasets, setError, bufferEpoch, editorView]);
// Re-fit the chart when its container resizes (e.g. a pane drag). Vega doesn't
// observe the element, so we do: one observer on the stable host node for the