@omrips/viewstl 2.0.0-rc.7 → 2.0.0-rc.9

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.
@@ -0,0 +1,20 @@
1
+ # ViewSTL 2.0.0-rc.9
2
+
3
+ The plugin handles 3D models and scenes without requiring ViewSTL website markup.
4
+ `ViewerSession` adds a UI-independent loading queue, memory policy, scene placement,
5
+ center-preserving model editing and optional canvas manipulation. The existing
6
+ `StlViewer` rendering, analysis, saving and camera APIs remain available.
7
+
8
+ **App helper migration:** `mountViewstlApp` and `ViewstlApp*` types are removed from
9
+ the ESM/CommonJS/classic plugin distributions. They were a controller for the
10
+ ViewSTL website's specific HTML, not a general viewer API. Website controls,
11
+ dialogs and presentation now live in the website project, outside this repository
12
+ and npm packages. Consumers of that helper must migrate their own UI to
13
+ `ViewerSession`/`StlViewer`, or keep their existing pinned rc.8 distribution while
14
+ migrating. Earlier npm versions, GitHub releases and legacy v1 are retained.
15
+
16
+ The native JavaScript/WebGL2 renderer, lazy workers/CAD assets, local-file privacy,
17
+ VSB/VSJ serialization and separate `viewstl/node` API are preserved.
18
+
19
+ See [usage](../v2-usage.md) and the dated [verification record](../v2-verification.md)
20
+ for API details and tested scope.
package/docs/v2-usage.md CHANGED
@@ -201,70 +201,68 @@ covered by the JS-heap limit. Size host/container limits for total concurrency;
201
201
  use process/container isolation when serving untrusted uploads. The library
202
202
  does not provide an HTTP endpoint, authentication or a filesystem sandbox.
203
203
 
204
- ## Full app controls
204
+ ## Viewer sessions and custom interfaces
205
205
 
206
- `mountViewstlApp` is the optional app controller, exported from the same
207
- `viewstl.js` bundle as `StlViewer` (and as a global in the classic script).
208
- It owns the file queue, memory admission, cancellation, selection, scene
209
- placement, translation/rotation/depth gestures, viewing modes, sectioning,
210
- colors, grid, PNG downloads, keyboard handling, and control state.
206
+ Use `StlViewer` directly for a viewer, or `ViewerSession` for a reusable loading
207
+ queue and model editing. Neither requires the ViewSTL website's controls, labels
208
+ or dialogs. Each session belongs to one container and starts its canvas/workers
209
+ only when loading begins (or when you explicitly call `ready()`).
211
210
 
212
211
  ```js
213
- import { mountViewstlApp } from './viewer/viewstl.js';
214
- const app = mountViewstlApp(document, {
215
- sample_url: new URL('./sample-vase.stl', import.meta.url).href,
216
- sample_name: 'Twist vase.stl'
212
+ import { ViewerSession } from './viewer/viewstl.js';
213
+ const session = new ViewerSession(document.getElementById('viewer'), {
214
+ device_memory: navigator.deviceMemory,
215
+ viewer_options: { worker_url: '/viewer/viewstl.worker.js' },
216
+ on_event(event) {
217
+ if (event.type === 'error') console.error(event.code, event.message);
218
+ if (event.type === 'progress') console.log(event.progress);
219
+ }
217
220
  });
218
- await app.openFiles(fileInput.files);
219
- console.log(app.getState()); // detached metadata snapshot, no geometry copies
220
- app.dispose(); // cancels work and releases listeners, workers and WebGL
221
+ await session.openFiles(fileInput.files);
222
+ const models = session.getModels(); // detached metadata; no mesh copies
223
+ if (models.length) session.setRotation(models[0].id, {x: 0, y: 0, z: 90});
224
+ // Existing export/analysis/camera APIs stay on StlViewer:
225
+ await session.viewer.download_scene({format: 'vsb'});
226
+ session.dispose();
221
227
  ```
222
228
 
223
- This controller binds the preview's HTML control layout; the host supplies
224
- markup and CSS. The reference layout is `Viewstl/site/index.html` in the sibling
225
- website workspace. `requiredControls` in `src/app.js` validates the control
226
- IDs before registering handlers. Missing controls and duplicate mounts produce
227
- a descriptive error. Custom integrations without that layout use `StlViewer`.
228
- Branding, page metadata, advertisements and static help/privacy text belong
229
- to the host page. The preview's JavaScript is only the initialization call.
230
-
231
- For an embedded app, pass an `HTMLElement` containing the layout. Queries,
232
- keyboard events and drops are scoped to that root. For multiple roots, prefix
233
- each layout's IDs and label/ARIA references and pass the matching `id_prefix`;
234
- the controller separates radio groups as well. `dispose()` permits remounting
235
- and prevents late reads from updating the new app.
236
-
237
- Optional shortcut buttons can reuse the app actions without extra host-side
238
- JavaScript. Use `data-open-file` for Open, and `data-viewstl-shortcut` with `save`,
239
- `select`, `front`, `right`, `top`, `back`, `left`, `bottom` or `isometric` for the
240
- other actions. Save requires the normal save-dialog control group. These
241
- buttons do not add required control IDs, so existing app layouts remain valid.
242
- Use real buttons with descriptive labels/tooltips. The host supplies responsive
243
- CSS; the ViewSTL website shows its shortcut row only on wide desktop screens.
244
-
245
- `select` toggles click-to-select mode and reflects it through `aria-pressed`.
246
- Camera gestures pause in this mode; clicking a model opens its existing tools.
247
- Escape, a camera shortcut or entering a model transform tool exits selection
248
- mode. A viewport resize also exits when all selection shortcuts become hidden.
249
- This is temporary interaction state, not a saved scene property. The existing
250
- double-click and Models-list selection mechanisms remain available.
251
-
252
- `openFiles()` accepts Files or configured `{name, url, size?}` sources and
253
- resolves when the queue settles. File errors appear in the notice; success is
254
- reflected by `getState().models`. Other methods are `select(id)`, `remove(id)`,
255
- `cancelLoading()` and `clear()`. An omitted `sample_url` hides the sample action.
256
- `worker_url`, `worker_factory` and `worker_timeout` support alternate hosting,
257
- bundlers and CommonJS use.
258
-
259
- Loading the bundle does not create a canvas or worker. The first file creates
260
- the WebGL2 viewer. App source modules are bundled into `viewstl.js`; the host
261
- ships no separate memory/layout/transform helpers. Worker JS, archive chunks
262
- and CAD WASM remain separate plugin-owned assets to keep parsing off the main
263
- thread and avoid downloading CAD code for STL/OBJ users.
264
-
265
- `get_model_info()` also exposes copied source `bounds`, `has_colors`, and
266
- `source_units` (`null` for unitless sources), so consumers need not inspect
267
- internal geometry or retain its buffers.
229
+ The host supplies any file input, toolbar and status display. `viewer_options`
230
+ accepts existing constructor options except `models` and `allow_drag_and_drop`;
231
+ pass initial/dropped files to the session loading methods so it tracks imported models. Existing viewer callbacks are
232
+ composed with session notifications. Optional `colors` supplies fallback colors
233
+ for files without their own colors. Without an override the memory policy uses
234
+ half the browser's supplied device-memory estimate, or half a conservative 2 GiB
235
+ fallback. This is a limit estimate, not a free-memory measurement.
236
+
237
+ | Session API | Contract |
238
+ | --- | --- |
239
+ | `ready()`, `viewer` | Explicitly initialize and await the viewer; the property is null before initialization. |
240
+ | `openFiles(files)` | Queue Files or configured {name, url, size?} sources. VSB/VSJ imports and VSJ companions use the same path. |
241
+ | `openURL(url, format?)` | Queue a remote model/scene through the explicitly configured same-origin relay. |
242
+ | `cancelLoading()` | Cancel queued/active loading, retaining existing models. |
243
+ | `getModel(id)`, `getModels()` | Detached metadata including name, bounds, transforms, reset baselines and animation definition/state; no private geometry buffers. |
244
+ | `setPosition(id, xyz)`, `setRotation(id, degrees)` | Edit center-preserving transforms; return false for invalid input. Stop only the edited model's animation. Original StlViewer methods continue to use radians. |
245
+ | `prepareManual(id)`, `centerPivot(id)` | Capture/stop current playback; optionally rebase the pivot without moving any rendered vertex. |
246
+ | `moveDepth(id, amount)` | Translate along the eye-to-model ray. Positive moves away, negative moves nearer. |
247
+ | `setArrangement(mode)` | original, side-by-side or custom; keep source geometry unchanged. |
248
+ | `setGrid(enabled, spacing?, height?)` | Configure the infinite XY grid. |
249
+ | `duplicate(id)`, `remove(id)`, `clear()` | Manage session models through these methods to retain session metadata/reset baselines. |
250
+ | `bindManipulation(options)` | After ready, bind move/rotate/depth canvas gestures; options supply getModelId(event?), getTool(), onChange/onStart/onEnd. Returns setEnabled/dispose. No toolbar or styles are created. |
251
+ | `dispose()` | Cancel work and release manipulation listeners, workers and viewer resources. Idempotent; later operations reject. |
252
+
253
+ Read-only `busy`, `arrangement`, `grid` and `memoryPolicy` expose current settings.
254
+ Events are `ready`, `busy`, `opening`, `progress`, `loaded`, `scene-loaded`,
255
+ `load-failed`, `error` and `animation`; their shapes are in the public types.
256
+ Queue promises settle after work drains, including per-file failures reported
257
+ through events. Inspect the resulting models/events rather than treating promise
258
+ resolution alone as proof every file succeeded. Invalid URL arguments throw.
259
+
260
+ **Migration from rc.8:** `mountViewstlApp` and its `ViewstlApp*` types are no longer
261
+ exported. That helper depended on ViewSTL-specific HTML IDs and UI policy. Use
262
+ `ViewerSession` or `StlViewer` with your own UI, or retain your pinned rc.8 build
263
+ while migrating. Existing published releases and legacy v1 remain available.
264
+ The ViewSTL website's controller is maintained separately, not distributed in
265
+ the plugin repository or npm package. Ordinary `StlViewer` integrations keep their API.
268
266
 
269
267
  ## Rendering and file processing
270
268
 
@@ -404,25 +402,12 @@ while the affected models are paused; subsequent motion makes the report stale.
404
402
  A self-contained example is in `examples/v2/animation.html` in the source
405
403
  checkout (serve with `pnpm start`). It includes Play, Pause, Resume, Stop and Reset.
406
404
 
407
- The app controller also supports an optional `animation-*` group (see the new
408
- site's HTML template): `animation-details`, `animation-fields`, `animation-axis`,
409
- `animation-seconds`, `animation-direction`, `animation-play`, `animation-pause`,
410
- `animation-stop`, `animation-status` and `animation-error`. Supply the whole group
411
- or omit it. It exposes selected-model spin around the mesh center, duration
412
- (0.1–3,600 seconds per turn), direction and playback buttons. Other models keep
413
- playing when selection changes. Manual tools capture the current animated pose.
414
- Readouts update at most four times per second; geometry and GPU buffers are reused.
415
-
416
- `mountViewstlApp` composes `animation_state_callback` and
417
- `animation_complete_callback` options with its own UI behavior. `app.getState()`
418
- includes each model's current transform and `animation` state. Ordinary files
419
- never auto-spin. Imported running animations are paused when the browser reports
420
- `prefers-reduced-motion: reduce`; explicit user playback remains available.
421
-
422
- App print checks pause running target models. Optional `print-resume` and
423
- `print-animation-note` elements expose resumption; closing the panel does not
424
- silently restart motion. Resuming clears stale results and keeps the panel open.
425
- Scene saving includes playback; PNG and regular model saving capture a pose.
405
+ Website animation controls are host-owned. Use the animation API above and
406
+ `ViewerSession.centerPivot(id)` for a spin around the mesh center. Session model
407
+ snapshots expose playback and definitions without accessing private model data.
408
+ The host decides how to respect reduced-motion preferences, pause for a print
409
+ check, present a Resume action and update its readouts. Scene saving retains
410
+ playback; PNG and regular model exports snapshot the current pose.
426
411
 
427
412
  ## Existing API and intentional differences
428
413
 
@@ -593,11 +578,10 @@ viewer.add_model({id: 0, remote_url: 'https://example.com/model.stl'});
593
578
  // Optional remote_format: 'stl', 'obj', '3mf', 'step', 'stp', 'iges', 'igs'.
594
579
  ```
595
580
 
596
- `mountViewstlApp` accepts the same endpoint and exposes `app.openURL(url, format)`.
597
- Its optional `url-dialog`/`url-form` controls are shown in the preview site's HTML.
598
- The site supplies markup, styles and configuration; URL interaction, loading,
599
- progress, cancellation and parsing live in the plugin. App jobs allow ten minutes
600
- by default; low-level viewer worker_timeout remains configurable as before.
581
+ `ViewerSession` accepts the endpoint inside `viewer_options` and exposes
582
+ `session.openURL(url, format)`. The host owns URL input and progress presentation;
583
+ the plugin owns validation, streaming, parsing, the queue and cancellation.
584
+ Session jobs default to a ten-minute worker timeout.
601
585
 
602
586
  The relay receives the URL in a JSON POST body and streams the response without
603
587
  file storage. A signed URL's query string is not displayed as a model name or
@@ -612,14 +596,9 @@ Downloaded names are metadata, not reloadable URLs; use VSB to package a scene
612
596
  containing these models. Embedders must provide their own compatible relay; no
613
597
  ViewSTL server is implicitly used by the library.
614
598
 
615
- When `url_import_endpoint` is configured, `mountViewstlApp` also accepts dropped
616
- links (`text/uri-list`), Firefox URL/title data, and plain HTTP/HTTPS URL text.
617
- URL drops use `openURL` and its existing queue, relay, progress, cancellation and
618
- error handling. Multiple URI-list links are deduplicated per drop. Local files
619
- take priority over accompanying URL metadata. Plain text is not searched for
620
- embedded links, HTML drag contents are not parsed, and drops into text inputs or
621
- editable content retain their normal behavior. This belongs to the optional app
622
- controller; the low-level viewer's existing file-drop contract is unchanged.
599
+ A host can extract links from its own drop events and call `session.openURL`.
600
+ Page-wide drag overlays, editable-field handling and URL dialogs belong to that
601
+ host. The low-level viewer's existing local file-drop contract is unchanged.
623
602
 
624
603
  The reference relay lives in the website repository's `relay/` directory. Its
625
604
  request is `{url, format, max_bytes}` and its response supplies X-ViewSTL-Format,
@@ -629,24 +608,10 @@ worker/fetch; the server then closes the upstream connection.
629
608
 
630
609
  ## Local mesh export
631
610
 
632
- The optional `mountViewstlApp` controller can bind a Save dialog using the
633
- `save-*` control group in the preview site's `site/index.html`. Include the entire
634
- group or omit it; incomplete groups fail before mounting. All event handling,
635
- selection, progress, cancellation and download dispatch compile into `viewstl.js`.
636
- The host supplies markup, styles and explanatory copy (format option `data-note`
637
- attributes and the CAD limitation paragraph). No Save UI is injected by the
638
- low-level viewer.
639
-
640
- The reference dialog exports only the current app selection for mesh formats,
641
- with positions/rotations applied and millimetre output. Unitless STL/OBJ inputs
642
- are assumed to be millimetres. Its optional color setting applies to OBJ/3MF;
643
- colored OBJ uses ZIP. It calls `download_models` with explicit model IDs, so
644
- closing an editing panel does not clear the export selection. VSB/VSJ always
645
- export the whole scene. `save-scope` is a text status element displaying the
646
- selected filename or whole-scene model count, not a scope dropdown. Cancel, Escape,
647
- the close button, backdrop dismissal, changing selection, starting an import,
648
- removing/clearing models and app disposal cancel an active export. Errors stay
649
- in the dialog and permit another format. Existing PNG controls remain separate.
611
+ The host owns its Save dialog and passes explicit model IDs/options to the
612
+ export methods. Model exports and whole-scene VSB/VSJ exports remain distinct.
613
+ Use AbortSignal to cancel when the host dismisses or changes an active operation;
614
+ the plugin does not prescribe a modal layout or panel-closing policy.
650
615
 
651
616
  All exporters live in the plugin and run in disposable workers. They generate
652
617
  local Blobs; no relay, upload, server conversion or third-party network endpoint
@@ -784,8 +749,7 @@ PNG and scene exports. Removing or clearing its model releases the frame.
784
749
  `pick_model(clientX, clientY)` returns `{id, distance}` for the nearest visible
785
750
  surface, or `null` for empty space. Coordinates use the same viewport coordinate
786
751
  system as mouse events. It respects transforms, hidden models and section cuts.
787
- The preview calls it on double-click only; ordinary dragging does not run a mesh
788
- intersection scan. The existing legacy click callbacks retain their behavior.
752
+ The host chooses when to pick: for example, on double-click or at the start of a selection drag. The existing legacy click callbacks retain their behavior.
789
753
 
790
754
  The preview provides Move, Rotate and Depth controls per model. Rotation uses
791
755
  degrees in the UI and compensates for the original mesh center; the plugin's
@@ -951,23 +915,14 @@ metadata uses weak references so retaining a report cannot retain removed meshes
951
915
 
952
916
  Highlights use temporary native WebGL line buffers and are excluded from PNG,
953
917
  mesh and scene exports. They show up to 128 faces or 256 edges per check, through
954
- occluding surfaces. Closing the site panel clears highlights. The preview exposes
955
- the feature under **Info → Check for 3D printing**, with selected/all model scope,
956
- basic/detailed depth and collapsed optional FDM settings. Unit confirmation resets
957
- when the checked scope or an existing result's geometry/transform changes. A complete
958
- optional `print-*` control group is bound by `mountViewstlApp`; hosts omitting the
959
- entire group keep their previous behavior. The website only supplies markup/styles.
960
-
961
- The check panel stays open while using the canvas, other controls or dialogs,
962
- loading files, selecting models and clearing the scene. Only its close button or
963
- Escape with focus inside the panel dismisses it. Reopening it from Info reveals
964
- and focuses the existing panel. Loading or changing the checked selection cancels
965
- an active check; stale results are cleared. Loading and empty scenes disable Run
966
- and show the current availability without closing the panel.
918
+ occluding surfaces. The host controls results presentation and calls
919
+ `clear_printability()` when appropriate. It decides when its panel closes, how
920
+ stale results are shown, and whether to pause/resume animation. The plugin exposes
921
+ analysis, cancellation, validity checks and geometry highlighting without a UI.
967
922
 
968
923
  ## Model size, units, duplicates, cameras and measurements (rc.6)
969
924
 
970
- All operations below are implemented inside the plugin. The optional site controls remain a thin HTML/CSS host.
925
+ All operations below are implemented inside the plugin. Their interface controls and presentation belong to the host.
971
926
 
972
927
  `viewer.resize_model(id, [2, 2, 2])` doubles the model about its world-space bounds center, preserving rotation and placement. Positive finite XYZ factors are required; independent factors allow nonuniform scaling. It stops only that model's animation. `get_model_size(id)` returns dimensions and the reset baseline in millimetres. `reset_model_size(id)` restores that baseline while retaining file-unit corrections.
973
928
 
@@ -987,4 +942,4 @@ Measurements use workers and support `signal`, `max_time_ms` (default 30 seconds
987
942
 
988
943
  VSB/VSJ retain size baselines, file-unit interpretation, display units, duplicate labels and bookmarks. VSB still embeds geometry; VSJ still needs the referenced source files. No second unit conversion occurs during import. Appending scenes merges bookmark names with numbered suffixes; a combined total above 32 rejects the incoming scene. Old files without the new optional fields continue to load. The `size_state.unit_factor` serialization field preserves source-unit correction separately from resize factors for exports with `apply_transforms:false`.
989
944
 
990
- The optional app control group is listed in `src/app-tools.js` (`toolsControls`). Provide the whole group or omit it when embedding older markup. The preview's `site/index.html` is a complete example. Models contains collapsed Size & units and Duplicate; View contains collapsed Camera & saved views; Info contains area and the volume calculation. No server is involved for local files or measurements.
945
+ Local measurements and model operations need no server. Use the public APIs with the interface of your choice.