mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Format entire codebase with Prettier (mechanical, no behavior change)
This commit is contained in:
@@ -5,7 +5,7 @@ the preview pane. This covers four mechanics: **embedding** a spec via
|
||||
`vega-embed`, **theming** so charts match the active UI theme, **debounced
|
||||
re-rendering** so typing stays smooth, and **error handling** so a broken spec
|
||||
produces a readable message and self-heals. It deliberately stops at the
|
||||
embedding boundary — the *content* of the spec (resolving named-dataset
|
||||
embedding boundary — the _content_ of the spec (resolving named-dataset
|
||||
references, applying fit-mode sizing) is prepared upstream by a pure transform;
|
||||
see §6.
|
||||
|
||||
@@ -63,9 +63,9 @@ export async function renderSpec(
|
||||
config: Config,
|
||||
): Promise<RenderHandle> {
|
||||
const result: EmbedResult = await vegaEmbed(node, spec, {
|
||||
actions: false, // no built-in export/source/editor menu — clean chart
|
||||
renderer: 'svg', // crisp, inspectable, copyable output
|
||||
config, // theme config (see §3)
|
||||
actions: false, // no built-in export/source/editor menu — clean chart
|
||||
renderer: 'svg', // crisp, inspectable, copyable output
|
||||
config, // theme config (see §3)
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -82,7 +82,7 @@ export async function renderSpec(
|
||||
|
||||
Every successful `vegaEmbed` returns a `result.view` (a live Vega `View`
|
||||
instance). It owns timers, signal listeners, and DOM. If you embed a new spec
|
||||
into the same node *without* finalizing the old view, the old one leaks — its
|
||||
into the same node _without_ finalizing the old view, the old one leaks — its
|
||||
listeners keep firing and resources accumulate over a long editing session.
|
||||
|
||||
The renderer that drives re-rendering must therefore hold the previous handle and
|
||||
@@ -92,7 +92,7 @@ destroy it before (or while) creating the next:
|
||||
let current: RenderHandle | null = null;
|
||||
|
||||
async function rerender(node: HTMLElement, spec: TopLevelSpec, config: Config) {
|
||||
current?.destroy(); // tear down the previous view first
|
||||
current?.destroy(); // tear down the previous view first
|
||||
current = await renderSpec(node, spec, config);
|
||||
}
|
||||
```
|
||||
@@ -181,7 +181,7 @@ re-rendering picks up the new config and the chart restyles automatically.
|
||||
|
||||
### Rules
|
||||
|
||||
- **Do** keep `chartConfigFor` as the *only* place that maps a UI theme to a Vega
|
||||
- **Do** keep `chartConfigFor` as the _only_ place that maps a UI theme to a Vega
|
||||
config. Adding a UI theme = adding one config and one map entry.
|
||||
- **Do** set chart `background: 'transparent'` so the pane's own background shows
|
||||
through and theme switches look seamless.
|
||||
@@ -233,8 +233,8 @@ export function escapeVegaField(name: string): string {
|
||||
encoding.x = { field: escapeVegaField(columnName), type: 'quantitative' };
|
||||
```
|
||||
|
||||
This matters wherever Astrolabe *constructs* spec fragments from data-derived
|
||||
column names — most notably the chart builder (see *Chart Builder* spec) and any
|
||||
This matters wherever Astrolabe _constructs_ spec fragments from data-derived
|
||||
column names — most notably the chart builder (see _Chart Builder_ spec) and any
|
||||
helper that injects an encoding. For specs the user authored by hand, escaping is
|
||||
the user's responsibility; Astrolabe does not rewrite hand-authored `field:`
|
||||
values.
|
||||
@@ -293,15 +293,21 @@ export function createDebouncedRenderer(opts: {
|
||||
|
||||
return {
|
||||
schedule() {
|
||||
if (timer) clearTimeout(timer); // cancel the pending render
|
||||
if (timer) clearTimeout(timer); // cancel the pending render
|
||||
timer = setTimeout(run, opts.delayMs());
|
||||
},
|
||||
flush() {
|
||||
if (timer) { clearTimeout(timer); timer = null; }
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
void run();
|
||||
},
|
||||
cancel() {
|
||||
if (timer) { clearTimeout(timer); timer = null; }
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
generation++; // abandon any in-flight result
|
||||
},
|
||||
};
|
||||
@@ -330,7 +336,7 @@ useSettingsStore.subscribe((s, prev) => {
|
||||
### Busy indicator
|
||||
|
||||
`setBusy(true/false)` toggles store state that the preview reads to overlay a
|
||||
**subtle, non-blocking** spinner/shimmer. It sits *over* the existing chart so the
|
||||
**subtle, non-blocking** spinner/shimmer. It sits _over_ the existing chart so the
|
||||
last good render stays visible while the next one computes — the pane never goes
|
||||
blank mid-edit.
|
||||
|
||||
@@ -366,8 +372,8 @@ It does two deterministic things, on a **deep copy** of the spec:
|
||||
Vega-Lite's `"container"` keyword (Original = untouched; Width/Height/Full set
|
||||
the corresponding dimension(s) to `"container"`), recursing the same way.
|
||||
|
||||
This is *content* preparation, not embedding, and it is fully covered by the
|
||||
*Live Preview* spec. The only invariant this doc cares about:
|
||||
This is _content_ preparation, not embedding, and it is fully covered by the
|
||||
_Live Preview_ spec. The only invariant this doc cares about:
|
||||
|
||||
> `prepareSpecForRender` runs on a copy and returns a new spec. The renderer
|
||||
> embeds that returned spec. **The user's stored spec is never mutated by
|
||||
@@ -392,11 +398,11 @@ A spec that cannot be rendered must produce a **readable** message in the previe
|
||||
area and recover on its own once the spec is valid again. Errors arise at three
|
||||
stages, all funneled to one error field the preview reads:
|
||||
|
||||
| Stage | Failure | Surfaced as |
|
||||
|---|---|---|
|
||||
| Parse | Invalid JSON | "Invalid JSON: …" |
|
||||
| Stage | Failure | Surfaced as |
|
||||
| -------------------------------- | -------------------------------------- | ---------------------- |
|
||||
| Parse | Invalid JSON | "Invalid JSON: …" |
|
||||
| Prepare (`prepareSpecForRender`) | Referenced dataset missing/unfetchable | "Dataset not found: …" |
|
||||
| Embed (`vega-embed`) | Vega-Lite compile / data error | "Rendering error: …" |
|
||||
| Embed (`vega-embed`) | Vega-Lite compile / data error | "Rendering error: …" |
|
||||
|
||||
```ts
|
||||
// inside render(), driven by the debounced renderer
|
||||
@@ -427,10 +433,12 @@ async function render(): Promise<void> {
|
||||
current = await renderSpec(node, prepared, config);
|
||||
usePreviewStore.getState().setError(null); // success clears any prior error
|
||||
} catch (e) {
|
||||
usePreviewStore.getState().setError(
|
||||
`Rendering error: ${(e as Error).message}. ` +
|
||||
`Check your JSON syntax and that the spec is valid Vega-Lite.`,
|
||||
);
|
||||
usePreviewStore
|
||||
.getState()
|
||||
.setError(
|
||||
`Rendering error: ${(e as Error).message}. ` +
|
||||
`Check your JSON syntax and that the spec is valid Vega-Lite.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -457,12 +465,12 @@ manual retry, no reload.
|
||||
|
||||
## Summary
|
||||
|
||||
| Concern | Mechanism | Source of truth |
|
||||
|---|---|---|
|
||||
| Embedding | One `renderSpec` over `vega-embed`, `actions: false`, `renderer: 'svg'` | `src/app/services/chart-renderer.ts` |
|
||||
| View teardown | `view.finalize()` before each re-render and on unmount | the renderer's `RenderHandle` |
|
||||
| Theming | Vega `Config` per UI theme, applied at embed time | `chartConfigFor()` in `src/core/vega-themes.ts` |
|
||||
| Field names | `escapeVegaField` on every data-derived `field:` | `src/core/rendering.ts` |
|
||||
| Debounce | `createDebouncedRenderer`, delay from `renderDebounce` setting | `src/app/services/debounced-renderer.ts` |
|
||||
| Spec prep | `prepareSpecForRender` (pure, on a copy) | `src/core/rendering.ts` (see *Live Preview*) |
|
||||
| Errors | One error field, cleared on success, empty = nothing | `PreviewStore.error` |
|
||||
| Concern | Mechanism | Source of truth |
|
||||
| ------------- | ----------------------------------------------------------------------- | ----------------------------------------------- |
|
||||
| Embedding | One `renderSpec` over `vega-embed`, `actions: false`, `renderer: 'svg'` | `src/app/services/chart-renderer.ts` |
|
||||
| View teardown | `view.finalize()` before each re-render and on unmount | the renderer's `RenderHandle` |
|
||||
| Theming | Vega `Config` per UI theme, applied at embed time | `chartConfigFor()` in `src/core/vega-themes.ts` |
|
||||
| Field names | `escapeVegaField` on every data-derived `field:` | `src/core/rendering.ts` |
|
||||
| Debounce | `createDebouncedRenderer`, delay from `renderDebounce` setting | `src/app/services/debounced-renderer.ts` |
|
||||
| Spec prep | `prepareSpecForRender` (pure, on a copy) | `src/core/rendering.ts` (see _Live Preview_) |
|
||||
| Errors | One error field, cleared on success, empty = nothing | `PreviewStore.error` |
|
||||
|
||||
Reference in New Issue
Block a user