@toolpath/viewer 0.4.0 → 1.0.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.
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { Group, Mesh, LineSegments, Box3, Plane, BufferGeometry, Camera, Vector3, OrthographicCamera, PerspectiveCamera, Object3D } from 'three';
2
+ import { Group, Mesh, LineSegments, Box3, Plane, BufferGeometry, Camera, Vector3 } from 'three';
3
3
 
4
4
  /**
5
5
  * The normalized part — the only thing the renderer consumes.
@@ -434,6 +434,21 @@ interface PartPick {
434
434
  /** The surface's outward normal in world space — the plane under the cursor. */
435
435
  readonly normal: readonly [number, number, number];
436
436
  readonly modifiers: PickModifiers;
437
+ /**
438
+ * Whether this click completed a double click on the part.
439
+ *
440
+ * Reported rather than interpreted, for the same reason the modifiers are:
441
+ * what a second click means belongs to the app. A viewer that decided —
442
+ * withholding the pick so a double click could not disturb the selection —
443
+ * would be right for a list that walks through a face's readings and wrong
444
+ * for an editor where clicking a face twice puts it in and takes it out
445
+ * again. Both are ordinary, and only the app knows which one it is showing.
446
+ *
447
+ * The viewport still acts on the gesture itself: `retargetOnDoubleClick`
448
+ * re-aims the orbit, which is a question about the view rather than about the
449
+ * part, and is nobody else's to answer.
450
+ */
451
+ readonly doubled: boolean;
437
452
  }
438
453
  /** A unit vector from the part toward the camera, for the owner ranking. */
439
454
  declare function viewDirection(camera: Camera, target: Vector3): Vec3;
@@ -452,6 +467,8 @@ interface BuildPickInput {
452
467
  */
453
468
  readonly activeDirection?: number | null;
454
469
  readonly viewDirection?: Vec3 | null;
470
+ /** Whether this click completed a double click. Defaults to `false`. */
471
+ readonly doubled?: boolean;
455
472
  }
456
473
  declare function buildPick(input: BuildPickInput): PartPick;
457
474
  /**
@@ -463,86 +480,6 @@ declare function buildPick(input: BuildPickInput): PartPick;
463
480
  */
464
481
  declare function focusForPick(pick: PartPick, previousRegion: number | null, previousFocus: FeatureTag | null): FeatureTag | null;
465
482
 
466
- type Projection = 'orthographic' | 'perspective';
467
- type ViewerCamera = OrthographicCamera | PerspectiveCamera;
468
- interface ViewportSize {
469
- readonly width: number;
470
- readonly height: number;
471
- }
472
- /** Vertical field of view, in degrees, for the perspective camera. */
473
- declare const PERSPECTIVE_FOV = 30;
474
- /** Padding around the framed bounds, as a multiple of its radius. */
475
- declare const DEFAULT_FIT_MARGIN = 1.2;
476
- /** Marks scene furniture — grid, axes — that the camera should not frame. */
477
- declare const EXCLUDE_FROM_FRAME = "viewerExcludeFromFrame";
478
- /**
479
- * What the camera frames: a bounding *sphere*, not a box.
480
- *
481
- * A sphere makes framing rotation-invariant — the part stays fully visible from
482
- * every angle, and a resize never needs to know the current pose. Framing
483
- * per-axis box dimensions instead means recomputing the camera distance on
484
- * every resize, and still clipping on some orientations.
485
- */
486
- interface SceneBounds {
487
- readonly center: Vector3;
488
- readonly radius: number;
489
- }
490
- /**
491
- * Bounds for a scene with nothing in it. A viewer is mounted before it has a
492
- * part, and a camera with a zero-size frustum renders nothing at all.
493
- */
494
- declare function defaultBounds(): SceneBounds;
495
- /**
496
- * A container can be laid out at zero size, and a degenerate aspect ratio
497
- * produces a `NaN` projection matrix that never recovers. Fall back to square.
498
- */
499
- declare function aspectRatio(size: ViewportSize): number;
500
- declare function boundsFromBox(box: Box3): SceneBounds;
501
- /**
502
- * The bounds of everything worth framing under `root`.
503
- *
504
- * Skips objects flagged with {@link EXCLUDE_FROM_FRAME} and their descendants:
505
- * a 100 mm grid around a 6 mm part would otherwise frame the grid, and the part
506
- * would be a speck.
507
- */
508
- declare function contentBounds(root: Object3D, into: Box3): SceneBounds;
509
- /**
510
- * The distance at which a sphere of `radius` fits inside a perspective frustum.
511
- * Uses the narrower of the two field-of-view angles, so a portrait viewport
512
- * frames on width and a landscape one on height.
513
- */
514
- declare function perspectiveFitDistance(fovDegrees: number, aspect: number, radius: number): number;
515
- /**
516
- * Half-height of an orthographic frustum that fits a sphere of `radius`. A
517
- * portrait viewport grows the height so the width still clears the sphere.
518
- */
519
- declare function orthographicHalfHeight(aspect: number, radius: number): number;
520
- declare function fitDistance(projection: Projection, size: ViewportSize, bounds: SceneBounds, margin?: number): number;
521
- declare function startPosition(projection: Projection, size: ViewportSize, bounds: SceneBounds, margin?: number): Vector3;
522
- /**
523
- * Points an existing camera's frustum at `bounds` for the current viewport.
524
- * Pose is untouched — that belongs to the controls.
525
- */
526
- declare function applyProjection(camera: ViewerCamera, size: ViewportSize, bounds: SceneBounds, margin?: number): void;
527
- /**
528
- * The world-up convention. The part data is Z-up (millimetres, no conversion) —
529
- * not the glTF-conventional Y-up — so the camera has to say so explicitly.
530
- */
531
- declare const CAD_CAMERA_UP: Vector3;
532
- /** Named viewing directions, as unit vectors from the part toward the camera. */
533
- declare const cadViewDirections: {
534
- readonly front: Vector3;
535
- readonly back: Vector3;
536
- readonly left: Vector3;
537
- readonly right: Vector3;
538
- readonly top: Vector3;
539
- readonly bottom: Vector3;
540
- readonly isometric: Vector3;
541
- };
542
- type ViewerView = keyof typeof cadViewDirections;
543
- /** The current orbit direction, so Fit can retain the direction being looked from. */
544
- declare function currentViewDirection(camera: ViewerCamera, target: Vector3, into: Vector3): Vector3;
545
-
546
483
  /**
547
484
  * Render order. The stencil pass must precede the cap, and the part must draw
548
485
  * after both or it overwrites the cap it is supposed to be capped by. The part
@@ -639,14 +576,6 @@ declare function sectionFromPick(surface: {
639
576
  declare function pickedStartDepth(box: Box3): number;
640
577
  /** The plane a cut sits on, for a placement or a swept offset. */
641
578
  declare function sectionPlane(box: Box3, normal: Vec3, offset: number, into?: Plane): Plane;
642
- /**
643
- * A world length that covers `pixels` on screen at `point`.
644
- *
645
- * A handle sized in world units is a thumbnail on a plate and a wall on an
646
- * insert; the whole reason it is measured this way is that it is a control
647
- * rather than part of the model.
648
- */
649
- declare function screenLength(camera: ViewerCamera, point: Vector3, viewport: ViewportSize, pixels: number): number;
650
579
  /**
651
580
  * The plane a drag is projected onto: the one containing the handle's axis and
652
581
  * facing the camera as squarely as it can.
@@ -889,4 +818,4 @@ declare function normalizePartReport(report: unknown): PartModel;
889
818
  */
890
819
  declare function assertSupportedKernelVersion(kernelVersion: string): void;
891
820
 
892
- export { applyHighlightLayers as $, type PartPick as A, type BuildPickInput as B, CAD_CAMERA_UP as C, DEFAULT_FIT_MARGIN as D, EnginePart as E, type FeatureTag as F, type PickModifiers as G, HANDLE_PIXELS as H, REGION_ATTRIBUTE as I, type RegionHighlight as J, type KnownFeatureType as K, type RegionPaint as L, MIN_KERNEL_VERSION as M, NO_MODIFIERS as N, type SceneBounds as O, type PartModel as P, type SectionAnchor as Q, type RegionIndex as R, SECTION_RENDER_ORDER as S, type TriangleRange as T, type SectionBounds as U, type Vec3 as V, type SectionOptions as W, type SectionPlacement as X, type SectionState as Y, SectionView as Z, type ViewportSize as _, type PartMeshRefs as a, applyProjection as a0, aspectRatio as a1, boundsFromBox as a2, buildPick as a3, buildRegionAttribute as a4, buildRegionTexels as a5, cadViewDirections as a6, contentBounds as a7, createPart as a8, currentViewDirection as a9, defaultBounds as aa, directionColor as ab, dragPlane as ac, fitDistance as ad, focusForPick as ae, orthographicHalfHeight as af, perspectiveFitDistance as ag, pickedStartDepth as ah, resolveSectionPlane as ai, resolveTheme as aj, screenLength as ak, sectionBounds as al, sectionConstant as am, sectionDepth as an, sectionDepthConstant as ao, sectionDepthRange as ap, sectionFromPick as aq, sectionOffset as ar, sectionPlane as as, startPosition as at, themesEqual as au, viewDirection as av, type EnginePartProps as b, assertSupportedKernelVersion as c, type ViewerTheme as d, type PartModelRegion as e, type ViewerCamera as f, type ViewerView as g, type Projection as h, type PartModelFeature as i, type FeatureType as j, CANDIDATE_WEIGHT as k, DEFAULT_THEME as l, DIRECTION_COLORS as m, normalizePartReport as n, EXCLUDE_FROM_FRAME as o, type FeatureHighlight as p, HIGHLIGHT_COLORS as q, HIGHLIGHT_WEIGHT as r, smoothRegionNormals as s, HOVER_WEIGHT as t, type HighlightLayers as u, PERSPECTIVE_FOV as v, PICKED_SURFACE_LABEL as w, PartMesh as x, type PartMeshProps as y, type PartObject as z };
821
+ export { resolveSectionPlane as $, type SectionOptions as A, type BuildPickInput as B, CANDIDATE_WEIGHT as C, DEFAULT_THEME as D, EnginePart as E, type FeatureTag as F, type SectionPlacement as G, HANDLE_PIXELS as H, type SectionState as I, SectionView as J, type KnownFeatureType as K, applyHighlightLayers as L, MIN_KERNEL_VERSION as M, NO_MODIFIERS as N, buildPick as O, type PartModel as P, buildRegionAttribute as Q, type RegionIndex as R, SECTION_RENDER_ORDER as S, type TriangleRange as T, buildRegionTexels as U, type Vec3 as V, createPart as W, directionColor as X, dragPlane as Y, focusForPick as Z, pickedStartDepth as _, type PartMeshRefs as a, resolveTheme as a0, sectionBounds as a1, sectionConstant as a2, sectionDepth as a3, sectionDepthConstant as a4, sectionDepthRange as a5, sectionFromPick as a6, sectionOffset as a7, sectionPlane as a8, themesEqual as a9, viewDirection as aa, type EnginePartProps as b, assertSupportedKernelVersion as c, type ViewerTheme as d, type PartModelRegion as e, type PartModelFeature as f, type FeatureType as g, DIRECTION_COLORS as h, type FeatureHighlight as i, HIGHLIGHT_COLORS as j, HIGHLIGHT_WEIGHT as k, HOVER_WEIGHT as l, type HighlightLayers as m, normalizePartReport as n, PICKED_SURFACE_LABEL as o, PartMesh as p, type PartMeshProps as q, type PartObject as r, smoothRegionNormals as s, type PartPick as t, type PickModifiers as u, REGION_ATTRIBUTE as v, type RegionHighlight as w, type RegionPaint as x, type SectionAnchor as y, type SectionBounds as z };
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@toolpath/viewer",
3
- "version": "0.4.0",
3
+ "version": "1.0.0",
4
4
  "description": "React Three Fiber viewer for Toolpath Engine part reports",
5
5
  "license": "MIT",
6
+ "engines": {
7
+ "node": ">=20"
8
+ },
6
9
  "repository": {
7
10
  "type": "git",
8
11
  "url": "https://github.com/toolpath/ui-packages.git",
@@ -62,6 +65,7 @@
62
65
  },
63
66
  "scripts": {
64
67
  "build": "tsup src/index.ts src/engine/index.ts --format esm --dts --clean --external react --external react-dom --external three --external @react-three/fiber --external @react-three/drei",
68
+ "build:watch": "tsup src/index.ts src/engine/index.ts --format esm --dts --watch --external react --external react-dom --external three --external @react-three/fiber --external @react-three/drei",
65
69
  "check-types": "tsc --noEmit",
66
70
  "test": "vitest run"
67
71
  }