@chestnutlabs/gcode-preview-element 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 +65 -5
- package/dist/gcode-preview-element.d.ts +22 -0
- package/dist/gcode-preview-element.d.ts.map +1 -1
- package/dist/gcode-preview-element.js +63 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/model/define.d.ts +2 -0
- package/dist/model/define.d.ts.map +1 -0
- package/dist/model/define.js +7 -0
- package/dist/model/gcode-model-viewer-element.d.ts +68 -0
- package/dist/model/gcode-model-viewer-element.d.ts.map +1 -0
- package/dist/model/gcode-model-viewer-element.js +249 -0
- package/dist/model/index.d.ts +9 -0
- package/dist/model/index.d.ts.map +1 -0
- package/dist/model/index.js +7 -0
- package/package.json +14 -5
package/README.md
CHANGED
|
@@ -43,29 +43,89 @@ Scalar options are **attributes** (also settable as properties); rich options ar
|
|
|
43
43
|
| Attribute | Property | Type | Default |
|
|
44
44
|
|---|---|---|---|
|
|
45
45
|
| `quality` | `quality` | `'auto' \| 'lines' \| 'tubes'` | `'auto'` |
|
|
46
|
+
| `renderer` | `renderer` | `'3d' \| '2d'` — **construction-time** | `'3d'` |
|
|
47
|
+
| `adjacent-layers` | `adjacentLayers` | integer (2D ghost layers) — **construction-time** | — |
|
|
46
48
|
| `camera-mode` | `cameraMode` | `'perspective' \| 'orthographic'` | `'perspective'` |
|
|
47
49
|
| `show-travel` | `showTravel` | `"true" \| "false"` | `true` |
|
|
48
50
|
| `show-retractions` | `showRetractions` | `"true" \| "false"` | `false` |
|
|
49
51
|
| `scrub` | `scrub` | integer | — (all) |
|
|
50
52
|
| `layer-range` | `layerRange` | `"start,end"` / `[number, number]` | — (all) |
|
|
53
|
+
| `hidden-feature-roles` | `hiddenFeatureRoles` | `"6,7"` / `number[]` — hide roles (Skirt, Brim…) | — |
|
|
51
54
|
| — | `source` | `Uint8Array \| ArrayBuffer \| File` | `null` |
|
|
52
55
|
| — | `colorMode` | `ColorMode` | — |
|
|
53
56
|
| — | `theme` | `Theme` | — |
|
|
57
|
+
| — | `tube` | `TubeOptions` — **construction-time** | — |
|
|
54
58
|
| — | `buildVolume` | `BuildVolumeDef \| MachineGeometry` | — |
|
|
55
59
|
| — | `progress` | `ProgressObservation \| null` | `null` |
|
|
56
60
|
| — | `createWorker` | `() => WorkerLike` | batteries default |
|
|
57
61
|
|
|
58
62
|
> `source` is a **property only** (never a URL attribute) — the element does not fetch.
|
|
63
|
+
> `colorMode`, `theme`, `tube`, and `buildVolume` are **property-only** because objects can't be HTML
|
|
64
|
+
> attributes — set them as JS properties. `hidden-feature-roles` gates on `capabilities.featureRoles`
|
|
65
|
+
> (declarative form of `controls.setFeatureRoleVisible`). This is a ~24-option surface; the rest of
|
|
66
|
+
> the declarative props (`qualityMode`, `view`, `cameraState`, `frameContent`, `scrubTime`,
|
|
67
|
+
> `showWipe`, `showVolumeCage`, `interactionQuality`, `parseOptions`, `rendererOptions`, `layerRange`)
|
|
68
|
+
> are set the same way.
|
|
59
69
|
|
|
60
70
|
### DOM events (`CustomEvent`, kebab-case `detail`)
|
|
61
71
|
|
|
62
|
-
`ready` · `
|
|
63
|
-
`
|
|
64
|
-
`machine-geometry-mismatch` · `error`.
|
|
72
|
+
`ready` · `camerachange` · `parse-error` · `parse-cancelled` · `parse-progress` · `stage` ·
|
|
73
|
+
`build-complete` · `disclosure` · `quality-fallback` · `progress-presentation-changed` ·
|
|
74
|
+
`machine-geometry-discovered` · `machine-geometry-mismatch` · `error`.
|
|
75
|
+
|
|
76
|
+
A few event `detail`s are DOM-wrapped, an accepted custom-element idiom: `disclosure` detail is
|
|
77
|
+
`{ text }`, `machine-geometry-discovered` is `{ machine }`, and `machine-geometry-mismatch` is
|
|
78
|
+
`{ message }`.
|
|
65
79
|
|
|
66
80
|
The underlying handle is also exposed as instance members (`state`, `controls`, `raw`, `onEvent`,
|
|
67
|
-
`parse`, `observeProgress`, `tickProgress`, `clearProgress`) for advanced use — the same
|
|
68
|
-
controller surface the other adapters expose.
|
|
81
|
+
`parse`, `observeProgress`, `tickProgress`, `clearProgress`, `capture`) for advanced use — the same
|
|
82
|
+
neutral controller surface the other adapters expose. `controls` reaches the imperative extras —
|
|
83
|
+
`getRenderStats()` (render diagnostics), `pickSegment(ndcX, ndcY, threshold?)` (source-mapping /
|
|
84
|
+
picking), and `isColorModeAvailable(mode)`; `capture(opts?)` (image `Blob`) is both a top-level
|
|
85
|
+
method and `controls.capture`. The handle `state` carries capability-aware UI data
|
|
86
|
+
(`availableColorModes`, `hasRetractions`, `hasColorChanges`).
|
|
87
|
+
|
|
88
|
+
## Model viewing (Prepare side)
|
|
89
|
+
|
|
90
|
+
The `/model/define` entry registers `<gcode-model-viewer>` — the **Prepare**-side counterpart to
|
|
91
|
+
`<gcode-preview>` (the tag deliberately avoids the reserved `<model-viewer>`). Where `<gcode-preview>`
|
|
92
|
+
draws the toolpath (how a print runs), `<gcode-model-viewer>` draws the **source model** (an `.stl` /
|
|
93
|
+
`.3mf` mesh) — the object before slicing.
|
|
94
|
+
|
|
95
|
+
```html
|
|
96
|
+
<script type="module">
|
|
97
|
+
import '@chestnutlabs/gcode-preview-element/model/define'; // registers <gcode-model-viewer>
|
|
98
|
+
|
|
99
|
+
const el = document.querySelector('gcode-model-viewer');
|
|
100
|
+
el.addEventListener('ready', (e) => console.log(e.detail.objectCount, e.detail.materials));
|
|
101
|
+
el.source = { kind: '3mf', bytes }; // rich options are properties; primitives are attributes
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<gcode-model-viewer background="transparent" style="width: 100%; height: 70vh"></gcode-model-viewer>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The `ready` event carries the honest material-colour tier: `e.detail.materials` is `'known'` /
|
|
108
|
+
`'approximated'` when the file declared colours the render used, and `'unavailable'` when it declared
|
|
109
|
+
none (a neutral default, never faked). The same attribute/property split as `<gcode-preview>` applies —
|
|
110
|
+
rich options (`.source`, `.cameraState`, `.renderScope`, …) are properties; primitives (`view`,
|
|
111
|
+
`background`, `camera-mode`) are attributes. See
|
|
112
|
+
[`docs/manual/adapters.md`](../../docs/manual/adapters.md) "Two viewers: Preview and Prepare" for the
|
|
113
|
+
cross-adapter tour, and `tools/example-webcomponent/model.html` for a runnable minimal page.
|
|
114
|
+
|
|
115
|
+
## Examples
|
|
116
|
+
|
|
117
|
+
`tools/example-webcomponent` in the repository is a framework-free Vite app with two tiers, both
|
|
118
|
+
driving this published element (no raw renderer or parser imports):
|
|
119
|
+
|
|
120
|
+
- **`minimal.html`** — the smallest real integration: import `/define` to register `<gcode-preview>`,
|
|
121
|
+
set the `source` property, listen for `ready`; the layer slider drives the `layer-range` attribute.
|
|
122
|
+
Shows the attribute/property split in ~40 lines.
|
|
123
|
+
- **`showcase.html`** — the full surface in vanilla JS: objects (`source`, `colorMode`,
|
|
124
|
+
`hiddenFeatureRoles`) set as properties, primitives (`layer-range`, `view`) as attributes;
|
|
125
|
+
capability-gated color modes; `getRenderStats()`/`pickSegment()` diagnostics via `element.controls`.
|
|
126
|
+
|
|
127
|
+
Run it with `npm install --prefix tools/example-webcomponent && npm run dev --prefix
|
|
128
|
+
tools/example-webcomponent` (port 5204).
|
|
69
129
|
|
|
70
130
|
## Workers
|
|
71
131
|
|
|
@@ -34,6 +34,8 @@ export declare class GcodePreviewElement extends HTMLElement {
|
|
|
34
34
|
private _createWorker;
|
|
35
35
|
private _rendererOptions;
|
|
36
36
|
private _cameraState;
|
|
37
|
+
/** Which roles the `hidden-feature-roles` attribute last hid, for prev→next diffing (DD-031 G3). */
|
|
38
|
+
private prevHiddenRoles;
|
|
37
39
|
get source(): GcodePreviewSource;
|
|
38
40
|
set source(v: GcodePreviewSource);
|
|
39
41
|
get parseOptions(): WireParseOptions | undefined;
|
|
@@ -52,6 +54,17 @@ export declare class GcodePreviewElement extends HTMLElement {
|
|
|
52
54
|
set createWorker(v: (() => WorkerLike) | undefined);
|
|
53
55
|
get rendererOptions(): ElementRendererOptions | undefined;
|
|
54
56
|
set rendererOptions(v: ElementRendererOptions | undefined);
|
|
57
|
+
/**
|
|
58
|
+
* DD-014 D5 renderer selection (DD-031 E1): reflected property accessor over the `renderer`
|
|
59
|
+
* attribute. Construction-time like every adapter — read once at connect; changing it after the
|
|
60
|
+
* element is connected has no effect (mode switching post-mount is out of scope), it just keeps the
|
|
61
|
+
* attribute and property in sync so the value is readable/consistent.
|
|
62
|
+
*/
|
|
63
|
+
get renderer(): string | null;
|
|
64
|
+
set renderer(v: string | null);
|
|
65
|
+
/** 2D only: preceding "ghost" layers (DD-031 E1). Construction-time; reflected accessor over the attribute. */
|
|
66
|
+
get adjacentLayers(): number | null;
|
|
67
|
+
set adjacentLayers(v: number | null);
|
|
55
68
|
get quality(): string | null;
|
|
56
69
|
set quality(v: string | null);
|
|
57
70
|
get qualityMode(): string | null;
|
|
@@ -92,6 +105,13 @@ export declare class GcodePreviewElement extends HTMLElement {
|
|
|
92
105
|
set scrubTime(v: number | null);
|
|
93
106
|
get layerRange(): [number, number] | null;
|
|
94
107
|
set layerRange(v: [number, number] | null);
|
|
108
|
+
/**
|
|
109
|
+
* DD-031 G3: feature roles to hide, as a comma-separated numeric list (`hidden-feature-roles="6,7"`
|
|
110
|
+
* for Skirt+Brim). Declarative form of `controls.setFeatureRoleVisible`; gate on
|
|
111
|
+
* `capabilities.featureRoles`. Import `FeatureRole` from `@chestnutlabs/toolpath-core` for the values.
|
|
112
|
+
*/
|
|
113
|
+
get hiddenFeatureRoles(): number[];
|
|
114
|
+
set hiddenFeatureRoles(v: number[] | null);
|
|
95
115
|
get state(): GcodePreviewState;
|
|
96
116
|
get controls(): GcodePreviewControls;
|
|
97
117
|
get raw(): PreviewController['raw'];
|
|
@@ -107,6 +127,8 @@ export declare class GcodePreviewElement extends HTMLElement {
|
|
|
107
127
|
attributeChangedCallback(name: string, _old: string | null, value: string | null): void;
|
|
108
128
|
/** Apply the runtime-only controls (the construction options were set at controller creation). */
|
|
109
129
|
private applyRuntimeState;
|
|
130
|
+
/** Feature-role visibility (DD-031 G3): diff prev→next so we only toggle roles this attribute owns. */
|
|
131
|
+
private applyHiddenRoles;
|
|
110
132
|
private applyProgress;
|
|
111
133
|
private reflect;
|
|
112
134
|
private requireController;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gcode-preview-element.d.ts","sourceRoot":"","sources":["../src/gcode-preview-element.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EACL,uBAAuB,EACvB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAElB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EACV,cAAc,EAEd,WAAW,EAEX,SAAS,EACT,KAAK,EACL,WAAW,EACZ,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"gcode-preview-element.d.ts","sourceRoot":"","sources":["../src/gcode-preview-element.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,7 +26,8 @@ const OBSERVED = [
|
|
|
26
26
|
'show-volume-cage',
|
|
27
27
|
'scrub',
|
|
28
28
|
'scrub-time',
|
|
29
|
-
'layer-range'
|
|
29
|
+
'layer-range',
|
|
30
|
+
'hidden-feature-roles'
|
|
30
31
|
];
|
|
31
32
|
/** The default tag name (DD-009 §4.5). */
|
|
32
33
|
export const DEFAULT_TAG = 'gcode-preview';
|
|
@@ -47,6 +48,8 @@ export class GcodePreviewElement extends HTMLElement {
|
|
|
47
48
|
_createWorker;
|
|
48
49
|
_rendererOptions;
|
|
49
50
|
_cameraState = null;
|
|
51
|
+
/** Which roles the `hidden-feature-roles` attribute last hid, for prev→next diffing (DD-031 G3). */
|
|
52
|
+
prevHiddenRoles = [];
|
|
50
53
|
// ---- rich-option property accessors ----
|
|
51
54
|
get source() {
|
|
52
55
|
return this._source;
|
|
@@ -111,6 +114,26 @@ export class GcodePreviewElement extends HTMLElement {
|
|
|
111
114
|
set rendererOptions(v) {
|
|
112
115
|
this._rendererOptions = v; // construction-only injectables
|
|
113
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* DD-014 D5 renderer selection (DD-031 E1): reflected property accessor over the `renderer`
|
|
119
|
+
* attribute. Construction-time like every adapter — read once at connect; changing it after the
|
|
120
|
+
* element is connected has no effect (mode switching post-mount is out of scope), it just keeps the
|
|
121
|
+
* attribute and property in sync so the value is readable/consistent.
|
|
122
|
+
*/
|
|
123
|
+
get renderer() {
|
|
124
|
+
return this.getAttribute('renderer');
|
|
125
|
+
}
|
|
126
|
+
set renderer(v) {
|
|
127
|
+
this.reflect('renderer', v);
|
|
128
|
+
}
|
|
129
|
+
/** 2D only: preceding "ghost" layers (DD-031 E1). Construction-time; reflected accessor over the attribute. */
|
|
130
|
+
get adjacentLayers() {
|
|
131
|
+
const a = this.getAttribute('adjacent-layers');
|
|
132
|
+
return a === null ? null : Number(a);
|
|
133
|
+
}
|
|
134
|
+
set adjacentLayers(v) {
|
|
135
|
+
this.reflect('adjacent-layers', v);
|
|
136
|
+
}
|
|
114
137
|
// ---- scalar-option accessors (reflect to attributes: one source of truth) ----
|
|
115
138
|
get quality() {
|
|
116
139
|
return this.getAttribute('quality');
|
|
@@ -216,6 +239,17 @@ export class GcodePreviewElement extends HTMLElement {
|
|
|
216
239
|
set layerRange(v) {
|
|
217
240
|
this.reflect('layer-range', v === null ? null : `${v[0]},${v[1]}`);
|
|
218
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* DD-031 G3: feature roles to hide, as a comma-separated numeric list (`hidden-feature-roles="6,7"`
|
|
244
|
+
* for Skirt+Brim). Declarative form of `controls.setFeatureRoleVisible`; gate on
|
|
245
|
+
* `capabilities.featureRoles`. Import `FeatureRole` from `@chestnutlabs/toolpath-core` for the values.
|
|
246
|
+
*/
|
|
247
|
+
get hiddenFeatureRoles() {
|
|
248
|
+
return parseRoleList(this.getAttribute('hidden-feature-roles'));
|
|
249
|
+
}
|
|
250
|
+
set hiddenFeatureRoles(v) {
|
|
251
|
+
this.reflect('hidden-feature-roles', v === null || v.length === 0 ? null : v.join(','));
|
|
252
|
+
}
|
|
219
253
|
// ---- handle-parity passthrough (advanced/parity surface; DOM events are the ergonomic one) ----
|
|
220
254
|
get state() {
|
|
221
255
|
return this.requireController().getState();
|
|
@@ -351,6 +385,9 @@ export class GcodePreviewElement extends HTMLElement {
|
|
|
351
385
|
c.setLayerRange(r[0], r[1]);
|
|
352
386
|
break;
|
|
353
387
|
}
|
|
388
|
+
case 'hidden-feature-roles':
|
|
389
|
+
this.applyHiddenRoles(parseRoleList(value));
|
|
390
|
+
break;
|
|
354
391
|
default:
|
|
355
392
|
break;
|
|
356
393
|
}
|
|
@@ -370,8 +407,24 @@ export class GcodePreviewElement extends HTMLElement {
|
|
|
370
407
|
c.setLayerRange(r[0], r[1]);
|
|
371
408
|
c.setScrubPosition(this.scrub);
|
|
372
409
|
c.setScrubTime(this.scrubTime);
|
|
410
|
+
this.applyHiddenRoles(this.hiddenFeatureRoles);
|
|
373
411
|
this.applyProgress();
|
|
374
412
|
}
|
|
413
|
+
/** Feature-role visibility (DD-031 G3): diff prev→next so we only toggle roles this attribute owns. */
|
|
414
|
+
applyHiddenRoles(next) {
|
|
415
|
+
if (this.controller === null)
|
|
416
|
+
return;
|
|
417
|
+
const c = this.controller.controls;
|
|
418
|
+
for (const role of this.prevHiddenRoles) {
|
|
419
|
+
if (!next.includes(role))
|
|
420
|
+
c.setFeatureRoleVisible(role, true);
|
|
421
|
+
}
|
|
422
|
+
for (const role of next) {
|
|
423
|
+
if (!this.prevHiddenRoles.includes(role))
|
|
424
|
+
c.setFeatureRoleVisible(role, false);
|
|
425
|
+
}
|
|
426
|
+
this.prevHiddenRoles = [...next];
|
|
427
|
+
}
|
|
375
428
|
applyProgress() {
|
|
376
429
|
if (this.controller === null)
|
|
377
430
|
return;
|
|
@@ -455,6 +508,15 @@ function parseLayerRange(value) {
|
|
|
455
508
|
return null;
|
|
456
509
|
return [parts[0], parts[1]];
|
|
457
510
|
}
|
|
511
|
+
/** Parse `hidden-feature-roles="6,7"` into a numeric role list; ignores blanks/NaN (DD-031 G3). */
|
|
512
|
+
function parseRoleList(value) {
|
|
513
|
+
if (value === null || value.trim() === '')
|
|
514
|
+
return [];
|
|
515
|
+
return value
|
|
516
|
+
.split(',')
|
|
517
|
+
.map((s) => Number(s.trim()))
|
|
518
|
+
.filter((n) => Number.isFinite(n));
|
|
519
|
+
}
|
|
458
520
|
/**
|
|
459
521
|
* Register `<gcode-preview>` (idempotent — safe to call repeatedly and from multiple
|
|
460
522
|
* bundles). Kept as a function (not a module side effect) so the package stays
|
package/dist/index.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* `@chestnutlabs/gcode-preview-element/define` to auto-register.
|
|
6
6
|
*/
|
|
7
7
|
export { GcodePreviewElement, defineGcodePreview, DEFAULT_TAG, type GcodePreviewSource, type ElementRendererOptions } from './gcode-preview-element.js';
|
|
8
|
-
export type { GcodePreviewControls, GcodePreviewState, ParseOutcome, PreviewEvent } from '@chestnutlabs/gcode-preview-core';
|
|
8
|
+
export type { GcodePreviewControls, GcodePreviewState, ParseOutcome, PreviewEvent, PreviewRenderer, RendererMode } from '@chestnutlabs/gcode-preview-core';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC5B,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC5B,MAAM,4BAA4B,CAAC;AAIpC,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACb,MAAM,kCAAkC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/model/define.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Side-effectful registration entry: `import '@chestnutlabs/gcode-preview-element/model/define'`
|
|
3
|
+
* auto-registers `<gcode-model-viewer>`. Kept as a separate subpath so `.../model` stays
|
|
4
|
+
* side-effect-free.
|
|
5
|
+
*/
|
|
6
|
+
import { defineGcodeModelViewer } from './index.js';
|
|
7
|
+
defineGcodeModelViewer();
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <gcode-model-viewer> — the framework-free Web Component for interactive source-model viewing
|
|
3
|
+
* (STL / 3MF), the Prepare-side counterpart to <gcode-preview> (DD-031). A SHELL over
|
|
4
|
+
* `createModelPreviewController`, exactly like the Vue/React/Svelte model adapters: attributes and
|
|
5
|
+
* properties map to controller options / `controls.*` calls, and controller events are re-emitted as
|
|
6
|
+
* DOM `CustomEvent`s. The handle is also exposed as instance members (`state`/`controls`/`raw`/`onEvent`/
|
|
7
|
+
* `setSource`/`capture`) so the shared model behavioral suite runs against it identically.
|
|
8
|
+
*
|
|
9
|
+
* The tag is `gcode-model-viewer` (not the reserved `model-viewer`). No framework peer dependency.
|
|
10
|
+
*/
|
|
11
|
+
import { type ModelBackground, type ModelLimits, type ModelLoader, type ModelPreviewControls, type ModelPreviewState, type ModelSourceInput, type ModelViewer, type ModelViewerEvent, type RenderScope } from '@chestnutlabs/gcode-model-renderer';
|
|
12
|
+
import type { CameraState, CaptureOptions, GLRendererLike, InteractiveStageOptions, RenderTargetCanvas } from '@chestnutlabs/gcode-renderer-three';
|
|
13
|
+
/** The default tag name for the model viewer. */
|
|
14
|
+
export declare const DEFAULT_MODEL_TAG = "gcode-model-viewer";
|
|
15
|
+
export declare class GcodeModelViewerElement extends HTMLElement {
|
|
16
|
+
static get observedAttributes(): string[];
|
|
17
|
+
private controller;
|
|
18
|
+
private canvasEl;
|
|
19
|
+
private _source;
|
|
20
|
+
private _cameraState;
|
|
21
|
+
private _background;
|
|
22
|
+
private _renderScope;
|
|
23
|
+
private _limits;
|
|
24
|
+
private _filamentPalette;
|
|
25
|
+
private _loaders;
|
|
26
|
+
private _createRenderer;
|
|
27
|
+
private _createControls;
|
|
28
|
+
get source(): ModelSourceInput | null;
|
|
29
|
+
set source(v: ModelSourceInput | null);
|
|
30
|
+
get cameraState(): CameraState | null;
|
|
31
|
+
set cameraState(v: CameraState | null);
|
|
32
|
+
get background(): ModelBackground | undefined;
|
|
33
|
+
set background(v: ModelBackground | undefined);
|
|
34
|
+
get renderScope(): RenderScope | null;
|
|
35
|
+
set renderScope(v: RenderScope | null);
|
|
36
|
+
get limits(): ModelLimits | undefined;
|
|
37
|
+
set limits(v: ModelLimits | undefined);
|
|
38
|
+
get filamentPalette(): readonly (string | undefined)[] | undefined;
|
|
39
|
+
set filamentPalette(v: readonly (string | undefined)[] | undefined);
|
|
40
|
+
get loaders(): readonly ModelLoader[] | undefined;
|
|
41
|
+
set loaders(v: readonly ModelLoader[] | undefined);
|
|
42
|
+
get createRenderer(): ((canvas: RenderTargetCanvas) => GLRendererLike) | undefined;
|
|
43
|
+
set createRenderer(v: ((canvas: RenderTargetCanvas) => GLRendererLike) | undefined);
|
|
44
|
+
get createControls(): NonNullable<InteractiveStageOptions['createControls']> | undefined;
|
|
45
|
+
set createControls(v: NonNullable<InteractiveStageOptions['createControls']> | undefined);
|
|
46
|
+
get view(): string | null;
|
|
47
|
+
set view(v: string | null);
|
|
48
|
+
get interactionQuality(): string | null;
|
|
49
|
+
set interactionQuality(v: string | null);
|
|
50
|
+
get cameraMode(): string | null;
|
|
51
|
+
set cameraMode(v: string | null);
|
|
52
|
+
get state(): ModelPreviewState;
|
|
53
|
+
get controls(): ModelPreviewControls;
|
|
54
|
+
get raw(): {
|
|
55
|
+
viewer: () => ModelViewer | null;
|
|
56
|
+
};
|
|
57
|
+
setSource(input: ModelSourceInput): Promise<import('@chestnutlabs/gcode-model-renderer').ModelReadyInfo>;
|
|
58
|
+
capture(opts?: CaptureOptions): Promise<Blob>;
|
|
59
|
+
onEvent(cb: (e: ModelViewerEvent) => void): () => void;
|
|
60
|
+
connectedCallback(): void;
|
|
61
|
+
disconnectedCallback(): void;
|
|
62
|
+
attributeChangedCallback(name: string, _old: string | null, value: string | null): void;
|
|
63
|
+
private reemit;
|
|
64
|
+
private requireController;
|
|
65
|
+
}
|
|
66
|
+
/** Register the element (idempotent). Import `.../model/define` for auto-registration. */
|
|
67
|
+
export declare function defineGcodeModelViewer(tag?: string): void;
|
|
68
|
+
//# sourceMappingURL=gcode-model-viewer-element.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gcode-model-viewer-element.d.ts","sourceRoot":"","sources":["../../src/model/gcode-model-viewer-element.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAEhB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EAErB,KAAK,WAAW,EACjB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAEV,WAAW,EAEX,cAAc,EACd,cAAc,EACd,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,oCAAoC,CAAC;AAK5C,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAEtD,qBAAa,uBAAwB,SAAQ,WAAW;IACtD,MAAM,KAAK,kBAAkB,IAAI,MAAM,EAAE,CAExC;IAED,OAAO,CAAC,UAAU,CAAuC;IACzD,OAAO,CAAC,QAAQ,CAAkC;IAGlD,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,eAAe,CAA+D;IACtF,OAAO,CAAC,eAAe,CAAqE;IAG5F,IAAI,MAAM,IAAI,gBAAgB,GAAG,IAAI,CAEpC;IACD,IAAI,MAAM,CAAC,CAAC,EAAE,gBAAgB,GAAG,IAAI,EAGpC;IACD,IAAI,WAAW,IAAI,WAAW,GAAG,IAAI,CAEpC;IACD,IAAI,WAAW,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,EAGpC;IACD,IAAI,UAAU,IAAI,eAAe,GAAG,SAAS,CAE5C;IACD,IAAI,UAAU,CAAC,CAAC,EAAE,eAAe,GAAG,SAAS,EAG5C;IACD,IAAI,WAAW,IAAI,WAAW,GAAG,IAAI,CAEpC;IACD,IAAI,WAAW,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,EAGpC;IACD,IAAI,MAAM,IAAI,WAAW,GAAG,SAAS,CAEpC;IACD,IAAI,MAAM,CAAC,CAAC,EAAE,WAAW,GAAG,SAAS,EAEpC;IACD,IAAI,eAAe,IAAI,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,GAAG,SAAS,CAEjE;IACD,IAAI,eAAe,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,GAAG,SAAS,EAEjE;IACD,IAAI,OAAO,IAAI,SAAS,WAAW,EAAE,GAAG,SAAS,CAEhD;IACD,IAAI,OAAO,CAAC,CAAC,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,EAEhD;IACD,IAAI,cAAc,IAAI,CAAC,CAAC,MAAM,EAAE,kBAAkB,KAAK,cAAc,CAAC,GAAG,SAAS,CAEjF;IACD,IAAI,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,kBAAkB,KAAK,cAAc,CAAC,GAAG,SAAS,EAEjF;IACD,IAAI,cAAc,IAAI,WAAW,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,CAAC,GAAG,SAAS,CAEvF;IACD,IAAI,cAAc,CAAC,CAAC,EAAE,WAAW,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,CAAC,GAAG,SAAS,EAEvF;IAGD,IAAI,IAAI,IAAI,MAAM,GAAG,IAAI,CAExB;IACD,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,EAGxB;IACD,IAAI,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAEtC;IACD,IAAI,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,EAGtC;IACD,IAAI,UAAU,IAAI,MAAM,GAAG,IAAI,CAE9B;IACD,IAAI,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,EAG9B;IAGD,IAAI,KAAK,IAAI,iBAAiB,CAE7B;IACD,IAAI,QAAQ,IAAI,oBAAoB,CAEnC;IACD,IAAI,GAAG,IAAI;QAAE,MAAM,EAAE,MAAM,WAAW,GAAG,IAAI,CAAA;KAAE,CAE9C;IACD,SAAS,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,oCAAoC,EAAE,cAAc,CAAC;IAGxG,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAG7C,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI;IAKtD,iBAAiB,IAAI,IAAI;IAoCzB,oBAAoB,IAAI,IAAI;IAO5B,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAqBvF,OAAO,CAAC,MAAM;IA4Bd,OAAO,CAAC,iBAAiB;CAM1B;AAED,0FAA0F;AAC1F,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,MAA0B,GAAG,IAAI,CAI5E"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <gcode-model-viewer> — the framework-free Web Component for interactive source-model viewing
|
|
3
|
+
* (STL / 3MF), the Prepare-side counterpart to <gcode-preview> (DD-031). A SHELL over
|
|
4
|
+
* `createModelPreviewController`, exactly like the Vue/React/Svelte model adapters: attributes and
|
|
5
|
+
* properties map to controller options / `controls.*` calls, and controller events are re-emitted as
|
|
6
|
+
* DOM `CustomEvent`s. The handle is also exposed as instance members (`state`/`controls`/`raw`/`onEvent`/
|
|
7
|
+
* `setSource`/`capture`) so the shared model behavioral suite runs against it identically.
|
|
8
|
+
*
|
|
9
|
+
* The tag is `gcode-model-viewer` (not the reserved `model-viewer`). No framework peer dependency.
|
|
10
|
+
*/
|
|
11
|
+
import { createModelPreviewController } from '@chestnutlabs/gcode-model-renderer';
|
|
12
|
+
/** Observed scalar attributes; rich options (source, cameraState, palettes, loaders, injectables) are property-only. */
|
|
13
|
+
const OBSERVED = ['view', 'background', 'interaction-quality', 'camera-mode'];
|
|
14
|
+
/** The default tag name for the model viewer. */
|
|
15
|
+
export const DEFAULT_MODEL_TAG = 'gcode-model-viewer';
|
|
16
|
+
export class GcodeModelViewerElement extends HTMLElement {
|
|
17
|
+
static get observedAttributes() {
|
|
18
|
+
return [...OBSERVED];
|
|
19
|
+
}
|
|
20
|
+
controller = null;
|
|
21
|
+
canvasEl = null;
|
|
22
|
+
// Rich options — objects/functions can't be attributes, so they are property-only.
|
|
23
|
+
_source = null;
|
|
24
|
+
_cameraState = null;
|
|
25
|
+
_background;
|
|
26
|
+
_renderScope = null;
|
|
27
|
+
_limits;
|
|
28
|
+
_filamentPalette;
|
|
29
|
+
_loaders;
|
|
30
|
+
_createRenderer;
|
|
31
|
+
_createControls;
|
|
32
|
+
// ---- rich-option property accessors ----
|
|
33
|
+
get source() {
|
|
34
|
+
return this._source;
|
|
35
|
+
}
|
|
36
|
+
set source(v) {
|
|
37
|
+
this._source = v;
|
|
38
|
+
if (v !== null && this.controller !== null)
|
|
39
|
+
void this.controller.controls.setSource(v);
|
|
40
|
+
}
|
|
41
|
+
get cameraState() {
|
|
42
|
+
return this._cameraState;
|
|
43
|
+
}
|
|
44
|
+
set cameraState(v) {
|
|
45
|
+
this._cameraState = v;
|
|
46
|
+
if (v !== null)
|
|
47
|
+
this.controller?.controls.setCameraState(v);
|
|
48
|
+
}
|
|
49
|
+
get background() {
|
|
50
|
+
return this._background;
|
|
51
|
+
}
|
|
52
|
+
set background(v) {
|
|
53
|
+
this._background = v;
|
|
54
|
+
if (v !== undefined)
|
|
55
|
+
this.controller?.controls.setBackground(v);
|
|
56
|
+
}
|
|
57
|
+
get renderScope() {
|
|
58
|
+
return this._renderScope;
|
|
59
|
+
}
|
|
60
|
+
set renderScope(v) {
|
|
61
|
+
this._renderScope = v;
|
|
62
|
+
this.controller?.controls.setRenderScope(v);
|
|
63
|
+
}
|
|
64
|
+
get limits() {
|
|
65
|
+
return this._limits;
|
|
66
|
+
}
|
|
67
|
+
set limits(v) {
|
|
68
|
+
this._limits = v; // construction-time only
|
|
69
|
+
}
|
|
70
|
+
get filamentPalette() {
|
|
71
|
+
return this._filamentPalette;
|
|
72
|
+
}
|
|
73
|
+
set filamentPalette(v) {
|
|
74
|
+
this._filamentPalette = v; // construction-time only
|
|
75
|
+
}
|
|
76
|
+
get loaders() {
|
|
77
|
+
return this._loaders;
|
|
78
|
+
}
|
|
79
|
+
set loaders(v) {
|
|
80
|
+
this._loaders = v; // construction-time only
|
|
81
|
+
}
|
|
82
|
+
get createRenderer() {
|
|
83
|
+
return this._createRenderer;
|
|
84
|
+
}
|
|
85
|
+
set createRenderer(v) {
|
|
86
|
+
this._createRenderer = v; // construction-time only
|
|
87
|
+
}
|
|
88
|
+
get createControls() {
|
|
89
|
+
return this._createControls;
|
|
90
|
+
}
|
|
91
|
+
set createControls(v) {
|
|
92
|
+
this._createControls = v; // construction-time only
|
|
93
|
+
}
|
|
94
|
+
// ---- scalar attribute accessors ----
|
|
95
|
+
get view() {
|
|
96
|
+
return this.getAttribute('view');
|
|
97
|
+
}
|
|
98
|
+
set view(v) {
|
|
99
|
+
if (v === null)
|
|
100
|
+
this.removeAttribute('view');
|
|
101
|
+
else
|
|
102
|
+
this.setAttribute('view', v);
|
|
103
|
+
}
|
|
104
|
+
get interactionQuality() {
|
|
105
|
+
return this.getAttribute('interaction-quality');
|
|
106
|
+
}
|
|
107
|
+
set interactionQuality(v) {
|
|
108
|
+
if (v === null)
|
|
109
|
+
this.removeAttribute('interaction-quality');
|
|
110
|
+
else
|
|
111
|
+
this.setAttribute('interaction-quality', v);
|
|
112
|
+
}
|
|
113
|
+
get cameraMode() {
|
|
114
|
+
return this.getAttribute('camera-mode');
|
|
115
|
+
}
|
|
116
|
+
set cameraMode(v) {
|
|
117
|
+
if (v === null)
|
|
118
|
+
this.removeAttribute('camera-mode');
|
|
119
|
+
else
|
|
120
|
+
this.setAttribute('camera-mode', v);
|
|
121
|
+
}
|
|
122
|
+
// ---- handle passthrough (parity with the other adapters) ----
|
|
123
|
+
get state() {
|
|
124
|
+
return this.requireController().getState();
|
|
125
|
+
}
|
|
126
|
+
get controls() {
|
|
127
|
+
return this.requireController().controls;
|
|
128
|
+
}
|
|
129
|
+
get raw() {
|
|
130
|
+
return this.requireController().raw;
|
|
131
|
+
}
|
|
132
|
+
setSource(input) {
|
|
133
|
+
return this.requireController().controls.setSource(input);
|
|
134
|
+
}
|
|
135
|
+
capture(opts) {
|
|
136
|
+
return this.requireController().controls.capture(opts);
|
|
137
|
+
}
|
|
138
|
+
onEvent(cb) {
|
|
139
|
+
return this.requireController().onEvent(cb);
|
|
140
|
+
}
|
|
141
|
+
// ---- lifecycle ----
|
|
142
|
+
connectedCallback() {
|
|
143
|
+
if (this.controller !== null)
|
|
144
|
+
return;
|
|
145
|
+
const root = this.shadowRoot ?? this.attachShadow({ mode: 'open' });
|
|
146
|
+
root.replaceChildren();
|
|
147
|
+
const style = document.createElement('style');
|
|
148
|
+
style.textContent = ':host{display:block;width:100%;height:100%}canvas{display:block;width:100%;height:100%}';
|
|
149
|
+
const canvas = document.createElement('canvas');
|
|
150
|
+
canvas.setAttribute('aria-label', '3D source-model preview');
|
|
151
|
+
canvas.setAttribute('tabindex', '0');
|
|
152
|
+
root.append(style, canvas);
|
|
153
|
+
this.canvasEl = canvas;
|
|
154
|
+
const bg = this._background ?? this.getAttribute('background') ?? undefined;
|
|
155
|
+
this.controller = createModelPreviewController({
|
|
156
|
+
...(this._loaders ? { loaders: this._loaders } : {}),
|
|
157
|
+
...(bg !== undefined ? { background: bg } : {}),
|
|
158
|
+
...(this.getAttribute('interaction-quality')
|
|
159
|
+
? { interactionQuality: this.getAttribute('interaction-quality') }
|
|
160
|
+
: {}),
|
|
161
|
+
...(this.getAttribute('camera-mode') ? { cameraMode: this.getAttribute('camera-mode') } : {}),
|
|
162
|
+
...(this._limits ? { limits: this._limits } : {}),
|
|
163
|
+
...(this._filamentPalette ? { filamentPalette: this._filamentPalette } : {}),
|
|
164
|
+
...(this._renderScope ? { renderScope: this._renderScope } : {}),
|
|
165
|
+
...(this._createRenderer ? { createRenderer: this._createRenderer } : {}),
|
|
166
|
+
...(this._createControls ? { createControls: this._createControls } : {}),
|
|
167
|
+
onProgress: (p) => this.dispatchEvent(new CustomEvent('progress', { detail: p }))
|
|
168
|
+
});
|
|
169
|
+
this.controller.onEvent((e) => this.reemit(e));
|
|
170
|
+
this.controller.bindCanvas(canvas);
|
|
171
|
+
// Apply runtime-only state that isn't a construction option.
|
|
172
|
+
const view = this.getAttribute('view');
|
|
173
|
+
if (view !== null)
|
|
174
|
+
this.controller.controls.setView(view);
|
|
175
|
+
if (this._cameraState !== null)
|
|
176
|
+
this.controller.controls.setCameraState(this._cameraState);
|
|
177
|
+
if (this._source !== null)
|
|
178
|
+
void this.controller.controls.setSource(this._source);
|
|
179
|
+
}
|
|
180
|
+
disconnectedCallback() {
|
|
181
|
+
this.controller?.dispose();
|
|
182
|
+
this.controller = null;
|
|
183
|
+
this.canvasEl = null;
|
|
184
|
+
this.shadowRoot?.replaceChildren();
|
|
185
|
+
}
|
|
186
|
+
attributeChangedCallback(name, _old, value) {
|
|
187
|
+
if (this.controller === null)
|
|
188
|
+
return;
|
|
189
|
+
const c = this.controller.controls;
|
|
190
|
+
switch (name) {
|
|
191
|
+
case 'view':
|
|
192
|
+
if (value !== null)
|
|
193
|
+
c.setView(value);
|
|
194
|
+
break;
|
|
195
|
+
case 'background':
|
|
196
|
+
if (value !== null)
|
|
197
|
+
c.setBackground(value);
|
|
198
|
+
break;
|
|
199
|
+
case 'interaction-quality':
|
|
200
|
+
if (value !== null)
|
|
201
|
+
c.setInteractionQuality(value);
|
|
202
|
+
break;
|
|
203
|
+
case 'camera-mode':
|
|
204
|
+
// Construction-time only (projection switching post-mount is out of scope); no-op at runtime.
|
|
205
|
+
break;
|
|
206
|
+
default:
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
reemit(e) {
|
|
211
|
+
const emit = (type, detail) => {
|
|
212
|
+
this.dispatchEvent(new CustomEvent(type, { detail }));
|
|
213
|
+
};
|
|
214
|
+
switch (e.type) {
|
|
215
|
+
case 'ready':
|
|
216
|
+
emit('ready', e.info);
|
|
217
|
+
break;
|
|
218
|
+
case 'camera-changed':
|
|
219
|
+
emit('camerachange', e.state);
|
|
220
|
+
break;
|
|
221
|
+
case 'error':
|
|
222
|
+
emit('error', { code: e.code, message: e.message });
|
|
223
|
+
break;
|
|
224
|
+
case 'renderer-unsupported':
|
|
225
|
+
emit('renderer-unsupported', { feature: e.feature, message: e.message });
|
|
226
|
+
break;
|
|
227
|
+
case 'context-lost':
|
|
228
|
+
emit('context-lost');
|
|
229
|
+
break;
|
|
230
|
+
case 'context-restored':
|
|
231
|
+
emit('context-restored');
|
|
232
|
+
break;
|
|
233
|
+
default:
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
requireController() {
|
|
238
|
+
if (this.controller === null) {
|
|
239
|
+
throw new Error('gcode-model-viewer: not connected to the DOM yet (no controller)');
|
|
240
|
+
}
|
|
241
|
+
return this.controller;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/** Register the element (idempotent). Import `.../model/define` for auto-registration. */
|
|
245
|
+
export function defineGcodeModelViewer(tag = DEFAULT_MODEL_TAG) {
|
|
246
|
+
if (customElements.get(tag) === undefined) {
|
|
247
|
+
customElements.define(tag, GcodeModelViewerElement);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @chestnutlabs/gcode-preview-element/model — the framework-free `<gcode-model-viewer>` Web Component
|
|
3
|
+
* for interactive source-model viewing (STL / 3MF), the Prepare-side counterpart to `<gcode-preview>`
|
|
4
|
+
* (DD-031). Registration is a function (`defineGcodeModelViewer`) so this entry stays side-effect-free;
|
|
5
|
+
* import `.../model/define` to auto-register. A thin shell over `createModelPreviewController`.
|
|
6
|
+
*/
|
|
7
|
+
export { GcodeModelViewerElement, defineGcodeModelViewer, DEFAULT_MODEL_TAG } from './gcode-model-viewer-element.js';
|
|
8
|
+
export type { ModelPreviewControls, ModelPreviewState, ModelViewer, ModelViewerEvent, ModelReadyInfo, ModelSourceInput } from '@chestnutlabs/gcode-model-renderer';
|
|
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;;;;;GAKG;AACH,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAGrH,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EACjB,MAAM,oCAAoC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @chestnutlabs/gcode-preview-element/model — the framework-free `<gcode-model-viewer>` Web Component
|
|
3
|
+
* for interactive source-model viewing (STL / 3MF), the Prepare-side counterpart to `<gcode-preview>`
|
|
4
|
+
* (DD-031). Registration is a function (`defineGcodeModelViewer`) so this entry stays side-effect-free;
|
|
5
|
+
* import `.../model/define` to auto-register. A thin shell over `createModelPreviewController`.
|
|
6
|
+
*/
|
|
7
|
+
export { GcodeModelViewerElement, defineGcodeModelViewer, DEFAULT_MODEL_TAG } from './gcode-model-viewer-element.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chestnutlabs/gcode-preview-element",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Framework-free <gcode-preview> Web Component for the Chestnut Labs G-code viewer (DD-007 D1 / DD-009 D5): a custom element bridging @chestnutlabs/gcode-preview-core, no framework peer dependency.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gcode",
|
|
@@ -38,6 +38,14 @@
|
|
|
38
38
|
"./define": {
|
|
39
39
|
"types": "./dist/define.d.ts",
|
|
40
40
|
"import": "./dist/define.js"
|
|
41
|
+
},
|
|
42
|
+
"./model": {
|
|
43
|
+
"types": "./dist/model/index.d.ts",
|
|
44
|
+
"import": "./dist/model/index.js"
|
|
45
|
+
},
|
|
46
|
+
"./model/define": {
|
|
47
|
+
"types": "./dist/model/define.d.ts",
|
|
48
|
+
"import": "./dist/model/define.js"
|
|
41
49
|
}
|
|
42
50
|
},
|
|
43
51
|
"files": [
|
|
@@ -52,9 +60,10 @@
|
|
|
52
60
|
"test": "vitest run"
|
|
53
61
|
},
|
|
54
62
|
"dependencies": {
|
|
55
|
-
"@chestnutlabs/gcode-
|
|
56
|
-
"@chestnutlabs/gcode-
|
|
57
|
-
"@chestnutlabs/gcode-
|
|
58
|
-
"@chestnutlabs/
|
|
63
|
+
"@chestnutlabs/gcode-model-renderer": "0.20.0",
|
|
64
|
+
"@chestnutlabs/gcode-parser": "0.20.0",
|
|
65
|
+
"@chestnutlabs/gcode-preview-core": "0.20.0",
|
|
66
|
+
"@chestnutlabs/gcode-renderer-three": "0.20.0",
|
|
67
|
+
"@chestnutlabs/toolpath-core": "0.20.0"
|
|
59
68
|
}
|
|
60
69
|
}
|