@geometra/renderer-three 0.2.0 → 1.4.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.
Files changed (47) hide show
  1. package/dist/__tests__/scene3d-manager.test.d.ts +2 -0
  2. package/dist/__tests__/scene3d-manager.test.d.ts.map +1 -0
  3. package/dist/__tests__/scene3d-manager.test.js +80 -0
  4. package/dist/__tests__/scene3d-manager.test.js.map +1 -0
  5. package/dist/host-css-coerce.d.ts +39 -0
  6. package/dist/host-css-coerce.d.ts.map +1 -0
  7. package/dist/host-css-coerce.js +69 -0
  8. package/dist/host-css-coerce.js.map +1 -0
  9. package/dist/host-layout-plain.d.ts +164 -0
  10. package/dist/host-layout-plain.d.ts.map +1 -0
  11. package/dist/host-layout-plain.js +255 -0
  12. package/dist/host-layout-plain.js.map +1 -0
  13. package/dist/index.d.ts +43 -5
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +42 -5
  16. package/dist/index.js.map +1 -1
  17. package/dist/layout-sync.d.ts +51 -0
  18. package/dist/layout-sync.d.ts.map +1 -0
  19. package/dist/layout-sync.js +59 -0
  20. package/dist/layout-sync.js.map +1 -0
  21. package/dist/page-host.d.ts +41 -0
  22. package/dist/page-host.d.ts.map +1 -0
  23. package/dist/page-host.js +89 -0
  24. package/dist/page-host.js.map +1 -0
  25. package/dist/scene3d-manager.d.ts +33 -0
  26. package/dist/scene3d-manager.d.ts.map +1 -0
  27. package/dist/scene3d-manager.js +394 -0
  28. package/dist/scene3d-manager.js.map +1 -0
  29. package/dist/split-host.d.ts +65 -9
  30. package/dist/split-host.d.ts.map +1 -1
  31. package/dist/split-host.js +115 -39
  32. package/dist/split-host.js.map +1 -1
  33. package/dist/stacked-host.d.ts +64 -14
  34. package/dist/stacked-host.d.ts.map +1 -1
  35. package/dist/stacked-host.js +77 -41
  36. package/dist/stacked-host.js.map +1 -1
  37. package/dist/three-scene-basics.d.ts +313 -2
  38. package/dist/three-scene-basics.d.ts.map +1 -1
  39. package/dist/three-scene-basics.js +418 -1
  40. package/dist/three-scene-basics.js.map +1 -1
  41. package/dist/utils.d.ts +156 -0
  42. package/dist/utils.d.ts.map +1 -1
  43. package/dist/utils.js +207 -6
  44. package/dist/utils.js.map +1 -1
  45. package/package.json +15 -18
  46. package/LICENSE +0 -21
  47. package/README.md +0 -111
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scene3d-manager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene3d-manager.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/scene3d-manager.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,80 @@
1
+ import * as THREE from 'three';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { group, scene3d, sphere } from '@geometra/core';
4
+ import { Scene3dManager } from '../scene3d-manager.js';
5
+ function sceneContentRoot(scene) {
6
+ const g = scene.children[0];
7
+ if (!g || !(g instanceof THREE.Group)) {
8
+ throw new Error('expected Scene3dManager scene group as first scene child');
9
+ }
10
+ return g;
11
+ }
12
+ describe('Scene3dManager', () => {
13
+ it('updates nested sphere props when wrapped in a group (in-place)', () => {
14
+ const scene = new THREE.Scene();
15
+ const camera = new THREE.PerspectiveCamera();
16
+ const mgr = new Scene3dManager(scene, camera);
17
+ mgr.sync(scene3d({
18
+ width: 100,
19
+ height: 80,
20
+ objects: [group({ objects: [sphere({ color: 0xff0000 })] })],
21
+ }));
22
+ const top = sceneContentRoot(scene).children[0];
23
+ const mesh = top.children[0];
24
+ expect(mesh.material.color.getHex()).toBe(0xff0000);
25
+ mgr.sync(scene3d({
26
+ width: 100,
27
+ height: 80,
28
+ objects: [group({ objects: [sphere({ color: 0x00ff00 })] })],
29
+ }));
30
+ expect(mesh.material.color.getHex()).toBe(0x00ff00);
31
+ expect(top.children[0]).toBe(mesh);
32
+ });
33
+ it('rebuilds group children when nested arity changes', () => {
34
+ const scene = new THREE.Scene();
35
+ const camera = new THREE.PerspectiveCamera();
36
+ const mgr = new Scene3dManager(scene, camera);
37
+ mgr.sync(scene3d({
38
+ width: 100,
39
+ height: 80,
40
+ objects: [group({ objects: [sphere({ color: 0xff0000 })] })],
41
+ }));
42
+ const top = sceneContentRoot(scene).children[0];
43
+ expect(top.children.length).toBe(1);
44
+ mgr.sync(scene3d({
45
+ width: 100,
46
+ height: 80,
47
+ objects: [group({ objects: [sphere({ color: 0xff0000 }), sphere({ color: 0x0000ff })] })],
48
+ }));
49
+ expect(top.children.length).toBe(2);
50
+ });
51
+ it('updates a sphere inside nested groups', () => {
52
+ const scene = new THREE.Scene();
53
+ const camera = new THREE.PerspectiveCamera();
54
+ const mgr = new Scene3dManager(scene, camera);
55
+ mgr.sync(scene3d({
56
+ width: 100,
57
+ height: 80,
58
+ objects: [
59
+ group({
60
+ objects: [group({ objects: [sphere({ color: 0xff0000 })] })],
61
+ }),
62
+ ],
63
+ }));
64
+ const outer = sceneContentRoot(scene).children[0];
65
+ const inner = outer.children[0];
66
+ const mesh = inner.children[0];
67
+ mgr.sync(scene3d({
68
+ width: 100,
69
+ height: 80,
70
+ objects: [
71
+ group({
72
+ objects: [group({ objects: [sphere({ color: 0x0000ff })] })],
73
+ }),
74
+ ],
75
+ }));
76
+ expect(mesh.material.color.getHex()).toBe(0x0000ff);
77
+ expect(inner.children[0]).toBe(mesh);
78
+ });
79
+ });
80
+ //# sourceMappingURL=scene3d-manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene3d-manager.test.js","sourceRoot":"","sources":["../../src/__tests__/scene3d-manager.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /** Corner anchor for the Geometra HUD overlay (same literals as {@link createThreeGeometraStackedHost}). */
2
+ export type GeometraHudPlacement = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
3
+ /**
4
+ * Normalize HUD corner placement from runtime strings (e.g. agent JSON or untyped config).
5
+ * Leading/trailing whitespace is trimmed and the four known literals are matched **case-insensitively**
6
+ * so payloads stay stable across generators. Unknown or empty values use `fallback` so the overlay
7
+ * keeps a valid `position: absolute` inset.
8
+ */
9
+ export declare function coerceGeometraHudPlacement(value: string | undefined, fallback: GeometraHudPlacement): GeometraHudPlacement;
10
+ /**
11
+ * CSS `pointer-events` for stacked HUD / overlay wrappers: trimmed non-empty strings pass through;
12
+ * otherwise `fallback` (avoids blank or invalid values from untyped config or agent JSON).
13
+ *
14
+ * {@link createThreeGeometraStackedHost} uses this for {@link ThreeGeometraStackedHostOptions.geometraHudPointerEvents}.
15
+ * Use next to {@link coerceHostStackingZIndexCss} when you build a custom stacked layout.
16
+ */
17
+ export declare function coerceGeometraHudPointerEvents(value: string | undefined | null, fallback?: string): string;
18
+ /**
19
+ * Finite, non-negative CSS px for host panel/HUD sizing; invalid values use `fallback`
20
+ * (avoids `NaNpx` / negative sizes in inline styles).
21
+ *
22
+ * Same helper {@link createThreeGeometraSplitHost} and {@link createThreeGeometraStackedHost} use for
23
+ * `geometraWidth`, HUD width/height, and margin. Use when building a custom hybrid layout next to
24
+ * {@link createGeometraHostLayoutSyncRaf} so numeric options stay consistent with those hosts.
25
+ *
26
+ * @param value - Requested size in CSS pixels; non-finite, negative, or non-number values are rejected.
27
+ * @param fallback - Default used when `value` is invalid (match the host default you document, e.g. 420).
28
+ * @returns Either `value` (when valid) or `fallback`.
29
+ */
30
+ export declare function coerceHostNonNegativeCssPx(value: number, fallback: number): number;
31
+ /**
32
+ * CSS `z-index` string for stacked HUD / overlay wrappers: finite numbers and non-blank strings pass
33
+ * through; otherwise `fallback` (avoids `NaN` / `Infinity` in inline styles).
34
+ *
35
+ * {@link createThreeGeometraStackedHost} uses this for {@link ThreeGeometraStackedHostOptions.geometraHudZIndex}.
36
+ * Use in custom stacking layouts next to {@link coerceHostNonNegativeCssPx} for consistent behavior.
37
+ */
38
+ export declare function coerceHostStackingZIndexCss(value: string | number, fallback: number): string;
39
+ //# sourceMappingURL=host-css-coerce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-css-coerce.d.ts","sourceRoot":"","sources":["../src/host-css-coerce.ts"],"names":[],"mappings":"AAAA,4GAA4G;AAC5G,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,aAAa,GAAG,WAAW,GAAG,UAAU,CAAA;AAE5F;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,oBAAoB,GAC7B,oBAAoB,CAYtB;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EAChC,QAAQ,SAAS,GAChB,MAAM,CAMR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAElF;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAS5F"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Normalize HUD corner placement from runtime strings (e.g. agent JSON or untyped config).
3
+ * Leading/trailing whitespace is trimmed and the four known literals are matched **case-insensitively**
4
+ * so payloads stay stable across generators. Unknown or empty values use `fallback` so the overlay
5
+ * keeps a valid `position: absolute` inset.
6
+ */
7
+ export function coerceGeometraHudPlacement(value, fallback) {
8
+ if (typeof value !== 'string')
9
+ return fallback;
10
+ const key = value.trim().toLowerCase();
11
+ switch (key) {
12
+ case 'bottom-right':
13
+ case 'bottom-left':
14
+ case 'top-right':
15
+ case 'top-left':
16
+ return key;
17
+ default:
18
+ return fallback;
19
+ }
20
+ }
21
+ /**
22
+ * CSS `pointer-events` for stacked HUD / overlay wrappers: trimmed non-empty strings pass through;
23
+ * otherwise `fallback` (avoids blank or invalid values from untyped config or agent JSON).
24
+ *
25
+ * {@link createThreeGeometraStackedHost} uses this for {@link ThreeGeometraStackedHostOptions.geometraHudPointerEvents}.
26
+ * Use next to {@link coerceHostStackingZIndexCss} when you build a custom stacked layout.
27
+ */
28
+ export function coerceGeometraHudPointerEvents(value, fallback = 'auto') {
29
+ if (typeof value === 'string') {
30
+ const t = value.trim();
31
+ if (t.length > 0)
32
+ return t;
33
+ }
34
+ return fallback;
35
+ }
36
+ /**
37
+ * Finite, non-negative CSS px for host panel/HUD sizing; invalid values use `fallback`
38
+ * (avoids `NaNpx` / negative sizes in inline styles).
39
+ *
40
+ * Same helper {@link createThreeGeometraSplitHost} and {@link createThreeGeometraStackedHost} use for
41
+ * `geometraWidth`, HUD width/height, and margin. Use when building a custom hybrid layout next to
42
+ * {@link createGeometraHostLayoutSyncRaf} so numeric options stay consistent with those hosts.
43
+ *
44
+ * @param value - Requested size in CSS pixels; non-finite, negative, or non-number values are rejected.
45
+ * @param fallback - Default used when `value` is invalid (match the host default you document, e.g. 420).
46
+ * @returns Either `value` (when valid) or `fallback`.
47
+ */
48
+ export function coerceHostNonNegativeCssPx(value, fallback) {
49
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : fallback;
50
+ }
51
+ /**
52
+ * CSS `z-index` string for stacked HUD / overlay wrappers: finite numbers and non-blank strings pass
53
+ * through; otherwise `fallback` (avoids `NaN` / `Infinity` in inline styles).
54
+ *
55
+ * {@link createThreeGeometraStackedHost} uses this for {@link ThreeGeometraStackedHostOptions.geometraHudZIndex}.
56
+ * Use in custom stacking layouts next to {@link coerceHostNonNegativeCssPx} for consistent behavior.
57
+ */
58
+ export function coerceHostStackingZIndexCss(value, fallback) {
59
+ if (typeof value === 'number' && Number.isFinite(value)) {
60
+ return String(value);
61
+ }
62
+ if (typeof value === 'string') {
63
+ const t = value.trim();
64
+ if (t.length > 0)
65
+ return t;
66
+ }
67
+ return String(fallback);
68
+ }
69
+ //# sourceMappingURL=host-css-coerce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-css-coerce.js","sourceRoot":"","sources":["../src/host-css-coerce.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,KAAyB,EACzB,QAA8B;IAE9B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC9C,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IACtC,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,cAAc,CAAC;QACpB,KAAK,aAAa,CAAC;QACnB,KAAK,WAAW,CAAC;QACjB,KAAK,UAAU;YACb,OAAO,GAAG,CAAA;QACZ;YACE,OAAO,QAAQ,CAAA;IACnB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,8BAA8B,CAC5C,KAAgC,EAChC,QAAQ,GAAG,MAAM;IAEjB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;QACtB,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,CAAA;IAC5B,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,0BAA0B,CAAC,KAAa,EAAE,QAAgB;IACxE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC7F,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAAsB,EAAE,QAAgB;IAClF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;IACtB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;QACtB,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,CAAA;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAA;AACzB,CAAC"}
@@ -0,0 +1,164 @@
1
+ import { type GeometraHudPlacement } from './host-css-coerce.js';
2
+ import { type GeometraThreeSceneBasicsOptions, type PlainGeometraThreeHostSnapshot } from './three-scene-basics.js';
3
+ /** Resolved Geometra column layout for {@link createThreeGeometraSplitHost} after coercion (JSON-friendly). */
4
+ export interface PlainGeometraSplitHostLayoutOptions {
5
+ geometraWidth: number;
6
+ geometraOnLeft: boolean;
7
+ }
8
+ export interface ToPlainGeometraSplitHostLayoutOptionsInput {
9
+ geometraWidth?: number;
10
+ geometraOnLeft?: boolean;
11
+ }
12
+ /**
13
+ * Resolved split-host layout fields for logs, tests, or agent-side JSON without constructing the DOM host.
14
+ * Uses the same coercion as {@link createThreeGeometraSplitHost}.
15
+ */
16
+ export declare function toPlainGeometraSplitHostLayoutOptions(options?: ToPlainGeometraSplitHostLayoutOptionsInput): PlainGeometraSplitHostLayoutOptions;
17
+ /** Resolved stacked HUD layout for {@link createThreeGeometraStackedHost} after coercion (JSON-friendly). */
18
+ export interface PlainGeometraStackedHostLayoutOptions {
19
+ geometraHudWidth: number;
20
+ geometraHudHeight: number;
21
+ geometraHudPlacement: GeometraHudPlacement;
22
+ geometraHudMargin: number;
23
+ geometraHudPointerEvents: string;
24
+ /** Coerced CSS `z-index` string (same value applied to the HUD wrapper in the stacked host). */
25
+ geometraHudZIndex: string;
26
+ }
27
+ export interface ToPlainGeometraStackedHostLayoutOptionsInput {
28
+ geometraHudWidth?: number;
29
+ geometraHudHeight?: number;
30
+ /** Runtime strings (e.g. from JSON) are normalized like {@link createThreeGeometraStackedHost}. */
31
+ geometraHudPlacement?: GeometraHudPlacement | string;
32
+ geometraHudMargin?: number;
33
+ geometraHudPointerEvents?: string;
34
+ geometraHudZIndex?: string | number;
35
+ }
36
+ /**
37
+ * Resolved stacked HUD layout fields for logs, tests, or agent-side JSON without constructing the DOM host.
38
+ * Uses the same coercion as {@link createThreeGeometraStackedHost}.
39
+ */
40
+ export declare function toPlainGeometraStackedHostLayoutOptions(options?: ToPlainGeometraStackedHostLayoutOptionsInput): PlainGeometraStackedHostLayoutOptions;
41
+ /**
42
+ * Axis-aligned HUD rectangle in the stacked host root’s coordinate system (origin top-left), matching
43
+ * the inset rules used by {@link createThreeGeometraStackedHost} (`right`/`bottom`/`left`/`top` on the
44
+ * absolutely positioned HUD wrapper).
45
+ *
46
+ * Root width and height are normalized with {@link normalizeGeometraLayoutPixels} per axis so they stay
47
+ * aligned with {@link PlainGeometraThreeViewSizingState.layoutWidth} / `layoutHeight` for the same CSS
48
+ * inputs. `width` and `height` are taken from {@link PlainGeometraStackedHostLayoutOptions} as-is.
49
+ *
50
+ * Use for custom overlay geometry, agent hit targets, or stacked layouts built outside this package
51
+ * without calling `getBoundingClientRect`.
52
+ */
53
+ export interface PlainGeometraStackedHudRect {
54
+ left: number;
55
+ top: number;
56
+ width: number;
57
+ height: number;
58
+ }
59
+ /** Fields read by {@link toPlainGeometraStackedHudRect} (satisfied by {@link PlainGeometraStackedHostLayoutOptions} and stacked composite snapshots). */
60
+ export type GeometraStackedHudRectLayoutInput = Pick<PlainGeometraStackedHostLayoutOptions, 'geometraHudWidth' | 'geometraHudHeight' | 'geometraHudPlacement' | 'geometraHudMargin'>;
61
+ /**
62
+ * Compute {@link PlainGeometraStackedHudRect} from resolved stacked layout and root CSS size.
63
+ *
64
+ * @param layout - From {@link toPlainGeometraStackedHostLayoutOptions}, or any object that includes the
65
+ * HUD width/height/placement/margin fields (for example {@link toPlainGeometraThreeStackedHostSnapshot}).
66
+ */
67
+ export declare function toPlainGeometraStackedHudRect(layout: GeometraStackedHudRectLayoutInput, rootCssWidth: number, rootCssHeight: number): PlainGeometraStackedHudRect;
68
+ /** Literal tag on composite plain snapshots so JSON consumers can tell hybrid layout without inferring fields. */
69
+ export type GeometraHybridHostKind = 'split' | 'stacked';
70
+ /** Every {@link GeometraHybridHostKind} value (stable iteration, prompts, or defensive checks). */
71
+ export declare const GEOMETRA_HYBRID_HOST_KINDS: readonly GeometraHybridHostKind[];
72
+ /**
73
+ * Narrow `unknown` to {@link GeometraHybridHostKind} when parsing composite snapshot JSON from logs or agents.
74
+ */
75
+ export declare function isGeometraHybridHostKind(value: unknown): value is GeometraHybridHostKind;
76
+ /**
77
+ * Narrow `unknown` to {@link GeometraHybridHostKind} using the same trim + case-insensitive literals as
78
+ * {@link coerceGeometraHybridHostKind} and {@link isPlainGeometraThreeSplitHostSnapshot} /
79
+ * {@link isPlainGeometraThreeStackedHostSnapshot}. Use when agent or log JSON may carry whitespace or mixed case;
80
+ * prefer {@link isGeometraHybridHostKind} when the value is already normalized.
81
+ */
82
+ export declare function isPlainGeometraHybridHostKind(value: unknown): value is GeometraHybridHostKind;
83
+ /**
84
+ * Normalize {@link GeometraHybridHostKind} from runtime values (e.g. agent JSON or untyped config).
85
+ * Literal `'split'` and `'stacked'` pass through. Strings are trimmed and matched **case-insensitively**;
86
+ * unknown or empty strings use `fallback` (same normalization idea as {@link coerceGeometraHudPlacement}).
87
+ *
88
+ * For narrowing without coercion, use {@link isGeometraHybridHostKind} for exact literals or
89
+ * {@link isPlainGeometraHybridHostKind} when payloads may use whitespace or mixed case.
90
+ */
91
+ export declare function coerceGeometraHybridHostKind(value: unknown, fallback: GeometraHybridHostKind): GeometraHybridHostKind;
92
+ /**
93
+ * Narrow `unknown` (e.g. `JSON.parse`) to {@link PlainGeometraSplitHostLayoutOptions} — the layout-only
94
+ * fields from {@link toPlainGeometraSplitHostLayoutOptions} without viewport or scene sizing. Extra keys
95
+ * are allowed. Composite {@link PlainGeometraThreeSplitHostSnapshot} values satisfy this guard as well.
96
+ */
97
+ export declare function isPlainGeometraSplitHostLayoutOptions(value: unknown): value is PlainGeometraSplitHostLayoutOptions;
98
+ /**
99
+ * Narrow `unknown` (e.g. `JSON.parse`) to {@link PlainGeometraStackedHostLayoutOptions} — the HUD layout
100
+ * fields from {@link toPlainGeometraStackedHostLayoutOptions} without viewport or scene. Extra keys are
101
+ * allowed. `geometraHudPlacement` must be exactly one of the four corner literals (same rule as
102
+ * {@link isPlainGeometraThreeStackedHostSnapshot}; normalize loose strings with {@link coerceGeometraHudPlacement}
103
+ * before asserting). Composite {@link PlainGeometraThreeStackedHostSnapshot} values satisfy this guard too.
104
+ */
105
+ export declare function isPlainGeometraStackedHostLayoutOptions(value: unknown): value is PlainGeometraStackedHostLayoutOptions;
106
+ /**
107
+ * Narrow `unknown` (e.g. `JSON.parse`) to {@link PlainGeometraThreeSplitHostSnapshot} when the object
108
+ * matches the shape produced by {@link toPlainGeometraThreeSplitHostSnapshot} /
109
+ * {@link toPlainGeometraThreeSplitHostSnapshotHeadless}. `geometraHybridHostKind` accepts the same trim +
110
+ * case-insensitive literals as {@link coerceGeometraHybridHostKind} (not only exact `'split'`).
111
+ * `geometraWidth` is finite and **≥ 0**, same as
112
+ * {@link coerceHostNonNegativeCssPx}. Complements {@link isGeometraHybridHostKind} for composite agent or log payloads.
113
+ */
114
+ export declare function isPlainGeometraThreeSplitHostSnapshot(value: unknown): value is PlainGeometraThreeSplitHostSnapshot;
115
+ /**
116
+ * Same idea as {@link isPlainGeometraThreeSplitHostSnapshot} for {@link PlainGeometraThreeStackedHostSnapshot}
117
+ * / {@link toPlainGeometraThreeStackedHostSnapshot} / {@link toPlainGeometraThreeStackedHostSnapshotHeadless}.
118
+ * `geometraHybridHostKind` accepts the same trim + case-insensitive literals as {@link coerceGeometraHybridHostKind}.
119
+ * HUD width, height, and margin are finite and **≥ 0**, same as {@link coerceHostNonNegativeCssPx}.
120
+ */
121
+ export declare function isPlainGeometraThreeStackedHostSnapshot(value: unknown): value is PlainGeometraThreeStackedHostSnapshot;
122
+ /**
123
+ * Split-host layout fields plus {@link PlainGeometraThreeHostSnapshot} in one JSON-friendly object —
124
+ * same coercion as {@link toPlainGeometraSplitHostLayoutOptions} and {@link toPlainGeometraThreeHostSnapshot}.
125
+ *
126
+ * Use for logs, tests, or agent payloads that describe column chrome and Three viewport/scene together.
127
+ * The `geometraHybridHostKind` field is always `'split'` on values from {@link toPlainGeometraThreeSplitHostSnapshot} /
128
+ * {@link toPlainGeometraThreeSplitHostSnapshotHeadless}.
129
+ */
130
+ export type PlainGeometraThreeSplitHostSnapshot = PlainGeometraSplitHostLayoutOptions & PlainGeometraThreeHostSnapshot & {
131
+ geometraHybridHostKind: 'split';
132
+ };
133
+ /**
134
+ * Stacked-host HUD layout plus {@link PlainGeometraThreeHostSnapshot} (full-viewport Three sizing, not HUD box size).
135
+ *
136
+ * Same coercion as {@link toPlainGeometraStackedHostLayoutOptions} and {@link toPlainGeometraThreeHostSnapshot}.
137
+ * The `geometraHybridHostKind` field is always `'stacked'` on values from {@link toPlainGeometraThreeStackedHostSnapshot} /
138
+ * {@link toPlainGeometraThreeStackedHostSnapshotHeadless}.
139
+ */
140
+ export type PlainGeometraThreeStackedHostSnapshot = PlainGeometraStackedHostLayoutOptions & PlainGeometraThreeHostSnapshot & {
141
+ geometraHybridHostKind: 'stacked';
142
+ };
143
+ /**
144
+ * Merge split layout and host viewport/scene plain fields for stable JSON.
145
+ *
146
+ * @see PlainGeometraThreeSplitHostSnapshot
147
+ */
148
+ export declare function toPlainGeometraThreeSplitHostSnapshot(layoutOptions: ToPlainGeometraSplitHostLayoutOptionsInput | undefined, cssWidth: number, cssHeight: number, rawDevicePixelRatio: number, maxDevicePixelRatio?: number, sceneBasicsOptions?: GeometraThreeSceneBasicsOptions): PlainGeometraThreeSplitHostSnapshot;
149
+ /**
150
+ * Same as {@link toPlainGeometraThreeSplitHostSnapshot} with raw device pixel ratio **1** —
151
+ * parity with {@link toPlainGeometraThreeHostSnapshotHeadless} for headless or agent payloads without a `window`.
152
+ */
153
+ export declare function toPlainGeometraThreeSplitHostSnapshotHeadless(layoutOptions: ToPlainGeometraSplitHostLayoutOptionsInput | undefined, cssWidth: number, cssHeight: number, maxDevicePixelRatio?: number, sceneBasicsOptions?: GeometraThreeSceneBasicsOptions): PlainGeometraThreeSplitHostSnapshot;
154
+ /**
155
+ * Merge stacked HUD layout and host viewport/scene plain fields for stable JSON.
156
+ *
157
+ * @see PlainGeometraThreeStackedHostSnapshot
158
+ */
159
+ export declare function toPlainGeometraThreeStackedHostSnapshot(layoutOptions: ToPlainGeometraStackedHostLayoutOptionsInput | undefined, cssWidth: number, cssHeight: number, rawDevicePixelRatio: number, maxDevicePixelRatio?: number, sceneBasicsOptions?: GeometraThreeSceneBasicsOptions): PlainGeometraThreeStackedHostSnapshot;
160
+ /**
161
+ * Same as {@link toPlainGeometraThreeStackedHostSnapshot} with raw device pixel ratio **1**.
162
+ */
163
+ export declare function toPlainGeometraThreeStackedHostSnapshotHeadless(layoutOptions: ToPlainGeometraStackedHostLayoutOptionsInput | undefined, cssWidth: number, cssHeight: number, maxDevicePixelRatio?: number, sceneBasicsOptions?: GeometraThreeSceneBasicsOptions): PlainGeometraThreeStackedHostSnapshot;
164
+ //# sourceMappingURL=host-layout-plain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-layout-plain.d.ts","sourceRoot":"","sources":["../src/host-layout-plain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,255 @@
1
+ import { GEOMETRA_SPLIT_HOST_LAYOUT_DEFAULTS } from './split-host.js';
2
+ import { GEOMETRA_STACKED_HOST_LAYOUT_DEFAULTS } from './stacked-host.js';
3
+ import { coerceGeometraHudPlacement, coerceGeometraHudPointerEvents, coerceHostNonNegativeCssPx, coerceHostStackingZIndexCss, } from './host-css-coerce.js';
4
+ import { isPlainGeometraThreeHostSnapshot, toPlainGeometraThreeHostSnapshot, toPlainGeometraThreeHostSnapshotHeadless, } from './three-scene-basics.js';
5
+ import { normalizeGeometraLayoutPixels } from './utils.js';
6
+ /**
7
+ * Resolved split-host layout fields for logs, tests, or agent-side JSON without constructing the DOM host.
8
+ * Uses the same coercion as {@link createThreeGeometraSplitHost}.
9
+ */
10
+ export function toPlainGeometraSplitHostLayoutOptions(options = {}) {
11
+ const d = GEOMETRA_SPLIT_HOST_LAYOUT_DEFAULTS;
12
+ const geometraWidth = coerceHostNonNegativeCssPx(options.geometraWidth ?? d.geometraWidth, d.geometraWidth);
13
+ return {
14
+ geometraWidth,
15
+ geometraOnLeft: options.geometraOnLeft ?? false,
16
+ };
17
+ }
18
+ /**
19
+ * Resolved stacked HUD layout fields for logs, tests, or agent-side JSON without constructing the DOM host.
20
+ * Uses the same coercion as {@link createThreeGeometraStackedHost}.
21
+ */
22
+ export function toPlainGeometraStackedHostLayoutOptions(options = {}) {
23
+ const d = GEOMETRA_STACKED_HOST_LAYOUT_DEFAULTS;
24
+ const geometraHudWidth = coerceHostNonNegativeCssPx(options.geometraHudWidth ?? d.geometraHudWidth, d.geometraHudWidth);
25
+ const geometraHudHeight = coerceHostNonNegativeCssPx(options.geometraHudHeight ?? d.geometraHudHeight, d.geometraHudHeight);
26
+ const geometraHudMargin = coerceHostNonNegativeCssPx(options.geometraHudMargin ?? d.geometraHudMargin, d.geometraHudMargin);
27
+ const geometraHudPlacementOpt = options.geometraHudPlacement ?? d.geometraHudPlacement;
28
+ const geometraHudPlacement = coerceGeometraHudPlacement(geometraHudPlacementOpt, d.geometraHudPlacement);
29
+ const geometraHudPointerEvents = coerceGeometraHudPointerEvents(options.geometraHudPointerEvents, 'auto');
30
+ const geometraHudZIndex = coerceHostStackingZIndexCss(options.geometraHudZIndex ?? 1, 1);
31
+ return {
32
+ geometraHudWidth,
33
+ geometraHudHeight,
34
+ geometraHudPlacement,
35
+ geometraHudMargin,
36
+ geometraHudPointerEvents,
37
+ geometraHudZIndex,
38
+ };
39
+ }
40
+ /**
41
+ * Compute {@link PlainGeometraStackedHudRect} from resolved stacked layout and root CSS size.
42
+ *
43
+ * @param layout - From {@link toPlainGeometraStackedHostLayoutOptions}, or any object that includes the
44
+ * HUD width/height/placement/margin fields (for example {@link toPlainGeometraThreeStackedHostSnapshot}).
45
+ */
46
+ export function toPlainGeometraStackedHudRect(layout, rootCssWidth, rootCssHeight) {
47
+ const rw = normalizeGeometraLayoutPixels(rootCssWidth);
48
+ const rh = normalizeGeometraLayoutPixels(rootCssHeight);
49
+ const { geometraHudWidth: w, geometraHudHeight: h, geometraHudPlacement: p, geometraHudMargin: m } = layout;
50
+ switch (p) {
51
+ case 'bottom-right':
52
+ return { left: rw - w - m, top: rh - h - m, width: w, height: h };
53
+ case 'bottom-left':
54
+ return { left: m, top: rh - h - m, width: w, height: h };
55
+ case 'top-right':
56
+ return { left: rw - w - m, top: m, width: w, height: h };
57
+ case 'top-left':
58
+ return { left: m, top: m, width: w, height: h };
59
+ }
60
+ }
61
+ /** Every {@link GeometraHybridHostKind} value (stable iteration, prompts, or defensive checks). */
62
+ export const GEOMETRA_HYBRID_HOST_KINDS = ['split', 'stacked'];
63
+ /**
64
+ * Parse a {@link GeometraHybridHostKind} from loose input (trim + case-insensitive literals) without a fallback.
65
+ * Used by {@link coerceGeometraHybridHostKind} and composite {@link isPlainGeometraThreeSplitHostSnapshot} /
66
+ * {@link isPlainGeometraThreeStackedHostSnapshot} guards so agent JSON matches coercion rules.
67
+ */
68
+ function parseGeometraHybridHostKindLiteral(value) {
69
+ if (value === 'split' || value === 'stacked')
70
+ return value;
71
+ if (typeof value !== 'string')
72
+ return undefined;
73
+ const key = value.trim().toLowerCase();
74
+ if (key === 'split' || key === 'stacked')
75
+ return key;
76
+ return undefined;
77
+ }
78
+ /**
79
+ * Narrow `unknown` to {@link GeometraHybridHostKind} when parsing composite snapshot JSON from logs or agents.
80
+ */
81
+ export function isGeometraHybridHostKind(value) {
82
+ return value === 'split' || value === 'stacked';
83
+ }
84
+ /**
85
+ * Narrow `unknown` to {@link GeometraHybridHostKind} using the same trim + case-insensitive literals as
86
+ * {@link coerceGeometraHybridHostKind} and {@link isPlainGeometraThreeSplitHostSnapshot} /
87
+ * {@link isPlainGeometraThreeStackedHostSnapshot}. Use when agent or log JSON may carry whitespace or mixed case;
88
+ * prefer {@link isGeometraHybridHostKind} when the value is already normalized.
89
+ */
90
+ export function isPlainGeometraHybridHostKind(value) {
91
+ return parseGeometraHybridHostKindLiteral(value) !== undefined;
92
+ }
93
+ /**
94
+ * Normalize {@link GeometraHybridHostKind} from runtime values (e.g. agent JSON or untyped config).
95
+ * Literal `'split'` and `'stacked'` pass through. Strings are trimmed and matched **case-insensitively**;
96
+ * unknown or empty strings use `fallback` (same normalization idea as {@link coerceGeometraHudPlacement}).
97
+ *
98
+ * For narrowing without coercion, use {@link isGeometraHybridHostKind} for exact literals or
99
+ * {@link isPlainGeometraHybridHostKind} when payloads may use whitespace or mixed case.
100
+ */
101
+ export function coerceGeometraHybridHostKind(value, fallback) {
102
+ return parseGeometraHybridHostKindLiteral(value) ?? fallback;
103
+ }
104
+ const GEOMETRA_HUD_PLACEMENT_LITERALS = new Set([
105
+ 'bottom-right',
106
+ 'bottom-left',
107
+ 'top-right',
108
+ 'top-left',
109
+ ]);
110
+ /**
111
+ * Narrow `unknown` (e.g. `JSON.parse`) to {@link PlainGeometraSplitHostLayoutOptions} — the layout-only
112
+ * fields from {@link toPlainGeometraSplitHostLayoutOptions} without viewport or scene sizing. Extra keys
113
+ * are allowed. Composite {@link PlainGeometraThreeSplitHostSnapshot} values satisfy this guard as well.
114
+ */
115
+ export function isPlainGeometraSplitHostLayoutOptions(value) {
116
+ if (value === null || typeof value !== 'object')
117
+ return false;
118
+ const o = value;
119
+ if (typeof o.geometraOnLeft !== 'boolean')
120
+ return false;
121
+ if (typeof o.geometraWidth !== 'number' || !Number.isFinite(o.geometraWidth) || o.geometraWidth < 0) {
122
+ return false;
123
+ }
124
+ return true;
125
+ }
126
+ /**
127
+ * Narrow `unknown` (e.g. `JSON.parse`) to {@link PlainGeometraStackedHostLayoutOptions} — the HUD layout
128
+ * fields from {@link toPlainGeometraStackedHostLayoutOptions} without viewport or scene. Extra keys are
129
+ * allowed. `geometraHudPlacement` must be exactly one of the four corner literals (same rule as
130
+ * {@link isPlainGeometraThreeStackedHostSnapshot}; normalize loose strings with {@link coerceGeometraHudPlacement}
131
+ * before asserting). Composite {@link PlainGeometraThreeStackedHostSnapshot} values satisfy this guard too.
132
+ */
133
+ export function isPlainGeometraStackedHostLayoutOptions(value) {
134
+ if (value === null || typeof value !== 'object')
135
+ return false;
136
+ const o = value;
137
+ if (typeof o.geometraHudWidth !== 'number' ||
138
+ !Number.isFinite(o.geometraHudWidth) ||
139
+ o.geometraHudWidth < 0 ||
140
+ typeof o.geometraHudHeight !== 'number' ||
141
+ !Number.isFinite(o.geometraHudHeight) ||
142
+ o.geometraHudHeight < 0 ||
143
+ typeof o.geometraHudMargin !== 'number' ||
144
+ !Number.isFinite(o.geometraHudMargin) ||
145
+ o.geometraHudMargin < 0) {
146
+ return false;
147
+ }
148
+ if (typeof o.geometraHudPlacement !== 'string' || !GEOMETRA_HUD_PLACEMENT_LITERALS.has(o.geometraHudPlacement)) {
149
+ return false;
150
+ }
151
+ if (typeof o.geometraHudPointerEvents !== 'string')
152
+ return false;
153
+ if (typeof o.geometraHudZIndex !== 'string')
154
+ return false;
155
+ return true;
156
+ }
157
+ /**
158
+ * Narrow `unknown` (e.g. `JSON.parse`) to {@link PlainGeometraThreeSplitHostSnapshot} when the object
159
+ * matches the shape produced by {@link toPlainGeometraThreeSplitHostSnapshot} /
160
+ * {@link toPlainGeometraThreeSplitHostSnapshotHeadless}. `geometraHybridHostKind` accepts the same trim +
161
+ * case-insensitive literals as {@link coerceGeometraHybridHostKind} (not only exact `'split'`).
162
+ * `geometraWidth` is finite and **≥ 0**, same as
163
+ * {@link coerceHostNonNegativeCssPx}. Complements {@link isGeometraHybridHostKind} for composite agent or log payloads.
164
+ */
165
+ export function isPlainGeometraThreeSplitHostSnapshot(value) {
166
+ if (value === null || typeof value !== 'object')
167
+ return false;
168
+ const o = value;
169
+ if (parseGeometraHybridHostKindLiteral(o.geometraHybridHostKind) !== 'split')
170
+ return false;
171
+ if (typeof o.geometraOnLeft !== 'boolean')
172
+ return false;
173
+ if (typeof o.geometraWidth !== 'number' || !Number.isFinite(o.geometraWidth) || o.geometraWidth < 0) {
174
+ return false;
175
+ }
176
+ return isPlainGeometraThreeHostSnapshot(value);
177
+ }
178
+ /**
179
+ * Same idea as {@link isPlainGeometraThreeSplitHostSnapshot} for {@link PlainGeometraThreeStackedHostSnapshot}
180
+ * / {@link toPlainGeometraThreeStackedHostSnapshot} / {@link toPlainGeometraThreeStackedHostSnapshotHeadless}.
181
+ * `geometraHybridHostKind` accepts the same trim + case-insensitive literals as {@link coerceGeometraHybridHostKind}.
182
+ * HUD width, height, and margin are finite and **≥ 0**, same as {@link coerceHostNonNegativeCssPx}.
183
+ */
184
+ export function isPlainGeometraThreeStackedHostSnapshot(value) {
185
+ if (value === null || typeof value !== 'object')
186
+ return false;
187
+ const o = value;
188
+ if (parseGeometraHybridHostKindLiteral(o.geometraHybridHostKind) !== 'stacked')
189
+ return false;
190
+ if (typeof o.geometraHudWidth !== 'number' ||
191
+ !Number.isFinite(o.geometraHudWidth) ||
192
+ o.geometraHudWidth < 0 ||
193
+ typeof o.geometraHudHeight !== 'number' ||
194
+ !Number.isFinite(o.geometraHudHeight) ||
195
+ o.geometraHudHeight < 0 ||
196
+ typeof o.geometraHudMargin !== 'number' ||
197
+ !Number.isFinite(o.geometraHudMargin) ||
198
+ o.geometraHudMargin < 0) {
199
+ return false;
200
+ }
201
+ if (typeof o.geometraHudPlacement !== 'string' || !GEOMETRA_HUD_PLACEMENT_LITERALS.has(o.geometraHudPlacement)) {
202
+ return false;
203
+ }
204
+ if (typeof o.geometraHudPointerEvents !== 'string')
205
+ return false;
206
+ if (typeof o.geometraHudZIndex !== 'string')
207
+ return false;
208
+ return isPlainGeometraThreeHostSnapshot(value);
209
+ }
210
+ /**
211
+ * Merge split layout and host viewport/scene plain fields for stable JSON.
212
+ *
213
+ * @see PlainGeometraThreeSplitHostSnapshot
214
+ */
215
+ export function toPlainGeometraThreeSplitHostSnapshot(layoutOptions = {}, cssWidth, cssHeight, rawDevicePixelRatio, maxDevicePixelRatio, sceneBasicsOptions = {}) {
216
+ return {
217
+ geometraHybridHostKind: 'split',
218
+ ...toPlainGeometraSplitHostLayoutOptions(layoutOptions),
219
+ ...toPlainGeometraThreeHostSnapshot(cssWidth, cssHeight, rawDevicePixelRatio, maxDevicePixelRatio, sceneBasicsOptions),
220
+ };
221
+ }
222
+ /**
223
+ * Same as {@link toPlainGeometraThreeSplitHostSnapshot} with raw device pixel ratio **1** —
224
+ * parity with {@link toPlainGeometraThreeHostSnapshotHeadless} for headless or agent payloads without a `window`.
225
+ */
226
+ export function toPlainGeometraThreeSplitHostSnapshotHeadless(layoutOptions = {}, cssWidth, cssHeight, maxDevicePixelRatio, sceneBasicsOptions = {}) {
227
+ return {
228
+ geometraHybridHostKind: 'split',
229
+ ...toPlainGeometraSplitHostLayoutOptions(layoutOptions),
230
+ ...toPlainGeometraThreeHostSnapshotHeadless(cssWidth, cssHeight, maxDevicePixelRatio, sceneBasicsOptions),
231
+ };
232
+ }
233
+ /**
234
+ * Merge stacked HUD layout and host viewport/scene plain fields for stable JSON.
235
+ *
236
+ * @see PlainGeometraThreeStackedHostSnapshot
237
+ */
238
+ export function toPlainGeometraThreeStackedHostSnapshot(layoutOptions = {}, cssWidth, cssHeight, rawDevicePixelRatio, maxDevicePixelRatio, sceneBasicsOptions = {}) {
239
+ return {
240
+ geometraHybridHostKind: 'stacked',
241
+ ...toPlainGeometraStackedHostLayoutOptions(layoutOptions),
242
+ ...toPlainGeometraThreeHostSnapshot(cssWidth, cssHeight, rawDevicePixelRatio, maxDevicePixelRatio, sceneBasicsOptions),
243
+ };
244
+ }
245
+ /**
246
+ * Same as {@link toPlainGeometraThreeStackedHostSnapshot} with raw device pixel ratio **1**.
247
+ */
248
+ export function toPlainGeometraThreeStackedHostSnapshotHeadless(layoutOptions = {}, cssWidth, cssHeight, maxDevicePixelRatio, sceneBasicsOptions = {}) {
249
+ return {
250
+ geometraHybridHostKind: 'stacked',
251
+ ...toPlainGeometraStackedHostLayoutOptions(layoutOptions),
252
+ ...toPlainGeometraThreeHostSnapshotHeadless(cssWidth, cssHeight, maxDevicePixelRatio, sceneBasicsOptions),
253
+ };
254
+ }
255
+ //# sourceMappingURL=host-layout-plain.js.map