@wildo-ai/presets-components-3d 1.1.6 → 1.1.8
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/dist/esm/focal-plane/focal-plane-settings.d.ts +35 -0
- package/dist/esm/focal-plane/focal-plane-settings.d.ts.map +1 -0
- package/dist/esm/focal-plane/focal-plane-settings.js +68 -0
- package/dist/esm/focal-plane/focal-plane-settings.js.map +1 -0
- package/dist/esm/focal-plane/focal-plane-shell-container.d.ts +13 -0
- package/dist/esm/focal-plane/focal-plane-shell-container.d.ts.map +1 -0
- package/dist/esm/focal-plane/focal-plane-shell-container.js +147 -0
- package/dist/esm/focal-plane/focal-plane-shell-container.js.map +1 -0
- package/dist/esm/focal-plane/focal-plane-stylesheet.d.ts +14 -0
- package/dist/esm/focal-plane/focal-plane-stylesheet.d.ts.map +1 -0
- package/dist/esm/focal-plane/focal-plane-stylesheet.js +236 -0
- package/dist/esm/focal-plane/focal-plane-stylesheet.js.map +1 -0
- package/dist/esm/focal-plane/use-pane-depth.d.ts +20 -0
- package/dist/esm/focal-plane/use-pane-depth.d.ts.map +1 -0
- package/dist/esm/focal-plane/use-pane-depth.js +162 -0
- package/dist/esm/focal-plane/use-pane-depth.js.map +1 -0
- package/dist/esm/focal-plane/use-shared-vanishing-point.d.ts +35 -0
- package/dist/esm/focal-plane/use-shared-vanishing-point.d.ts.map +1 -0
- package/dist/esm/focal-plane/use-shared-vanishing-point.js +86 -0
- package/dist/esm/focal-plane/use-shared-vanishing-point.js.map +1 -0
- package/dist/esm/frame/frame-canvas.js +3 -3
- package/dist/esm/frame/frame-canvas.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/layout/layout-3d-definition.d.ts +5 -6
- package/dist/esm/layout/layout-3d-definition.d.ts.map +1 -1
- package/dist/esm/layout/layout-3d-definition.js +13 -14
- package/dist/esm/layout/layout-3d-definition.js.map +1 -1
- package/dist/esm/layout/layout-3d-vocabulary.d.ts +13 -8
- package/dist/esm/layout/layout-3d-vocabulary.d.ts.map +1 -1
- package/dist/esm/layout/layout-3d-vocabulary.js +12 -7
- package/dist/esm/layout/layout-3d-vocabulary.js.map +1 -1
- package/dist/esm/layout-3d-main-container.d.ts +6 -0
- package/dist/esm/layout-3d-main-container.d.ts.map +1 -1
- package/dist/esm/layout-3d-main-container.js +8 -1
- package/dist/esm/layout-3d-main-container.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +3 -3
- package/dist/esm/spatial/spatial-camera.d.ts +0 -106
- package/dist/esm/spatial/spatial-camera.d.ts.map +0 -1
- package/dist/esm/spatial/spatial-camera.js +0 -151
- package/dist/esm/spatial/spatial-camera.js.map +0 -1
- package/dist/esm/spatial/spatial-environment.d.ts +0 -6
- package/dist/esm/spatial/spatial-environment.d.ts.map +0 -1
- package/dist/esm/spatial/spatial-environment.js +0 -166
- package/dist/esm/spatial/spatial-environment.js.map +0 -1
- package/dist/esm/spatial/spatial-environment.lazy.d.ts +0 -10
- package/dist/esm/spatial/spatial-environment.lazy.d.ts.map +0 -1
- package/dist/esm/spatial/spatial-environment.lazy.js +0 -13
- package/dist/esm/spatial/spatial-environment.lazy.js.map +0 -1
- package/dist/esm/spatial/spatial-shell-container.d.ts +0 -21
- package/dist/esm/spatial/spatial-shell-container.d.ts.map +0 -1
- package/dist/esm/spatial/spatial-shell-container.js +0 -231
- package/dist/esm/spatial/spatial-shell-container.js.map +0 -1
- package/dist/esm/spatial/spatial-stage-store.d.ts +0 -27
- package/dist/esm/spatial/spatial-stage-store.d.ts.map +0 -1
- package/dist/esm/spatial/spatial-stage-store.js +0 -33
- package/dist/esm/spatial/spatial-stage-store.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ShellAppearance } from '@wildo-ai/presets-components-models';
|
|
2
2
|
import { HEADER_FIRST_FRAME_STYLES, INHERIT_FRAME_STYLES } from '../frame/frame-3d-style.js';
|
|
3
3
|
import { HeaderFirstShellContainer } from './header-first-shell-container.js';
|
|
4
|
-
import {
|
|
4
|
+
import { FocalPlaneShellContainer } from '../focal-plane/focal-plane-shell-container.js';
|
|
5
5
|
import { ShellLayoutPlacementKind } from './shell-layout-placement.js';
|
|
6
6
|
import { crossFadesAppearance, frameChoreography, rimsFocusedZone } from './layout-3d-transition-choreography.js';
|
|
7
7
|
import { Layout3DAppearanceTransition, Layout3DCamera, Layout3DId, Layout3DFrameChoreography, Layout3DRestPose, Layout3DZoneFocusTransition, } from './layout-3d-vocabulary.js';
|
|
@@ -37,17 +37,15 @@ export const HEADER_FIRST_LAYOUT_3D = {
|
|
|
37
37
|
},
|
|
38
38
|
constraints: { requiredShellAppearance: ShellAppearance.CONTINUOUS, restPose: Layout3DRestPose.FLAT },
|
|
39
39
|
};
|
|
40
|
-
/** @wildo_source:part:end presets.3d.layout-contract */
|
|
41
40
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* seen and judged in the running application before it is designed into a production layout.
|
|
41
|
+
* The focal plane (#2049): the shell regions, each navigation pane and each popup are glass objects in depth under one
|
|
42
|
+
* still camera. Whatever you work with rests on the focal plane; the rest steps back. No WebGL frame: the depth is in
|
|
43
|
+
* the HTML objects themselves, so the frame styles and frame transitions below are not drawn.
|
|
46
44
|
*/
|
|
47
|
-
export const
|
|
48
|
-
id:
|
|
49
|
-
placement: { kind: ShellLayoutPlacementKind.COMPOSED, container:
|
|
50
|
-
scene: { camera: Layout3DCamera.
|
|
45
|
+
export const FOCAL_PLANE_LAYOUT_3D = {
|
|
46
|
+
id: Layout3DId.FOCAL_PLANE,
|
|
47
|
+
placement: { kind: ShellLayoutPlacementKind.COMPOSED, container: FocalPlaneShellContainer },
|
|
48
|
+
scene: { camera: Layout3DCamera.STILL_PERSPECTIVE, frameStyles: INHERIT_FRAME_STYLES },
|
|
51
49
|
transitions: {
|
|
52
50
|
appearance: Layout3DAppearanceTransition.CROSS_FADE,
|
|
53
51
|
navigation: Layout3DFrameChoreography.NONE,
|
|
@@ -56,10 +54,12 @@ export const SPATIAL_PROTOTYPE_LAYOUT_3D = {
|
|
|
56
54
|
},
|
|
57
55
|
constraints: { requiredShellAppearance: ShellAppearance.CONTINUOUS, restPose: Layout3DRestPose.FLAT },
|
|
58
56
|
};
|
|
57
|
+
/** @wildo_source:part:end presets.3d.layout-contract */
|
|
59
58
|
/** Every built-in layout, keyed by its id: total over {@link Layout3DId}, so a new member must ship a layout. */
|
|
60
59
|
export const BUILT_IN_LAYOUTS_3D = {
|
|
61
60
|
[Layout3DId.INHERIT]: INHERIT_LAYOUT_3D,
|
|
62
61
|
[Layout3DId.HEADER_FIRST]: HEADER_FIRST_LAYOUT_3D,
|
|
62
|
+
[Layout3DId.FOCAL_PLANE]: FOCAL_PLANE_LAYOUT_3D,
|
|
63
63
|
};
|
|
64
64
|
/**
|
|
65
65
|
* Refuses a layout the renderer cannot draw as declared: a camera, a transition or a rest pose it does not
|
|
@@ -72,11 +72,10 @@ export function assertSupportedLayout3D(layout) {
|
|
|
72
72
|
switch (camera) {
|
|
73
73
|
case Layout3DCamera.FLAT_ORTHOGRAPHIC:
|
|
74
74
|
break;
|
|
75
|
-
case Layout3DCamera.
|
|
76
|
-
//
|
|
77
|
-
// container cannot.
|
|
75
|
+
case Layout3DCamera.STILL_PERSPECTIVE:
|
|
76
|
+
// The captured flat container stages nothing in depth; only a composed placement that does can use this camera.
|
|
78
77
|
if (layout.placement.kind !== ShellLayoutPlacementKind.COMPOSED) {
|
|
79
|
-
throw new Error(`3D layout '${layout.id}': the
|
|
78
|
+
throw new Error(`3D layout '${layout.id}': the still-perspective camera needs a composed placement that stages the shell in depth.`);
|
|
80
79
|
}
|
|
81
80
|
break;
|
|
82
81
|
default: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-3d-definition.js","sourceRoot":"","sources":["../../../../src/layout/layout-3d-definition.ts"],"names":[],"mappings":"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","sourcesContent":["import { ShellAppearance } from '@wildo-ai/presets-components-models';\n\nimport { HEADER_FIRST_FRAME_STYLES, INHERIT_FRAME_STYLES, type Frame3DStyleCatalog } from '../frame/frame-3d-style';\nimport { HeaderFirstShellContainer } from './header-first-shell-container';\nimport { SpatialShellContainer } from '../spatial/spatial-shell-container';\nimport { ShellLayoutPlacementKind, type ShellLayoutPlacement } from './shell-layout-placement';\nimport { crossFadesAppearance, frameChoreography, rimsFocusedZone } from './layout-3d-transition-choreography';\nimport {\n Layout3DAppearanceTransition,\n Layout3DCamera,\n Layout3DId,\n Layout3DFrameChoreography,\n Layout3DRestPose,\n Layout3DZoneFocusTransition,\n type Layout3DTransitions,\n} from './layout-3d-vocabulary';\n\n/** @wildo_source:part:start presets.3d.layout-contract facet:layer:frontend facet:family:layout-3d facet:audience:app-developer */\n/**\n * A 3D layout: where the regions go (`placement`, 3D-free), and what the frame draws around them (`scene`,\n * `transitions`), under `constraints`.\n */\nexport interface Layout3DDefinition {\n /** A {@link Layout3DId} for a built-in layout; an application's own layout names itself. */\n id: string;\n placement: ShellLayoutPlacement;\n scene: {\n camera: Layout3DCamera;\n /** The frame styles, per theme, with a fallback for any theme id the catalog does not name. */\n frameStyles: Frame3DStyleCatalog;\n };\n /** What the frame plays on an appearance change, a navigation, a sidebar resize and a zone focus. */\n transitions: Layout3DTransitions;\n constraints: {\n /** The shell appearance the layout is designed for; any other is reported once (a console warning), never switched. */\n requiredShellAppearance: ShellAppearance | null;\n restPose: Layout3DRestPose;\n };\n}\n\n/**\n * The 2D disposal, unchanged, with the frame under it. On navigation the content slab lifts and settles; when\n * the sidebar collapses or expands, the light swings across and back.\n */\nexport const INHERIT_LAYOUT_3D: Layout3DDefinition = {\n id: Layout3DId.INHERIT,\n placement: { kind: ShellLayoutPlacementKind.INHERIT },\n scene: { camera: Layout3DCamera.FLAT_ORTHOGRAPHIC, frameStyles: INHERIT_FRAME_STYLES },\n transitions: {\n appearance: Layout3DAppearanceTransition.CROSS_FADE,\n navigation: Layout3DFrameChoreography.ELEVATION_SETTLE,\n sidebarResize: Layout3DFrameChoreography.LIGHT_SWEEP,\n zoneFocus: Layout3DZoneFocusTransition.RIM,\n },\n constraints: { requiredShellAppearance: ShellAppearance.CONTINUOUS, restPose: Layout3DRestPose.FLAT },\n};\n\n/**\n * The header-first disposal, with the frame lit from the header down. On navigation the light swings from the header\n * and returns; when the sidebar collapses or expands, the content slab lifts and settles.\n */\nexport const HEADER_FIRST_LAYOUT_3D: Layout3DDefinition = {\n id: Layout3DId.HEADER_FIRST,\n placement: { kind: ShellLayoutPlacementKind.COMPOSED, container: HeaderFirstShellContainer },\n scene: { camera: Layout3DCamera.FLAT_ORTHOGRAPHIC, frameStyles: HEADER_FIRST_FRAME_STYLES },\n transitions: {\n appearance: Layout3DAppearanceTransition.CROSS_FADE,\n navigation: Layout3DFrameChoreography.LIGHT_SWEEP,\n sidebarResize: Layout3DFrameChoreography.ELEVATION_SETTLE,\n zoneFocus: Layout3DZoneFocusTransition.RIM,\n },\n constraints: { requiredShellAppearance: ShellAppearance.CONTINUOUS, restPose: Layout3DRestPose.FLAT },\n};\n/** @wildo_source:part:end presets.3d.layout-contract */\n\n/**\n * PROTOTYPE (Paul, 2026-09-30): the shell's panels in space, seen through a moving perspective camera — clean spatial,\n * content facing the camera, side columns angled, the camera gliding on arrival, navigation, pane focus and sidebar\n * resize. Not a built-in yet (its id is its own, and it is absent from {@link BUILT_IN_LAYOUTS_3D}): it is here to be\n * seen and judged in the running application before it is designed into a production layout.\n */\nexport const SPATIAL_PROTOTYPE_LAYOUT_3D: Layout3DDefinition = {\n id: 'spatial-prototype',\n placement: { kind: ShellLayoutPlacementKind.COMPOSED, container: SpatialShellContainer },\n scene: { camera: Layout3DCamera.SPATIAL_PERSPECTIVE, frameStyles: INHERIT_FRAME_STYLES },\n transitions: {\n appearance: Layout3DAppearanceTransition.CROSS_FADE,\n navigation: Layout3DFrameChoreography.NONE,\n sidebarResize: Layout3DFrameChoreography.NONE,\n zoneFocus: Layout3DZoneFocusTransition.NONE,\n },\n constraints: { requiredShellAppearance: ShellAppearance.CONTINUOUS, restPose: Layout3DRestPose.FLAT },\n};\n\n/** Every built-in layout, keyed by its id: total over {@link Layout3DId}, so a new member must ship a layout. */\nexport const BUILT_IN_LAYOUTS_3D: Record<Layout3DId, Layout3DDefinition> = {\n [Layout3DId.INHERIT]: INHERIT_LAYOUT_3D,\n [Layout3DId.HEADER_FIRST]: HEADER_FIRST_LAYOUT_3D,\n};\n\n/**\n * Refuses a layout the renderer cannot draw as declared: a camera, a transition or a rest pose it does not\n * implement. Exhaustive switches, so a member added to one of those vocabularies fails to compile here until the\n * renderer supports it — and a value that reaches it at runtime anyway (an application's own layout, built without\n * the types) is refused instead of being silently drawn as something else.\n */\nexport function assertSupportedLayout3D(layout: Layout3DDefinition): void {\n const camera = layout.scene.camera;\n switch (camera) {\n case Layout3DCamera.FLAT_ORTHOGRAPHIC:\n break;\n case Layout3DCamera.SPATIAL_PERSPECTIVE:\n // Only a placement that builds the CSS 3D stage can be seen through the spatial camera; the captured flat\n // container cannot.\n if (layout.placement.kind !== ShellLayoutPlacementKind.COMPOSED) {\n throw new Error(`3D layout '${layout.id}': the spatial camera needs a composed placement that builds the spatial stage.`);\n }\n break;\n default: {\n const unsupported: never = camera;\n throw new Error(`3D layout '${layout.id}': the frame has no camera '${String(unsupported)}'.`);\n }\n }\n // Each throws on a member the frame does not play (a value built without the types).\n crossFadesAppearance(layout.transitions.appearance);\n frameChoreography(layout.transitions.navigation);\n frameChoreography(layout.transitions.sidebarResize);\n rimsFocusedZone(layout.transitions.zoneFocus);\n const pose = layout.constraints.restPose;\n switch (pose) {\n // FLAT is what the container renders: the placement, untransformed.\n case Layout3DRestPose.FLAT:\n break;\n default: {\n const unsupported: never = pose;\n throw new Error(`3D layout '${layout.id}': the rest pose '${String(unsupported)}' is not supported (only FLAT exists: no region is transformed at rest).`);\n }\n }\n if (layout.placement.kind !== ShellLayoutPlacementKind.INHERIT && layout.placement.kind !== ShellLayoutPlacementKind.COMPOSED) {\n throw new Error(`3D layout '${layout.id}': unknown placement kind '${String((layout.placement as { kind: unknown }).kind)}'.`);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"layout-3d-definition.js","sourceRoot":"","sources":["../../../../src/layout/layout-3d-definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAEtE,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAA4B,MAAM,yBAAyB,CAAC;AACpH,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AACtF,OAAO,EAAE,wBAAwB,EAA6B,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC/G,OAAO,EACL,4BAA4B,EAC5B,cAAc,EACd,UAAU,EACV,yBAAyB,EACzB,gBAAgB,EAChB,2BAA2B,GAE5B,MAAM,wBAAwB,CAAC;AAyBhC;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAuB;IACnD,EAAE,EAAE,UAAU,CAAC,OAAO;IACtB,SAAS,EAAE,EAAE,IAAI,EAAE,wBAAwB,CAAC,OAAO,EAAE;IACrD,KAAK,EAAE,EAAE,MAAM,EAAE,cAAc,CAAC,iBAAiB,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACtF,WAAW,EAAE;QACX,UAAU,EAAE,4BAA4B,CAAC,UAAU;QACnD,UAAU,EAAE,yBAAyB,CAAC,gBAAgB;QACtD,aAAa,EAAE,yBAAyB,CAAC,WAAW;QACpD,SAAS,EAAE,2BAA2B,CAAC,GAAG;KAC3C;IACD,WAAW,EAAE,EAAE,uBAAuB,EAAE,eAAe,CAAC,UAAU,EAAE,QAAQ,EAAE,gBAAgB,CAAC,IAAI,EAAE;CACtG,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAuB;IACxD,EAAE,EAAE,UAAU,CAAC,YAAY;IAC3B,SAAS,EAAE,EAAE,IAAI,EAAE,wBAAwB,CAAC,QAAQ,EAAE,SAAS,EAAE,yBAAyB,EAAE;IAC5F,KAAK,EAAE,EAAE,MAAM,EAAE,cAAc,CAAC,iBAAiB,EAAE,WAAW,EAAE,yBAAyB,EAAE;IAC3F,WAAW,EAAE;QACX,UAAU,EAAE,4BAA4B,CAAC,UAAU;QACnD,UAAU,EAAE,yBAAyB,CAAC,WAAW;QACjD,aAAa,EAAE,yBAAyB,CAAC,gBAAgB;QACzD,SAAS,EAAE,2BAA2B,CAAC,GAAG;KAC3C;IACD,WAAW,EAAE,EAAE,uBAAuB,EAAE,eAAe,CAAC,UAAU,EAAE,QAAQ,EAAE,gBAAgB,CAAC,IAAI,EAAE;CACtG,CAAC;AACF;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAuB;IACvD,EAAE,EAAE,UAAU,CAAC,WAAW;IAC1B,SAAS,EAAE,EAAE,IAAI,EAAE,wBAAwB,CAAC,QAAQ,EAAE,SAAS,EAAE,wBAAwB,EAAE;IAC3F,KAAK,EAAE,EAAE,MAAM,EAAE,cAAc,CAAC,iBAAiB,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACtF,WAAW,EAAE;QACX,UAAU,EAAE,4BAA4B,CAAC,UAAU;QACnD,UAAU,EAAE,yBAAyB,CAAC,IAAI;QAC1C,aAAa,EAAE,yBAAyB,CAAC,IAAI;QAC7C,SAAS,EAAE,2BAA2B,CAAC,IAAI;KAC5C;IACD,WAAW,EAAE,EAAE,uBAAuB,EAAE,eAAe,CAAC,UAAU,EAAE,QAAQ,EAAE,gBAAgB,CAAC,IAAI,EAAE;CACtG,CAAC;AACF,wDAAwD;AAExD,iHAAiH;AACjH,MAAM,CAAC,MAAM,mBAAmB,GAA2C;IACzE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB;IACvC,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,sBAAsB;IACjD,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,qBAAqB;CAChD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAA0B;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;IACnC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,cAAc,CAAC,iBAAiB;YACnC,MAAM;QACR,KAAK,cAAc,CAAC,iBAAiB;YACnC,gHAAgH;YAChH,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,KAAK,wBAAwB,CAAC,QAAQ,EAAE,CAAC;gBAChE,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,CAAC,EAAE,4FAA4F,CAAC,CAAC;YACvI,CAAC;YACD,MAAM;QACR,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,WAAW,GAAU,MAAM,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,CAAC,EAAE,+BAA+B,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IACD,qFAAqF;IACrF,oBAAoB,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACpD,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACjD,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IACpD,eAAe,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC;IACzC,QAAQ,IAAI,EAAE,CAAC;QACb,oEAAoE;QACpE,KAAK,gBAAgB,CAAC,IAAI;YACxB,MAAM;QACR,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,WAAW,GAAU,IAAI,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,CAAC,EAAE,qBAAqB,MAAM,CAAC,WAAW,CAAC,0EAA0E,CAAC,CAAC;QAC7J,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,KAAK,wBAAwB,CAAC,OAAO,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,KAAK,wBAAwB,CAAC,QAAQ,EAAE,CAAC;QAC9H,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,CAAC,EAAE,8BAA8B,MAAM,CAAE,MAAM,CAAC,SAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjI,CAAC;AACH,CAAC","sourcesContent":["import { ShellAppearance } from '@wildo-ai/presets-components-models';\n\nimport { HEADER_FIRST_FRAME_STYLES, INHERIT_FRAME_STYLES, type Frame3DStyleCatalog } from '../frame/frame-3d-style';\nimport { HeaderFirstShellContainer } from './header-first-shell-container';\nimport { FocalPlaneShellContainer } from '../focal-plane/focal-plane-shell-container';\nimport { ShellLayoutPlacementKind, type ShellLayoutPlacement } from './shell-layout-placement';\nimport { crossFadesAppearance, frameChoreography, rimsFocusedZone } from './layout-3d-transition-choreography';\nimport {\n Layout3DAppearanceTransition,\n Layout3DCamera,\n Layout3DId,\n Layout3DFrameChoreography,\n Layout3DRestPose,\n Layout3DZoneFocusTransition,\n type Layout3DTransitions,\n} from './layout-3d-vocabulary';\n\n/** @wildo_source:part:start presets.3d.layout-contract facet:layer:frontend facet:family:layout-3d facet:audience:app-developer */\n/**\n * A 3D layout: where the regions go (`placement`, 3D-free), and what the frame draws around them (`scene`,\n * `transitions`), under `constraints`.\n */\nexport interface Layout3DDefinition {\n /** A {@link Layout3DId} for a built-in layout; an application's own layout names itself. */\n id: string;\n placement: ShellLayoutPlacement;\n scene: {\n camera: Layout3DCamera;\n /** The frame styles, per theme, with a fallback for any theme id the catalog does not name. */\n frameStyles: Frame3DStyleCatalog;\n };\n /** What the frame plays on an appearance change, a navigation, a sidebar resize and a zone focus. */\n transitions: Layout3DTransitions;\n constraints: {\n /** The shell appearance the layout is designed for; any other is reported once (a console warning), never switched. */\n requiredShellAppearance: ShellAppearance | null;\n restPose: Layout3DRestPose;\n };\n}\n\n/**\n * The 2D disposal, unchanged, with the frame under it. On navigation the content slab lifts and settles; when\n * the sidebar collapses or expands, the light swings across and back.\n */\nexport const INHERIT_LAYOUT_3D: Layout3DDefinition = {\n id: Layout3DId.INHERIT,\n placement: { kind: ShellLayoutPlacementKind.INHERIT },\n scene: { camera: Layout3DCamera.FLAT_ORTHOGRAPHIC, frameStyles: INHERIT_FRAME_STYLES },\n transitions: {\n appearance: Layout3DAppearanceTransition.CROSS_FADE,\n navigation: Layout3DFrameChoreography.ELEVATION_SETTLE,\n sidebarResize: Layout3DFrameChoreography.LIGHT_SWEEP,\n zoneFocus: Layout3DZoneFocusTransition.RIM,\n },\n constraints: { requiredShellAppearance: ShellAppearance.CONTINUOUS, restPose: Layout3DRestPose.FLAT },\n};\n\n/**\n * The header-first disposal, with the frame lit from the header down. On navigation the light swings from the header\n * and returns; when the sidebar collapses or expands, the content slab lifts and settles.\n */\nexport const HEADER_FIRST_LAYOUT_3D: Layout3DDefinition = {\n id: Layout3DId.HEADER_FIRST,\n placement: { kind: ShellLayoutPlacementKind.COMPOSED, container: HeaderFirstShellContainer },\n scene: { camera: Layout3DCamera.FLAT_ORTHOGRAPHIC, frameStyles: HEADER_FIRST_FRAME_STYLES },\n transitions: {\n appearance: Layout3DAppearanceTransition.CROSS_FADE,\n navigation: Layout3DFrameChoreography.LIGHT_SWEEP,\n sidebarResize: Layout3DFrameChoreography.ELEVATION_SETTLE,\n zoneFocus: Layout3DZoneFocusTransition.RIM,\n },\n constraints: { requiredShellAppearance: ShellAppearance.CONTINUOUS, restPose: Layout3DRestPose.FLAT },\n};\n/**\n * The focal plane (#2049): the shell regions, each navigation pane and each popup are glass objects in depth under one\n * still camera. Whatever you work with rests on the focal plane; the rest steps back. No WebGL frame: the depth is in\n * the HTML objects themselves, so the frame styles and frame transitions below are not drawn.\n */\nexport const FOCAL_PLANE_LAYOUT_3D: Layout3DDefinition = {\n id: Layout3DId.FOCAL_PLANE,\n placement: { kind: ShellLayoutPlacementKind.COMPOSED, container: FocalPlaneShellContainer },\n scene: { camera: Layout3DCamera.STILL_PERSPECTIVE, frameStyles: INHERIT_FRAME_STYLES },\n transitions: {\n appearance: Layout3DAppearanceTransition.CROSS_FADE,\n navigation: Layout3DFrameChoreography.NONE,\n sidebarResize: Layout3DFrameChoreography.NONE,\n zoneFocus: Layout3DZoneFocusTransition.NONE,\n },\n constraints: { requiredShellAppearance: ShellAppearance.CONTINUOUS, restPose: Layout3DRestPose.FLAT },\n};\n/** @wildo_source:part:end presets.3d.layout-contract */\n\n/** Every built-in layout, keyed by its id: total over {@link Layout3DId}, so a new member must ship a layout. */\nexport const BUILT_IN_LAYOUTS_3D: Record<Layout3DId, Layout3DDefinition> = {\n [Layout3DId.INHERIT]: INHERIT_LAYOUT_3D,\n [Layout3DId.HEADER_FIRST]: HEADER_FIRST_LAYOUT_3D,\n [Layout3DId.FOCAL_PLANE]: FOCAL_PLANE_LAYOUT_3D,\n};\n\n/**\n * Refuses a layout the renderer cannot draw as declared: a camera, a transition or a rest pose it does not\n * implement. Exhaustive switches, so a member added to one of those vocabularies fails to compile here until the\n * renderer supports it — and a value that reaches it at runtime anyway (an application's own layout, built without\n * the types) is refused instead of being silently drawn as something else.\n */\nexport function assertSupportedLayout3D(layout: Layout3DDefinition): void {\n const camera = layout.scene.camera;\n switch (camera) {\n case Layout3DCamera.FLAT_ORTHOGRAPHIC:\n break;\n case Layout3DCamera.STILL_PERSPECTIVE:\n // The captured flat container stages nothing in depth; only a composed placement that does can use this camera.\n if (layout.placement.kind !== ShellLayoutPlacementKind.COMPOSED) {\n throw new Error(`3D layout '${layout.id}': the still-perspective camera needs a composed placement that stages the shell in depth.`);\n }\n break;\n default: {\n const unsupported: never = camera;\n throw new Error(`3D layout '${layout.id}': the frame has no camera '${String(unsupported)}'.`);\n }\n }\n // Each throws on a member the frame does not play (a value built without the types).\n crossFadesAppearance(layout.transitions.appearance);\n frameChoreography(layout.transitions.navigation);\n frameChoreography(layout.transitions.sidebarResize);\n rimsFocusedZone(layout.transitions.zoneFocus);\n const pose = layout.constraints.restPose;\n switch (pose) {\n // FLAT is what the container renders: the placement, untransformed.\n case Layout3DRestPose.FLAT:\n break;\n default: {\n const unsupported: never = pose;\n throw new Error(`3D layout '${layout.id}': the rest pose '${String(unsupported)}' is not supported (only FLAT exists: no region is transformed at rest).`);\n }\n }\n if (layout.placement.kind !== ShellLayoutPlacementKind.INHERIT && layout.placement.kind !== ShellLayoutPlacementKind.COMPOSED) {\n throw new Error(`3D layout '${layout.id}': unknown placement kind '${String((layout.placement as { kind: unknown }).kind)}'.`);\n }\n}\n"]}
|
|
@@ -14,22 +14,27 @@ export declare enum Layout3DId {
|
|
|
14
14
|
* The menubar and the status bars span the whole width; the navigation rails (activity bar, sidebar, utility
|
|
15
15
|
* panel) sit between them, beside the content. The default disposal is sidebar-first; this one is header-first.
|
|
16
16
|
*/
|
|
17
|
-
HEADER_FIRST = "header-first"
|
|
17
|
+
HEADER_FIRST = "header-first",
|
|
18
|
+
/**
|
|
19
|
+
* The focal plane (#2049): one still perspective camera; the shell regions, each navigation pane and each popup are
|
|
20
|
+
* separate glass objects that travel in depth. Whatever you work with rests on the focal plane at its true size;
|
|
21
|
+
* everything else steps back. Nothing is angled and the camera never moves (Paul, 2026-09-30).
|
|
22
|
+
*/
|
|
23
|
+
FOCAL_PLANE = "focal-plane"
|
|
18
24
|
}
|
|
19
25
|
/**
|
|
20
|
-
* The cameras
|
|
21
|
-
*
|
|
26
|
+
* The cameras a 3D layout is seen through. The flat camera's transitions are all drawn IN the flat frame (elevation,
|
|
27
|
+
* light, rims), so a slab never leaves its region's box; the still-perspective camera moves the HTML objects instead.
|
|
22
28
|
*/
|
|
23
29
|
export declare enum Layout3DCamera {
|
|
24
30
|
/** Orthographic, matched 1:1 to CSS pixels: the frame lies flat under the regions, exactly on their boxes. */
|
|
25
31
|
FLAT_ORTHOGRAPHIC = "flat-orthographic",
|
|
26
32
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* around them. Only a placement that builds that stage can use it (`SPATIAL_PROTOTYPE_LAYOUT_3D`).
|
|
33
|
+
* A still perspective camera, in CSS: the HTML objects themselves carry depth, around one shared vanishing point, and
|
|
34
|
+
* no WebGL frame is drawn. The camera never moves; objects do (#2049). Only a placement that stages the objects can
|
|
35
|
+
* be seen through it.
|
|
31
36
|
*/
|
|
32
|
-
|
|
37
|
+
STILL_PERSPECTIVE = "still-perspective"
|
|
33
38
|
}
|
|
34
39
|
/**
|
|
35
40
|
* How the frame answers an APPEARANCE change: a theme, a density, a reduced-motion switch.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-3d-vocabulary.d.ts","sourceRoot":"","sources":["../../../../src/layout/layout-3d-vocabulary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mIAAmI;AACnI;;;GAGG;AACH,oBAAY,UAAU;IACpB,yFAAyF;IACzF,OAAO,YAAY;IACnB;;;OAGG;IACH,YAAY,iBAAiB;
|
|
1
|
+
{"version":3,"file":"layout-3d-vocabulary.d.ts","sourceRoot":"","sources":["../../../../src/layout/layout-3d-vocabulary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mIAAmI;AACnI;;;GAGG;AACH,oBAAY,UAAU;IACpB,yFAAyF;IACzF,OAAO,YAAY;IACnB;;;OAGG;IACH,YAAY,iBAAiB;IAC7B;;;;OAIG;IACH,WAAW,gBAAgB;CAC5B;AAED;;;GAGG;AACH,oBAAY,cAAc;IACxB,8GAA8G;IAC9G,iBAAiB,sBAAsB;IACvC;;;;OAIG;IACH,iBAAiB,sBAAsB;CACxC;AAED;;;;;GAKG;AACH,oBAAY,4BAA4B;IACtC,2FAA2F;IAC3F,UAAU,eAAe;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,oBAAY,yBAAyB;IACnC,+FAA+F;IAC/F,IAAI,SAAS;IACb;;;;OAIG;IACH,gBAAgB,qBAAqB;IACrC;;;OAGG;IACH,WAAW,gBAAgB;CAC5B;AAED;;;GAGG;AACH,oBAAY,2BAA2B;IACrC,mDAAmD;IACnD,IAAI,SAAS;IACb;;;;;;OAMG;IACH,GAAG,QAAQ;CACZ;AAED;;;;GAIG;AACH,oBAAY,gBAAgB;IAC1B,iDAAiD;IACjD,IAAI,SAAS;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,UAAU,EAAE,4BAA4B,CAAC;IACzC;;;;OAIG;IACH,UAAU,EAAE,yBAAyB,CAAC;IACtC,4GAA4G;IAC5G,aAAa,EAAE,yBAAyB,CAAC;IACzC,4FAA4F;IAC5F,SAAS,EAAE,2BAA2B,CAAC;CACxC;AACD,wDAAwD"}
|
|
@@ -16,22 +16,27 @@ export var Layout3DId;
|
|
|
16
16
|
* panel) sit between them, beside the content. The default disposal is sidebar-first; this one is header-first.
|
|
17
17
|
*/
|
|
18
18
|
Layout3DId["HEADER_FIRST"] = "header-first";
|
|
19
|
+
/**
|
|
20
|
+
* The focal plane (#2049): one still perspective camera; the shell regions, each navigation pane and each popup are
|
|
21
|
+
* separate glass objects that travel in depth. Whatever you work with rests on the focal plane at its true size;
|
|
22
|
+
* everything else steps back. Nothing is angled and the camera never moves (Paul, 2026-09-30).
|
|
23
|
+
*/
|
|
24
|
+
Layout3DId["FOCAL_PLANE"] = "focal-plane";
|
|
19
25
|
})(Layout3DId || (Layout3DId = {}));
|
|
20
26
|
/**
|
|
21
|
-
* The cameras
|
|
22
|
-
*
|
|
27
|
+
* The cameras a 3D layout is seen through. The flat camera's transitions are all drawn IN the flat frame (elevation,
|
|
28
|
+
* light, rims), so a slab never leaves its region's box; the still-perspective camera moves the HTML objects instead.
|
|
23
29
|
*/
|
|
24
30
|
export var Layout3DCamera;
|
|
25
31
|
(function (Layout3DCamera) {
|
|
26
32
|
/** Orthographic, matched 1:1 to CSS pixels: the frame lies flat under the regions, exactly on their boxes. */
|
|
27
33
|
Layout3DCamera["FLAT_ORTHOGRAPHIC"] = "flat-orthographic";
|
|
28
34
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* around them. Only a placement that builds that stage can use it (`SPATIAL_PROTOTYPE_LAYOUT_3D`).
|
|
35
|
+
* A still perspective camera, in CSS: the HTML objects themselves carry depth, around one shared vanishing point, and
|
|
36
|
+
* no WebGL frame is drawn. The camera never moves; objects do (#2049). Only a placement that stages the objects can
|
|
37
|
+
* be seen through it.
|
|
33
38
|
*/
|
|
34
|
-
Layout3DCamera["
|
|
39
|
+
Layout3DCamera["STILL_PERSPECTIVE"] = "still-perspective";
|
|
35
40
|
})(Layout3DCamera || (Layout3DCamera = {}));
|
|
36
41
|
/**
|
|
37
42
|
* How the frame answers an APPEARANCE change: a theme, a density, a reduced-motion switch.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-3d-vocabulary.js","sourceRoot":"","sources":["../../../../src/layout/layout-3d-vocabulary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mIAAmI;AACnI;;;GAGG;AACH,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"layout-3d-vocabulary.js","sourceRoot":"","sources":["../../../../src/layout/layout-3d-vocabulary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mIAAmI;AACnI;;;GAGG;AACH,MAAM,CAAN,IAAY,UAcX;AAdD,WAAY,UAAU;IACpB,yFAAyF;IACzF,iCAAmB,CAAA;IACnB;;;OAGG;IACH,2CAA6B,CAAA;IAC7B;;;;OAIG;IACH,yCAA2B,CAAA;AAC7B,CAAC,EAdW,UAAU,KAAV,UAAU,QAcrB;AAED;;;GAGG;AACH,MAAM,CAAN,IAAY,cASX;AATD,WAAY,cAAc;IACxB,8GAA8G;IAC9G,yDAAuC,CAAA;IACvC;;;;OAIG;IACH,yDAAuC,CAAA;AACzC,CAAC,EATW,cAAc,KAAd,cAAc,QASzB;AAED;;;;;GAKG;AACH,MAAM,CAAN,IAAY,4BAGX;AAHD,WAAY,4BAA4B;IACtC,2FAA2F;IAC3F,yDAAyB,CAAA;AAC3B,CAAC,EAHW,4BAA4B,KAA5B,4BAA4B,QAGvC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAN,IAAY,yBAcX;AAdD,WAAY,yBAAyB;IACnC,+FAA+F;IAC/F,0CAAa,CAAA;IACb;;;;OAIG;IACH,kEAAqC,CAAA;IACrC;;;OAGG;IACH,wDAA2B,CAAA;AAC7B,CAAC,EAdW,yBAAyB,KAAzB,yBAAyB,QAcpC;AAED;;;GAGG;AACH,MAAM,CAAN,IAAY,2BAWX;AAXD,WAAY,2BAA2B;IACrC,mDAAmD;IACnD,4CAAa,CAAA;IACb;;;;;;OAMG;IACH,0CAAW,CAAA;AACb,CAAC,EAXW,2BAA2B,KAA3B,2BAA2B,QAWtC;AAED;;;;GAIG;AACH,MAAM,CAAN,IAAY,gBAGX;AAHD,WAAY,gBAAgB;IAC1B,iDAAiD;IACjD,iCAAa,CAAA;AACf,CAAC,EAHW,gBAAgB,KAAhB,gBAAgB,QAG3B;AAsBD,wDAAwD","sourcesContent":["/**\n * The 3D layout vocabularies (#1843), in a module that imports NOTHING: the lazily loaded frame canvas reads\n * `Layout3DCamera`, and must not pull the layout definitions (and their shell containers) into its chunk to do so.\n */\n\n/** @wildo_source:part:start presets.3d.layout-contract facet:layer:frontend facet:family:layout-3d facet:audience:app-developer */\n/**\n * The built-in 3D layouts. An application uses exactly ONE, chosen when it registers the library; there\n * is no switch. An application may also define its own layout with an id of its own.\n */\nexport enum Layout3DId {\n /** The 2D shell's own disposal, unchanged, with the 3D frame drawn under its regions. */\n INHERIT = 'inherit',\n /**\n * The menubar and the status bars span the whole width; the navigation rails (activity bar, sidebar, utility\n * panel) sit between them, beside the content. The default disposal is sidebar-first; this one is header-first.\n */\n HEADER_FIRST = 'header-first',\n /**\n * The focal plane (#2049): one still perspective camera; the shell regions, each navigation pane and each popup are\n * separate glass objects that travel in depth. Whatever you work with rests on the focal plane at its true size;\n * everything else steps back. Nothing is angled and the camera never moves (Paul, 2026-09-30).\n */\n FOCAL_PLANE = 'focal-plane',\n}\n\n/**\n * The cameras a 3D layout is seen through. The flat camera's transitions are all drawn IN the flat frame (elevation,\n * light, rims), so a slab never leaves its region's box; the still-perspective camera moves the HTML objects instead.\n */\nexport enum Layout3DCamera {\n /** Orthographic, matched 1:1 to CSS pixels: the frame lies flat under the regions, exactly on their boxes. */\n FLAT_ORTHOGRAPHIC = 'flat-orthographic',\n /**\n * A still perspective camera, in CSS: the HTML objects themselves carry depth, around one shared vanishing point, and\n * no WebGL frame is drawn. The camera never moves; objects do (#2049). Only a placement that stages the objects can\n * be seen through it.\n */\n STILL_PERSPECTIVE = 'still-perspective',\n}\n\n/**\n * How the frame answers an APPEARANCE change: a theme, a density, a reduced-motion switch.\n *\n * Whatever the member, a light/dark switch SNAPS: text changes colour at once, and a backdrop halfway between two\n * modes is bounded against neither foreground.\n */\nexport enum Layout3DAppearanceTransition {\n /** The frame cross-fades to the new appearance over the theme's normal motion duration. */\n CROSS_FADE = 'cross-fade',\n}\n\n/**\n * A choreography the frame plays once, as a PULSE that rises and settles, when a shell state changes. The same\n * vocabulary serves every pulse-shaped trigger of {@link Layout3DTransitions} (a navigation, a sidebar resize), so a\n * layout picks per trigger and a new choreography is available to every trigger at once.\n *\n * Every member is drawn in the FRAME. No member transforms a region: a CSS transform blurs text while it runs and\n * makes the region the containing block of its `position: fixed` overlays. A choreography that moved regions would\n * need an untransformed portal target on the shell providers (a default-off option, not built) and its own\n * member here; none exists.\n *\n * Every member stays inside the contrast bound (see each), and plays nothing under reduced motion, where the theme's\n * motion duration is zero.\n */\nexport enum Layout3DFrameChoreography {\n /** Nothing moves. For an application's own layout that wants a still frame on this trigger. */\n NONE = 'none',\n /**\n * The content slab lifts toward the reader and settles back: its shadow spreads and drops further, and its rim\n * brightens toward its hover opacity, then both return. Only blur, offset and rim move — never the shadow's\n * opacity, and never the rim past the hover opacity the bound was proved for.\n */\n ELEVATION_SETTLE = 'elevation-settle',\n /**\n * The light swings across the frame and back: every gradient re-orients along the moving light. Every colour it\n * shows is a point of a gradient the bound already covers; only its direction changes.\n */\n LIGHT_SWEEP = 'light-sweep',\n}\n\n/**\n * What the frame shows for the FOCUSED navigation zone (`useNavigationState().focusedZone`), when two or more zones\n * are side by side.\n */\nexport enum Layout3DZoneFocusTransition {\n /** Nothing marks the focused zone in the frame. */\n NONE = 'none',\n /**\n * A rim in the content slab's rim colour, at most its hover opacity, around the focused zone; it moves to another\n * zone with the theme's gesture spring. Inset clear of the content slab's own rim band, so where it is drawn it is\n * the case the bound was proved for — a rim at hover opacity over the frost — except that it is written as a second\n * framebuffer layer, rounded to 8 bits twice rather than once (at most 1/255 apart), and that the emphasis values\n * between rest and hover are not checked one by one: both limits are shared with the slab rim's own hover emphasis.\n */\n RIM = 'rim',\n}\n\n/**\n * What a layout does to the regions at rest. Only FLAT exists: a CSS 3D transform blurs text, and any transform\n * makes a region the containing block of its `position: fixed` descendants. A layout that wants a persistent tilt\n * needs an untransformed portal target on the shell providers (not built: no choreography moves a region) and a new member here.\n */\nexport enum Layout3DRestPose {\n /** The regions are never transformed at rest. */\n FLAT = 'flat',\n}\n\n/**\n * What a layout plays, per trigger. The triggers are read from existing state only: the navigation state\n * (`useNavigationState`) and the shell's own region measurement. Whatever a layout picks, the frame FOLLOWS every\n * region's box frame by frame while the shell animates (the alignment invariant); these are what it plays\n * ON TOP of following.\n */\nexport interface Layout3DTransitions {\n /** A theme, density or reduced-motion change. */\n appearance: Layout3DAppearanceTransition;\n /**\n * The content changed: any structural zone's top entry is a different place (its URL). The route sync hooks mirror\n * router navigations into those stacks, so a sidebar link and a record opened beside a list both count; the\n * overlay zone does not (a dialog is not a place).\n */\n navigation: Layout3DFrameChoreography;\n /** The sidebar collapsed, expanded or was resized: its measured width changed while it stayed on screen. */\n sidebarResize: Layout3DFrameChoreography;\n /** The navigation state's focused zone changed while two or more zones are side by side. */\n zoneFocus: Layout3DZoneFocusTransition;\n}\n/** @wildo_source:part:end presets.3d.layout-contract */\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type AppLayoutPreset_MainContainer_DefaultProps } from '@wildo-ai/saas-frontend-lib';
|
|
3
3
|
import type { Frame3DStyleOverrides } from './frame/frame-3d-style';
|
|
4
|
+
import { type FocalPlaneSettings } from './focal-plane/focal-plane-settings';
|
|
4
5
|
import { type Layout3DDefinition } from './layout/layout-3d-definition';
|
|
5
6
|
/**
|
|
6
7
|
* The brand a 3D main container carries. `Symbol.for`, not `Symbol`: the component registry lives on
|
|
@@ -19,6 +20,11 @@ export interface Layout3DOptions {
|
|
|
19
20
|
layout?: Layout3DDefinition;
|
|
20
21
|
/** Frame-style overrides layered over the layout's built-in styles. */
|
|
21
22
|
frameStyles?: Frame3DStyleOverrides;
|
|
23
|
+
/**
|
|
24
|
+
* Overrides of the focal plane's numbers (camera distance, layer depth, motion, dims, blurs, window opacity), for
|
|
25
|
+
* {@link FOCAL_PLANE_LAYOUT_3D}; each is checked at registration. Omitted, the defaults.
|
|
26
|
+
*/
|
|
27
|
+
focalPlane?: Partial<FocalPlaneSettings>;
|
|
22
28
|
}
|
|
23
29
|
/** @wildo_source:part:end presets.3d.register-layout */
|
|
24
30
|
/** A 3D main container: the component, the 2D container it captured, and the layout it draws. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-3d-main-container.d.ts","sourceRoot":"","sources":["../../../src/layout-3d-main-container.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAEzC,OAAO,EAA6B,KAAK,0CAA0C,EAAE,MAAM,6BAA6B,CAAC;AAGzH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAA8C,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAMpH;;;;GAIG;AACH,QAAA,MAAM,8BAA8B,eAA+D,CAAC;AAEpG,KAAK,sBAAsB,GAAG,KAAK,CAAC,aAAa,CAAC,0CAA0C,CAAC,CAAC;AAE9F,mIAAmI;AACnI,+FAA+F;AAC/F,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,uEAAuE;IACvE,WAAW,CAAC,EAAE,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"layout-3d-main-container.d.ts","sourceRoot":"","sources":["../../../src/layout-3d-main-container.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAEzC,OAAO,EAA6B,KAAK,0CAA0C,EAAE,MAAM,6BAA6B,CAAC;AAGzH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAwD,KAAK,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACnI,OAAO,EAA8C,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAMpH;;;;GAIG;AACH,QAAA,MAAM,8BAA8B,eAA+D,CAAC;AAEpG,KAAK,sBAAsB,GAAG,KAAK,CAAC,aAAa,CAAC,0CAA0C,CAAC,CAAC;AAE9F,mIAAmI;AACnI,+FAA+F;AAC/F,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,uEAAuE;IACvE,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC1C;AACD,wDAAwD;AAExD,iGAAiG;AACjG,MAAM,MAAM,qBAAqB,GAAG,sBAAsB,GAAG;IAC3D,QAAQ,CAAC,CAAC,8BAA8B,CAAC,EAAE,IAAI,CAAC;IAChD;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;IAC1C,uCAAuC;IACvC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,uEAAuE;IACvE,QAAQ,CAAC,WAAW,EAAE,qBAAqB,GAAG,SAAS,CAAC;CACzD,CAAC;AAEF,kGAAkG;AAClG,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,IAAI,qBAAqB,CAE9F;AAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,sBAAsB,EAAE,OAAO,GAAE,eAAoB,GAAG,qBAAqB,CAoD5H"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
import { useNavigationState, useUI } from '@wildo-ai/saas-frontend-lib';
|
|
4
4
|
import { FrameCanvasDoor } from './frame/frame-canvas.lazy.js';
|
|
5
|
+
import { FocalPlaneSettingsContext, resolveFocalPlaneSettings } from './focal-plane/focal-plane-settings.js';
|
|
5
6
|
import { assertSupportedLayout3D, INHERIT_LAYOUT_3D } from './layout/layout-3d-definition.js';
|
|
6
7
|
import { crossFadesAppearance } from './layout/layout-3d-transition-choreography.js';
|
|
7
8
|
import { Layout3DCamera } from './layout/layout-3d-vocabulary.js';
|
|
@@ -61,6 +62,12 @@ const APPEARANCE_MISMATCH_REPORT_DELAY_MS = 5000;
|
|
|
61
62
|
export function create3DMainContainer(captured, options = {}) {
|
|
62
63
|
const layout = options.layout ?? INHERIT_LAYOUT_3D;
|
|
63
64
|
const frameStyles = options.frameStyles;
|
|
65
|
+
// Checked here, at registration, like the layout itself. Only the still-perspective camera reads them: settings a
|
|
66
|
+
// layout would silently ignore are refused instead.
|
|
67
|
+
if (options.focalPlane !== undefined && layout.scene.camera !== Layout3DCamera.STILL_PERSPECTIVE) {
|
|
68
|
+
throw new Error(`register3DLayout(): 'focalPlane' tunes the focal-plane layout, and the layout '${layout.id}' is not seen through its still camera.`);
|
|
69
|
+
}
|
|
70
|
+
const focalPlane = resolveFocalPlaneSettings(options.focalPlane);
|
|
64
71
|
// A camera, transition kind or rest pose the renderer does not implement is refused here, at registration.
|
|
65
72
|
assertSupportedLayout3D(layout);
|
|
66
73
|
const crossFadeAppearance = crossFadesAppearance(layout.transitions.appearance);
|
|
@@ -85,7 +92,7 @@ export function create3DMainContainer(captured, options = {}) {
|
|
|
85
92
|
}, APPEARANCE_MISMATCH_REPORT_DELAY_MS);
|
|
86
93
|
return () => clearTimeout(report);
|
|
87
94
|
}, [shellAppearance, required]);
|
|
88
|
-
return (_jsxs(_Fragment, { children: [layout.scene.camera === Layout3DCamera.FLAT_ORTHOGRAPHIC && _jsx(FrameSlot, { layout: layout, frameStyles: frameStyles, crossFadeAppearance: crossFadeAppearance }), _jsx(Placement, { ...props })] }));
|
|
95
|
+
return (_jsxs(_Fragment, { children: [layout.scene.camera === Layout3DCamera.FLAT_ORTHOGRAPHIC && _jsx(FrameSlot, { layout: layout, frameStyles: frameStyles, crossFadeAppearance: crossFadeAppearance }), _jsx(FocalPlaneSettingsContext.Provider, { value: focalPlane, children: _jsx(Placement, { ...props }) })] }));
|
|
89
96
|
}
|
|
90
97
|
return Object.assign(Layout3DMainContainer, {
|
|
91
98
|
[LAYOUT_3D_MAIN_CONTAINER_BRAND]: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-3d-main-container.js","sourceRoot":"","sources":["../../../src/layout-3d-main-container.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect } from 'react';\n\nimport { useNavigationState, useUI, type AppLayoutPreset_MainContainer_DefaultProps } from '@wildo-ai/saas-frontend-lib';\n\nimport { FrameCanvasDoor } from './frame/frame-canvas.lazy';\nimport type { Frame3DStyleOverrides } from './frame/frame-3d-style';\nimport { assertSupportedLayout3D, INHERIT_LAYOUT_3D, type Layout3DDefinition } from './layout/layout-3d-definition';\nimport { crossFadesAppearance } from './layout/layout-3d-transition-choreography';\nimport { Layout3DCamera } from './layout/layout-3d-vocabulary';\nimport { ShellLayoutPlacementKind } from './layout/shell-layout-placement';\nimport { useFrameAppearance } from './frame/use-frame-appearance';\n\n/**\n * The brand a 3D main container carries. `Symbol.for`, not `Symbol`: the component registry lives on\n * `globalThis` and survives a hot reload, while a reloaded module would mint a new `Symbol` and fail to\n * recognise the container it registered last time — and then capture it as \"the 2D shell\".\n */\nconst LAYOUT_3D_MAIN_CONTAINER_BRAND = Symbol.for('@wildo-ai/presets-components-3d/main-container');\n\ntype MainContainerComponent = React.ComponentType<AppLayoutPreset_MainContainer_DefaultProps>;\n\n/** @wildo_source:part:start presets.3d.register-layout facet:layer:frontend facet:family:layout-3d facet:audience:app-developer */\n/** What a 3D main container draws: the layout, and the application's frame-style overrides. */\nexport interface Layout3DOptions {\n /**\n * The layout: its disposal, its scene and its transitions. Defaults to {@link INHERIT_LAYOUT_3D}, the 2D disposal\n * with the frame under it. An application uses ONE layout for its whole life.\n */\n layout?: Layout3DDefinition;\n /** Frame-style overrides layered over the layout's built-in styles. */\n frameStyles?: Frame3DStyleOverrides;\n}\n/** @wildo_source:part:end presets.3d.register-layout */\n\n/** A 3D main container: the component, the 2D container it captured, and the layout it draws. */\nexport type Layout3DMainContainer = MainContainerComponent & {\n readonly [LAYOUT_3D_MAIN_CONTAINER_BRAND]: true;\n /**\n * The 2D main container captured at registration: rendered unchanged by an INHERIT placement, and kept by every\n * layout so a re-registration wraps IT rather than a 3D container.\n */\n readonly captured: MainContainerComponent;\n /** The layout this container draws. */\n readonly layout: Layout3DDefinition;\n /** The application's frame-style overrides, when it registered any. */\n readonly frameStyles: Frame3DStyleOverrides | undefined;\n};\n\n/** Whether a registered main container is a 3D one — and so carries the 2D container it wraps. */\nexport function isLayout3DMainContainer(component: unknown): component is Layout3DMainContainer {\n return typeof component === 'function' && (component as Partial<Layout3DMainContainer>)[LAYOUT_3D_MAIN_CONTAINER_BRAND] === true;\n}\n\nlet appearanceMismatchWarned = false;\n\n/**\n * How long a shell appearance other than the one the layout requires must persist before it is reported. The UI\n * context starts from the DEFAULT theme and resolves the application's own theme a moment later, so the first value\n * this container sees is routinely SEPARATED even in a CONTINUOUS application — measured on Wonder Todos, whose\n * shell renders `bg-transparent` while the first-render value read SEPARATED. Only a value that survives\n * bootstrap is the application's.\n */\nconst APPEARANCE_MISMATCH_REPORT_DELAY_MS = 5000;\n\n/**\n * Build the 3D main container: a captured 2D container, and a layout that either renders it (INHERIT) or arranges\n * the regions with a container of its own (COMPOSED).\n *\n * It renders exactly two children, at FIXED positions:\n *\n * - **index 0, the frame slot** ({@link FrameSlot}): the decorative canvas behind its lazy door (`FrameCanvasDoor`),\n * whose `LazyDoorErrorBoundary` contains any failure of it. The theme and the navigation state are read in the\n * slot, in the DOM tree, and passed to the canvas as props: a theme, mode, breakpoint or navigation change\n * re-renders index 0 and never touches index 1.\n * It is `position: fixed` with NO z-index, `aria-hidden` and `pointer-events: none`.\n * - **index 1, the placement**: the captured 2D container, unchanged, for an INHERIT layout; the layout's own\n * container, composed from the same shell building blocks, otherwise. Either way every region, provider,\n * context, portal and latch is the application's own.\n *\n * Why no wrapper, and no `isolate` (the #1821 text proposed `<div class=\"isolate\">` with the canvas at\n * `-z-10`): `isolate` would make the whole shell ONE stacking context, so anything positioned OUTSIDE it\n * with a lower z-index — the consent prompt (`z-50`) — would paint over the shell's own dialogs\n * (`--z-overlay`, 300). #1830 measured that exact reordering and chose `relative` for the 2D shell root\n * for that reason. Instead, a positioned element with no z-index paints at the z-index:0 level in TREE\n * order, which puts the canvas after the theme's background layer (`UIContext`'s `isolate` wrapper,\n * earlier in the tree) and before the shell root (`relative`, the next sibling) — frame above the theme\n * background, shell above the frame — while every z-index inside the shell keeps its global order.\n *\n * The precondition this places on the placement: its ROOT must be positioned (the 2D default and the\n * header-first container are `relative`, #1830), or its in-flow content paints at a lower level than the frame and\n * under it. The frame never takes a click either way — it handles no pointer events at all.\n *\n * Why fixed positions: a canvas failure empties only index 0. The placement never moves and keeps one component\n * type for the application's life, so it never remounts — a remount there would unmount every navigation zone and\n * lose its state.\n */\nexport function create3DMainContainer(captured: MainContainerComponent, options: Layout3DOptions = {}): Layout3DMainContainer {\n const layout = options.layout ?? INHERIT_LAYOUT_3D;\n const frameStyles = options.frameStyles;\n // A camera, transition kind or rest pose the renderer does not implement is refused here, at registration.\n assertSupportedLayout3D(layout);\n const crossFadeAppearance = crossFadesAppearance(layout.transitions.appearance);\n // Chosen ONCE, outside the component: the element at index 1 keeps one type for the application's life, so it\n // never remounts.\n const Placement: MainContainerComponent = layout.placement.kind === ShellLayoutPlacementKind.INHERIT ? captured : layout.placement.container;\n function Layout3DMainContainer(props: AppLayoutPreset_MainContainer_DefaultProps): React.JSX.Element {\n const { shellAppearance } = useUI();\n const required = layout.constraints.requiredShellAppearance;\n\n useEffect(() => {\n // The frame is visible only where regions paint nothing. A layout states the shell appearance it is designed\n // for; any other is the application's choice to correct, so it is said once and nothing switches.\n if (required === null || shellAppearance === required || appearanceMismatchWarned) return undefined;\n const report = setTimeout(() => {\n // Checked again here: several containers (or a remount) may have armed a timer before the first fired.\n if (appearanceMismatchWarned) return;\n appearanceMismatchWarned = true;\n console.warn(\n `[presets-components-3d] the 3D layout '${layout.id}' is designed for a '${String(required)}' shell, and this theme's `\n + `shell appearance is '${String(shellAppearance)}': opaque regions will cover the frame drawn under them.`,\n );\n }, APPEARANCE_MISMATCH_REPORT_DELAY_MS);\n return () => clearTimeout(report);\n }, [shellAppearance, required]);\n\n return (\n <>\n {/* A spatial layout's placement draws its own environment; the flat frame belongs to the flat camera only. */}\n {layout.scene.camera === Layout3DCamera.FLAT_ORTHOGRAPHIC && <FrameSlot layout={layout} frameStyles={frameStyles} crossFadeAppearance={crossFadeAppearance} />}\n <Placement {...props} />\n </>\n );\n }\n\n return Object.assign(Layout3DMainContainer, {\n [LAYOUT_3D_MAIN_CONTAINER_BRAND]: true as const,\n captured,\n layout,\n frameStyles,\n });\n}\n\n/**\n * Index 0 of a 3D main container: reads what the frame follows — the theme (`useFrameAppearance`) and the navigation\n * state (#1826) — and hands it to the canvas. Its own component, so a navigation, which changes the navigation state\n * many times a second during some flows, re-renders this slot and never the placement beside it.\n *\n * The navigation signature is every structural zone's top entry (`getTopEntry`, so a tabbed zone reports its visible\n * tab), identified by its URL PATH:\n * - not by its id, which is minted again on every push or replace, so a route sync that re-lands the SAME place would\n * read as a navigation nobody made (the id stands in only for an entry without a URL);\n * - not by its query string, which carries VIEW state on the same content (`?section=`, `?dataMode=`, which the\n * engine updates in place as \"same id, same content\"): switching a board's section tab or a list's mode is not\n * going somewhere, and does not play.\n * The route sync hooks mirror router navigations into those stacks, so a sidebar link and a record opened beside a\n * list both change it; the overlay zone is not a place and does not. While no zone holds anything yet, the signature\n * is empty, which the frame never records (see `FrameDriver.setNavigation`).\n */\nfunction FrameSlot({\n layout,\n frameStyles,\n crossFadeAppearance,\n}: {\n layout: Layout3DDefinition;\n frameStyles: Frame3DStyleOverrides | undefined;\n crossFadeAppearance: boolean;\n}): React.JSX.Element {\n const appearance = useFrameAppearance(layout.scene.frameStyles, frameStyles);\n const navigation = useNavigationState();\n const zones = Object.keys(navigation.state.zones) as Array<keyof typeof navigation.state.zones>;\n const places = zones.map((zone) => {\n const top = navigation.getTopEntry(zone);\n return top ? (top.urlPath?.split(/[?#]/)[0] ?? top.id) : '';\n });\n const navigationSignature = places.some((place) => place !== '') ? zones.map((zone, index) => `${zone}:${places[index]}`).join('|') : '';\n return (\n <FrameCanvasDoor\n appearance={appearance}\n camera={layout.scene.camera}\n crossFadeAppearance={crossFadeAppearance}\n navigationTransition={layout.transitions.navigation}\n sidebarResizeTransition={layout.transitions.sidebarResize}\n zoneFocusTransition={layout.transitions.zoneFocus}\n navigationSignature={navigationSignature}\n focusedZone={navigation.focusedZone}\n />\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"layout-3d-main-container.js","sourceRoot":"","sources":["../../../src/layout-3d-main-container.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect } from 'react';\n\nimport { useNavigationState, useUI, type AppLayoutPreset_MainContainer_DefaultProps } from '@wildo-ai/saas-frontend-lib';\n\nimport { FrameCanvasDoor } from './frame/frame-canvas.lazy';\nimport type { Frame3DStyleOverrides } from './frame/frame-3d-style';\nimport { FocalPlaneSettingsContext, resolveFocalPlaneSettings, type FocalPlaneSettings } from './focal-plane/focal-plane-settings';\nimport { assertSupportedLayout3D, INHERIT_LAYOUT_3D, type Layout3DDefinition } from './layout/layout-3d-definition';\nimport { crossFadesAppearance } from './layout/layout-3d-transition-choreography';\nimport { Layout3DCamera } from './layout/layout-3d-vocabulary';\nimport { ShellLayoutPlacementKind } from './layout/shell-layout-placement';\nimport { useFrameAppearance } from './frame/use-frame-appearance';\n\n/**\n * The brand a 3D main container carries. `Symbol.for`, not `Symbol`: the component registry lives on\n * `globalThis` and survives a hot reload, while a reloaded module would mint a new `Symbol` and fail to\n * recognise the container it registered last time — and then capture it as \"the 2D shell\".\n */\nconst LAYOUT_3D_MAIN_CONTAINER_BRAND = Symbol.for('@wildo-ai/presets-components-3d/main-container');\n\ntype MainContainerComponent = React.ComponentType<AppLayoutPreset_MainContainer_DefaultProps>;\n\n/** @wildo_source:part:start presets.3d.register-layout facet:layer:frontend facet:family:layout-3d facet:audience:app-developer */\n/** What a 3D main container draws: the layout, and the application's frame-style overrides. */\nexport interface Layout3DOptions {\n /**\n * The layout: its disposal, its scene and its transitions. Defaults to {@link INHERIT_LAYOUT_3D}, the 2D disposal\n * with the frame under it. An application uses ONE layout for its whole life.\n */\n layout?: Layout3DDefinition;\n /** Frame-style overrides layered over the layout's built-in styles. */\n frameStyles?: Frame3DStyleOverrides;\n /**\n * Overrides of the focal plane's numbers (camera distance, layer depth, motion, dims, blurs, window opacity), for\n * {@link FOCAL_PLANE_LAYOUT_3D}; each is checked at registration. Omitted, the defaults.\n */\n focalPlane?: Partial<FocalPlaneSettings>;\n}\n/** @wildo_source:part:end presets.3d.register-layout */\n\n/** A 3D main container: the component, the 2D container it captured, and the layout it draws. */\nexport type Layout3DMainContainer = MainContainerComponent & {\n readonly [LAYOUT_3D_MAIN_CONTAINER_BRAND]: true;\n /**\n * The 2D main container captured at registration: rendered unchanged by an INHERIT placement, and kept by every\n * layout so a re-registration wraps IT rather than a 3D container.\n */\n readonly captured: MainContainerComponent;\n /** The layout this container draws. */\n readonly layout: Layout3DDefinition;\n /** The application's frame-style overrides, when it registered any. */\n readonly frameStyles: Frame3DStyleOverrides | undefined;\n};\n\n/** Whether a registered main container is a 3D one — and so carries the 2D container it wraps. */\nexport function isLayout3DMainContainer(component: unknown): component is Layout3DMainContainer {\n return typeof component === 'function' && (component as Partial<Layout3DMainContainer>)[LAYOUT_3D_MAIN_CONTAINER_BRAND] === true;\n}\n\nlet appearanceMismatchWarned = false;\n\n/**\n * How long a shell appearance other than the one the layout requires must persist before it is reported. The UI\n * context starts from the DEFAULT theme and resolves the application's own theme a moment later, so the first value\n * this container sees is routinely SEPARATED even in a CONTINUOUS application — measured on Wonder Todos, whose\n * shell renders `bg-transparent` while the first-render value read SEPARATED. Only a value that survives\n * bootstrap is the application's.\n */\nconst APPEARANCE_MISMATCH_REPORT_DELAY_MS = 5000;\n\n/**\n * Build the 3D main container: a captured 2D container, and a layout that either renders it (INHERIT) or arranges\n * the regions with a container of its own (COMPOSED).\n *\n * It renders exactly two children, at FIXED positions:\n *\n * - **index 0, the frame slot** ({@link FrameSlot}): the decorative canvas behind its lazy door (`FrameCanvasDoor`),\n * whose `LazyDoorErrorBoundary` contains any failure of it. The theme and the navigation state are read in the\n * slot, in the DOM tree, and passed to the canvas as props: a theme, mode, breakpoint or navigation change\n * re-renders index 0 and never touches index 1.\n * It is `position: fixed` with NO z-index, `aria-hidden` and `pointer-events: none`.\n * - **index 1, the placement**: the captured 2D container, unchanged, for an INHERIT layout; the layout's own\n * container, composed from the same shell building blocks, otherwise. Either way every region, provider,\n * context, portal and latch is the application's own.\n *\n * Why no wrapper, and no `isolate` (the #1821 text proposed `<div class=\"isolate\">` with the canvas at\n * `-z-10`): `isolate` would make the whole shell ONE stacking context, so anything positioned OUTSIDE it\n * with a lower z-index — the consent prompt (`z-50`) — would paint over the shell's own dialogs\n * (`--z-overlay`, 300). #1830 measured that exact reordering and chose `relative` for the 2D shell root\n * for that reason. Instead, a positioned element with no z-index paints at the z-index:0 level in TREE\n * order, which puts the canvas after the theme's background layer (`UIContext`'s `isolate` wrapper,\n * earlier in the tree) and before the shell root (`relative`, the next sibling) — frame above the theme\n * background, shell above the frame — while every z-index inside the shell keeps its global order.\n *\n * The precondition this places on the placement: its ROOT must be positioned (the 2D default and the\n * header-first container are `relative`, #1830), or its in-flow content paints at a lower level than the frame and\n * under it. The frame never takes a click either way — it handles no pointer events at all.\n *\n * Why fixed positions: a canvas failure empties only index 0. The placement never moves and keeps one component\n * type for the application's life, so it never remounts — a remount there would unmount every navigation zone and\n * lose its state.\n */\nexport function create3DMainContainer(captured: MainContainerComponent, options: Layout3DOptions = {}): Layout3DMainContainer {\n const layout = options.layout ?? INHERIT_LAYOUT_3D;\n const frameStyles = options.frameStyles;\n // Checked here, at registration, like the layout itself. Only the still-perspective camera reads them: settings a\n // layout would silently ignore are refused instead.\n if (options.focalPlane !== undefined && layout.scene.camera !== Layout3DCamera.STILL_PERSPECTIVE) {\n throw new Error(`register3DLayout(): 'focalPlane' tunes the focal-plane layout, and the layout '${layout.id}' is not seen through its still camera.`);\n }\n const focalPlane = resolveFocalPlaneSettings(options.focalPlane);\n // A camera, transition kind or rest pose the renderer does not implement is refused here, at registration.\n assertSupportedLayout3D(layout);\n const crossFadeAppearance = crossFadesAppearance(layout.transitions.appearance);\n // Chosen ONCE, outside the component: the element at index 1 keeps one type for the application's life, so it\n // never remounts.\n const Placement: MainContainerComponent = layout.placement.kind === ShellLayoutPlacementKind.INHERIT ? captured : layout.placement.container;\n function Layout3DMainContainer(props: AppLayoutPreset_MainContainer_DefaultProps): React.JSX.Element {\n const { shellAppearance } = useUI();\n const required = layout.constraints.requiredShellAppearance;\n\n useEffect(() => {\n // The frame is visible only where regions paint nothing. A layout states the shell appearance it is designed\n // for; any other is the application's choice to correct, so it is said once and nothing switches.\n if (required === null || shellAppearance === required || appearanceMismatchWarned) return undefined;\n const report = setTimeout(() => {\n // Checked again here: several containers (or a remount) may have armed a timer before the first fired.\n if (appearanceMismatchWarned) return;\n appearanceMismatchWarned = true;\n console.warn(\n `[presets-components-3d] the 3D layout '${layout.id}' is designed for a '${String(required)}' shell, and this theme's `\n + `shell appearance is '${String(shellAppearance)}': opaque regions will cover the frame drawn under them.`,\n );\n }, APPEARANCE_MISMATCH_REPORT_DELAY_MS);\n return () => clearTimeout(report);\n }, [shellAppearance, required]);\n\n return (\n <>\n {/* The flat frame belongs to the flat camera; a still-perspective placement stages its own depth. */}\n {layout.scene.camera === Layout3DCamera.FLAT_ORTHOGRAPHIC && <FrameSlot layout={layout} frameStyles={frameStyles} crossFadeAppearance={crossFadeAppearance} />}\n <FocalPlaneSettingsContext.Provider value={focalPlane}>\n <Placement {...props} />\n </FocalPlaneSettingsContext.Provider>\n </>\n );\n }\n\n return Object.assign(Layout3DMainContainer, {\n [LAYOUT_3D_MAIN_CONTAINER_BRAND]: true as const,\n captured,\n layout,\n frameStyles,\n });\n}\n\n/**\n * Index 0 of a 3D main container: reads what the frame follows — the theme (`useFrameAppearance`) and the navigation\n * state (#1826) — and hands it to the canvas. Its own component, so a navigation, which changes the navigation state\n * many times a second during some flows, re-renders this slot and never the placement beside it.\n *\n * The navigation signature is every structural zone's top entry (`getTopEntry`, so a tabbed zone reports its visible\n * tab), identified by its URL PATH:\n * - not by its id, which is minted again on every push or replace, so a route sync that re-lands the SAME place would\n * read as a navigation nobody made (the id stands in only for an entry without a URL);\n * - not by its query string, which carries VIEW state on the same content (`?section=`, `?dataMode=`, which the\n * engine updates in place as \"same id, same content\"): switching a board's section tab or a list's mode is not\n * going somewhere, and does not play.\n * The route sync hooks mirror router navigations into those stacks, so a sidebar link and a record opened beside a\n * list both change it; the overlay zone is not a place and does not. While no zone holds anything yet, the signature\n * is empty, which the frame never records (see `FrameDriver.setNavigation`).\n */\nfunction FrameSlot({\n layout,\n frameStyles,\n crossFadeAppearance,\n}: {\n layout: Layout3DDefinition;\n frameStyles: Frame3DStyleOverrides | undefined;\n crossFadeAppearance: boolean;\n}): React.JSX.Element {\n const appearance = useFrameAppearance(layout.scene.frameStyles, frameStyles);\n const navigation = useNavigationState();\n const zones = Object.keys(navigation.state.zones) as Array<keyof typeof navigation.state.zones>;\n const places = zones.map((zone) => {\n const top = navigation.getTopEntry(zone);\n return top ? (top.urlPath?.split(/[?#]/)[0] ?? top.id) : '';\n });\n const navigationSignature = places.some((place) => place !== '') ? zones.map((zone, index) => `${zone}:${places[index]}`).join('|') : '';\n return (\n <FrameCanvasDoor\n appearance={appearance}\n camera={layout.scene.camera}\n crossFadeAppearance={crossFadeAppearance}\n navigationTransition={layout.transitions.navigation}\n sidebarResizeTransition={layout.transitions.sidebarResize}\n zoneFocusTransition={layout.transitions.zoneFocus}\n navigationSignature={navigationSignature}\n focusedZone={navigation.focusedZone}\n />\n );\n}\n"]}
|