@layoutit/polycss 0.2.1 → 0.2.3

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
@@ -1,6 +1,6 @@
1
1
  # PolyCSS
2
2
 
3
- A CSS polygon mesh library. A 3D engine for the DOM. Renders OBJ/MTL, GLB and VOX as real HTML elements transformed with CSS `matrix3d(...)`. Supports colors, textures, lighting, shadows, shapes and animations. Works with React, Vue or plain JavaScript.
3
+ A CSS polygon mesh library. A 3D engine for the DOM. Renders OBJ/MTL, STL, glTF/GLB, and VOX as real HTML elements transformed with CSS `matrix3d(...)`. Supports colors, textures, lighting, shadows, shapes and animations. Works with React, Vue or plain JavaScript.
4
4
 
5
5
  Visit [polycss.com](https://polycss.com) for docs and model examples.
6
6
 
@@ -72,7 +72,6 @@ export default function App() {
72
72
  - `directionalLight` and `ambientLight` control scene lighting.
73
73
  - `textureLighting` chooses `"baked"` or `"dynamic"`.
74
74
  - `textureQuality` controls atlas raster budget.
75
- - Solid seam bleed is automatic on detected shared solid edges.
76
75
  - `strategies` can disable selected render strategies for diagnostics.
77
76
  - `autoCenter` rotates around the rendered mesh bounds instead of world origin.
78
77
 
@@ -83,8 +82,9 @@ export default function App() {
83
82
  - `polygons` accepts pre-parsed geometry.
84
83
  - `position`, `scale`, and `rotation` transform the mesh wrapper.
85
84
  - `autoCenter` shifts the mesh bbox center to local origin.
86
- - `meshResolution` chooses `"lossy"` (default) or `"lossless"` optimization.
85
+ - `meshResolution` chooses `"lossy"` (default) or `"lossless"` optimization. STL imports use the conservative lossless path in both modes.
87
86
  - `castShadow` emits CSS-projected shadows in dynamic lighting mode.
87
+ - Tooling can reuse `buildPolyMeshTransform`, `worldPositionToPolyCss`, and `worldDirectionToPolyCss` for renderer-compatible transforms.
88
88
 
89
89
  ### Controls
90
90
 
@@ -93,6 +93,18 @@ export default function App() {
93
93
  - `<PolyFirstPersonControls>` provides keyboard and pointer-look navigation.
94
94
  - `<PolyTransformControls>` adds translate/rotate gizmos for selected mesh handles.
95
95
 
96
+ ### Snapshot Export
97
+
98
+ The vanilla package exports `exportPolySceneSnapshot(target)`. It clones the current rendered `.polycss-camera` / `.polycss-scene` DOM, injects only the PolyCSS CSS needed by that snapshot, inlines CSS `url(...)` image assets as `data:image/...;base64,...`, strips scripts and inline event handlers, and returns a standalone HTML document string with no PolyCSS runtime import. It works with rendered React/Vue scenes too; import it from `@layoutit/polycss` and pass the rendered camera or scene element.
99
+
100
+ ```ts
101
+ import { exportPolySceneSnapshot } from "@layoutit/polycss";
102
+
103
+ const html = await exportPolySceneSnapshot(scene.host);
104
+ ```
105
+
106
+ If any referenced asset cannot be inlined, the function throws `PolySceneSnapshotError` with `code: "ASSET_INLINE_FAILED"`.
107
+
96
108
  ### Polygon Data Model
97
109
 
98
110
  Each polygon describes one renderable face:
@@ -149,22 +161,14 @@ scene.add(mesh);
149
161
  Supported formats:
150
162
 
151
163
  - OBJ + MTL, including `map_Kd` textures and UV coordinates.
164
+ - STL triangle meshes, including binary Magics face colors. STL has no standard units, textures, UVs, or hierarchy, so imports skip lossy simplification and ray-based interior culling.
152
165
  - glTF / GLB, including embedded images and `TEXCOORD_0`.
153
166
  - MagicaVoxel `.vox`, with direct voxel fast paths when eligible.
154
167
  - Generated primitives: box, plane, ring, sphere, torus, cylinder, cone, and Platonic solids.
155
168
 
156
169
  ## Performance
157
170
 
158
- PolyCSS renders in the DOM, so performance is mostly determined by how many polygons are mounted and how much texture atlas area they consume. The renderer uses several CSS strategies so simple surfaces stay cheap and textured or irregular surfaces fall back to atlas slices.
159
-
160
- - One visible polygon becomes one leaf DOM element.
161
- - Flat rectangles and stable quads use solid CSS leaves.
162
- - Textured polygons are packed into generated texture atlases.
163
- - Dynamic lighting runs through CSS custom properties instead of per-frame JavaScript.
164
- - Voxel-shaped meshes mount only camera-facing leaves when the mesh is eligible.
165
- - `meshResolution: "lossy"` merges compatible polygons, then may spend a small split budget to repair high-risk seams.
166
-
167
- Renderer internals:
171
+ PolyCSS renders through the DOM, so performance is mostly shaped by two things: the number of mounted leaves, and the amount of texture atlas area the browser has to paint. The renderer tries to keep the common cases cheap. Simple surfaces stay as solid CSS elements, while textured, irregular, or high-detail geometry falls back to atlas-backed slices only when needed.
168
172
 
169
173
  Each visible polygon is emitted as one leaf element; the renderer chooses the least expensive CSS primitive that can represent the polygon, then uses `matrix3d(...)` to place that primitive in 3D space.
170
174
 
@@ -9,7 +9,7 @@ interface PolyCameraOptions {
9
9
  distance?: number;
10
10
  }
11
11
  interface PolyPerspectiveCameraOptions extends PolyCameraOptions {
12
- /** CSS perspective distance in pixels. Default 8000. */
12
+ /** CSS perspective distance in pixels. Default 32000. */
13
13
  perspective?: number;
14
14
  }
15
15
  interface PolyOrthographicCameraOptions extends PolyCameraOptions {
@@ -28,7 +28,7 @@ interface PolyOrthographicCameraHandle extends CameraHandle {
28
28
  /**
29
29
  * Creates a perspective camera handle. The `perspectiveStyle` property
30
30
  * returns the CSS value to apply to the camera container's `perspective`
31
- * property (default `"8000px"`).
31
+ * property (default `"32000px"`).
32
32
  */
33
33
  declare function createPolyPerspectiveCamera(options?: PolyPerspectiveCameraOptions): PolyPerspectiveCameraHandle;
34
34
  /**
@@ -47,25 +47,10 @@ declare function createPolyOrthographicCamera(options?: PolyOrthographicCameraOp
47
47
  declare const createPolyCamera: typeof createPolyOrthographicCamera;
48
48
 
49
49
  /**
50
- * createPolyScene imperative scene API. The vanilla counterpart to
51
- * `<PolyScene>` in React / Vue.
52
- *
53
- * Per §API freeze: takes a host element + scene options, returns a
54
- * `PolySceneHandle` whose `add(parseResult, transform?)` mounts a mesh under
55
- * the scene root and returns a removable `PolyMeshHandle`.
56
- *
57
- * Implementation:
58
- * - Inserts a `<div class="polycss-scene">` into the host.
59
- * - Each `add(...)` creates a `<div class="polycss-mesh">` with the
60
- * mesh transform; mounts every valid polygon as an atlas-backed
61
- * background sprite.
62
- * - `destroy()` removes the scene element and disposes every mesh
63
- * (which in turn disposes generated atlas blob URLs).
64
- *
65
- * The scene element is a 0×0 anchor at world (0,0,0) — pinned via
66
- * top:50%/left:50% so it sits at the visible center of the host. This
67
- * matches React/Vue's PolyScene anchor pattern. Polygons render around
68
- * the anchor via their own matrix3d translations.
50
+ * Public + internal types for the scene module, extracted from
51
+ * createPolyScene.ts so other scene/* helpers can import them without
52
+ * pulling in the whole factory body. createPolyScene.ts re-exports the
53
+ * public ones so the polycss package public surface is unchanged.
69
54
  */
70
55
 
71
56
  interface PolySceneOptions {
@@ -131,6 +116,15 @@ interface PolySceneOptions {
131
116
  */
132
117
  maxExtend?: number;
133
118
  };
119
+ /**
120
+ * When `true`, emit `data-poly-shadow-*` attribution attributes on every
121
+ * shadow SVG and path (type, receiver mesh id, receiver face index,
122
+ * member poly indices, caster ids, caster poly indices). Useful for
123
+ * DevTools inspection and per-poly attribution in debug benches. When
124
+ * `false` (default), these attributes are suppressed entirely — production
125
+ * scenes ship a cleaner DOM and avoid serializing per-frame JSON.
126
+ */
127
+ debugShadowAttrs?: boolean;
134
128
  }
135
129
  interface PolyMeshTransform {
136
130
  /** Stable identifier — exposed on the handle and reflected on the
@@ -193,8 +187,7 @@ interface PolyMeshHandle {
193
187
  * the wrapper as `data-poly-mesh-id`. */
194
188
  readonly id?: string;
195
189
  /** Current transform snapshot (position / rotation / scale). Returned
196
- * by reference — treat as read-only and use `setTransform` to
197
- * mutate. */
190
+ * by reference — treat as read-only and use `setTransform` to mutate. */
198
191
  readonly transform: PolyMeshTransform;
199
192
  /** Remove the mesh from the scene. */
200
193
  remove(): void;
@@ -265,6 +258,11 @@ interface PolySceneHandle {
265
258
  * FPV controls toggle `.polycss-fpv-host` on this element.
266
259
  */
267
260
  readonly cameraEl: HTMLElement;
261
+ /**
262
+ * The `.polycss-scene` root element inside `cameraEl`. Mesh wrappers, shadow
263
+ * roots, and helper DOM are mounted under this element.
264
+ */
265
+ readonly sceneElement: HTMLElement;
268
266
  /**
269
267
  * The camera handle this scene is bound to. Controls update camera state
270
268
  * via `scene.camera.update({...})` then call `scene.applyCamera()` to
@@ -290,10 +288,101 @@ interface PolySceneHandle {
290
288
  * the element doesn't belong to this scene. */
291
289
  findMeshByElement(element: Element | null): PolyMeshHandle | null;
292
290
  }
293
- declare function createPolyScene(host: HTMLElement, options: PolySceneOptions): PolySceneHandle;
294
291
 
295
- declare const ELEMENT_BASE$a: typeof HTMLElement;
296
- declare class PolySceneElement extends ELEMENT_BASE$a {
292
+ /**
293
+ * Shared types, constants, and utilities for orbit/map controls factories.
294
+ * Not part of the public API surface — use createPolyOrbitControls or
295
+ * createPolyMapControls.
296
+ */
297
+
298
+ interface PolyControlsAnimateOptions {
299
+ /**
300
+ * Rotation rate in degrees per 60 Hz-equivalent frame. The tick is
301
+ * dt-clamped so 0.3 deg/frame ≈ 18 deg/sec on every refresh rate.
302
+ * Default: 0.3.
303
+ */
304
+ speed?: number;
305
+ /** Rotation axis. Default: "y" (yaw, rotates around vertical world Z). */
306
+ axis?: "x" | "y";
307
+ /** Halt the loop while a pointer drag is in progress. Default: true. */
308
+ pauseOnInteraction?: boolean;
309
+ }
310
+ interface PolyControlsBaseOptions {
311
+ /** Pointer-drag. Default: true. */
312
+ drag?: boolean;
313
+ /** Wheel / pinch zoom. Default: true. */
314
+ wheel?: boolean;
315
+ /**
316
+ * When `true`, wheel events change `distance` (camera pull-back in CSS px)
317
+ * instead of `zoom`. Mirrors Three.js OrbitControls dolly behaviour.
318
+ * Default: false (zoom mode).
319
+ */
320
+ dolly?: boolean;
321
+ /**
322
+ * Drag-direction inversion. `false` = natural, `true` = invert (×-1),
323
+ * a number multiplies sensitivity (negative inverts). Default: false.
324
+ */
325
+ invert?: boolean | number;
326
+ /** Minimum CSS zoom. Default: 0.1. */
327
+ minZoom?: number;
328
+ /** Maximum CSS zoom. Default: 10. */
329
+ maxZoom?: number;
330
+ /** Minimum dolly distance in CSS pixels. Default: 0. Only used when `dolly: true`. */
331
+ minDistance?: number;
332
+ /** Maximum dolly distance in CSS pixels. Default: Infinity. Only used when `dolly: true`. */
333
+ maxDistance?: number;
334
+ /** Auto-rotate. Pass false (or omit) to disable. */
335
+ animate?: false | PolyControlsAnimateOptions;
336
+ }
337
+ interface PolyControlsCamera {
338
+ rotX: number;
339
+ rotY: number;
340
+ zoom: number;
341
+ target: Vec3;
342
+ distance: number;
343
+ }
344
+ interface PolyControlsChangeEvent {
345
+ type: "change";
346
+ camera: PolyControlsCamera;
347
+ }
348
+ interface PolyControlsInteractionEvent {
349
+ type: "start" | "end";
350
+ camera: PolyControlsCamera;
351
+ }
352
+ type PolyControlsEvent = PolyControlsChangeEvent | PolyControlsInteractionEvent;
353
+ type PolyControlsListener<E extends PolyControlsEvent = PolyControlsEvent> = (event: E) => void;
354
+ interface PolyControlsHandle {
355
+ update(partial: PolyControlsBaseOptions): void;
356
+ resume(): void;
357
+ pause(): void;
358
+ destroy(): void;
359
+ addEventListener<T extends PolyControlsEvent["type"]>(type: T, listener: PolyControlsListener<Extract<PolyControlsEvent, {
360
+ type: T;
361
+ }>>): void;
362
+ removeEventListener<T extends PolyControlsEvent["type"]>(type: T, listener: PolyControlsListener<Extract<PolyControlsEvent, {
363
+ type: T;
364
+ }>>): void;
365
+ hasEventListener<T extends PolyControlsEvent["type"]>(type: T, listener: PolyControlsListener<Extract<PolyControlsEvent, {
366
+ type: T;
367
+ }>>): boolean;
368
+ }
369
+
370
+ /**
371
+ * createPolyOrbitControls — orbit-mode camera input for a PolyScene.
372
+ *
373
+ * Left-drag rotates rotX / rotY around the target (orbit). Wheel zooms or
374
+ * dollies. Mirrors Three.js OrbitControls semantics.
375
+ *
376
+ * For map/pan semantics (left-drag pans, right-drag orbits) use
377
+ * `createPolyMapControls` instead.
378
+ */
379
+
380
+ type PolyOrbitControlsOptions = PolyControlsBaseOptions;
381
+ type PolyOrbitControlsHandle = PolyControlsHandle;
382
+ declare function createPolyOrbitControls(scene: PolySceneHandle, options?: PolyOrbitControlsOptions): PolyOrbitControlsHandle;
383
+
384
+ declare const ELEMENT_BASE$b: typeof HTMLElement;
385
+ declare class PolySceneElement extends ELEMENT_BASE$b {
297
386
  static get observedAttributes(): string[];
298
387
  private _scene;
299
388
  private _implicitCamera;
@@ -312,8 +401,8 @@ declare class PolySceneElement extends ELEMENT_BASE$a {
312
401
  attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
313
402
  }
314
403
 
315
- declare const ELEMENT_BASE$9: typeof HTMLElement;
316
- declare class PolyMeshElement extends ELEMENT_BASE$9 {
404
+ declare const ELEMENT_BASE$a: typeof HTMLElement;
405
+ declare class PolyMeshElement extends ELEMENT_BASE$a {
317
406
  static get observedAttributes(): string[];
318
407
  private _handle;
319
408
  private _parseResult;
@@ -327,6 +416,21 @@ declare class PolyMeshElement extends ELEMENT_BASE$9 {
327
416
  private _maybeLoad;
328
417
  }
329
418
 
419
+ declare const ELEMENT_BASE$9: typeof HTMLElement;
420
+ declare class PolyIframeElement extends ELEMENT_BASE$9 {
421
+ static get observedAttributes(): string[];
422
+ private _wrapper;
423
+ private _iframe;
424
+ /** The iframe element this <poly-iframe> mounted, or null when detached. */
425
+ getIframeElement(): HTMLIFrameElement | null;
426
+ connectedCallback(): void;
427
+ disconnectedCallback(): void;
428
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
429
+ private _mount;
430
+ private _applyGeometry;
431
+ private _teardown;
432
+ }
433
+
330
434
  declare const ELEMENT_BASE$8: typeof HTMLElement;
331
435
  declare class PolyPolygonElement extends ELEMENT_BASE$8 {
332
436
  static get observedAttributes(): string[];
@@ -342,6 +446,11 @@ declare const ELEMENT_BASE$7: typeof HTMLElement;
342
446
  declare class PolyOrbitControlsElement extends ELEMENT_BASE$7 {
343
447
  static get observedAttributes(): string[];
344
448
  private _controls;
449
+ /** Returns the wrapped PolyOrbitControlsHandle once the element has
450
+ * connected to its `<poly-scene>` ancestor. Lets external callers attach
451
+ * `change` listeners (or call `update()` / `pause()`) the same way they
452
+ * would on a vanilla `createPolyOrbitControls(scene, ...)` handle. */
453
+ getControls(): PolyOrbitControlsHandle | null;
345
454
  private _readAnimate;
346
455
  private _readOptions;
347
456
  private _findScene;
@@ -385,7 +494,7 @@ declare class PolyFirstPersonControlsElement extends ELEMENT_BASE$5 {
385
494
  * CSS `perspective` property set.
386
495
  *
387
496
  * Attributes (all optional):
388
- * perspective — number, CSS perspective in pixels (default 8000)
497
+ * perspective — number, CSS perspective in pixels (default 32000)
389
498
  * zoom — number
390
499
  * rot-x — number, degrees (default 65)
391
500
  * rot-y — number, degrees (default 45)
@@ -405,7 +514,7 @@ declare class PolyPerspectiveCameraElement extends ELEMENT_BASE$4 {
405
514
  private _teardown;
406
515
  connectedCallback(): void;
407
516
  disconnectedCallback(): void;
408
- attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void;
517
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
409
518
  }
410
519
 
411
520
  /**
@@ -498,6 +607,7 @@ declare abstract class PolyShapeElement extends ELEMENT_BASE {
498
607
  abstract buildPolygons(): Polygon[];
499
608
  connectedCallback(): void;
500
609
  disconnectedCallback(): void;
610
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
501
611
  private _tearDown;
502
612
  private _mount;
503
613
  }
@@ -546,4 +656,4 @@ declare class PolyTorusElement extends PolyShapeElement {
546
656
  buildPolygons(): Polygon[];
547
657
  }
548
658
 
549
- export { PolySphereElement as A, PolyTetrahedronElement as B, PolyTorusElement as C, PolyTransformControlsElement as D, createPolyCamera as E, createPolyOrthographicCamera as F, createPolyPerspectiveCamera as G, createPolyScene as H, type PolySceneHandle as P, type PolyMeshHandle as a, PolyBoxElement as b, PolyCameraElement as c, type PolyCameraOptions as d, PolyConeElement as e, PolyCylinderElement as f, PolyDodecahedronElement as g, PolyFirstPersonControlsElement as h, PolyIcosahedronElement as i, PolyMapControlsElement as j, PolyMeshElement as k, type PolyMeshTransform as l, PolyOctahedronElement as m, PolyOrbitControlsElement as n, PolyOrthographicCameraElement as o, type PolyOrthographicCameraHandle as p, type PolyOrthographicCameraOptions as q, PolyPerspectiveCameraElement as r, type PolyPerspectiveCameraHandle as s, type PolyPerspectiveCameraOptions as t, PolyPlaneElement as u, PolyPolygonElement as v, PolyRingElement as w, PolySceneElement as x, type PolySceneOptions as y, PolySelectElement as z };
659
+ export { PolyOrthographicCameraElement as A, type PolyOrthographicCameraHandle as B, type PolyOrthographicCameraOptions as C, PolyPerspectiveCameraElement as D, type PolyPerspectiveCameraHandle as E, type PolyPerspectiveCameraOptions as F, PolyPlaneElement as G, PolyPolygonElement as H, PolyRingElement as I, PolySceneElement as J, PolySelectElement as K, PolySphereElement as L, PolyTetrahedronElement as M, PolyTorusElement as N, PolyTransformControlsElement as O, type PolySceneOptions as P, createPolyCamera as Q, createPolyOrbitControls as R, createPolyOrthographicCamera as S, createPolyPerspectiveCamera as T, type PolySceneHandle as a, type PolyControlsHandle as b, type PolyControlsBaseOptions as c, type PolyControlsEvent as d, type PolyControlsListener as e, type PolyMeshHandle as f, PolyBoxElement as g, PolyCameraElement as h, type PolyCameraOptions as i, PolyConeElement as j, type PolyControlsAnimateOptions as k, type PolyControlsCamera as l, type PolyControlsChangeEvent as m, type PolyControlsInteractionEvent as n, PolyCylinderElement as o, PolyDodecahedronElement as p, PolyFirstPersonControlsElement as q, PolyIcosahedronElement as r, PolyIframeElement as s, PolyMapControlsElement as t, PolyMeshElement as u, type PolyMeshTransform as v, PolyOctahedronElement as w, PolyOrbitControlsElement as x, type PolyOrbitControlsHandle as y, type PolyOrbitControlsOptions as z };
@@ -9,7 +9,7 @@ interface PolyCameraOptions {
9
9
  distance?: number;
10
10
  }
11
11
  interface PolyPerspectiveCameraOptions extends PolyCameraOptions {
12
- /** CSS perspective distance in pixels. Default 8000. */
12
+ /** CSS perspective distance in pixels. Default 32000. */
13
13
  perspective?: number;
14
14
  }
15
15
  interface PolyOrthographicCameraOptions extends PolyCameraOptions {
@@ -28,7 +28,7 @@ interface PolyOrthographicCameraHandle extends CameraHandle {
28
28
  /**
29
29
  * Creates a perspective camera handle. The `perspectiveStyle` property
30
30
  * returns the CSS value to apply to the camera container's `perspective`
31
- * property (default `"8000px"`).
31
+ * property (default `"32000px"`).
32
32
  */
33
33
  declare function createPolyPerspectiveCamera(options?: PolyPerspectiveCameraOptions): PolyPerspectiveCameraHandle;
34
34
  /**
@@ -47,25 +47,10 @@ declare function createPolyOrthographicCamera(options?: PolyOrthographicCameraOp
47
47
  declare const createPolyCamera: typeof createPolyOrthographicCamera;
48
48
 
49
49
  /**
50
- * createPolyScene imperative scene API. The vanilla counterpart to
51
- * `<PolyScene>` in React / Vue.
52
- *
53
- * Per §API freeze: takes a host element + scene options, returns a
54
- * `PolySceneHandle` whose `add(parseResult, transform?)` mounts a mesh under
55
- * the scene root and returns a removable `PolyMeshHandle`.
56
- *
57
- * Implementation:
58
- * - Inserts a `<div class="polycss-scene">` into the host.
59
- * - Each `add(...)` creates a `<div class="polycss-mesh">` with the
60
- * mesh transform; mounts every valid polygon as an atlas-backed
61
- * background sprite.
62
- * - `destroy()` removes the scene element and disposes every mesh
63
- * (which in turn disposes generated atlas blob URLs).
64
- *
65
- * The scene element is a 0×0 anchor at world (0,0,0) — pinned via
66
- * top:50%/left:50% so it sits at the visible center of the host. This
67
- * matches React/Vue's PolyScene anchor pattern. Polygons render around
68
- * the anchor via their own matrix3d translations.
50
+ * Public + internal types for the scene module, extracted from
51
+ * createPolyScene.ts so other scene/* helpers can import them without
52
+ * pulling in the whole factory body. createPolyScene.ts re-exports the
53
+ * public ones so the polycss package public surface is unchanged.
69
54
  */
70
55
 
71
56
  interface PolySceneOptions {
@@ -131,6 +116,15 @@ interface PolySceneOptions {
131
116
  */
132
117
  maxExtend?: number;
133
118
  };
119
+ /**
120
+ * When `true`, emit `data-poly-shadow-*` attribution attributes on every
121
+ * shadow SVG and path (type, receiver mesh id, receiver face index,
122
+ * member poly indices, caster ids, caster poly indices). Useful for
123
+ * DevTools inspection and per-poly attribution in debug benches. When
124
+ * `false` (default), these attributes are suppressed entirely — production
125
+ * scenes ship a cleaner DOM and avoid serializing per-frame JSON.
126
+ */
127
+ debugShadowAttrs?: boolean;
134
128
  }
135
129
  interface PolyMeshTransform {
136
130
  /** Stable identifier — exposed on the handle and reflected on the
@@ -193,8 +187,7 @@ interface PolyMeshHandle {
193
187
  * the wrapper as `data-poly-mesh-id`. */
194
188
  readonly id?: string;
195
189
  /** Current transform snapshot (position / rotation / scale). Returned
196
- * by reference — treat as read-only and use `setTransform` to
197
- * mutate. */
190
+ * by reference — treat as read-only and use `setTransform` to mutate. */
198
191
  readonly transform: PolyMeshTransform;
199
192
  /** Remove the mesh from the scene. */
200
193
  remove(): void;
@@ -265,6 +258,11 @@ interface PolySceneHandle {
265
258
  * FPV controls toggle `.polycss-fpv-host` on this element.
266
259
  */
267
260
  readonly cameraEl: HTMLElement;
261
+ /**
262
+ * The `.polycss-scene` root element inside `cameraEl`. Mesh wrappers, shadow
263
+ * roots, and helper DOM are mounted under this element.
264
+ */
265
+ readonly sceneElement: HTMLElement;
268
266
  /**
269
267
  * The camera handle this scene is bound to. Controls update camera state
270
268
  * via `scene.camera.update({...})` then call `scene.applyCamera()` to
@@ -290,10 +288,101 @@ interface PolySceneHandle {
290
288
  * the element doesn't belong to this scene. */
291
289
  findMeshByElement(element: Element | null): PolyMeshHandle | null;
292
290
  }
293
- declare function createPolyScene(host: HTMLElement, options: PolySceneOptions): PolySceneHandle;
294
291
 
295
- declare const ELEMENT_BASE$a: typeof HTMLElement;
296
- declare class PolySceneElement extends ELEMENT_BASE$a {
292
+ /**
293
+ * Shared types, constants, and utilities for orbit/map controls factories.
294
+ * Not part of the public API surface — use createPolyOrbitControls or
295
+ * createPolyMapControls.
296
+ */
297
+
298
+ interface PolyControlsAnimateOptions {
299
+ /**
300
+ * Rotation rate in degrees per 60 Hz-equivalent frame. The tick is
301
+ * dt-clamped so 0.3 deg/frame ≈ 18 deg/sec on every refresh rate.
302
+ * Default: 0.3.
303
+ */
304
+ speed?: number;
305
+ /** Rotation axis. Default: "y" (yaw, rotates around vertical world Z). */
306
+ axis?: "x" | "y";
307
+ /** Halt the loop while a pointer drag is in progress. Default: true. */
308
+ pauseOnInteraction?: boolean;
309
+ }
310
+ interface PolyControlsBaseOptions {
311
+ /** Pointer-drag. Default: true. */
312
+ drag?: boolean;
313
+ /** Wheel / pinch zoom. Default: true. */
314
+ wheel?: boolean;
315
+ /**
316
+ * When `true`, wheel events change `distance` (camera pull-back in CSS px)
317
+ * instead of `zoom`. Mirrors Three.js OrbitControls dolly behaviour.
318
+ * Default: false (zoom mode).
319
+ */
320
+ dolly?: boolean;
321
+ /**
322
+ * Drag-direction inversion. `false` = natural, `true` = invert (×-1),
323
+ * a number multiplies sensitivity (negative inverts). Default: false.
324
+ */
325
+ invert?: boolean | number;
326
+ /** Minimum CSS zoom. Default: 0.1. */
327
+ minZoom?: number;
328
+ /** Maximum CSS zoom. Default: 10. */
329
+ maxZoom?: number;
330
+ /** Minimum dolly distance in CSS pixels. Default: 0. Only used when `dolly: true`. */
331
+ minDistance?: number;
332
+ /** Maximum dolly distance in CSS pixels. Default: Infinity. Only used when `dolly: true`. */
333
+ maxDistance?: number;
334
+ /** Auto-rotate. Pass false (or omit) to disable. */
335
+ animate?: false | PolyControlsAnimateOptions;
336
+ }
337
+ interface PolyControlsCamera {
338
+ rotX: number;
339
+ rotY: number;
340
+ zoom: number;
341
+ target: Vec3;
342
+ distance: number;
343
+ }
344
+ interface PolyControlsChangeEvent {
345
+ type: "change";
346
+ camera: PolyControlsCamera;
347
+ }
348
+ interface PolyControlsInteractionEvent {
349
+ type: "start" | "end";
350
+ camera: PolyControlsCamera;
351
+ }
352
+ type PolyControlsEvent = PolyControlsChangeEvent | PolyControlsInteractionEvent;
353
+ type PolyControlsListener<E extends PolyControlsEvent = PolyControlsEvent> = (event: E) => void;
354
+ interface PolyControlsHandle {
355
+ update(partial: PolyControlsBaseOptions): void;
356
+ resume(): void;
357
+ pause(): void;
358
+ destroy(): void;
359
+ addEventListener<T extends PolyControlsEvent["type"]>(type: T, listener: PolyControlsListener<Extract<PolyControlsEvent, {
360
+ type: T;
361
+ }>>): void;
362
+ removeEventListener<T extends PolyControlsEvent["type"]>(type: T, listener: PolyControlsListener<Extract<PolyControlsEvent, {
363
+ type: T;
364
+ }>>): void;
365
+ hasEventListener<T extends PolyControlsEvent["type"]>(type: T, listener: PolyControlsListener<Extract<PolyControlsEvent, {
366
+ type: T;
367
+ }>>): boolean;
368
+ }
369
+
370
+ /**
371
+ * createPolyOrbitControls — orbit-mode camera input for a PolyScene.
372
+ *
373
+ * Left-drag rotates rotX / rotY around the target (orbit). Wheel zooms or
374
+ * dollies. Mirrors Three.js OrbitControls semantics.
375
+ *
376
+ * For map/pan semantics (left-drag pans, right-drag orbits) use
377
+ * `createPolyMapControls` instead.
378
+ */
379
+
380
+ type PolyOrbitControlsOptions = PolyControlsBaseOptions;
381
+ type PolyOrbitControlsHandle = PolyControlsHandle;
382
+ declare function createPolyOrbitControls(scene: PolySceneHandle, options?: PolyOrbitControlsOptions): PolyOrbitControlsHandle;
383
+
384
+ declare const ELEMENT_BASE$b: typeof HTMLElement;
385
+ declare class PolySceneElement extends ELEMENT_BASE$b {
297
386
  static get observedAttributes(): string[];
298
387
  private _scene;
299
388
  private _implicitCamera;
@@ -312,8 +401,8 @@ declare class PolySceneElement extends ELEMENT_BASE$a {
312
401
  attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
313
402
  }
314
403
 
315
- declare const ELEMENT_BASE$9: typeof HTMLElement;
316
- declare class PolyMeshElement extends ELEMENT_BASE$9 {
404
+ declare const ELEMENT_BASE$a: typeof HTMLElement;
405
+ declare class PolyMeshElement extends ELEMENT_BASE$a {
317
406
  static get observedAttributes(): string[];
318
407
  private _handle;
319
408
  private _parseResult;
@@ -327,6 +416,21 @@ declare class PolyMeshElement extends ELEMENT_BASE$9 {
327
416
  private _maybeLoad;
328
417
  }
329
418
 
419
+ declare const ELEMENT_BASE$9: typeof HTMLElement;
420
+ declare class PolyIframeElement extends ELEMENT_BASE$9 {
421
+ static get observedAttributes(): string[];
422
+ private _wrapper;
423
+ private _iframe;
424
+ /** The iframe element this <poly-iframe> mounted, or null when detached. */
425
+ getIframeElement(): HTMLIFrameElement | null;
426
+ connectedCallback(): void;
427
+ disconnectedCallback(): void;
428
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
429
+ private _mount;
430
+ private _applyGeometry;
431
+ private _teardown;
432
+ }
433
+
330
434
  declare const ELEMENT_BASE$8: typeof HTMLElement;
331
435
  declare class PolyPolygonElement extends ELEMENT_BASE$8 {
332
436
  static get observedAttributes(): string[];
@@ -342,6 +446,11 @@ declare const ELEMENT_BASE$7: typeof HTMLElement;
342
446
  declare class PolyOrbitControlsElement extends ELEMENT_BASE$7 {
343
447
  static get observedAttributes(): string[];
344
448
  private _controls;
449
+ /** Returns the wrapped PolyOrbitControlsHandle once the element has
450
+ * connected to its `<poly-scene>` ancestor. Lets external callers attach
451
+ * `change` listeners (or call `update()` / `pause()`) the same way they
452
+ * would on a vanilla `createPolyOrbitControls(scene, ...)` handle. */
453
+ getControls(): PolyOrbitControlsHandle | null;
345
454
  private _readAnimate;
346
455
  private _readOptions;
347
456
  private _findScene;
@@ -385,7 +494,7 @@ declare class PolyFirstPersonControlsElement extends ELEMENT_BASE$5 {
385
494
  * CSS `perspective` property set.
386
495
  *
387
496
  * Attributes (all optional):
388
- * perspective — number, CSS perspective in pixels (default 8000)
497
+ * perspective — number, CSS perspective in pixels (default 32000)
389
498
  * zoom — number
390
499
  * rot-x — number, degrees (default 65)
391
500
  * rot-y — number, degrees (default 45)
@@ -405,7 +514,7 @@ declare class PolyPerspectiveCameraElement extends ELEMENT_BASE$4 {
405
514
  private _teardown;
406
515
  connectedCallback(): void;
407
516
  disconnectedCallback(): void;
408
- attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void;
517
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
409
518
  }
410
519
 
411
520
  /**
@@ -498,6 +607,7 @@ declare abstract class PolyShapeElement extends ELEMENT_BASE {
498
607
  abstract buildPolygons(): Polygon[];
499
608
  connectedCallback(): void;
500
609
  disconnectedCallback(): void;
610
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
501
611
  private _tearDown;
502
612
  private _mount;
503
613
  }
@@ -546,4 +656,4 @@ declare class PolyTorusElement extends PolyShapeElement {
546
656
  buildPolygons(): Polygon[];
547
657
  }
548
658
 
549
- export { PolySphereElement as A, PolyTetrahedronElement as B, PolyTorusElement as C, PolyTransformControlsElement as D, createPolyCamera as E, createPolyOrthographicCamera as F, createPolyPerspectiveCamera as G, createPolyScene as H, type PolySceneHandle as P, type PolyMeshHandle as a, PolyBoxElement as b, PolyCameraElement as c, type PolyCameraOptions as d, PolyConeElement as e, PolyCylinderElement as f, PolyDodecahedronElement as g, PolyFirstPersonControlsElement as h, PolyIcosahedronElement as i, PolyMapControlsElement as j, PolyMeshElement as k, type PolyMeshTransform as l, PolyOctahedronElement as m, PolyOrbitControlsElement as n, PolyOrthographicCameraElement as o, type PolyOrthographicCameraHandle as p, type PolyOrthographicCameraOptions as q, PolyPerspectiveCameraElement as r, type PolyPerspectiveCameraHandle as s, type PolyPerspectiveCameraOptions as t, PolyPlaneElement as u, PolyPolygonElement as v, PolyRingElement as w, PolySceneElement as x, type PolySceneOptions as y, PolySelectElement as z };
659
+ export { PolyOrthographicCameraElement as A, type PolyOrthographicCameraHandle as B, type PolyOrthographicCameraOptions as C, PolyPerspectiveCameraElement as D, type PolyPerspectiveCameraHandle as E, type PolyPerspectiveCameraOptions as F, PolyPlaneElement as G, PolyPolygonElement as H, PolyRingElement as I, PolySceneElement as J, PolySelectElement as K, PolySphereElement as L, PolyTetrahedronElement as M, PolyTorusElement as N, PolyTransformControlsElement as O, type PolySceneOptions as P, createPolyCamera as Q, createPolyOrbitControls as R, createPolyOrthographicCamera as S, createPolyPerspectiveCamera as T, type PolySceneHandle as a, type PolyControlsHandle as b, type PolyControlsBaseOptions as c, type PolyControlsEvent as d, type PolyControlsListener as e, type PolyMeshHandle as f, PolyBoxElement as g, PolyCameraElement as h, type PolyCameraOptions as i, PolyConeElement as j, type PolyControlsAnimateOptions as k, type PolyControlsCamera as l, type PolyControlsChangeEvent as m, type PolyControlsInteractionEvent as n, PolyCylinderElement as o, PolyDodecahedronElement as p, PolyFirstPersonControlsElement as q, PolyIcosahedronElement as r, PolyIframeElement as s, PolyMapControlsElement as t, PolyMeshElement as u, type PolyMeshTransform as v, PolyOctahedronElement as w, PolyOrbitControlsElement as x, type PolyOrbitControlsHandle as y, type PolyOrbitControlsOptions as z };