@chestnutlabs/gcode-preview-svelte 0.18.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,14 +25,20 @@ it automatically; pnpm/yarn users add it explicitly. See the
25
25
  </div>
26
26
  ```
27
27
 
28
- That is a complete viewer. The component ships as a **raw `.svelte` file** (standard Svelte
29
- library packaging — your bundler's svelte plugin compiles it via the `svelte` export condition).
30
- Full defaulted prop surface: `source`, `parseOptions`, `buildVolume` (consumer-wins bed
31
- precedence), `quality`, `colorMode`, `layerRange`, `scrub`, `showTravel`, `progress` (DD-006
32
- observation), `createWorker`. Events: `ready`, `parseerror`, `parsecancelled`, `parseprogress`,
33
- `buildcomplete`, `qualityfallback`, `machinegeometrymismatch`/`discovered`,
34
- `progresspresentationchanged`, `disclosure`, `error`. The full handle is exported as `preview`
35
- (`bind:this` then `.preview`).
28
+ That is a complete viewer. The component ships from the `/GcodePreview.svelte` subpath as a **raw
29
+ `.svelte` file** (standard Svelte library packaging — your bundler's svelte plugin compiles it via
30
+ the `svelte` export condition), not from the package index. The ~24-prop defaulted surface covers
31
+ `source`, `parseOptions`, `buildVolume` (consumer-wins bed precedence), `quality` / `qualityMode`,
32
+ `colorMode`, `theme`, `cameraMode` / `view` / `frameContent`, `layerRange`, `scrub`, `showTravel` /
33
+ `showRetractions` / `showWipe`, `hiddenFeatureRoles` (hide feature roles like Skirt or Brim; gate on
34
+ `capabilities.featureRoles`), `progress` (DD-006 observation), and `createWorker`. Events (13):
35
+ `ready`, `camerachange`, `parseerror`, `parsecancelled`, `parseprogress`, `stage`, `buildcomplete`,
36
+ `qualityfallback`, `machinegeometrymismatch`/`discovered`, `progresspresentationchanged`,
37
+ `disclosure`, `error`. The full handle is exported as `preview` (`bind:this` then `.preview`); its
38
+ `controls` reach the imperative surface — `getRenderStats()` (render diagnostics),
39
+ `pickSegment(ndcX, ndcY, threshold?)` (source-mapping / picking), `isColorModeAvailable(mode)`, and
40
+ `capture(opts?)` (image `Blob`, also `preview.capture`). The handle `state` carries capability-aware
41
+ UI data (`availableColorModes`, `hasRetractions`, `hasColorChanges`).
36
42
 
37
43
  ## Store/action API (build your own controls)
38
44
 
@@ -61,7 +67,44 @@ Batteries default (all dialect adapters + `.gcode.3mf`) needs zero setup under V
61
67
  identical across all three framework adapters by design (see the Vue README for the shared worker
62
68
  documentation).
63
69
 
64
- ## Example
70
+ ## Model viewing (Prepare side)
65
71
 
66
- `tools/example-svelte` in the repository is a complete Vite + Svelte app (corpus load,
67
- layer/scrub, simulated live progress) compiling the raw component through the export condition.
72
+ The `/model` subpath ships a `<ModelViewer>` — the **Prepare**-side counterpart to `<GcodePreview>`.
73
+ Where `<GcodePreview>` draws the toolpath (how a print runs), `<ModelViewer>` draws the **source
74
+ model** (an `.stl` / `.3mf` mesh) — the object before slicing.
75
+
76
+ ```svelte
77
+ <script>
78
+ import ModelViewer from '@chestnutlabs/gcode-preview-svelte/model/ModelViewer.svelte';
79
+ export let bytes;
80
+ </script>
81
+
82
+ <div style="height: 70vh">
83
+ <ModelViewer
84
+ source={{ kind: '3mf', bytes }}
85
+ on:ready={(e) => console.log(e.detail.objectCount, e.detail.materials)}
86
+ />
87
+ </div>
88
+ ```
89
+
90
+ `on:ready` (detail-wrapped, like the other Svelte events) carries the honest material-colour tier:
91
+ `e.detail.materials` is `'known'` / `'approximated'` when the file declared colours the render used,
92
+ and `'unavailable'` when it declared none (a neutral default, never faked). The `createModelViewer`
93
+ store handle mirrors the toolpath component. See
94
+ [`docs/manual/adapters.md`](../../docs/manual/adapters.md) "Two viewers: Preview and Prepare" for the
95
+ cross-adapter tour, and `tools/example-svelte/model.html` for a runnable minimal page.
96
+
97
+ ## Examples
98
+
99
+ `tools/example-svelte` in the repository is a Vite app with two tiers, both driving this published
100
+ package through the `.svelte` export condition (no raw renderer or parser imports):
101
+
102
+ - **`minimal.html`** — the smallest real integration: `<GcodePreview {source}>` plus a fixture
103
+ picker and a layer slider. One short component to copy when getting started.
104
+ - **`showcase.html`** — the full declarative surface: capability-gated color modes (a mode greys out
105
+ with a plain-language reason when the file can't support it), declarative `hiddenFeatureRoles`,
106
+ camera, and `getRenderStats()`/`pickSegment()` diagnostics through the `bind:this` handle
107
+ (`viewer.preview.controls`); the handle's store-contract `state` supplies the reactive UI data.
108
+
109
+ Run it with `npm install --prefix tools/example-svelte && npm run dev --prefix tools/example-svelte`
110
+ (port 5202).
@@ -51,6 +51,9 @@
51
51
  export let showRetractions = false;
52
52
  /** #306/#6: show the build-volume wireframe cage (independent of the bed/plate). Default true. */
53
53
  export let showVolumeCage = true;
54
+ /** DD-031 G3: feature roles to hide (e.g. `[FeatureRole.Skirt, FeatureRole.Brim]`). Declarative
55
+ * form of `controls.setFeatureRoleVisible`; gate on `capabilities.featureRoles`. */
56
+ export let hiddenFeatureRoles = undefined;
54
57
  /** DD-006 live progress observation; null hides the overlay. */
55
58
  export let progress = null;
56
59
  /** Worker factory escape hatch (DD-005 slim/custom entries; D2). */
@@ -166,6 +169,18 @@
166
169
  $: if (progress === null || progress === undefined) preview.clearProgress();
167
170
  else preview.observeProgress(progress);
168
171
 
172
+ // Feature-role visibility (DD-031 G3): diff prev→next so we only toggle roles this prop owns.
173
+ // `roleState` is a plain object (property mutation isn't Svelte-tracked) so the reactive block
174
+ // depends only on `hiddenFeatureRoles` and can't loop on its own bookkeeping.
175
+ const roleState = { prev: [] };
176
+ function applyHiddenRoles(roles) {
177
+ const next = roles ?? [];
178
+ for (const role of roleState.prev) if (!next.includes(role)) preview.controls.setFeatureRoleVisible(role, true);
179
+ for (const role of next) if (!roleState.prev.includes(role)) preview.controls.setFeatureRoleVisible(role, false);
180
+ roleState.prev = [...next];
181
+ }
182
+ $: applyHiddenRoles(hiddenFeatureRoles);
183
+
169
184
  onDestroy(() => preview.dispose());
170
185
  </script>
171
186
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import type { GcodeParseSession, WireParseOptions } from '@chestnutlabs/gcode-parser';
12
12
  import type { MappedProgress, ProgressObservation } from '@chestnutlabs/toolpath-core';
13
- import { type GcodePreviewControls, type GcodePreviewState, type ParseOutcome, type PreviewControllerOptions, type PreviewEvent, type PreviewRenderer } from '@chestnutlabs/gcode-preview-core';
13
+ import { type CaptureOptions, type GcodePreviewControls, type GcodePreviewState, type ParseOutcome, type PreviewControllerOptions, type PreviewEvent, type PreviewRenderer } from '@chestnutlabs/gcode-preview-core';
14
14
  export type { GcodePreviewControls, GcodePreviewState, ParseOutcome, PreviewEvent, PreviewRenderer, RendererMode } from '@chestnutlabs/gcode-preview-core';
15
15
  /** Svelte-facing options — identical to the controller's (the alias is the public name). */
16
16
  export type CreateGcodePreviewOptions = PreviewControllerOptions;
@@ -34,6 +34,9 @@ export interface SvelteGcodePreview {
34
34
  observeProgress(obs: ProgressObservation): MappedProgress | null;
35
35
  tickProgress(nowMs: number): MappedProgress | null;
36
36
  clearProgress(): void;
37
+ /** Capture the current view as an image `Blob` (DD-030 D1, DD-031 G5) — handle-level parity with the
38
+ * Web Component's `capture()`. Also reachable as `controls.capture`. Rejects on the 2D renderer. */
39
+ capture(opts?: CaptureOptions): Promise<Blob>;
37
40
  controls: GcodePreviewControls;
38
41
  raw: {
39
42
  session: GcodeParseSession;
@@ -1 +1 @@
1
- {"version":3,"file":"create-gcode-preview.d.ts","sourceRoot":"","sources":["../src/create-gcode-preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EACjB,KAAK,eAAe,EACrB,MAAM,kCAAkC,CAAC;AAG1C,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACb,MAAM,kCAAkC,CAAC;AAE1C,4FAA4F;AAC5F,MAAM,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAEjE;4EAC4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAChE;AAED,0DAA0D;AAC1D,MAAM,WAAW,kBAAkB;IACjC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC;yEACqE;IACrE,KAAK,EAAE,aAAa,CAAC;IACrB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,EAAE,iBAAiB,GAAG,kBAAkB,CAAC;IAClD,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9F,MAAM,IAAI,IAAI,CAAC;IACf,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG,cAAc,GAAG,IAAI,CAAC;IACjE,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;IACnD,aAAa,IAAI,IAAI,CAAC;IACtB,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,GAAG,EAAE;QAAE,OAAO,EAAE,iBAAiB,CAAC;QAAC,QAAQ,EAAE,MAAM,eAAe,GAAG,IAAI,CAAA;KAAE,CAAC;IAC5E,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACnD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,yBAA8B,GAAG,kBAAkB,CAuB9F"}
1
+ {"version":3,"file":"create-gcode-preview.d.ts","sourceRoot":"","sources":["../src/create-gcode-preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EACjB,KAAK,eAAe,EACrB,MAAM,kCAAkC,CAAC;AAG1C,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACb,MAAM,kCAAkC,CAAC;AAE1C,4FAA4F;AAC5F,MAAM,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAEjE;4EAC4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAChE;AAED,0DAA0D;AAC1D,MAAM,WAAW,kBAAkB;IACjC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC;yEACqE;IACrE,KAAK,EAAE,aAAa,CAAC;IACrB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,EAAE,iBAAiB,GAAG,kBAAkB,CAAC;IAClD,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9F,MAAM,IAAI,IAAI,CAAC;IACf,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG,cAAc,GAAG,IAAI,CAAC;IACjE,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;IACnD,aAAa,IAAI,IAAI,CAAC;IACtB;yGACqG;IACrG,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,GAAG,EAAE;QAAE,OAAO,EAAE,iBAAiB,CAAC;QAAC,QAAQ,EAAE,MAAM,eAAe,GAAG,IAAI,CAAA;KAAE,CAAC;IAC5E,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACnD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,yBAA8B,GAAG,kBAAkB,CAwB9F"}
@@ -17,6 +17,7 @@ export function createGcodePreview(options = {}) {
17
17
  observeProgress: controller.observeProgress,
18
18
  tickProgress: controller.tickProgress,
19
19
  clearProgress: controller.clearProgress,
20
+ capture: controller.controls.capture,
20
21
  controls: controller.controls,
21
22
  raw: controller.raw,
22
23
  onEvent: controller.onEvent,
@@ -0,0 +1,96 @@
1
+ <script>
2
+ /**
3
+ * <ModelViewer> — the ready-to-use Svelte component for interactive source-model viewing (STL / 3MF),
4
+ * the Prepare-side counterpart to <GcodePreview> (DD-031). A SHELL over `createModelViewer` (the
5
+ * Svelte store/action handle): every prop is a reactive statement into the handle, every dispatched
6
+ * event re-fires a controller event, and the handle is exported for bind:this access (`viewer`).
7
+ * `<ModelViewer source={file} />` alone is a working viewer.
8
+ *
9
+ * Shipped RAW — the consumer's bundler compiles it via the "svelte" export condition.
10
+ */
11
+ import { createEventDispatcher, onDestroy } from 'svelte';
12
+ import { createModelViewer } from './create-model-viewer.js';
13
+
14
+ /** The source model. Changing it re-parses. */
15
+ export let source = null;
16
+ /** Snap to a preset orientation (shared vocabulary with the toolpath camera). */
17
+ export let view = undefined;
18
+ /** Restore a saved camera pose. Pair with the `camerachange` event for two-way binding. */
19
+ export let cameraState = undefined;
20
+ /** 'transparent' (default) | CSS colour | 0xRRGGBB. */
21
+ export let background = undefined;
22
+ /** DD-020 interaction-aware quality; default 'auto'. */
23
+ export let interactionQuality = undefined;
24
+ /** Initial camera projection; default 'perspective'. */
25
+ export let cameraMode = undefined;
26
+ /** Render only a subset: { plateId } / { objectIds } / { instanceFilter }; null = whole source. */
27
+ export let renderScope = undefined;
28
+ /** Source-model triangle / byte caps. */
29
+ export let limits = undefined;
30
+ /** 3MF paint_color palette override (hex per 0-based slot). */
31
+ export let filamentPalette = undefined;
32
+ /** Loader registry (open kind). Default: STL + 3MF. */
33
+ export let loaders = undefined;
34
+ /** Advanced/test: inject GL / orbit controls. */
35
+ export let createRenderer = undefined;
36
+ export let createControls = undefined;
37
+
38
+ const dispatch = createEventDispatcher();
39
+
40
+ /** The full store/action handle — reachable via bind:this={c} then c.viewer. */
41
+ export const viewer = createModelViewer({
42
+ background,
43
+ interactionQuality,
44
+ cameraMode,
45
+ limits,
46
+ filamentPalette,
47
+ loaders,
48
+ renderScope,
49
+ createRenderer,
50
+ createControls,
51
+ onProgress: (p) => dispatch('progress', p)
52
+ });
53
+
54
+ viewer.onEvent((e) => {
55
+ switch (e.type) {
56
+ case 'ready':
57
+ dispatch('ready', e.info);
58
+ break;
59
+ case 'camera-changed':
60
+ dispatch('camerachange', e.state);
61
+ break;
62
+ case 'error':
63
+ dispatch('error', { code: e.code, message: e.message });
64
+ break;
65
+ case 'renderer-unsupported':
66
+ dispatch('rendererunsupported', { feature: e.feature, message: e.message });
67
+ break;
68
+ case 'context-lost':
69
+ dispatch('contextlost');
70
+ break;
71
+ case 'context-restored':
72
+ dispatch('contextrestored');
73
+ break;
74
+ default:
75
+ break;
76
+ }
77
+ });
78
+
79
+ // ---- prop wiring: each prop is a thin reactive call into the handle (D1 shell rule) ----
80
+ $: if (source !== null && source !== undefined) void viewer.controls.setSource(source);
81
+ $: if (view !== undefined) viewer.controls.setView(view);
82
+ $: if (cameraState !== undefined && cameraState !== null) viewer.controls.setCameraState(cameraState);
83
+ $: if (background !== undefined) viewer.controls.setBackground(background);
84
+ $: if (interactionQuality !== undefined) viewer.controls.setInteractionQuality(interactionQuality);
85
+ $: if (renderScope !== undefined) viewer.controls.setRenderScope(renderScope);
86
+
87
+ onDestroy(() => viewer.dispose());
88
+ </script>
89
+
90
+ <!-- tabindex makes the canvas focusable → keyboard camera (DD-004 a11y) -->
91
+ <canvas
92
+ use:viewer.canvas
93
+ tabindex="0"
94
+ style="width: 100%; height: 100%; display: block; touch-action: none;"
95
+ aria-label="3D source-model preview"
96
+ ></canvas>
@@ -0,0 +1,38 @@
1
+ /**
2
+ * createModelViewer — the Svelte reactivity bridge for interactive **source-model** viewing (the
3
+ * Prepare side), the analogue of `createGcodePreview` for the toolpath/Preview side (DD-031). Owns
4
+ * only the Svelte-isms: a store-contract `state` (subscribe receiving controller snapshots) and a
5
+ * `use:` action for the canvas. Engine/state/contracts live in `@chestnutlabs/gcode-model-renderer`
6
+ * and are re-exported, never redeclared (the D1 drift firewall).
7
+ *
8
+ * Named `createModelViewer` to parallel `createGcodePreview`; the underlying engine factory of the same
9
+ * name is imported here under an alias.
10
+ */
11
+ import { type ModelPreviewControllerOptions, type ModelPreviewControls, type ModelPreviewState, type ModelViewer as ModelViewerEngine, type ModelViewerEvent, type ModelReadyInfo } from '@chestnutlabs/gcode-model-renderer';
12
+ import type { CaptureOptions } from '@chestnutlabs/gcode-renderer-three';
13
+ export type { ModelPreviewControls, ModelPreviewState, ModelViewerEvent, ModelReadyInfo };
14
+ /** Svelte-facing options — identical to the controller's (the alias is the public name). */
15
+ export type CreateModelViewerOptions = ModelPreviewControllerOptions;
16
+ /** Minimal svelte/store Readable contract — declared structurally so the shipped JS never imports 'svelte'. */
17
+ export interface ReadableModelState {
18
+ subscribe(run: (state: ModelPreviewState) => void): () => void;
19
+ }
20
+ export interface CanvasActionResult {
21
+ destroy(): void;
22
+ }
23
+ export interface SvelteModelViewer {
24
+ /** Store-contract state: subscribers get the current snapshot immediately, then every replacement. */
25
+ state: ReadableModelState;
26
+ /** Canvas binding as a Svelte action: `<canvas use:viewer.canvas />`. */
27
+ canvas(el: HTMLCanvasElement): CanvasActionResult;
28
+ setSource: ModelPreviewControls['setSource'];
29
+ capture(opts?: CaptureOptions): Promise<Blob>;
30
+ controls: ModelPreviewControls;
31
+ raw: {
32
+ viewer: () => ModelViewerEngine | null;
33
+ };
34
+ onEvent(cb: (e: ModelViewerEvent) => void): () => void;
35
+ dispose(): void;
36
+ }
37
+ export declare function createModelViewer(options?: CreateModelViewerOptions): SvelteModelViewer;
38
+ //# sourceMappingURL=create-model-viewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-model-viewer.d.ts","sourceRoot":"","sources":["../../src/model/create-model-viewer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,WAAW,IAAI,iBAAiB,EACrC,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,CAAC;AAC1F,4FAA4F;AAC5F,MAAM,MAAM,wBAAwB,GAAG,6BAA6B,CAAC;AAErE,+GAA+G;AAC/G,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAChE;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,sGAAsG;IACtG,KAAK,EAAE,kBAAkB,CAAC;IAC1B,yEAAyE;IACzE,MAAM,CAAC,EAAE,EAAE,iBAAiB,GAAG,kBAAkB,CAAC;IAClD,SAAS,EAAE,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,iBAAiB,GAAG,IAAI,CAAA;KAAE,CAAC;IAChD,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACvD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,iBAAiB,CAoB3F"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * createModelViewer — the Svelte reactivity bridge for interactive **source-model** viewing (the
3
+ * Prepare side), the analogue of `createGcodePreview` for the toolpath/Preview side (DD-031). Owns
4
+ * only the Svelte-isms: a store-contract `state` (subscribe receiving controller snapshots) and a
5
+ * `use:` action for the canvas. Engine/state/contracts live in `@chestnutlabs/gcode-model-renderer`
6
+ * and are re-exported, never redeclared (the D1 drift firewall).
7
+ *
8
+ * Named `createModelViewer` to parallel `createGcodePreview`; the underlying engine factory of the same
9
+ * name is imported here under an alias.
10
+ */
11
+ import { createModelPreviewController } from '@chestnutlabs/gcode-model-renderer';
12
+ export function createModelViewer(options = {}) {
13
+ const controller = createModelPreviewController(options);
14
+ return {
15
+ state: {
16
+ subscribe(run) {
17
+ run(controller.getState()); // store contract: immediate emission
18
+ return controller.onStateChange(run);
19
+ }
20
+ },
21
+ canvas: (el) => {
22
+ controller.bindCanvas(el);
23
+ return { destroy: () => controller.bindCanvas(null) };
24
+ },
25
+ setSource: controller.controls.setSource,
26
+ capture: controller.controls.capture,
27
+ controls: controller.controls,
28
+ raw: controller.raw,
29
+ onEvent: controller.onEvent,
30
+ dispose: controller.dispose
31
+ };
32
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @chestnutlabs/gcode-preview-svelte/model — the Svelte integration for interactive **source-model**
3
+ * viewing (STL / 3MF), the Prepare-side counterpart to the toolpath API (DD-031). `createModelViewer`
4
+ * store/action handle + the raw `ModelViewer.svelte` component (import from
5
+ * '@chestnutlabs/gcode-preview-svelte/model/ModelViewer.svelte'). Both are thin bridges over
6
+ * `createModelPreviewController` — never a separate viewer.
7
+ */
8
+ export * from './create-model-viewer.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/model/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @chestnutlabs/gcode-preview-svelte/model — the Svelte integration for interactive **source-model**
3
+ * viewing (STL / 3MF), the Prepare-side counterpart to the toolpath API (DD-031). `createModelViewer`
4
+ * store/action handle + the raw `ModelViewer.svelte` component (import from
5
+ * '@chestnutlabs/gcode-preview-svelte/model/ModelViewer.svelte'). Both are thin bridges over
6
+ * `createModelPreviewController` — never a separate viewer.
7
+ */
8
+ export * from './create-model-viewer.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chestnutlabs/gcode-preview-svelte",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "description": "Thin Svelte integration for the Chestnut Labs G-code viewer (DD-007 D1 amendment): createGcodePreview store/action API + GcodePreview component as a reactivity bridge over @chestnutlabs/gcode-preview-core.",
5
5
  "keywords": [
6
6
  "gcode",
@@ -41,6 +41,15 @@
41
41
  "./GcodePreview.svelte": {
42
42
  "svelte": "./dist/GcodePreview.svelte",
43
43
  "import": "./dist/GcodePreview.svelte"
44
+ },
45
+ "./model": {
46
+ "types": "./dist/model/index.d.ts",
47
+ "svelte": "./dist/model/index.js",
48
+ "import": "./dist/model/index.js"
49
+ },
50
+ "./model/ModelViewer.svelte": {
51
+ "svelte": "./dist/model/ModelViewer.svelte",
52
+ "import": "./dist/model/ModelViewer.svelte"
44
53
  }
45
54
  },
46
55
  "files": [
@@ -55,10 +64,11 @@
55
64
  "test": "vitest run"
56
65
  },
57
66
  "dependencies": {
58
- "@chestnutlabs/gcode-parser": "0.18.0",
59
- "@chestnutlabs/gcode-preview-core": "0.18.0",
60
- "@chestnutlabs/gcode-renderer-three": "0.18.0",
61
- "@chestnutlabs/toolpath-core": "0.18.0"
67
+ "@chestnutlabs/gcode-model-renderer": "0.20.0",
68
+ "@chestnutlabs/gcode-parser": "0.20.0",
69
+ "@chestnutlabs/gcode-preview-core": "0.20.0",
70
+ "@chestnutlabs/gcode-renderer-three": "0.20.0",
71
+ "@chestnutlabs/toolpath-core": "0.20.0"
62
72
  },
63
73
  "peerDependencies": {
64
74
  "svelte": "^4.0.0 || ^5.0.0"