Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2642f04
feat(adapters): close dark-capability gaps with full four-adapter par…
sobechestnut-dev Aug 28, 2026
8810ba4
docs(adapters): correct parity claims + document the closed dark-capa…
sobechestnut-dev Aug 28, 2026
718d1bd
feat(renderer-three): capture({ includeBuildVolume: false }) for grid…
sobechestnut-dev Aug 28, 2026
90cee34
feat(demo): rebuild the demo as the Feature Lab on the published core…
sobechestnut-dev Aug 28, 2026
3ea5f9c
feat(example-react): two-tier example on the published adapter (DD-03…
sobechestnut-dev Aug 29, 2026
cc588e7
feat(example-vue): new two-tier Vue example on the published adapter …
sobechestnut-dev Aug 29, 2026
92f9fcd
feat(example-svelte): two-tier example on the published adapter (DD-0…
sobechestnut-dev Aug 29, 2026
76f1d9e
feat(example-webcomponent): new two-tier Web Component example (DD-03…
sobechestnut-dev Aug 29, 2026
972d58f
docs(adapters): point READMEs + manual at the two-tier examples (DD-0…
sobechestnut-dev Aug 29, 2026
b7f1fc0
chore(examples): expose showcase handle on window + WC diagnostics pa…
sobechestnut-dev Aug 29, 2026
829cacc
docs(visual-coverage): record the DD-031 consumer-UX demonstration su…
sobechestnut-dev Aug 29, 2026
0e5ff63
fix(demo,examples): rail-collapse overlap + WC travel desync + clean …
sobechestnut-dev Aug 29, 2026
c256ae8
feat(model-adapters): shared model controller + React model-viewer ad…
sobechestnut-dev Aug 29, 2026
7922dcd
feat(model-adapters): Vue, Svelte & Web Component model-viewer adapte…
sobechestnut-dev Aug 29, 2026
2fa364c
feat(demo-kit,example-react): model fixtures + React Prepare/Preview …
sobechestnut-dev Aug 29, 2026
9ad74c6
feat(demo,examples): Prepare/Preview model viewing in Feature Lab + a…
sobechestnut-dev Aug 29, 2026
9530df1
fix(demo): hide toolpath count-pill + scrub strip in Prepare mode (DD…
sobechestnut-dev Aug 29, 2026
b25ddb6
docs(model-adapters): document source-model viewing + changeset (DD-031)
sobechestnut-dev Aug 29, 2026
01dfa77
test(adapters): resolve gcode-model-renderer from source in adapter v…
sobechestnut-dev Aug 30, 2026
639d982
fix(release-gates): consumer-vue + pack-check + formatting for the mo…
sobechestnut-dev Aug 30, 2026
b1e1258
fix(lint): clear eslint/prettier errors surfaced by the first branch …
sobechestnut-dev Aug 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/capture-exclude-build-volume.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@chestnutlabs/gcode-renderer-three": minor
---

`CaptureOptions` gains `includeBuildVolume?: boolean` (default `true`). Set it to `false` to exclude
the whole build-volume group (grid + bed surface + origin + cage) from the off-screen capture render
only — so `capture({ background: 'transparent', includeBuildVolume: false })` produces a clean
toolpath-only cutout, matching `ModelRenderer` thumbnails. The live view is untouched (visibility is
restored synchronously, no intermediate frame is painted). The option flows through
`GcodePreviewControls.capture` to every adapter; it is a no-op where there is no build volume
(`ModelViewer`) or no capture (the 2D renderer).
37 changes: 37 additions & 0 deletions .changeset/consumer-ux-parity-dark-capabilities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
"@chestnutlabs/gcode-preview-core": minor
"@chestnutlabs/gcode-preview-vue": minor
"@chestnutlabs/gcode-preview-react": minor
"@chestnutlabs/gcode-preview-svelte": minor
"@chestnutlabs/gcode-preview-element": minor
---

Close the dark-capability gaps so no shipped capability is reachable only through the
`raw.renderer()` escape hatch, with full parity across all four framework adapters (DD-031).

**New on the public controller (`GcodePreviewControls`), so it flows to every adapter's `controls`:**

- `getRenderStats()` — the DD-027 render-diagnostics snapshot (backend, GPU, geometry mode, build
parallelism, timings), previously reachable only on the Three renderer. Returns `null` on the 2D
renderer (which produces no GPU/geometry diagnostics — never a fabricated stats object).
- `pickSegment(ndcX, ndcY, threshold?)` — source-mapping / segment picking, previously renderer-only.
- `isColorModeAvailable(mode)` — the honest per-file color-mode capability gate.

**New capability-aware state (`GcodePreviewState`):** `availableColorModes`, `hasRetractions`,
`hasColorChanges` — refreshed after each parse, so a UI can offer and *explain* controls instead of
guessing (e.g. gray out feature coloring on a file with no feature roles, with a reason).

**Adapter parity:**

- `hiddenFeatureRoles` is now a declarative prop (Vue/React/Svelte) and a `hidden-feature-roles`
attribute (Web Component) — the declarative form of `setFeatureRoleVisible` (hide Skirt/Brim to
declutter a part). Gate it on `capabilities.featureRoles`.
- `capture()` is now a top-level method on the Vue/React/Svelte handles too, matching the Web
Component's `element.capture()`.
- Web Component: `renderer`/`adjacentLayers` gain property accessors; the package now also re-exports
`RendererMode` and `PreviewRenderer`.

All additive — existing code keeps working unchanged; the 2D renderer honors the widened contract as
documented no-ops / honest `null`. The portable behavioral suite is extended (layer-range, color-mode
gating, diagnostics + picking reachability) and gains a controls-completeness parity guard so a
capability can no longer ship in core and silently vanish from an adapter.
39 changes: 39 additions & 0 deletions .changeset/model-viewer-adapters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
"@chestnutlabs/gcode-model-renderer": minor
"@chestnutlabs/gcode-preview-vue": minor
"@chestnutlabs/gcode-preview-react": minor
"@chestnutlabs/gcode-preview-svelte": minor
"@chestnutlabs/gcode-preview-element": minor
---

Make interactive **source-model viewing** (STL / 3MF) a first-class, declarative half of the SDK —
the Prepare side alongside the toolpath Preview side — so consumers no longer have to drop to the
imperative `createModelViewer` engine to show a model in a framework (DD-031).

**New framework-neutral controller** (`@chestnutlabs/gcode-model-renderer`):

- `createModelPreviewController(options)` — the Prepare-side analogue of `gcode-preview-core`'s toolpath
controller. It wraps the existing `createModelViewer` engine unchanged and adds what a framework
binding needs: canvas-deferred construction with `bindCanvas` (rebuilding on a canvas swap and
replaying the last source), a reactive `getState()`/`onStateChange()` snapshot derived from the
engine's events (`ModelPreviewState`: `loading`/`ready`/`rendererSupported`/`objectCount`/`materials`/
`instancedCount`/`decimationApplied`/`bounds`/`plates`/`hasPlates`/`cameraState`/`progress`/`error`),
and an op queue for calls made before the canvas binds. `ModelPreviewControls` exposes `setSource`,
`setView`, get/`setCameraState`, `setBackground`, `setInteractionQuality`, `setRenderScope`, `frame`,
`resize`, and `capture`.
- A portable model behavioral suite ships via the `@chestnutlabs/gcode-model-renderer/testing` subpath
(`runModelBehavioralSuite`) with controls/state completeness parity guards.

**New `/model` adapter subpath on every framework** — thin shells over the one controller, mirroring
each framework's toolpath idiom:

- `@chestnutlabs/gcode-preview-react/model` — `useModelViewer` hook + `<ModelViewer>` component.
- `@chestnutlabs/gcode-preview-vue/model` — `useModelViewer` composable + `<ModelViewer>` component.
- `@chestnutlabs/gcode-preview-svelte/model` — `createModelViewer` store/action + the raw
`@chestnutlabs/gcode-preview-svelte/model/ModelViewer.svelte` component.
- `@chestnutlabs/gcode-preview-element/model` (+ `/model/define`) — the `<gcode-model-viewer>` custom
element (tag chosen to avoid the reserved `<model-viewer>`).

All additive — the toolpath surface is unchanged, and toolpath-only consumers don't pull the model
renderer (it lives behind the opt-in `/model` subpath). Every adapter passes the portable model
behavioral suite; each package gains `@chestnutlabs/gcode-model-renderer` as a dependency.
22 changes: 22 additions & 0 deletions .claude/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,28 @@
"tools/example-svelte"
],
"port": 5202
},
{
"name": "example-vue",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"dev",
"--prefix",
"tools/example-vue"
],
"port": 5203
},
{
"name": "example-webcomponent",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"dev",
"--prefix",
"tools/example-webcomponent"
],
"port": 5204
}
]
}
31 changes: 31 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,37 @@ homepage, feature gallery, manual, demo/examples, screenshots, and the coverage
inventory, then resolve the review. Surfaces live in `tools/release/doc-surfaces.mjs`; the flow is
documented in [`docs/reference/release-process.md`](docs/reference/release-process.md).

## Framework parity completion check (mandatory)

**A public capability is not "done" until it has a deliberate parity decision across every framework
adapter** (DD-031). This applies to **both** viewer surfaces: the toolpath/Preview side
(`GcodePreview` over `gcode-preview-core`) and the source-model/Prepare side (`ModelViewer` over
`gcode-model-renderer`'s `createModelPreviewController`, exposed on each adapter's `/model` subpath).
When a change adds or materially changes a consumer-meaningful capability on a controller or a
renderer, answer each — "not applicable" is a valid, explicit answer, but it must be a decision, not
an omission:

1. Does **core** (`GcodePreviewControls` / `GcodePreviewState` / `PreviewEvent`) expose it correctly?
2. Do **Vue**, **React**, **Svelte**, and the **Web Component** expose it — declaratively where it
logically belongs, imperatively via `controls` otherwise?
3. Are the **lower-level APIs** (`useGcodePreview` / `createGcodePreview` / `element`) covered?
4. Are **events/callbacks** equivalent (allowing each framework's naming idiom)?
5. Is it exercised by the **portable behavioral suite** (`gcode-preview-core/src/testing.ts` for
toolpath; `gcode-model-renderer/src/model-testing.ts` for the model viewer)? The
controls/state-completeness **parity guards** there fail CI if a `GcodePreviewControls` /
`ModelPreviewControls` method (or a state field) isn't reachable through an adapter — add new
controls/state to the matching required list.
6. Does the **Feature Lab demo** expose it, and do the **framework showcase examples** demonstrate it
where useful?
7. Is it **documented** consistently across the adapter READMEs + `docs/manual/adapters.md`, and does
**visual coverage** (`docs/VISUAL_FEATURE_COVERAGE.md`) need updating?

Deliberate per-framework differences (e.g. the Web Component's property-vs-attribute split and the
`<gcode-model-viewer>` tag, Svelte's `.svelte` subpath, the `/model` subpath for source-model viewing)
are fine — but they must be **documented as intentional**, never accidental drift.
No capability should be reachable only through the `raw.renderer()` escape hatch for lack of a public
surface. The release review (`RELEASE_REVIEW.md`) carries a parity line so this is checked before a cut.

## Repo orientation

- `packages/*` — the 14 published packages (foundation → parse → color → render → adapters). Build
Expand Down
33 changes: 31 additions & 2 deletions docs/VISUAL_FEATURE_COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,33 @@ Genuinely deferred, each with a recorded reason (valid dispositions, not silent
These are tracked here so the next release's Public Product + Documentation + Visual Review picks
them up rather than rediscovering them.

## This pass (2026-08-29, DD-031) — consumer UX & framework parity

The consumer-experience pass reworked the *demonstration surfaces* (it added no new engine
capabilities, so the per-capability rows below are unchanged):

- The demo is rebuilt as the **Feature Lab** on the published `gcode-preview-core` controller —
viewport-first, intent-grouped controls, and **capability-aware** UI (a color mode greys out with
a plain-language reason when the file can't support it; the CNC tab appears only when a tool-power
channel exists; capability confidence is shown as tiered badges).
- Every adapter now ships a **two-tier example** (`tools/example-{react,vue,svelte,webcomponent}`):
a genuinely minimal getting-started page and a full **showcase** that mirrors the Feature Lab's
capability-aware UX in that framework's idiom, on the shared demo-kit. This is what makes "find the
interactive version of everything in the docs" true per-framework, not just in the demo.
- Review screenshots of the Feature Lab and the four showcases were captured this pass (dark app UI).
These are **not yet canonical `docs/media` assets**: the manifest harness produces the mid-grey
capability presentation, not app chrome. Deferred: teach the harness to emit app-UI shots (or add a
dark-app class) so these become tracked media — carried to the next Visual Review.
- `getRenderStats` diagnostics and `pickSegment` picking are now reachable through the **public
adapter surface** in all four showcases (previously controls/raw-only) — the dark-capability
closure that section 1's `pickSegment` row and section 4's diagnostics row depend on.
- **Source-model viewing became a first-class declarative half of the SDK**: a `<ModelViewer>` adapter
on each framework's `/model` subpath (over the new `createModelPreviewController`), a Preview/Prepare
toggle in the Feature Lab and all four showcases, and a minimal model page per framework. This moves
the interactive model viewer (§6) from "needs demo exposure" to demonstrated everywhere consumers
look. App-UI screenshots of Prepare mode were captured for review but, like the toolpath showcase
shots, are not yet canonical `docs/media` (same harness gap).

## 1. Toolpath inspection

| Capability | User-facing | Demo | Media | README | Pages gallery | Manual/pkg | Status |
Expand Down Expand Up @@ -165,7 +192,8 @@ them up rather than rediscovering them.
| Toolpath vs source-model (two renderers) | ✅ | model page | `model-render-stl-3mf` | ✅ | gallery | — | covered |
| STL presentation still | ✅ | model page | (in pair) | ✅ | gallery | model-renderer README | covered |
| 3MF material/color presentation | ✅ | model page | (in pair) | ✅ | gallery | model-renderer README | covered |
| Interactive model viewer (`createModelViewer`) | ✅ | model-viewer page | — | ✅ (prose) | gallery | model-renderer README | needs demo exposure (link) + needs animation |
| Interactive model viewer (`createModelViewer`) | ✅ | model-viewer page + Feature Lab (Prepare) | — | ✅ (prose) | gallery | model-renderer README | covered (interactive) — Feature Lab + all 4 showcases have a Prepare mode; animation still nice-to-have |
| Model-viewer framework adapters (`<ModelViewer>` / `/model`) | ✅ | Feature Lab + 4 showcases (Prepare) + model.html minimals | — | ✅ (table) | — | adapters + 4 READMEs | covered (code + examples); app-UI media pending harness support |
| Multi-object files | ✅ | model page | — | mention | gallery | — | needs screenshot |
| Multi-plate files + per-plate render | ✅ | ❌ | — | ❌ | gallery | — | needs demo exposure + needs comparison |
| Render scope / object subsets (`RenderScope`) | ✅ | ❌ | — | ❌ | gallery | recipes | needs demo exposure + needs comparison |
Expand Down Expand Up @@ -207,7 +235,8 @@ them up rather than rediscovering them.

| Capability | User-facing | Demo | Media | README | Pages gallery | Manual/pkg | Status |
|---|:---:|:---:|:---:|:---:|:---:|:---:|---|
| Vue / React / Svelte / Web Component adapters | ✅ | examples | — | ✅ (table) | — | adapters | not visually meaningful (code) |
| Vue / React / Svelte / Web Component adapters | ✅ | two-tier examples + Feature Lab | — | ✅ (table) | — | adapters | covered (code + examples) — each adapter has a minimal + showcase example on the shared design language; canonical app-UI media pending harness support |
| Capability-aware consumer UX (gated modes + reasons, confidence tiers, contextual controls) | ✅ | Feature Lab + 4 showcases | — | ✅ (prose) | — | adapters | demonstrated in demo + examples; review captures exist (dark app UI), not yet canonical mid-grey media |
| Headless toolpath still (`renderStill`) | ✅ | still page | — | ✅ | gallery | reference/still-render | needs screenshot (server-thumbnail context) |
| Headless model still (`renderModelStill`) | ✅ | model page | `model-render-stl-3mf` | ✅ | gallery | model-renderer README | covered |
| Off-thread parsing / cancellation / limits | ✅ | ✅ | — | ✅ (prose) | — | concept-workers | not visually meaningful |
Expand Down
Loading
Loading