@wildo-ai/presets-components-3d 1.1.6 → 1.1.7
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-3d-style.d.ts.map +1 -1
- package/dist/esm/frame/frame-3d-style.js.map +1 -1
- package/dist/esm/frame/frame-appearance.d.ts.map +1 -1
- package/dist/esm/frame/frame-appearance.js.map +1 -1
- package/dist/esm/frame/frame-canvas.d.ts.map +1 -1
- package/dist/esm/frame/frame-canvas.js +3 -3
- package/dist/esm/frame/frame-canvas.js.map +1 -1
- package/dist/esm/frame/frame-canvas.lazy.d.ts.map +1 -1
- package/dist/esm/frame/frame-canvas.lazy.js.map +1 -1
- package/dist/esm/frame/frame-color.d.ts.map +1 -1
- package/dist/esm/frame/frame-color.js.map +1 -1
- package/dist/esm/frame/frame-driver.d.ts.map +1 -1
- package/dist/esm/frame/frame-driver.js.map +1 -1
- package/dist/esm/frame/frame-renderer.d.ts.map +1 -1
- package/dist/esm/frame/frame-renderer.js.map +1 -1
- package/dist/esm/frame/frame-shaders.d.ts.map +1 -1
- package/dist/esm/frame/frame-shaders.js.map +1 -1
- package/dist/esm/frame/use-frame-appearance.d.ts.map +1 -1
- package/dist/esm/frame/use-frame-appearance.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/header-first-shell-container.d.ts.map +1 -1
- package/dist/esm/layout/header-first-shell-container.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-transition-choreography.d.ts.map +1 -1
- package/dist/esm/layout/layout-3d-transition-choreography.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/shell-layout-placement.d.ts.map +1 -1
- package/dist/esm/layout/shell-layout-placement.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/esm/register-3d-layout.d.ts.map +1 -1
- package/dist/esm/register-3d-layout.js.map +1 -1
- package/dist/esm/shell-region-measurement.d.ts.map +1 -1
- package/dist/esm/shell-region-measurement.js.map +1 -1
- package/dist/esm/tokens/design-token-resolution.d.ts.map +1 -1
- package/dist/esm/tokens/design-token-resolution.js.map +1 -1
- package/dist/esm/tokens/use-design-token-resolution.d.ts.map +1 -1
- package/dist/esm/tokens/use-design-token-resolution.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,231 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { HorizontalPlacement, ShellRegion, SurfaceVariant, VerticalPlacement } from '@wildo-ai/presets-components-models';
|
|
4
|
-
import { AppShellContentOutlet, AppShellLoadingState, AppShellOverlayPortalLayer, AppShellOverlaysOutlet, AppShellProviders, AppShellRegionOutlet, NON_CANONICAL_SHELL_SURFACE_POLICY_OVERRIDE, Surface, useAppShellFirstReady, useAppShellLayout, useNavigationState, useUI, } from '@wildo-ai/saas-frontend-lib';
|
|
5
|
-
import { cameraMoveFor, cssCameraTransform, layoutSpatialPanels, panelTransform, restPose, sampleMove, SPATIAL_CAMERA_DISTANCE_PX, SpatialCameraCue, SpatialPanelId, } from './spatial-camera.js';
|
|
6
|
-
import { SpatialEnvironmentDoor } from './spatial-environment.lazy.js';
|
|
7
|
-
import { SpatialStageStore } from './spatial-stage-store.js';
|
|
8
|
-
/**
|
|
9
|
-
* The spatial layout's placement (PROTOTYPE, Paul 2026-09-30: "something futurist, with a real camera aspect and
|
|
10
|
-
* transitions" — clean spatial, side panels angled, content frontal).
|
|
11
|
-
*
|
|
12
|
-
* The regions are the application's own, rendered by the standard outlets with every context; this container only
|
|
13
|
-
* groups them into five glass panels and stands those panels in a CSS 3D stage:
|
|
14
|
-
*
|
|
15
|
-
* - a perspective root the size of the viewport;
|
|
16
|
-
* - a CAMERA element at its centre, `preserve-3d`, whose transform is the inverse of the camera pose;
|
|
17
|
-
* - the panels, each centred on that element and moved/turned to its place (`layoutSpatialPanels`).
|
|
18
|
-
*
|
|
19
|
-
* At rest the camera faces the centre panel from exactly the perspective distance, so the content is drawn at its CSS
|
|
20
|
-
* size — crisp. The camera moves on the shell's transitions and always returns to rest.
|
|
21
|
-
*
|
|
22
|
-
* Overlays render in `AppShellOverlayPortalLayer`, OUTSIDE the stage: a dialog inside a transformed panel would be
|
|
23
|
-
* confined to it, and a menu would be placed in the wrong coordinates.
|
|
24
|
-
*/
|
|
25
|
-
export function SpatialShellContainer({ children }) {
|
|
26
|
-
const layoutInfo = useAppShellLayout();
|
|
27
|
-
const hasLayoutBeenReady = useAppShellFirstReady(layoutInfo.isLayoutReady);
|
|
28
|
-
if (!layoutInfo.isLayoutReady && !hasLayoutBeenReady)
|
|
29
|
-
return _jsx(AppShellLoadingState, {});
|
|
30
|
-
return (_jsx(AppShellProviders, { layout: layoutInfo, children: _jsx(SpatialStage, { children: children }) }));
|
|
31
|
-
}
|
|
32
|
-
const PANEL_TRANSITION = 'transform 700ms cubic-bezier(0.2, 0.8, 0.2, 1), width 700ms cubic-bezier(0.2, 0.8, 0.2, 1), height 700ms cubic-bezier(0.2, 0.8, 0.2, 1)';
|
|
33
|
-
function SpatialStage({ children }) {
|
|
34
|
-
const { isDark, prefersReducedMotion } = useUI();
|
|
35
|
-
const viewport = useViewportSize();
|
|
36
|
-
const store = useMemo(() => new SpatialStageStore(), []);
|
|
37
|
-
const cameraRef = useRef(null);
|
|
38
|
-
const startRef = useRef(null);
|
|
39
|
-
const endRef = useRef(null);
|
|
40
|
-
const topRef = useRef(null);
|
|
41
|
-
const bottomRef = useRef(null);
|
|
42
|
-
const sizeRefs = useMemo(() => ({ start: startRef, end: endRef, top: topRef, bottom: bottomRef }), []);
|
|
43
|
-
const sizes = useNaturalSizes(sizeRefs);
|
|
44
|
-
const panels = useMemo(() => layoutSpatialPanels({ viewport, startWidth: sizes.start, endWidth: sizes.end, topHeight: sizes.top, bottomHeight: sizes.bottom }), [viewport, sizes.start, sizes.end, sizes.top, sizes.bottom]);
|
|
45
|
-
const shown = useMemo(() => {
|
|
46
|
-
const visible = { [SpatialPanelId.CENTRE]: panels[SpatialPanelId.CENTRE] };
|
|
47
|
-
if (sizes.start > 0)
|
|
48
|
-
visible[SpatialPanelId.START_COLUMN] = panels[SpatialPanelId.START_COLUMN];
|
|
49
|
-
if (sizes.end > 0)
|
|
50
|
-
visible[SpatialPanelId.END_COLUMN] = panels[SpatialPanelId.END_COLUMN];
|
|
51
|
-
if (sizes.top > 0)
|
|
52
|
-
visible[SpatialPanelId.TOP] = panels[SpatialPanelId.TOP];
|
|
53
|
-
if (sizes.bottom > 0)
|
|
54
|
-
visible[SpatialPanelId.BOTTOM] = panels[SpatialPanelId.BOTTOM];
|
|
55
|
-
return visible;
|
|
56
|
-
}, [panels, sizes.start, sizes.end, sizes.top, sizes.bottom]);
|
|
57
|
-
useLayoutEffect(() => {
|
|
58
|
-
store.set({ viewport, panels: shown, isDark });
|
|
59
|
-
}, [store, viewport, shown, isDark]);
|
|
60
|
-
const play = useCameraPlayer(cameraRef, store, prefersReducedMotion);
|
|
61
|
-
useSpatialCues(play, sizes.start, sizes.start + sizes.end + sizes.top + sizes.bottom > 0, viewport);
|
|
62
|
-
const panel = (id, ref, size, content) => {
|
|
63
|
-
const placement = panels[id];
|
|
64
|
-
const style = {
|
|
65
|
-
position: 'absolute',
|
|
66
|
-
left: 0,
|
|
67
|
-
top: 0,
|
|
68
|
-
transform: panelTransform(placement),
|
|
69
|
-
transition: prefersReducedMotion ? undefined : PANEL_TRANSITION,
|
|
70
|
-
backfaceVisibility: 'hidden',
|
|
71
|
-
visibility: shown[id] ? 'visible' : 'hidden',
|
|
72
|
-
...(size !== 'natural-width' ? { width: placement.width } : {}),
|
|
73
|
-
...(size !== 'natural-height' ? { height: placement.height } : {}),
|
|
74
|
-
...GLASS_STYLE,
|
|
75
|
-
};
|
|
76
|
-
return (_jsx("div", { ref: ref ?? undefined, "data-spatial-panel": id, className: "flex overflow-hidden", style: style, children: content }));
|
|
77
|
-
};
|
|
78
|
-
return (_jsx(Surface, { asChild: true, emitPolicyVars: false, variant: SurfaceVariant.SHELL, policyOverride: NON_CANONICAL_SHELL_SURFACE_POLICY_OVERRIDE, children: _jsxs("div", { className: "relative h-screen w-screen overflow-hidden bg-background", "data-spatial-stage": "", children: [_jsx(SpatialEnvironmentDoor, { store: store }), _jsx("div", { className: "absolute inset-0", style: { perspective: `${SPATIAL_CAMERA_DISTANCE_PX}px`, perspectiveOrigin: '50% 50%' }, children: _jsxs("div", { ref: cameraRef, "data-spatial-camera": "", style: { position: 'absolute', left: '50%', top: '50%', width: 0, height: 0, transformStyle: 'preserve-3d', transform: cssCameraTransform(restPose()) }, children: [panel(SpatialPanelId.START_COLUMN, startRef, 'natural-width', (_jsxs(_Fragment, { children: [_jsx(AppShellRegionOutlet, { region: ShellRegion.ACTIVITY_BAR }), _jsx(AppShellRegionOutlet, { region: ShellRegion.SIDEBAR, placement: HorizontalPlacement.START }), _jsx(AppShellRegionOutlet, { region: ShellRegion.UTILITY_PANEL, placement: HorizontalPlacement.START })] }))), panel(SpatialPanelId.CENTRE, null, 'fixed', (_jsxs("div", { className: "flex-1 flex flex-col min-w-0 min-h-0", children: [_jsx(AppShellRegionOutlet, { region: ShellRegion.TOOLBAR }), _jsx(AppShellContentOutlet, { className: "flex-1 relative min-w-0 min-h-0", children: children })] }))), panel(SpatialPanelId.END_COLUMN, endRef, 'natural-width', (_jsxs(_Fragment, { children: [_jsx(AppShellRegionOutlet, { region: ShellRegion.SIDEBAR, placement: HorizontalPlacement.END }), _jsx(AppShellRegionOutlet, { region: ShellRegion.UTILITY_PANEL, placement: HorizontalPlacement.END })] }))), panel(SpatialPanelId.TOP, topRef, 'natural-height', (_jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [_jsx(AppShellRegionOutlet, { region: ShellRegion.STATUS_BAR, placement: VerticalPlacement.TOP }), _jsx(AppShellRegionOutlet, { region: ShellRegion.MENUBAR })] }))), panel(SpatialPanelId.BOTTOM, bottomRef, 'natural-height', (_jsx("div", { className: "flex-1 flex flex-col min-w-0", children: _jsx(AppShellRegionOutlet, { region: ShellRegion.STATUS_BAR, placement: VerticalPlacement.BOTTOM }) })))] }) }), _jsx(AppShellOverlaysOutlet, {}), _jsx(AppShellOverlayPortalLayer, {})] }) }));
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* The glass every panel is made of: a translucent card colour over a blurred backdrop, a hairline light edge and a
|
|
82
|
-
* deep soft shadow. Colours come from the theme's tokens, so light and dark modes follow the theme.
|
|
83
|
-
*/
|
|
84
|
-
const GLASS_STYLE = {
|
|
85
|
-
borderRadius: 22,
|
|
86
|
-
background: 'color-mix(in oklab, var(--card, var(--background)) 74%, transparent)',
|
|
87
|
-
backdropFilter: 'blur(28px) saturate(1.3)',
|
|
88
|
-
border: '1px solid color-mix(in oklab, var(--border) 55%, white 45%)',
|
|
89
|
-
boxShadow: '0 40px 90px -30px rgb(15 23 42 / 0.35), 0 12px 30px -12px rgb(15 23 42 / 0.18), inset 0 1px 0 0 rgb(255 255 255 / 0.45)',
|
|
90
|
-
};
|
|
91
|
-
function useViewportSize() {
|
|
92
|
-
const read = () => ({ width: window.innerWidth, height: window.innerHeight });
|
|
93
|
-
const [size, setSize] = useState(read);
|
|
94
|
-
useEffect(() => {
|
|
95
|
-
const onResize = () => setSize(read());
|
|
96
|
-
window.addEventListener('resize', onResize);
|
|
97
|
-
return () => window.removeEventListener('resize', onResize);
|
|
98
|
-
}, []);
|
|
99
|
-
return size;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* The natural (untransformed) sizes of the panels whose size comes from their content: the side columns' widths and
|
|
103
|
-
* the strips' heights. `offsetWidth`/`offsetHeight` ignore transforms, so a turned column reads its real width.
|
|
104
|
-
*/
|
|
105
|
-
function useNaturalSizes(refs) {
|
|
106
|
-
const [sizes, setSizes] = useState({ start: 0, end: 0, top: 0, bottom: 0 });
|
|
107
|
-
useLayoutEffect(() => {
|
|
108
|
-
const measure = () => {
|
|
109
|
-
const width = (ref) => (ref.current && ref.current.childElementCount > 0 ? ref.current.offsetWidth : 0);
|
|
110
|
-
const height = (ref) => (ref.current && hasRenderedRegion(ref.current) ? ref.current.offsetHeight : 0);
|
|
111
|
-
const next = { start: width(refs.start), end: width(refs.end), top: height(refs.top), bottom: height(refs.bottom) };
|
|
112
|
-
setSizes((previous) => (previous.start === next.start && previous.end === next.end && previous.top === next.top && previous.bottom === next.bottom ? previous : next));
|
|
113
|
-
};
|
|
114
|
-
measure();
|
|
115
|
-
const observer = new ResizeObserver(measure);
|
|
116
|
-
for (const ref of Object.values(refs))
|
|
117
|
-
if (ref.current)
|
|
118
|
-
observer.observe(ref.current);
|
|
119
|
-
const mutations = new MutationObserver(measure);
|
|
120
|
-
for (const ref of Object.values(refs))
|
|
121
|
-
if (ref.current)
|
|
122
|
-
mutations.observe(ref.current, { childList: true, subtree: true });
|
|
123
|
-
return () => {
|
|
124
|
-
observer.disconnect();
|
|
125
|
-
mutations.disconnect();
|
|
126
|
-
};
|
|
127
|
-
}, [refs]);
|
|
128
|
-
return sizes;
|
|
129
|
-
}
|
|
130
|
-
function hasRenderedRegion(element) {
|
|
131
|
-
return element.querySelector('[data-component-area]') !== null;
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Plays camera moves on the camera element (the stage's OWN element, so writing its inline transform touches nothing
|
|
135
|
-
* React renders) and publishes every pose to the store for the environment. Under reduced motion every move is a cut
|
|
136
|
-
* to its final pose. Returns `play(move)`; a new move replaces the one in progress, starting from where it stands.
|
|
137
|
-
*/
|
|
138
|
-
function useCameraPlayer(cameraRef, store, reduced) {
|
|
139
|
-
const frame = useRef(0);
|
|
140
|
-
useEffect(() => () => cancelAnimationFrame(frame.current), []);
|
|
141
|
-
return useMemo(() => {
|
|
142
|
-
const apply = (pose) => {
|
|
143
|
-
if (cameraRef.current)
|
|
144
|
-
cameraRef.current.style.transform = cssCameraTransform(pose);
|
|
145
|
-
store.set({ pose });
|
|
146
|
-
};
|
|
147
|
-
return (move) => {
|
|
148
|
-
cancelAnimationFrame(frame.current);
|
|
149
|
-
if (reduced) {
|
|
150
|
-
apply(move.keyframes[move.keyframes.length - 1].pose);
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
// Start from where the camera stands, so an interrupted move blends instead of jumping.
|
|
154
|
-
const from = store.get().pose;
|
|
155
|
-
const blended = { ...move, keyframes: [{ at: 0, pose: from }, ...move.keyframes.filter((keyframe) => keyframe.at > 0)] };
|
|
156
|
-
const start = performance.now();
|
|
157
|
-
const tick = () => {
|
|
158
|
-
const elapsed = performance.now() - start;
|
|
159
|
-
apply(sampleMove(blended, elapsed));
|
|
160
|
-
if (elapsed < blended.durationMs)
|
|
161
|
-
frame.current = requestAnimationFrame(tick);
|
|
162
|
-
};
|
|
163
|
-
frame.current = requestAnimationFrame(tick);
|
|
164
|
-
};
|
|
165
|
-
}, [cameraRef, store, reduced]);
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* What moves the camera: the shell arriving, the content changing (a structural zone's top entry is another place,
|
|
169
|
-
* by URL path — the same signature the flat frame uses), focus moving between side-by-side panes, and the start
|
|
170
|
-
* column resizing (the sidebar collapsing or expanding).
|
|
171
|
-
*/
|
|
172
|
-
function useSpatialCues(play, startWidth, measured, viewport) {
|
|
173
|
-
const navigation = useNavigationState();
|
|
174
|
-
const zones = Object.keys(navigation.state.zones);
|
|
175
|
-
const places = zones.map((zone) => {
|
|
176
|
-
const top = navigation.getTopEntry(zone);
|
|
177
|
-
return top ? (top.urlPath?.split(/[?#]/)[0] ?? top.id) : '';
|
|
178
|
-
});
|
|
179
|
-
const signature = places.some((place) => place !== '') ? zones.map((zone, index) => `${zone}:${places[index]}`).join('|') : '';
|
|
180
|
-
const arrived = useRef(false);
|
|
181
|
-
useEffect(() => {
|
|
182
|
-
if (arrived.current || !measured)
|
|
183
|
-
return;
|
|
184
|
-
arrived.current = true;
|
|
185
|
-
play(cameraMoveFor(SpatialCameraCue.ARRIVAL));
|
|
186
|
-
}, [play, measured]);
|
|
187
|
-
const lastSignature = useRef(null);
|
|
188
|
-
useEffect(() => {
|
|
189
|
-
if (signature === '')
|
|
190
|
-
return;
|
|
191
|
-
const previous = lastSignature.current;
|
|
192
|
-
lastSignature.current = signature;
|
|
193
|
-
if (previous !== null && previous !== signature)
|
|
194
|
-
play(cameraMoveFor(SpatialCameraCue.NAVIGATION));
|
|
195
|
-
}, [play, signature]);
|
|
196
|
-
const lastFocus = useRef(null);
|
|
197
|
-
useEffect(() => {
|
|
198
|
-
const zone = navigation.focusedZone ?? null;
|
|
199
|
-
const previous = lastFocus.current;
|
|
200
|
-
lastFocus.current = zone;
|
|
201
|
-
if (previous === null || zone === null || previous === zone)
|
|
202
|
-
return;
|
|
203
|
-
const panes = [...document.querySelectorAll(`[data-component-area="${ShellRegion.CONTENT}"] [data-content-area]`)].filter((pane) => pane.offsetWidth > 0);
|
|
204
|
-
const focused = panes.find((pane) => pane.dataset.contentArea === zone);
|
|
205
|
-
if (panes.length < 2 || !focused)
|
|
206
|
-
return;
|
|
207
|
-
const rect = focused.getBoundingClientRect();
|
|
208
|
-
play(cameraMoveFor(SpatialCameraCue.ZONE_FOCUS, SPATIAL_CAMERA_DISTANCE_PX, rect.left + rect.width / 2 - viewport.width / 2));
|
|
209
|
-
}, [play, navigation.focusedZone, viewport.width]);
|
|
210
|
-
// A collapse animates the width over many frames: cue once per settled change, not once per frame.
|
|
211
|
-
const settledStart = useRef(0);
|
|
212
|
-
const lastResizeCue = useRef(0);
|
|
213
|
-
useEffect(() => {
|
|
214
|
-
if (startWidth === 0)
|
|
215
|
-
return;
|
|
216
|
-
const previous = settledStart.current;
|
|
217
|
-
if (previous === 0) {
|
|
218
|
-
settledStart.current = startWidth;
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
if (Math.abs(previous - startWidth) <= 24)
|
|
222
|
-
return;
|
|
223
|
-
settledStart.current = startWidth;
|
|
224
|
-
const now = performance.now();
|
|
225
|
-
if (now - lastResizeCue.current < 900)
|
|
226
|
-
return;
|
|
227
|
-
lastResizeCue.current = now;
|
|
228
|
-
play(cameraMoveFor(SpatialCameraCue.COLUMN_RESIZE));
|
|
229
|
-
}, [play, startWidth]);
|
|
230
|
-
}
|
|
231
|
-
//# sourceMappingURL=spatial-shell-container.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spatial-shell-container.js","sourceRoot":"","sources":["../../../../src/spatial/spatial-shell-container.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\n\nimport { HorizontalPlacement, ShellRegion, SurfaceVariant, VerticalPlacement } from '@wildo-ai/presets-components-models';\nimport {\n AppShellContentOutlet,\n AppShellLoadingState,\n AppShellOverlayPortalLayer,\n AppShellOverlaysOutlet,\n AppShellProviders,\n AppShellRegionOutlet,\n NON_CANONICAL_SHELL_SURFACE_POLICY_OVERRIDE,\n Surface,\n useAppShellFirstReady,\n useAppShellLayout,\n useNavigationState,\n useUI,\n type AppLayoutPreset_MainContainer_DefaultProps,\n} from '@wildo-ai/saas-frontend-lib';\n\nimport {\n cameraMoveFor,\n cssCameraTransform,\n layoutSpatialPanels,\n panelTransform,\n restPose,\n sampleMove,\n SPATIAL_CAMERA_DISTANCE_PX,\n SpatialCameraCue,\n SpatialPanelId,\n type SpatialCameraMove,\n type SpatialPanelPlacement,\n} from './spatial-camera';\nimport { SpatialEnvironmentDoor } from './spatial-environment.lazy';\nimport { SpatialStageStore } from './spatial-stage-store';\n\n/**\n * The spatial layout's placement (PROTOTYPE, Paul 2026-09-30: \"something futurist, with a real camera aspect and\n * transitions\" — clean spatial, side panels angled, content frontal).\n *\n * The regions are the application's own, rendered by the standard outlets with every context; this container only\n * groups them into five glass panels and stands those panels in a CSS 3D stage:\n *\n * - a perspective root the size of the viewport;\n * - a CAMERA element at its centre, `preserve-3d`, whose transform is the inverse of the camera pose;\n * - the panels, each centred on that element and moved/turned to its place (`layoutSpatialPanels`).\n *\n * At rest the camera faces the centre panel from exactly the perspective distance, so the content is drawn at its CSS\n * size — crisp. The camera moves on the shell's transitions and always returns to rest.\n *\n * Overlays render in `AppShellOverlayPortalLayer`, OUTSIDE the stage: a dialog inside a transformed panel would be\n * confined to it, and a menu would be placed in the wrong coordinates.\n */\nexport function SpatialShellContainer({ children }: AppLayoutPreset_MainContainer_DefaultProps): React.JSX.Element {\n const layoutInfo = useAppShellLayout();\n const hasLayoutBeenReady = useAppShellFirstReady(layoutInfo.isLayoutReady);\n if (!layoutInfo.isLayoutReady && !hasLayoutBeenReady) return <AppShellLoadingState />;\n return (\n <AppShellProviders layout={layoutInfo}>\n <SpatialStage>{children}</SpatialStage>\n </AppShellProviders>\n );\n}\n\nconst PANEL_TRANSITION = 'transform 700ms cubic-bezier(0.2, 0.8, 0.2, 1), width 700ms cubic-bezier(0.2, 0.8, 0.2, 1), height 700ms cubic-bezier(0.2, 0.8, 0.2, 1)';\n\nfunction SpatialStage({ children }: { children: React.ReactNode }): React.JSX.Element {\n const { isDark, prefersReducedMotion } = useUI();\n const viewport = useViewportSize();\n const store = useMemo(() => new SpatialStageStore(), []);\n const cameraRef = useRef<HTMLDivElement>(null);\n const startRef = useRef<HTMLDivElement>(null);\n const endRef = useRef<HTMLDivElement>(null);\n const topRef = useRef<HTMLDivElement>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const sizeRefs = useMemo(() => ({ start: startRef, end: endRef, top: topRef, bottom: bottomRef }), []);\n const sizes = useNaturalSizes(sizeRefs);\n const panels = useMemo(\n () => layoutSpatialPanels({ viewport, startWidth: sizes.start, endWidth: sizes.end, topHeight: sizes.top, bottomHeight: sizes.bottom }),\n [viewport, sizes.start, sizes.end, sizes.top, sizes.bottom],\n );\n const shown = useMemo(() => {\n const visible: Partial<Record<SpatialPanelId, SpatialPanelPlacement>> = { [SpatialPanelId.CENTRE]: panels[SpatialPanelId.CENTRE] };\n if (sizes.start > 0) visible[SpatialPanelId.START_COLUMN] = panels[SpatialPanelId.START_COLUMN];\n if (sizes.end > 0) visible[SpatialPanelId.END_COLUMN] = panels[SpatialPanelId.END_COLUMN];\n if (sizes.top > 0) visible[SpatialPanelId.TOP] = panels[SpatialPanelId.TOP];\n if (sizes.bottom > 0) visible[SpatialPanelId.BOTTOM] = panels[SpatialPanelId.BOTTOM];\n return visible;\n }, [panels, sizes.start, sizes.end, sizes.top, sizes.bottom]);\n\n useLayoutEffect(() => {\n store.set({ viewport, panels: shown, isDark });\n }, [store, viewport, shown, isDark]);\n\n const play = useCameraPlayer(cameraRef, store, prefersReducedMotion);\n useSpatialCues(play, sizes.start, sizes.start + sizes.end + sizes.top + sizes.bottom > 0, viewport);\n\n const panel = (id: SpatialPanelId, ref: React.Ref<HTMLDivElement> | null, size: 'fixed' | 'natural-width' | 'natural-height', content: React.ReactNode): React.JSX.Element => {\n const placement = panels[id];\n const style: React.CSSProperties = {\n position: 'absolute',\n left: 0,\n top: 0,\n transform: panelTransform(placement),\n transition: prefersReducedMotion ? undefined : PANEL_TRANSITION,\n backfaceVisibility: 'hidden',\n visibility: shown[id] ? 'visible' : 'hidden',\n ...(size !== 'natural-width' ? { width: placement.width } : {}),\n ...(size !== 'natural-height' ? { height: placement.height } : {}),\n ...GLASS_STYLE,\n };\n return (\n <div ref={ref ?? undefined} data-spatial-panel={id} className=\"flex overflow-hidden\" style={style}>\n {content}\n </div>\n );\n };\n\n return (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.SHELL} policyOverride={NON_CANONICAL_SHELL_SURFACE_POLICY_OVERRIDE}>\n <div className=\"relative h-screen w-screen overflow-hidden bg-background\" data-spatial-stage=\"\">\n <SpatialEnvironmentDoor store={store} />\n <div className=\"absolute inset-0\" style={{ perspective: `${SPATIAL_CAMERA_DISTANCE_PX}px`, perspectiveOrigin: '50% 50%' }}>\n <div\n ref={cameraRef}\n data-spatial-camera=\"\"\n style={{ position: 'absolute', left: '50%', top: '50%', width: 0, height: 0, transformStyle: 'preserve-3d', transform: cssCameraTransform(restPose()) }}\n >\n {panel(SpatialPanelId.START_COLUMN, startRef, 'natural-width', (\n <>\n <AppShellRegionOutlet region={ShellRegion.ACTIVITY_BAR} />\n <AppShellRegionOutlet region={ShellRegion.SIDEBAR} placement={HorizontalPlacement.START} />\n <AppShellRegionOutlet region={ShellRegion.UTILITY_PANEL} placement={HorizontalPlacement.START} />\n </>\n ))}\n {panel(SpatialPanelId.CENTRE, null, 'fixed', (\n <div className=\"flex-1 flex flex-col min-w-0 min-h-0\">\n <AppShellRegionOutlet region={ShellRegion.TOOLBAR} />\n <AppShellContentOutlet className=\"flex-1 relative min-w-0 min-h-0\">{children}</AppShellContentOutlet>\n </div>\n ))}\n {panel(SpatialPanelId.END_COLUMN, endRef, 'natural-width', (\n <>\n <AppShellRegionOutlet region={ShellRegion.SIDEBAR} placement={HorizontalPlacement.END} />\n <AppShellRegionOutlet region={ShellRegion.UTILITY_PANEL} placement={HorizontalPlacement.END} />\n </>\n ))}\n {panel(SpatialPanelId.TOP, topRef, 'natural-height', (\n <div className=\"flex-1 flex flex-col min-w-0\">\n <AppShellRegionOutlet region={ShellRegion.STATUS_BAR} placement={VerticalPlacement.TOP} />\n <AppShellRegionOutlet region={ShellRegion.MENUBAR} />\n </div>\n ))}\n {panel(SpatialPanelId.BOTTOM, bottomRef, 'natural-height', (\n <div className=\"flex-1 flex flex-col min-w-0\">\n <AppShellRegionOutlet region={ShellRegion.STATUS_BAR} placement={VerticalPlacement.BOTTOM} />\n </div>\n ))}\n </div>\n </div>\n <AppShellOverlaysOutlet />\n <AppShellOverlayPortalLayer />\n </div>\n </Surface>\n );\n}\n\n/**\n * The glass every panel is made of: a translucent card colour over a blurred backdrop, a hairline light edge and a\n * deep soft shadow. Colours come from the theme's tokens, so light and dark modes follow the theme.\n */\nconst GLASS_STYLE: React.CSSProperties = {\n borderRadius: 22,\n background: 'color-mix(in oklab, var(--card, var(--background)) 74%, transparent)',\n backdropFilter: 'blur(28px) saturate(1.3)',\n border: '1px solid color-mix(in oklab, var(--border) 55%, white 45%)',\n boxShadow: '0 40px 90px -30px rgb(15 23 42 / 0.35), 0 12px 30px -12px rgb(15 23 42 / 0.18), inset 0 1px 0 0 rgb(255 255 255 / 0.45)',\n};\n\nfunction useViewportSize(): { width: number; height: number } {\n const read = (): { width: number; height: number } => ({ width: window.innerWidth, height: window.innerHeight });\n const [size, setSize] = useState(read);\n useEffect(() => {\n const onResize = (): void => setSize(read());\n window.addEventListener('resize', onResize);\n return () => window.removeEventListener('resize', onResize);\n }, []);\n return size;\n}\n\n/**\n * The natural (untransformed) sizes of the panels whose size comes from their content: the side columns' widths and\n * the strips' heights. `offsetWidth`/`offsetHeight` ignore transforms, so a turned column reads its real width.\n */\nfunction useNaturalSizes(refs: Record<'start' | 'end' | 'top' | 'bottom', React.RefObject<HTMLDivElement | null>>): Record<'start' | 'end' | 'top' | 'bottom', number> {\n const [sizes, setSizes] = useState({ start: 0, end: 0, top: 0, bottom: 0 });\n useLayoutEffect(() => {\n const measure = (): void => {\n const width = (ref: React.RefObject<HTMLDivElement | null>): number => (ref.current && ref.current.childElementCount > 0 ? ref.current.offsetWidth : 0);\n const height = (ref: React.RefObject<HTMLDivElement | null>): number => (ref.current && hasRenderedRegion(ref.current) ? ref.current.offsetHeight : 0);\n const next = { start: width(refs.start), end: width(refs.end), top: height(refs.top), bottom: height(refs.bottom) };\n setSizes((previous) => (previous.start === next.start && previous.end === next.end && previous.top === next.top && previous.bottom === next.bottom ? previous : next));\n };\n measure();\n const observer = new ResizeObserver(measure);\n for (const ref of Object.values(refs)) if (ref.current) observer.observe(ref.current);\n const mutations = new MutationObserver(measure);\n for (const ref of Object.values(refs)) if (ref.current) mutations.observe(ref.current, { childList: true, subtree: true });\n return () => {\n observer.disconnect();\n mutations.disconnect();\n };\n }, [refs]);\n return sizes;\n}\n\nfunction hasRenderedRegion(element: HTMLElement): boolean {\n return element.querySelector('[data-component-area]') !== null;\n}\n\n/**\n * Plays camera moves on the camera element (the stage's OWN element, so writing its inline transform touches nothing\n * React renders) and publishes every pose to the store for the environment. Under reduced motion every move is a cut\n * to its final pose. Returns `play(move)`; a new move replaces the one in progress, starting from where it stands.\n */\nfunction useCameraPlayer(cameraRef: React.RefObject<HTMLDivElement | null>, store: SpatialStageStore, reduced: boolean): (move: SpatialCameraMove) => void {\n const frame = useRef(0);\n useEffect(() => () => cancelAnimationFrame(frame.current), []);\n return useMemo(() => {\n const apply = (pose: ReturnType<typeof restPose>): void => {\n if (cameraRef.current) cameraRef.current.style.transform = cssCameraTransform(pose);\n store.set({ pose });\n };\n return (move: SpatialCameraMove): void => {\n cancelAnimationFrame(frame.current);\n if (reduced) {\n apply(move.keyframes[move.keyframes.length - 1]!.pose);\n return;\n }\n // Start from where the camera stands, so an interrupted move blends instead of jumping.\n const from = store.get().pose;\n const blended: SpatialCameraMove = { ...move, keyframes: [{ at: 0, pose: from }, ...move.keyframes.filter((keyframe) => keyframe.at > 0)] };\n const start = performance.now();\n const tick = (): void => {\n const elapsed = performance.now() - start;\n apply(sampleMove(blended, elapsed));\n if (elapsed < blended.durationMs) frame.current = requestAnimationFrame(tick);\n };\n frame.current = requestAnimationFrame(tick);\n };\n }, [cameraRef, store, reduced]);\n}\n\n/**\n * What moves the camera: the shell arriving, the content changing (a structural zone's top entry is another place,\n * by URL path — the same signature the flat frame uses), focus moving between side-by-side panes, and the start\n * column resizing (the sidebar collapsing or expanding).\n */\nfunction useSpatialCues(play: (move: SpatialCameraMove) => void, startWidth: number, measured: boolean, viewport: { width: number; height: number }): void {\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 signature = places.some((place) => place !== '') ? zones.map((zone, index) => `${zone}:${places[index]}`).join('|') : '';\n\n const arrived = useRef(false);\n useEffect(() => {\n if (arrived.current || !measured) return;\n arrived.current = true;\n play(cameraMoveFor(SpatialCameraCue.ARRIVAL));\n }, [play, measured]);\n\n const lastSignature = useRef<string | null>(null);\n useEffect(() => {\n if (signature === '') return;\n const previous = lastSignature.current;\n lastSignature.current = signature;\n if (previous !== null && previous !== signature) play(cameraMoveFor(SpatialCameraCue.NAVIGATION));\n }, [play, signature]);\n\n const lastFocus = useRef<string | null>(null);\n useEffect(() => {\n const zone = navigation.focusedZone ?? null;\n const previous = lastFocus.current;\n lastFocus.current = zone;\n if (previous === null || zone === null || previous === zone) return;\n const panes = [...document.querySelectorAll<HTMLElement>(`[data-component-area=\"${ShellRegion.CONTENT}\"] [data-content-area]`)].filter((pane) => pane.offsetWidth > 0);\n const focused = panes.find((pane) => pane.dataset.contentArea === zone);\n if (panes.length < 2 || !focused) return;\n const rect = focused.getBoundingClientRect();\n play(cameraMoveFor(SpatialCameraCue.ZONE_FOCUS, SPATIAL_CAMERA_DISTANCE_PX, rect.left + rect.width / 2 - viewport.width / 2));\n }, [play, navigation.focusedZone, viewport.width]);\n\n // A collapse animates the width over many frames: cue once per settled change, not once per frame.\n const settledStart = useRef(0);\n const lastResizeCue = useRef(0);\n useEffect(() => {\n if (startWidth === 0) return;\n const previous = settledStart.current;\n if (previous === 0) {\n settledStart.current = startWidth;\n return;\n }\n if (Math.abs(previous - startWidth) <= 24) return;\n settledStart.current = startWidth;\n const now = performance.now();\n if (now - lastResizeCue.current < 900) return;\n lastResizeCue.current = now;\n play(cameraMoveFor(SpatialCameraCue.COLUMN_RESIZE));\n }, [play, startWidth]);\n}\n"]}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { type SpatialCameraPose, type SpatialPanelId, type SpatialPanelPlacement } from './spatial-camera';
|
|
2
|
-
/** What the WebGL environment needs to draw the same world the HTML stage shows. */
|
|
3
|
-
export interface SpatialStageSnapshot {
|
|
4
|
-
pose: SpatialCameraPose;
|
|
5
|
-
distance: number;
|
|
6
|
-
viewport: {
|
|
7
|
-
width: number;
|
|
8
|
-
height: number;
|
|
9
|
-
};
|
|
10
|
-
/** Only the panels that show something (a column with no region is absent). */
|
|
11
|
-
panels: Partial<Record<SpatialPanelId, SpatialPanelPlacement>>;
|
|
12
|
-
isDark: boolean;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* The one piece of state the HTML stage and the WebGL environment share (PROTOTYPE). The stage WRITES it — the camera
|
|
16
|
-
* player on every frame of a move, the layout when a panel is re-arranged — and the environment, in its lazily loaded
|
|
17
|
-
* chunk, SUBSCRIBES and renders. A plain store rather than React state, so a camera frame re-renders no component.
|
|
18
|
-
*/
|
|
19
|
-
export declare class SpatialStageStore {
|
|
20
|
-
private snapshot;
|
|
21
|
-
private readonly listeners;
|
|
22
|
-
constructor(initial?: Partial<SpatialStageSnapshot>);
|
|
23
|
-
get(): SpatialStageSnapshot;
|
|
24
|
-
set(change: Partial<SpatialStageSnapshot>): void;
|
|
25
|
-
subscribe(listener: (snapshot: SpatialStageSnapshot) => void): () => void;
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=spatial-stage-store.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spatial-stage-store.d.ts","sourceRoot":"","sources":["../../../../src/spatial/spatial-stage-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwC,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEjJ,oFAAoF;AACpF,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,+EAA+E;IAC/E,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAC,CAAC;IAC/D,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuD;gBAErE,OAAO,GAAE,OAAO,CAAC,oBAAoB,CAAM;IAWvD,GAAG,IAAI,oBAAoB;IAI3B,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,IAAI;IAKhD,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI;CAI1E"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { restPose, SPATIAL_CAMERA_DISTANCE_PX } from './spatial-camera.js';
|
|
2
|
-
/**
|
|
3
|
-
* The one piece of state the HTML stage and the WebGL environment share (PROTOTYPE). The stage WRITES it — the camera
|
|
4
|
-
* player on every frame of a move, the layout when a panel is re-arranged — and the environment, in its lazily loaded
|
|
5
|
-
* chunk, SUBSCRIBES and renders. A plain store rather than React state, so a camera frame re-renders no component.
|
|
6
|
-
*/
|
|
7
|
-
export class SpatialStageStore {
|
|
8
|
-
snapshot;
|
|
9
|
-
listeners = new Set();
|
|
10
|
-
constructor(initial = {}) {
|
|
11
|
-
this.snapshot = {
|
|
12
|
-
pose: restPose(),
|
|
13
|
-
distance: SPATIAL_CAMERA_DISTANCE_PX,
|
|
14
|
-
viewport: { width: 1440, height: 900 },
|
|
15
|
-
panels: {},
|
|
16
|
-
isDark: false,
|
|
17
|
-
...initial,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
get() {
|
|
21
|
-
return this.snapshot;
|
|
22
|
-
}
|
|
23
|
-
set(change) {
|
|
24
|
-
this.snapshot = { ...this.snapshot, ...change };
|
|
25
|
-
for (const listener of this.listeners)
|
|
26
|
-
listener(this.snapshot);
|
|
27
|
-
}
|
|
28
|
-
subscribe(listener) {
|
|
29
|
-
this.listeners.add(listener);
|
|
30
|
-
return () => this.listeners.delete(listener);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=spatial-stage-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spatial-stage-store.js","sourceRoot":"","sources":["../../../../src/spatial/spatial-stage-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,0BAA0B,EAA2E,MAAM,kBAAkB,CAAC;AAYjJ;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IACpB,QAAQ,CAAuB;IACtB,SAAS,GAAG,IAAI,GAAG,EAA4C,CAAC;IAEjF,YAAY,UAAyC,EAAE;QACrD,IAAI,CAAC,QAAQ,GAAG;YACd,IAAI,EAAE,QAAQ,EAAE;YAChB,QAAQ,EAAE,0BAA0B;YACpC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;YACtC,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,KAAK;YACb,GAAG,OAAO;SACX,CAAC;IACJ,CAAC;IAED,GAAG;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,GAAG,CAAC,MAAqC;QACvC,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;QAChD,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjE,CAAC;IAED,SAAS,CAAC,QAAkD;QAC1D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;CACF","sourcesContent":["import { restPose, SPATIAL_CAMERA_DISTANCE_PX, type SpatialCameraPose, type SpatialPanelId, type SpatialPanelPlacement } from './spatial-camera';\n\n/** What the WebGL environment needs to draw the same world the HTML stage shows. */\nexport interface SpatialStageSnapshot {\n pose: SpatialCameraPose;\n distance: number;\n viewport: { width: number; height: number };\n /** Only the panels that show something (a column with no region is absent). */\n panels: Partial<Record<SpatialPanelId, SpatialPanelPlacement>>;\n isDark: boolean;\n}\n\n/**\n * The one piece of state the HTML stage and the WebGL environment share (PROTOTYPE). The stage WRITES it — the camera\n * player on every frame of a move, the layout when a panel is re-arranged — and the environment, in its lazily loaded\n * chunk, SUBSCRIBES and renders. A plain store rather than React state, so a camera frame re-renders no component.\n */\nexport class SpatialStageStore {\n private snapshot: SpatialStageSnapshot;\n private readonly listeners = new Set<(snapshot: SpatialStageSnapshot) => void>();\n\n constructor(initial: Partial<SpatialStageSnapshot> = {}) {\n this.snapshot = {\n pose: restPose(),\n distance: SPATIAL_CAMERA_DISTANCE_PX,\n viewport: { width: 1440, height: 900 },\n panels: {},\n isDark: false,\n ...initial,\n };\n }\n\n get(): SpatialStageSnapshot {\n return this.snapshot;\n }\n\n set(change: Partial<SpatialStageSnapshot>): void {\n this.snapshot = { ...this.snapshot, ...change };\n for (const listener of this.listeners) listener(this.snapshot);\n }\n\n subscribe(listener: (snapshot: SpatialStageSnapshot) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n}\n"]}
|