@wildo-ai/presets-components-3d 1.1.7 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/esm/focal-plane/focal-plane-settings.d.ts.map +1 -1
  2. package/dist/esm/focal-plane/focal-plane-settings.js.map +1 -1
  3. package/dist/esm/focal-plane/focal-plane-shell-container.d.ts.map +1 -1
  4. package/dist/esm/focal-plane/focal-plane-shell-container.js.map +1 -1
  5. package/dist/esm/focal-plane/focal-plane-stylesheet.d.ts.map +1 -1
  6. package/dist/esm/focal-plane/focal-plane-stylesheet.js.map +1 -1
  7. package/dist/esm/focal-plane/use-pane-depth.d.ts.map +1 -1
  8. package/dist/esm/focal-plane/use-pane-depth.js.map +1 -1
  9. package/dist/esm/focal-plane/use-shared-vanishing-point.d.ts.map +1 -1
  10. package/dist/esm/focal-plane/use-shared-vanishing-point.js.map +1 -1
  11. package/dist/esm/frame/frame-3d-style.d.ts.map +1 -1
  12. package/dist/esm/frame/frame-3d-style.js.map +1 -1
  13. package/dist/esm/frame/frame-appearance.d.ts.map +1 -1
  14. package/dist/esm/frame/frame-appearance.js.map +1 -1
  15. package/dist/esm/frame/frame-canvas.d.ts.map +1 -1
  16. package/dist/esm/frame/frame-canvas.js.map +1 -1
  17. package/dist/esm/frame/frame-canvas.lazy.d.ts.map +1 -1
  18. package/dist/esm/frame/frame-canvas.lazy.js.map +1 -1
  19. package/dist/esm/frame/frame-color.d.ts.map +1 -1
  20. package/dist/esm/frame/frame-color.js.map +1 -1
  21. package/dist/esm/frame/frame-driver.d.ts.map +1 -1
  22. package/dist/esm/frame/frame-driver.js.map +1 -1
  23. package/dist/esm/frame/frame-renderer.d.ts.map +1 -1
  24. package/dist/esm/frame/frame-renderer.js.map +1 -1
  25. package/dist/esm/frame/frame-shaders.d.ts.map +1 -1
  26. package/dist/esm/frame/frame-shaders.js.map +1 -1
  27. package/dist/esm/frame/use-frame-appearance.d.ts.map +1 -1
  28. package/dist/esm/frame/use-frame-appearance.js.map +1 -1
  29. package/dist/esm/index.d.ts.map +1 -1
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/layout/header-first-shell-container.d.ts.map +1 -1
  32. package/dist/esm/layout/header-first-shell-container.js.map +1 -1
  33. package/dist/esm/layout/layout-3d-definition.d.ts.map +1 -1
  34. package/dist/esm/layout/layout-3d-definition.js.map +1 -1
  35. package/dist/esm/layout/layout-3d-transition-choreography.d.ts.map +1 -1
  36. package/dist/esm/layout/layout-3d-transition-choreography.js.map +1 -1
  37. package/dist/esm/layout/layout-3d-vocabulary.d.ts.map +1 -1
  38. package/dist/esm/layout/layout-3d-vocabulary.js.map +1 -1
  39. package/dist/esm/layout/shell-layout-placement.d.ts.map +1 -1
  40. package/dist/esm/layout/shell-layout-placement.js.map +1 -1
  41. package/dist/esm/layout-3d-main-container.d.ts.map +1 -1
  42. package/dist/esm/layout-3d-main-container.js.map +1 -1
  43. package/dist/esm/register-3d-layout.d.ts.map +1 -1
  44. package/dist/esm/register-3d-layout.js.map +1 -1
  45. package/dist/esm/shell-region-measurement.d.ts.map +1 -1
  46. package/dist/esm/shell-region-measurement.js.map +1 -1
  47. package/dist/esm/tokens/design-token-resolution.d.ts.map +1 -1
  48. package/dist/esm/tokens/design-token-resolution.js.map +1 -1
  49. package/dist/esm/tokens/use-design-token-resolution.d.ts.map +1 -1
  50. package/dist/esm/tokens/use-design-token-resolution.js.map +1 -1
  51. package/dist/tsconfig.build.tsbuildinfo +1 -1
  52. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"focal-plane-settings.d.ts","sourceRoot":"","sources":["../../../src/focal-plane/focal-plane-settings.ts"],"names":[],"mappings":"AAEA,wIAAwI;AACxI;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,yHAAyH;IACzH,gBAAgB,EAAE,MAAM,CAAC;IACzB,wGAAwG;IACxG,YAAY,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,YAAY,EAAE,MAAM,CAAC;IACrB,sGAAsG;IACtG,WAAW,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,aAAa,EAAE,MAAM,CAAC;IACtB,sFAAsF;IACtF,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,oBAAoB,EAAE,kBASlC,CAAC;AAeF;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAAG,kBAAkB,CAmBzG;AAED,4GAA4G;AAC5G,eAAO,MAAM,yBAAyB,6CAA0D,CAAC;AAEjG,wBAAgB,qBAAqB,IAAI,kBAAkB,CAE1D;AAED,qHAAqH;AACrH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,aAAa,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYnH"}
1
+ {"version":3,"file":"focal-plane-settings.d.ts","sourceRoot":"","sources":["../../../../src/focal-plane/focal-plane-settings.ts"],"names":[],"mappings":"AAEA,wIAAwI;AACxI;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,yHAAyH;IACzH,gBAAgB,EAAE,MAAM,CAAC;IACzB,wGAAwG;IACxG,YAAY,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,YAAY,EAAE,MAAM,CAAC;IACrB,sGAAsG;IACtG,WAAW,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,aAAa,EAAE,MAAM,CAAC;IACtB,sFAAsF;IACtF,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,oBAAoB,EAAE,kBASlC,CAAC;AAeF;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAAG,kBAAkB,CAmBzG;AAED,4GAA4G;AAC5G,eAAO,MAAM,yBAAyB,6CAA0D,CAAC;AAEjG,wBAAgB,qBAAqB,IAAI,kBAAkB,CAE1D;AAED,qHAAqH;AACrH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,aAAa,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYnH"}
@@ -1 +1 @@
1
- {"version":3,"file":"focal-plane-settings.js","sourceRoot":"","sources":["../../../src/focal-plane/focal-plane-settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { createContext, useContext } from 'react';\n\n/** @wildo_source:part:start presets.3d.focal-plane-settings facet:layer:frontend facet:family:layout-3d facet:audience:app-developer */\n/**\n * The focal plane's numbers (#2049). The defaults are the values Paul settled on in the prototype on 2026-09-30.\n * They reach the stylesheet as CSS custom properties on the layout's root, so every object reads one source.\n */\nexport interface FocalPlaneSettings {\n /** The still camera's distance from the focal plane, in CSS pixels: the `perspective()` every object is seen through. */\n cameraDistancePx: number;\n /** How far back one layer steps, in CSS pixels. A pane behind the focused one steps back part of it. */\n layerDepthPx: number;\n /** How long an object takes to travel, in milliseconds. */\n motionMs: number;\n /** How much a receding object dims per layer, 0-1. */\n recedeDim: number;\n /** How much a receding PANE blurs per layer, in CSS pixels (navigation; 0 keeps panes sharp). */\n recedeBlurPx: number;\n /** How much everything blurs behind a MODAL popup (dialog, sheet, command palette), in CSS pixels. */\n modalBlurPx: number;\n /** How opaque a glass window is, 0-1: the rest is the background blurred through it. */\n windowOpacity: number;\n /** How far a shell panel rises toward the camera under the pointer, in CSS pixels. */\n hoverLiftPx: number;\n}\n\nexport const FOCAL_PLANE_DEFAULTS: FocalPlaneSettings = {\n cameraDistancePx: 1000,\n layerDepthPx: 240,\n motionMs: 580,\n recedeDim: 0.18,\n recedeBlurPx: 0,\n modalBlurPx: 2.5,\n windowOpacity: 0.56,\n hoverLiftPx: 16,\n};\n/** @wildo_source:part:end presets.3d.focal-plane-settings */\n\n/** The range each setting accepts: outside it the layout would draw nonsense (a camera behind the plane, a negative dim). */\nconst SETTING_RANGES: Record<keyof FocalPlaneSettings, readonly [number, number]> = {\n cameraDistancePx: [200, 10000],\n layerDepthPx: [0, 2000],\n motionMs: [0, 5000],\n recedeDim: [0, 0.9],\n recedeBlurPx: [0, 20],\n modalBlurPx: [0, 20],\n windowOpacity: [0.05, 1],\n hoverLiftPx: [0, 200],\n};\n\n/**\n * The application's overrides over the defaults, checked: an unknown key or a value outside its range is refused at\n * registration, naming the setting, rather than drawn as something the application did not mean.\n */\nexport function resolveFocalPlaneSettings(overrides: Partial<FocalPlaneSettings> = {}): FocalPlaneSettings {\n const resolved: FocalPlaneSettings = { ...FOCAL_PLANE_DEFAULTS };\n for (const [key, value] of Object.entries(overrides)) {\n if (!(key in SETTING_RANGES)) throw new Error(`register3DLayout(): the focal plane has no setting '${key}'.`);\n const [min, max] = SETTING_RANGES[key as keyof FocalPlaneSettings];\n if (typeof value !== 'number' || !Number.isFinite(value) || value < min || value > max) {\n throw new Error(`register3DLayout(): focalPlane.${key} must be a number from ${min} to ${max}; got ${String(value)}.`);\n }\n resolved[key as keyof FocalPlaneSettings] = value;\n }\n // Each value alone can be in range and the combination still put an object at or behind the camera: the nearest any\n // object comes is a sheet arriving at 0.9 of a layer in front of the plane, and a hovered panel at its lift.\n if (resolved.layerDepthPx * 0.9 >= resolved.cameraDistancePx * 0.8) {\n throw new Error(`register3DLayout(): focalPlane.layerDepthPx (${resolved.layerDepthPx}) is too deep for a camera ${resolved.cameraDistancePx}px away: a popup arriving from in front would reach the camera. Keep it under ${Math.floor((resolved.cameraDistancePx * 0.8) / 0.9)}.`);\n }\n if (resolved.hoverLiftPx >= resolved.cameraDistancePx * 0.5) {\n throw new Error(`register3DLayout(): focalPlane.hoverLiftPx (${resolved.hoverLiftPx}) must stay under half the camera distance (${resolved.cameraDistancePx * 0.5}).`);\n }\n return resolved;\n}\n\n/** The resolved settings, provided by the 3D main container to its placement. Outside one, the defaults. */\nexport const FocalPlaneSettingsContext = createContext<FocalPlaneSettings>(FOCAL_PLANE_DEFAULTS);\n\nexport function useFocalPlaneSettings(): FocalPlaneSettings {\n return useContext(FocalPlaneSettingsContext);\n}\n\n/** The settings as the custom properties the focal-plane stylesheet reads. Reduced motion zeroes the travel time. */\nexport function focalPlaneCssVariables(settings: FocalPlaneSettings, reducedMotion: boolean): Record<string, string> {\n return {\n '--fp-distance': `${settings.cameraDistancePx}px`,\n '--fp-step': `${settings.layerDepthPx}px`,\n '--fp-motion': `${reducedMotion ? 0 : settings.motionMs}ms`,\n '--fp-dim': String(settings.recedeDim),\n '--fp-recede-blur': `${settings.recedeBlurPx}px`,\n '--fp-modal-blur': `${settings.modalBlurPx}px`,\n '--fp-glass': `${Math.round(settings.windowOpacity * 100)}%`,\n '--fp-hover-lift': `${settings.hoverLiftPx}px`,\n '--fp-ease': 'cubic-bezier(0.2, 0.9, 0.25, 1)',\n };\n}\n"]}
1
+ {"version":3,"file":"focal-plane-settings.js","sourceRoot":"","sources":["../../../../src/focal-plane/focal-plane-settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { createContext, useContext } from 'react';\n\n/** @wildo_source:part:start presets.3d.focal-plane-settings facet:layer:frontend facet:family:layout-3d facet:audience:app-developer */\n/**\n * The focal plane's numbers (#2049). The defaults are the values Paul settled on in the prototype on 2026-09-30.\n * They reach the stylesheet as CSS custom properties on the layout's root, so every object reads one source.\n */\nexport interface FocalPlaneSettings {\n /** The still camera's distance from the focal plane, in CSS pixels: the `perspective()` every object is seen through. */\n cameraDistancePx: number;\n /** How far back one layer steps, in CSS pixels. A pane behind the focused one steps back part of it. */\n layerDepthPx: number;\n /** How long an object takes to travel, in milliseconds. */\n motionMs: number;\n /** How much a receding object dims per layer, 0-1. */\n recedeDim: number;\n /** How much a receding PANE blurs per layer, in CSS pixels (navigation; 0 keeps panes sharp). */\n recedeBlurPx: number;\n /** How much everything blurs behind a MODAL popup (dialog, sheet, command palette), in CSS pixels. */\n modalBlurPx: number;\n /** How opaque a glass window is, 0-1: the rest is the background blurred through it. */\n windowOpacity: number;\n /** How far a shell panel rises toward the camera under the pointer, in CSS pixels. */\n hoverLiftPx: number;\n}\n\nexport const FOCAL_PLANE_DEFAULTS: FocalPlaneSettings = {\n cameraDistancePx: 1000,\n layerDepthPx: 240,\n motionMs: 580,\n recedeDim: 0.18,\n recedeBlurPx: 0,\n modalBlurPx: 2.5,\n windowOpacity: 0.56,\n hoverLiftPx: 16,\n};\n/** @wildo_source:part:end presets.3d.focal-plane-settings */\n\n/** The range each setting accepts: outside it the layout would draw nonsense (a camera behind the plane, a negative dim). */\nconst SETTING_RANGES: Record<keyof FocalPlaneSettings, readonly [number, number]> = {\n cameraDistancePx: [200, 10000],\n layerDepthPx: [0, 2000],\n motionMs: [0, 5000],\n recedeDim: [0, 0.9],\n recedeBlurPx: [0, 20],\n modalBlurPx: [0, 20],\n windowOpacity: [0.05, 1],\n hoverLiftPx: [0, 200],\n};\n\n/**\n * The application's overrides over the defaults, checked: an unknown key or a value outside its range is refused at\n * registration, naming the setting, rather than drawn as something the application did not mean.\n */\nexport function resolveFocalPlaneSettings(overrides: Partial<FocalPlaneSettings> = {}): FocalPlaneSettings {\n const resolved: FocalPlaneSettings = { ...FOCAL_PLANE_DEFAULTS };\n for (const [key, value] of Object.entries(overrides)) {\n if (!(key in SETTING_RANGES)) throw new Error(`register3DLayout(): the focal plane has no setting '${key}'.`);\n const [min, max] = SETTING_RANGES[key as keyof FocalPlaneSettings];\n if (typeof value !== 'number' || !Number.isFinite(value) || value < min || value > max) {\n throw new Error(`register3DLayout(): focalPlane.${key} must be a number from ${min} to ${max}; got ${String(value)}.`);\n }\n resolved[key as keyof FocalPlaneSettings] = value;\n }\n // Each value alone can be in range and the combination still put an object at or behind the camera: the nearest any\n // object comes is a sheet arriving at 0.9 of a layer in front of the plane, and a hovered panel at its lift.\n if (resolved.layerDepthPx * 0.9 >= resolved.cameraDistancePx * 0.8) {\n throw new Error(`register3DLayout(): focalPlane.layerDepthPx (${resolved.layerDepthPx}) is too deep for a camera ${resolved.cameraDistancePx}px away: a popup arriving from in front would reach the camera. Keep it under ${Math.floor((resolved.cameraDistancePx * 0.8) / 0.9)}.`);\n }\n if (resolved.hoverLiftPx >= resolved.cameraDistancePx * 0.5) {\n throw new Error(`register3DLayout(): focalPlane.hoverLiftPx (${resolved.hoverLiftPx}) must stay under half the camera distance (${resolved.cameraDistancePx * 0.5}).`);\n }\n return resolved;\n}\n\n/** The resolved settings, provided by the 3D main container to its placement. Outside one, the defaults. */\nexport const FocalPlaneSettingsContext = createContext<FocalPlaneSettings>(FOCAL_PLANE_DEFAULTS);\n\nexport function useFocalPlaneSettings(): FocalPlaneSettings {\n return useContext(FocalPlaneSettingsContext);\n}\n\n/** The settings as the custom properties the focal-plane stylesheet reads. Reduced motion zeroes the travel time. */\nexport function focalPlaneCssVariables(settings: FocalPlaneSettings, reducedMotion: boolean): Record<string, string> {\n return {\n '--fp-distance': `${settings.cameraDistancePx}px`,\n '--fp-step': `${settings.layerDepthPx}px`,\n '--fp-motion': `${reducedMotion ? 0 : settings.motionMs}ms`,\n '--fp-dim': String(settings.recedeDim),\n '--fp-recede-blur': `${settings.recedeBlurPx}px`,\n '--fp-modal-blur': `${settings.modalBlurPx}px`,\n '--fp-glass': `${Math.round(settings.windowOpacity * 100)}%`,\n '--fp-hover-lift': `${settings.hoverLiftPx}px`,\n '--fp-ease': 'cubic-bezier(0.2, 0.9, 0.25, 1)',\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"focal-plane-shell-container.d.ts","sourceRoot":"","sources":["../../../src/focal-plane/focal-plane-shell-container.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuD,MAAM,OAAO,CAAC;AAG5E,OAAO,EAcL,KAAK,0CAA0C,EAChD,MAAM,6BAA6B,CAAC;AAOrC;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,QAAQ,EAAE,EAAE,0CAA0C,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CASpH"}
1
+ {"version":3,"file":"focal-plane-shell-container.d.ts","sourceRoot":"","sources":["../../../../src/focal-plane/focal-plane-shell-container.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuD,MAAM,OAAO,CAAC;AAG5E,OAAO,EAcL,KAAK,0CAA0C,EAChD,MAAM,6BAA6B,CAAC;AAOrC;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,QAAQ,EAAE,EAAE,0CAA0C,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CASpH"}
@@ -1 +1 @@
1
- {"version":3,"file":"focal-plane-shell-container.js","sourceRoot":"","sources":["../../../src/focal-plane/focal-plane-shell-container.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useLayoutEffect, 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 NavigationZone,\n useNavigationState,\n useUI,\n type AppLayoutPreset_MainContainer_DefaultProps,\n} from '@wildo-ai/saas-frontend-lib';\n\nimport { focalPlaneCssVariables, useFocalPlaneSettings, type FocalPlaneSettings } from './focal-plane-settings';\nimport { installFocalPlaneStylesheet } from './focal-plane-stylesheet';\nimport { usePaneDepth } from './use-pane-depth';\nimport { useSharedVanishingPoint } from './use-shared-vanishing-point';\n\n/**\n * The focal plane's placement (#2049). The regions are the application's own, rendered by the standard outlets with\n * every context; this container arranges them as floating glass windows over an ambient background, and marks each\n * as an object the still camera sees in depth. The navigation panes inside the content region are objects too, found\n * by the engine's own markers (see `focal-plane-stylesheet.ts`).\n *\n * Overlays render in `AppShellOverlayPortalLayer`, outside every transformed object: a dialog inside a transformed pane\n * would be confined to it, and a menu placed in the wrong coordinates.\n */\nexport function FocalPlaneShellContainer({ 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 <FocalPlaneStage>{children}</FocalPlaneStage>\n </AppShellProviders>\n );\n}\n\nfunction FocalPlaneStage({ children }: { children: React.ReactNode }): React.JSX.Element {\n const { prefersReducedMotion } = useUI();\n const rootRef = useRef<HTMLDivElement>(null);\n const settings = useFocalPlaneSettings();\n const navigation = useNavigationState();\n useLayoutEffect(() => installFocalPlaneStylesheet(), []);\n useSharedVanishingPoint(rootRef);\n const { dip } = usePaneDepth(rootRef, settings, prefersReducedMotion);\n const front = useFrontPane(rootRef, navigation.focusedZone);\n useColumnDip(rootRef, settings, prefersReducedMotion);\n usePlaceChanges(navigation, (zone, how) => {\n if (how === PlaceChange.CHANGED) dip(zone);\n front.bringForward(zone);\n });\n const shell = (content: React.ReactNode): React.JSX.Element => <div data-fp-object=\"shell\">{content}</div>;\n\n return (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.SHELL} policyOverride={NON_CANONICAL_SHELL_SURFACE_POLICY_OVERRIDE}>\n <div\n ref={rootRef}\n data-focal-plane=\"\"\n data-fp-focus={front.zone}\n style={focalPlaneCssVariables(settings, prefersReducedMotion) as React.CSSProperties}\n >\n <div className=\"fp-ghosts\" aria-hidden=\"true\" />\n <div className=\"fp-backdrop\" aria-hidden=\"true\">\n <i className=\"fp-a\" />\n <i className=\"fp-b\" />\n <i className=\"fp-c\" />\n </div>\n <div className=\"fp-grid\">\n {shell(<AppShellRegionOutlet region={ShellRegion.STATUS_BAR} placement={VerticalPlacement.TOP} />)}\n {shell(<AppShellRegionOutlet region={ShellRegion.MENUBAR} />)}\n <div className=\"fp-row fp-middle\">\n {shell(<AppShellRegionOutlet region={ShellRegion.ACTIVITY_BAR} />)}\n {shell(<AppShellRegionOutlet region={ShellRegion.SIDEBAR} placement={HorizontalPlacement.START} />)}\n {shell(<AppShellRegionOutlet region={ShellRegion.UTILITY_PANEL} placement={HorizontalPlacement.START} />)}\n <div className=\"fp-column\">\n {shell(<AppShellRegionOutlet region={ShellRegion.TOOLBAR} />)}\n <div className=\"fp-content\">\n <AppShellContentOutlet className=\"flex-1 relative min-w-0 min-h-0\">{children}</AppShellContentOutlet>\n </div>\n </div>\n {shell(<AppShellRegionOutlet region={ShellRegion.UTILITY_PANEL} placement={HorizontalPlacement.END} />)}\n {shell(<AppShellRegionOutlet region={ShellRegion.SIDEBAR} placement={HorizontalPlacement.END} />)}\n </div>\n {shell(<AppShellRegionOutlet region={ShellRegion.STATUS_BAR} placement={VerticalPlacement.BOTTOM} />)}\n </div>\n <div className=\"fp-ghosts fp-ghosts-front\" aria-hidden=\"true\" />\n <AppShellOverlaysOutlet />\n <AppShellOverlayPortalLayer />\n </div>\n </Surface>\n );\n}\n\n/**\n * Which pane is in front: the one you last pressed in or moved keyboard focus into, or the one that last opened or\n * changed place. Kept by the layout rather than read from the navigation state's `focusedZone` alone, because that\n * follows only interaction: opening a record beside the list leaves the LIST focused (the click happened there), and\n * the prototype this layout follows brings the new pane forward. The engine's focus state is never written.\n */\nfunction useFrontPane(rootRef: React.RefObject<HTMLElement | null>, focusedZone: string): { zone: string; bringForward: (zone: string) => void } {\n const [zone, setZone] = useState<string>(focusedZone);\n useEffect(() => setZone(focusedZone), [focusedZone]);\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return undefined;\n const fromEvent = (event: Event): void => {\n const target = event.target instanceof Element ? event.target : null;\n const pane = target?.closest<HTMLElement>(`[data-component-area=\"${ShellRegion.CONTENT}\"] :is([data-content-area], [data-panel-id^=\"nav-\"])`);\n const name = pane?.dataset.contentArea ?? pane?.dataset.panelId?.replace(/^nav-/, '');\n if (name) setZone(name);\n };\n root.addEventListener('pointerdown', fromEvent, true);\n root.addEventListener('focusin', fromEvent, true);\n return () => {\n root.removeEventListener('pointerdown', fromEvent, true);\n root.removeEventListener('focusin', fromEvent, true);\n };\n }, [rootRef]);\n return { zone, bringForward: setZone };\n}\n\nconst STRUCTURAL_ZONES: ReadonlySet<string> = new Set([NavigationZone.PRIMARY, NavigationZone.SECONDARY, NavigationZone.COMPANION]);\n\n/** How a navigation zone's place moved between two renders. */\nenum PlaceChange {\n /** The zone held nothing and now holds a place: a pane opened. */\n APPEARED = 'appeared',\n /** The zone showed one place and now shows another, in the same pane. */\n CHANGED = 'changed',\n}\n\n/**\n * A zone that APPEARS (it held nothing, now it holds a place) or CHANGES place (the same zone now shows another URL\n * path) is reported: a change dips back and returns, and either way the pane comes forward. The arrival itself is the\n * stylesheet's (a side pane arrives from depth when it mounts).\n */\nfunction usePlaceChanges(navigation: ReturnType<typeof useNavigationState>, onPlace: (zone: string, how: PlaceChange) => void): void {\n // The structural zones only: the overlay zone is a dialog, not a pane, and must never become the \"front pane\".\n const zones = (Object.keys(navigation.state.zones) as Array<keyof typeof navigation.state.zones>).filter((zone) => STRUCTURAL_ZONES.has(String(zone)));\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 = zones.map((zone, index) => `${String(zone)}:${places[index]}`).join('|');\n const previous = useRef<Map<string, string> | null>(null);\n useEffect(() => {\n const current = new Map(zones.map((zone, index) => [String(zone), places[index] ?? '']));\n const before = previous.current;\n previous.current = current;\n if (!before) return;\n for (const [zone, place] of current) {\n const was = before.get(zone) ?? '';\n if (place === '' || was === place) continue;\n onPlace(zone, was === '' ? PlaceChange.APPEARED : PlaceChange.CHANGED);\n }\n // `signature` is the whole dependency: the zones and places are derived from the same render.\n }, [signature]);\n}\n\n/**\n * A side column (the sidebar folding to its rail or unfolding) dips back and returns while the panes re-arrange. The\n * width animates over many frames, so the dip plays once per settled change of more than a few pixels, not per frame.\n * The dip runs on this layout's OWN wrapper, through the Web Animations API, so nothing is written on a region.\n */\nfunction useColumnDip(rootRef: React.RefObject<HTMLElement | null>, settings: FocalPlaneSettings, reducedMotion: boolean): void {\n useEffect(() => {\n const root = rootRef.current;\n if (!root || reducedMotion || typeof ResizeObserver === 'undefined') return undefined;\n const columns = [...root.querySelectorAll<HTMLElement>('[data-fp-object=\"shell\"]')].filter((wrapper) =>\n wrapper.querySelector(`:scope > [data-component-area=\"${ShellRegion.SIDEBAR}\"], :scope > [data-component-area=\"${ShellRegion.UTILITY_PANEL}\"]`));\n const settled = new Map<HTMLElement, number>();\n const lastDip = new Map<HTMLElement, number>();\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const wrapper = entry.target as HTMLElement;\n const width = wrapper.offsetWidth;\n const previous = settled.get(wrapper);\n if (previous === undefined || width === 0) { settled.set(wrapper, width); continue; }\n if (Math.abs(width - previous) <= 24) continue;\n settled.set(wrapper, width);\n const now = performance.now();\n if (now - (lastDip.get(wrapper) ?? 0) < settings.motionMs) continue;\n lastDip.set(wrapper, now);\n wrapper.animate(\n [{ offset: 0.5, transform: `perspective(${settings.cameraDistancePx}px) translate3d(0, 0, ${-settings.layerDepthPx * 0.3}px)` }],\n { duration: settings.motionMs, easing: 'cubic-bezier(0.2, 0.9, 0.25, 1)' },\n );\n }\n });\n for (const column of columns) observer.observe(column);\n return () => observer.disconnect();\n }, [rootRef, settings, reducedMotion]);\n}\n"]}
1
+ {"version":3,"file":"focal-plane-shell-container.js","sourceRoot":"","sources":["../../../../src/focal-plane/focal-plane-shell-container.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useLayoutEffect, 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 NavigationZone,\n useNavigationState,\n useUI,\n type AppLayoutPreset_MainContainer_DefaultProps,\n} from '@wildo-ai/saas-frontend-lib';\n\nimport { focalPlaneCssVariables, useFocalPlaneSettings, type FocalPlaneSettings } from './focal-plane-settings';\nimport { installFocalPlaneStylesheet } from './focal-plane-stylesheet';\nimport { usePaneDepth } from './use-pane-depth';\nimport { useSharedVanishingPoint } from './use-shared-vanishing-point';\n\n/**\n * The focal plane's placement (#2049). The regions are the application's own, rendered by the standard outlets with\n * every context; this container arranges them as floating glass windows over an ambient background, and marks each\n * as an object the still camera sees in depth. The navigation panes inside the content region are objects too, found\n * by the engine's own markers (see `focal-plane-stylesheet.ts`).\n *\n * Overlays render in `AppShellOverlayPortalLayer`, outside every transformed object: a dialog inside a transformed pane\n * would be confined to it, and a menu placed in the wrong coordinates.\n */\nexport function FocalPlaneShellContainer({ 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 <FocalPlaneStage>{children}</FocalPlaneStage>\n </AppShellProviders>\n );\n}\n\nfunction FocalPlaneStage({ children }: { children: React.ReactNode }): React.JSX.Element {\n const { prefersReducedMotion } = useUI();\n const rootRef = useRef<HTMLDivElement>(null);\n const settings = useFocalPlaneSettings();\n const navigation = useNavigationState();\n useLayoutEffect(() => installFocalPlaneStylesheet(), []);\n useSharedVanishingPoint(rootRef);\n const { dip } = usePaneDepth(rootRef, settings, prefersReducedMotion);\n const front = useFrontPane(rootRef, navigation.focusedZone);\n useColumnDip(rootRef, settings, prefersReducedMotion);\n usePlaceChanges(navigation, (zone, how) => {\n if (how === PlaceChange.CHANGED) dip(zone);\n front.bringForward(zone);\n });\n const shell = (content: React.ReactNode): React.JSX.Element => <div data-fp-object=\"shell\">{content}</div>;\n\n return (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.SHELL} policyOverride={NON_CANONICAL_SHELL_SURFACE_POLICY_OVERRIDE}>\n <div\n ref={rootRef}\n data-focal-plane=\"\"\n data-fp-focus={front.zone}\n style={focalPlaneCssVariables(settings, prefersReducedMotion) as React.CSSProperties}\n >\n <div className=\"fp-ghosts\" aria-hidden=\"true\" />\n <div className=\"fp-backdrop\" aria-hidden=\"true\">\n <i className=\"fp-a\" />\n <i className=\"fp-b\" />\n <i className=\"fp-c\" />\n </div>\n <div className=\"fp-grid\">\n {shell(<AppShellRegionOutlet region={ShellRegion.STATUS_BAR} placement={VerticalPlacement.TOP} />)}\n {shell(<AppShellRegionOutlet region={ShellRegion.MENUBAR} />)}\n <div className=\"fp-row fp-middle\">\n {shell(<AppShellRegionOutlet region={ShellRegion.ACTIVITY_BAR} />)}\n {shell(<AppShellRegionOutlet region={ShellRegion.SIDEBAR} placement={HorizontalPlacement.START} />)}\n {shell(<AppShellRegionOutlet region={ShellRegion.UTILITY_PANEL} placement={HorizontalPlacement.START} />)}\n <div className=\"fp-column\">\n {shell(<AppShellRegionOutlet region={ShellRegion.TOOLBAR} />)}\n <div className=\"fp-content\">\n <AppShellContentOutlet className=\"flex-1 relative min-w-0 min-h-0\">{children}</AppShellContentOutlet>\n </div>\n </div>\n {shell(<AppShellRegionOutlet region={ShellRegion.UTILITY_PANEL} placement={HorizontalPlacement.END} />)}\n {shell(<AppShellRegionOutlet region={ShellRegion.SIDEBAR} placement={HorizontalPlacement.END} />)}\n </div>\n {shell(<AppShellRegionOutlet region={ShellRegion.STATUS_BAR} placement={VerticalPlacement.BOTTOM} />)}\n </div>\n <div className=\"fp-ghosts fp-ghosts-front\" aria-hidden=\"true\" />\n <AppShellOverlaysOutlet />\n <AppShellOverlayPortalLayer />\n </div>\n </Surface>\n );\n}\n\n/**\n * Which pane is in front: the one you last pressed in or moved keyboard focus into, or the one that last opened or\n * changed place. Kept by the layout rather than read from the navigation state's `focusedZone` alone, because that\n * follows only interaction: opening a record beside the list leaves the LIST focused (the click happened there), and\n * the prototype this layout follows brings the new pane forward. The engine's focus state is never written.\n */\nfunction useFrontPane(rootRef: React.RefObject<HTMLElement | null>, focusedZone: string): { zone: string; bringForward: (zone: string) => void } {\n const [zone, setZone] = useState<string>(focusedZone);\n useEffect(() => setZone(focusedZone), [focusedZone]);\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return undefined;\n const fromEvent = (event: Event): void => {\n const target = event.target instanceof Element ? event.target : null;\n const pane = target?.closest<HTMLElement>(`[data-component-area=\"${ShellRegion.CONTENT}\"] :is([data-content-area], [data-panel-id^=\"nav-\"])`);\n const name = pane?.dataset.contentArea ?? pane?.dataset.panelId?.replace(/^nav-/, '');\n if (name) setZone(name);\n };\n root.addEventListener('pointerdown', fromEvent, true);\n root.addEventListener('focusin', fromEvent, true);\n return () => {\n root.removeEventListener('pointerdown', fromEvent, true);\n root.removeEventListener('focusin', fromEvent, true);\n };\n }, [rootRef]);\n return { zone, bringForward: setZone };\n}\n\nconst STRUCTURAL_ZONES: ReadonlySet<string> = new Set([NavigationZone.PRIMARY, NavigationZone.SECONDARY, NavigationZone.COMPANION]);\n\n/** How a navigation zone's place moved between two renders. */\nenum PlaceChange {\n /** The zone held nothing and now holds a place: a pane opened. */\n APPEARED = 'appeared',\n /** The zone showed one place and now shows another, in the same pane. */\n CHANGED = 'changed',\n}\n\n/**\n * A zone that APPEARS (it held nothing, now it holds a place) or CHANGES place (the same zone now shows another URL\n * path) is reported: a change dips back and returns, and either way the pane comes forward. The arrival itself is the\n * stylesheet's (a side pane arrives from depth when it mounts).\n */\nfunction usePlaceChanges(navigation: ReturnType<typeof useNavigationState>, onPlace: (zone: string, how: PlaceChange) => void): void {\n // The structural zones only: the overlay zone is a dialog, not a pane, and must never become the \"front pane\".\n const zones = (Object.keys(navigation.state.zones) as Array<keyof typeof navigation.state.zones>).filter((zone) => STRUCTURAL_ZONES.has(String(zone)));\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 = zones.map((zone, index) => `${String(zone)}:${places[index]}`).join('|');\n const previous = useRef<Map<string, string> | null>(null);\n useEffect(() => {\n const current = new Map(zones.map((zone, index) => [String(zone), places[index] ?? '']));\n const before = previous.current;\n previous.current = current;\n if (!before) return;\n for (const [zone, place] of current) {\n const was = before.get(zone) ?? '';\n if (place === '' || was === place) continue;\n onPlace(zone, was === '' ? PlaceChange.APPEARED : PlaceChange.CHANGED);\n }\n // `signature` is the whole dependency: the zones and places are derived from the same render.\n }, [signature]);\n}\n\n/**\n * A side column (the sidebar folding to its rail or unfolding) dips back and returns while the panes re-arrange. The\n * width animates over many frames, so the dip plays once per settled change of more than a few pixels, not per frame.\n * The dip runs on this layout's OWN wrapper, through the Web Animations API, so nothing is written on a region.\n */\nfunction useColumnDip(rootRef: React.RefObject<HTMLElement | null>, settings: FocalPlaneSettings, reducedMotion: boolean): void {\n useEffect(() => {\n const root = rootRef.current;\n if (!root || reducedMotion || typeof ResizeObserver === 'undefined') return undefined;\n const columns = [...root.querySelectorAll<HTMLElement>('[data-fp-object=\"shell\"]')].filter((wrapper) =>\n wrapper.querySelector(`:scope > [data-component-area=\"${ShellRegion.SIDEBAR}\"], :scope > [data-component-area=\"${ShellRegion.UTILITY_PANEL}\"]`));\n const settled = new Map<HTMLElement, number>();\n const lastDip = new Map<HTMLElement, number>();\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const wrapper = entry.target as HTMLElement;\n const width = wrapper.offsetWidth;\n const previous = settled.get(wrapper);\n if (previous === undefined || width === 0) { settled.set(wrapper, width); continue; }\n if (Math.abs(width - previous) <= 24) continue;\n settled.set(wrapper, width);\n const now = performance.now();\n if (now - (lastDip.get(wrapper) ?? 0) < settings.motionMs) continue;\n lastDip.set(wrapper, now);\n wrapper.animate(\n [{ offset: 0.5, transform: `perspective(${settings.cameraDistancePx}px) translate3d(0, 0, ${-settings.layerDepthPx * 0.3}px)` }],\n { duration: settings.motionMs, easing: 'cubic-bezier(0.2, 0.9, 0.25, 1)' },\n );\n }\n });\n for (const column of columns) observer.observe(column);\n return () => observer.disconnect();\n }, [rootRef, settings, reducedMotion]);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"focal-plane-stylesheet.d.ts","sourceRoot":"","sources":["../../../src/focal-plane/focal-plane-stylesheet.ts"],"names":[],"mappings":"AA8BA;;;GAGG;AACH,eAAO,MAAM,yBAAyB,8IAA8F,CAAC;AAqCrI,qFAAqF;AACrF,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAAgB,CAAC;AAEtE,eAAO,MAAM,eAAe,QAoI3B,CAAC;AAKF;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,GAAE,QAAmB,GAAG,MAAM,IAAI,CAqBhF"}
1
+ {"version":3,"file":"focal-plane-stylesheet.d.ts","sourceRoot":"","sources":["../../../../src/focal-plane/focal-plane-stylesheet.ts"],"names":[],"mappings":"AA8BA;;;GAGG;AACH,eAAO,MAAM,yBAAyB,8IAA8F,CAAC;AAqCrI,qFAAqF;AACrF,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAAgB,CAAC;AAEtE,eAAO,MAAM,eAAe,QAoI3B,CAAC;AAKF;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,GAAE,QAAmB,GAAG,MAAM,IAAI,CAqBhF"}
@@ -1 +1 @@
1
- {"version":3,"file":"focal-plane-stylesheet.js","sourceRoot":"","sources":["../../../src/focal-plane/focal-plane-stylesheet.ts"],"names":[],"mappings":"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","sourcesContent":["import { ShellRegion } from '@wildo-ai/presets-components-models';\nimport { NavigationZone } from '@wildo-ai/saas-frontend-lib';\n\n/**\n * The focal plane's stylesheet (#2049), scoped to `[data-focal-plane]`, so it touches nothing outside the layout.\n *\n * ## One still camera, without a nested 3D context\n *\n * Every object carries its OWN `perspective(d) translate3d(0, 0, z)`, with its `transform-origin` set (per element, by\n * `useSharedVanishingPoint`) to the one vanishing point of the stage. That is the projection of a single still camera,\n * and it needs no `transform-style: preserve-3d` ancestor — which matters, because a nested 3D context disables\n * `backdrop-filter`, and the glass windows are made of it.\n *\n * ## What counts as an object\n *\n * - the shell panels this layout wraps (`[data-fp-object]`);\n * - each navigation pane inside the content region, by the engine's own markers: `[data-content-area]` (the static and\n * single-zone branches) and the resizable panel `[data-panel-id^=\"nav-\"]` (NOT its inner `[data-content-area]`, which\n * the panel's inline `overflow: hidden` would clip).\n *\n * Depth is a custom property (`--fp-z`); states set it, and the transform reads it, so rules compose instead of fighting\n * over `transform`.\n *\n * ## Why a constructable stylesheet\n *\n * It is installed through `document.adoptedStyleSheets`, which a content security policy without `'unsafe-inline'`\n * does not block, where a `<style>` element would be.\n */\nconst ROOT = '[data-focal-plane]';\nconst CONTENT = `[data-component-area=\"${ShellRegion.CONTENT}\"]`;\n/**\n * The navigation panes, by the engine's markers: the zone itself in the static and single-zone branches, the panel in\n * the resizable branch — never the zone INSIDE a panel, which would be moved twice.\n */\nexport const FOCAL_PLANE_PANE_SELECTOR = `${CONTENT} [data-content-area]:not([data-panel-id] *), ${CONTENT} [data-panel-id^=\"nav-\"]`;\n/** The zone names the navigation state focuses, and the markers each one is found by in either branch. */\nconst ZONES = [NavigationZone.PRIMARY, NavigationZone.SECONDARY, NavigationZone.COMPANION] as const;\nconst zoneMarker = (zone: (typeof ZONES)[number]): string => `:is([data-content-area=\"${zone}\"], [data-panel-id=\"nav-${zone}\"])`;\nconst VISIBLE_PANE = `:is(${FOCAL_PLANE_PANE_SELECTOR}):not([data-zone-hidden])`;\n/** Two panes or more are side by side (the other panes are siblings in both branches). */\nconst SPLIT = `${CONTENT}:has(${VISIBLE_PANE} ~ ${VISIBLE_PANE})`;\nconst PANES = `:is(${FOCAL_PLANE_PANE_SELECTOR})`;\nconst OBJECTS = `:is([data-fp-object], ${FOCAL_PLANE_PANE_SELECTOR})`;\n/**\n * The popups the focal plane moves, by the stable `data-slot` of their portalled content (Radix `data-state` on the\n * same element). Lifting popups carry the CSS variable Radix publishes as their trigger-relative origin.\n */\nconst POPUPS = {\n lift: [\n ['dropdown-menu-content', '--radix-dropdown-menu-content-transform-origin'],\n ['dropdown-menu-sub-content', '--radix-dropdown-menu-content-transform-origin'],\n ['context-menu-content', '--radix-context-menu-content-transform-origin'],\n ['context-menu-sub-content', '--radix-context-menu-content-transform-origin'],\n ['popover-content', '--radix-popover-content-transform-origin'],\n ['hover-card-content', '--radix-hover-card-content-transform-origin'],\n ['tooltip-content', '--radix-tooltip-content-transform-origin'],\n ['select-content', '--radix-select-content-transform-origin'],\n ['menubar-content', '--radix-menubar-content-transform-origin'],\n ['menubar-sub-content', '--radix-menubar-content-transform-origin'],\n ],\n rise: ['dialog-content', 'alert-dialog-content'],\n} as const;\n/**\n * A MODAL popup is open: a dialog, an alert dialog, a sheet or a drawer, by their content SLOT. Not by `role=\"dialog\"`:\n * a Radix popover's content carries that role too (date pickers, linked-record pickers, the notification centre), and\n * opening one must not step the form you are editing back. Not by `body[data-scroll-locked]` either, which dropdown\n * and context menus also set.\n */\nconst MODAL_SLOTS = ['dialog-content', 'alert-dialog-content', 'sheet-content', 'drawer-content'] as const;\nconst MODAL_OPEN = `:has([data-shell-overlay-layer] :is(${MODAL_SLOTS.map((slot) => `[data-slot=\"${slot}\"]`).join(', ')})[data-state=\"open\"])`;\n\n/** The modal content slots, exported for the tests that pin what counts as modal. */\nexport const FOCAL_PLANE_MODAL_SLOTS: readonly string[] = MODAL_SLOTS;\n\nexport const FOCAL_PLANE_CSS = `\n/* Positioned, never isolated: an isolated root would be one stacking context, and anything positioned outside the\n shell with a lower z-index (a consent prompt) would paint over the shell's own dialogs (#1830). */\n${ROOT} { position: relative; height: 100vh; width: 100vw; overflow: hidden; background: var(--background); }\n\n/* The ambient background: soft fields of the theme's own colours, drifting very slowly. */\n${ROOT} .fp-backdrop { position: absolute; inset: -20%; z-index: 0; pointer-events: none; }\n${ROOT} .fp-backdrop i { position: absolute; border-radius: 50%; filter: blur(70px); opacity: 0.8; }\n${ROOT} .fp-backdrop .fp-a { width: 58%; height: 62%; left: 6%; top: 4%; background: radial-gradient(closest-side, color-mix(in oklab, var(--primary) 38%, var(--background)), transparent); animation: fp-drift-a 48s ease-in-out infinite alternate; }\n${ROOT} .fp-backdrop .fp-b { width: 52%; height: 58%; right: 4%; top: 30%; background: radial-gradient(closest-side, color-mix(in oklab, var(--accent, var(--primary)) 30%, var(--background)), transparent); animation: fp-drift-b 61s ease-in-out infinite alternate; }\n${ROOT} .fp-backdrop .fp-c { width: 46%; height: 50%; left: 34%; bottom: 0; background: radial-gradient(closest-side, color-mix(in oklab, var(--primary) 22%, var(--foreground) 8%), transparent); animation: fp-drift-c 55s ease-in-out infinite alternate; }\n@keyframes fp-drift-a { to { transform: translate(9%, 7%) scale(1.08); } }\n@keyframes fp-drift-b { to { transform: translate(-8%, -6%) scale(0.94); } }\n@keyframes fp-drift-c { to { transform: translate(-6%, -9%) scale(1.1); } }\n\n/* The arrangement: floating windows with a margin and gaps, never edge to edge. */\n${ROOT} .fp-grid { position: absolute; inset: 0; z-index: 1; display: flex; flex-direction: column; gap: 12px; padding: 14px; }\n${ROOT} .fp-row { display: flex; gap: 12px; min-height: 0; min-width: 0; }\n${ROOT} .fp-middle { flex: 1; }\n${ROOT} .fp-column { flex: 1; display: flex; flex-direction: column; gap: 12px; min-width: 0; min-height: 0; }\n${ROOT} .fp-content { flex: 1; min-height: 0; min-width: 0; position: relative; display: flex; flex-direction: column; }\n${ROOT} [data-fp-object]:empty { display: none; }\n${ROOT} [data-fp-object] { position: relative; display: flex; min-height: 0; min-width: 0; }\n${ROOT} [data-fp-object] > * { flex: 1; min-width: 0; min-height: 0; }\n\n/* Every object: seen through the one still camera, at its depth. */\n${ROOT} ${OBJECTS} {\n transform-origin: var(--fp-ox, 50%) var(--fp-oy, 50%);\n transform: perspective(var(--fp-distance)) translate3d(0, 0, var(--fp-z, 0px));\n filter: var(--fp-filter, none);\n transition: transform var(--fp-motion) var(--fp-ease), filter var(--fp-motion) var(--fp-ease), box-shadow var(--fp-motion) var(--fp-ease);\n}\n\n/* Glass: the theme's card colour, translucent, over the background blurred through it. */\n${ROOT} :is([data-fp-object=\"shell\"], ${FOCAL_PLANE_PANE_SELECTOR}) {\n background: color-mix(in oklab, var(--card, var(--background)) var(--fp-glass), transparent);\n -webkit-backdrop-filter: blur(26px) saturate(1.5);\n backdrop-filter: blur(26px) saturate(1.5);\n border: 1px solid color-mix(in oklab, var(--border) 55%, transparent);\n border-radius: 14px;\n box-shadow: 0 18px 44px -22px rgb(0 0 0 / 0.30), 0 1px 3px rgb(0 0 0 / 0.05);\n}\n${ROOT} ${CONTENT} { background: transparent; }\n${ROOT} ${CONTENT} :is([data-content-area=\"${NavigationZone.SECONDARY}\"], [data-content-area=\"${NavigationZone.COMPANION}\"]):not([data-panel-id] *) { margin-left: 12px; }\n\n/* Side by side, the pane you work in rests on the focal plane; every other pane steps back and dims. The focused\n zone comes from the navigation state, written on the root as data-fp-focus. Clicking a pane focuses it (the\n engine does that), which brings it forward. */\n${ZONES.map((zone) => `${ROOT}[data-fp-focus=\"${zone}\"] ${SPLIT} ${VISIBLE_PANE}:not(${zoneMarker(zone)})`).join(', ')} {\n --fp-z: calc(var(--fp-step) * -0.55);\n --fp-filter: brightness(calc(1 - var(--fp-dim) * 0.55)) saturate(calc(1 - var(--fp-dim) * 0.5)) blur(calc(var(--fp-recede-blur) * 0.55));\n}\n\n/* A side pane arrives from depth when it opens. */\n${ROOT} ${CONTENT} :is(${zoneMarker(NavigationZone.SECONDARY)}, ${zoneMarker(NavigationZone.COMPANION)}):is(${FOCAL_PLANE_PANE_SELECTOR}) {\n animation: fp-pane-arrive var(--fp-motion) var(--fp-ease);\n}\n@keyframes fp-pane-arrive {\n from { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -1.2)); opacity: 0; }\n}\n\n/* Ghosts: a discarded pane flying away, and the still image of the panes an expanded pane stands in front of. */\n${ROOT} .fp-ghosts { position: absolute; inset: 0; z-index: 0; pointer-events: none; }\n${ROOT} .fp-ghosts-front { z-index: 2; }\n${ROOT} .fp-ghost {\n position: absolute; box-sizing: border-box; overflow: hidden;\n transform-origin: var(--fp-ox) var(--fp-oy);\n transform: perspective(var(--fp-distance)) translate3d(0, 0, var(--fp-z, 0px));\n filter: var(--fp-filter, none);\n transition: transform var(--fp-motion) var(--fp-ease), filter var(--fp-motion) var(--fp-ease), opacity var(--fp-motion) var(--fp-ease);\n background: color-mix(in oklab, var(--card, var(--background)) var(--fp-glass), transparent);\n border: 1px solid color-mix(in oklab, var(--border) 55%, transparent);\n border-radius: 14px;\n box-shadow: 0 18px 44px -22px rgb(0 0 0 / 0.30);\n}\n\n/* The shell panel under the pointer rises toward the camera; its items zoom a little. */\n${ROOT} [data-fp-object=\"shell\"]:hover { --fp-z: var(--fp-hover-lift); }\n${ROOT} [data-fp-object=\"shell\"] :is(button, a):not(:disabled) { transition: transform 180ms var(--fp-ease); }\n${ROOT} [data-fp-object=\"shell\"] :is(button, a):not(:disabled):hover { transform: scale(1.045); }\n\n/* Behind a modal popup, everything steps back, dims and blurs lightly. A menu is not modal: it only lifts. */\n${ROOT}${MODAL_OPEN} ${OBJECTS} {\n --fp-z: calc(var(--fp-step) * -0.6);\n --fp-filter: brightness(calc(1 - var(--fp-dim) * 0.6)) saturate(0.9) blur(var(--fp-modal-blur));\n}\n\n/* Popups are objects too. Their recipe animations (tw-animate's enter/exit) are replaced by depth KEYFRAMES —\n keyframes, because the overlay library keeps a closing popup mounted only until its exit ANIMATION ends; a\n transition would be cut off. Each popup rests at its true size: depth shows while it travels.\n - A menu, popover or tooltip lifts off its trigger: the library publishes the trigger point as the transform\n origin, and perspective() grows the popup out of it.\n - A dialog (the command palette is one) rises from depth to the focal plane.\n - A sheet arrives from in front of the plane and leaves back into depth.\n Drawers and toasts keep their own motion: their libraries position and stack them with transforms. */\n${POPUPS.lift.map(([slot, origin]) => `${ROOT} [data-shell-overlay-layer] [data-slot=\"${slot}\"] { transform-origin: var(${origin}); }`).join('\\n')}\n${ROOT} [data-shell-overlay-layer] :is(${POPUPS.lift.map(([slot]) => `[data-slot=\"${slot}\"]`).join(', ')}):is([data-state=\"open\"], [data-state=\"delayed-open\"], [data-state=\"instant-open\"]) { animation: fp-lift-in calc(var(--fp-motion) * 0.6) var(--fp-ease) both; }\n${ROOT} [data-shell-overlay-layer] :is(${POPUPS.lift.map(([slot]) => `[data-slot=\"${slot}\"]`).join(', ')})[data-state=\"closed\"] { animation: fp-lift-out calc(var(--fp-motion) * 0.45) var(--fp-ease) both; }\n${ROOT} [data-shell-overlay-layer] :is(${POPUPS.rise.map((slot) => `[data-slot=\"${slot}\"]`).join(', ')})[data-state=\"open\"] { animation: fp-rise-in var(--fp-motion) var(--fp-ease) both; }\n${ROOT} [data-shell-overlay-layer] :is(${POPUPS.rise.map((slot) => `[data-slot=\"${slot}\"]`).join(', ')})[data-state=\"closed\"] { animation: fp-rise-out calc(var(--fp-motion) * 0.7) var(--fp-ease) both; }\n${ROOT} [data-shell-overlay-layer] [data-slot=\"sheet-content\"][data-state=\"open\"] { animation: fp-arrive-in var(--fp-motion) var(--fp-ease) both; }\n${ROOT} [data-shell-overlay-layer] [data-slot=\"sheet-content\"][data-state=\"closed\"] { animation: fp-arrive-out calc(var(--fp-motion) * 0.7) var(--fp-ease) both; }\n/* Popups are glass, a little more opaque than windows (they carry text you act on at once). Tooltips keep their own\n inverse colours. */\n${ROOT} [data-shell-overlay-layer] :is(${[...POPUPS.lift.filter(([slot]) => slot !== 'tooltip-content').map(([slot]) => slot), ...POPUPS.rise, 'sheet-content'].map((slot) => `[data-slot=\"${slot}\"]`).join(', ')}) {\n background: color-mix(in oklab, var(--popover, var(--card, var(--background))) calc(var(--fp-glass) + 26%), transparent);\n -webkit-backdrop-filter: blur(24px) saturate(1.5);\n backdrop-filter: blur(24px) saturate(1.5);\n border-color: color-mix(in oklab, var(--border) 60%, transparent);\n}\n@keyframes fp-lift-in { from { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -0.35)); opacity: 0; } to { transform: none; opacity: 1; } }\n@keyframes fp-lift-out { from { transform: none; opacity: 1; } to { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -0.35)); opacity: 0; } }\n@keyframes fp-rise-in { from { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -1.4)); opacity: 0; } to { transform: none; opacity: 1; } }\n@keyframes fp-rise-out { from { transform: none; opacity: 1; } to { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -1.4)); opacity: 0; } }\n@keyframes fp-arrive-in { from { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * 0.9)); opacity: 0; } to { transform: none; opacity: 1; } }\n@keyframes fp-arrive-out { from { transform: none; opacity: 1; } to { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -0.5)); opacity: 0; } }\n\n/* The modal scrim: in the focal plane, stepping back and the light blur above ARE the scrim, so the engine's dark\n overlay (and its own backdrop blur) would double it into a heavy grey. Keep the overlay element (it still catches\n the outside click), just transparent. */\n${ROOT} [data-shell-overlay-layer] :is([data-slot=\"dialog-overlay\"], [data-slot=\"alert-dialog-overlay\"], [data-slot=\"sheet-overlay\"], [data-slot=\"drawer-overlay\"]) {\n background: transparent;\n -webkit-backdrop-filter: none;\n backdrop-filter: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n /* !important: the motion rules above are more specific (the drifting fields, the item zoom), and the reader's\n setting must win over every one of them. */\n ${ROOT} ${OBJECTS}, ${ROOT} .fp-ghost, ${ROOT} [data-fp-object=\"shell\"] :is(button, a), ${ROOT} [data-shell-overlay-layer] [data-slot] { transition-duration: 0ms !important; animation: none !important; }\n ${ROOT} .fp-backdrop i { animation: none !important; }\n}\n`;\n\nlet installed: CSSStyleSheet | null = null;\nlet users = 0;\n\n/**\n * Installs the stylesheet while at least one focal-plane layout is mounted, and removes it when the last one unmounts.\n * Returns the release function. Falls back to a `<style>` element where constructable stylesheets are missing.\n */\nexport function installFocalPlaneStylesheet(doc: Document = document): () => void {\n users += 1;\n if (users === 1) {\n if ('adoptedStyleSheets' in doc && typeof CSSStyleSheet !== 'undefined' && 'replaceSync' in CSSStyleSheet.prototype) {\n installed = new CSSStyleSheet();\n installed.replaceSync(FOCAL_PLANE_CSS);\n doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, installed];\n } else {\n const style = doc.createElement('style');\n style.dataset.focalPlane = '';\n style.textContent = FOCAL_PLANE_CSS;\n doc.head.appendChild(style);\n }\n }\n return () => {\n users -= 1;\n if (users > 0) return;\n if (installed) doc.adoptedStyleSheets = doc.adoptedStyleSheets.filter((sheet) => sheet !== installed);\n doc.head.querySelector('style[data-focal-plane]')?.remove();\n installed = null;\n };\n}\n"]}
1
+ {"version":3,"file":"focal-plane-stylesheet.js","sourceRoot":"","sources":["../../../../src/focal-plane/focal-plane-stylesheet.ts"],"names":[],"mappings":"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","sourcesContent":["import { ShellRegion } from '@wildo-ai/presets-components-models';\nimport { NavigationZone } from '@wildo-ai/saas-frontend-lib';\n\n/**\n * The focal plane's stylesheet (#2049), scoped to `[data-focal-plane]`, so it touches nothing outside the layout.\n *\n * ## One still camera, without a nested 3D context\n *\n * Every object carries its OWN `perspective(d) translate3d(0, 0, z)`, with its `transform-origin` set (per element, by\n * `useSharedVanishingPoint`) to the one vanishing point of the stage. That is the projection of a single still camera,\n * and it needs no `transform-style: preserve-3d` ancestor — which matters, because a nested 3D context disables\n * `backdrop-filter`, and the glass windows are made of it.\n *\n * ## What counts as an object\n *\n * - the shell panels this layout wraps (`[data-fp-object]`);\n * - each navigation pane inside the content region, by the engine's own markers: `[data-content-area]` (the static and\n * single-zone branches) and the resizable panel `[data-panel-id^=\"nav-\"]` (NOT its inner `[data-content-area]`, which\n * the panel's inline `overflow: hidden` would clip).\n *\n * Depth is a custom property (`--fp-z`); states set it, and the transform reads it, so rules compose instead of fighting\n * over `transform`.\n *\n * ## Why a constructable stylesheet\n *\n * It is installed through `document.adoptedStyleSheets`, which a content security policy without `'unsafe-inline'`\n * does not block, where a `<style>` element would be.\n */\nconst ROOT = '[data-focal-plane]';\nconst CONTENT = `[data-component-area=\"${ShellRegion.CONTENT}\"]`;\n/**\n * The navigation panes, by the engine's markers: the zone itself in the static and single-zone branches, the panel in\n * the resizable branch — never the zone INSIDE a panel, which would be moved twice.\n */\nexport const FOCAL_PLANE_PANE_SELECTOR = `${CONTENT} [data-content-area]:not([data-panel-id] *), ${CONTENT} [data-panel-id^=\"nav-\"]`;\n/** The zone names the navigation state focuses, and the markers each one is found by in either branch. */\nconst ZONES = [NavigationZone.PRIMARY, NavigationZone.SECONDARY, NavigationZone.COMPANION] as const;\nconst zoneMarker = (zone: (typeof ZONES)[number]): string => `:is([data-content-area=\"${zone}\"], [data-panel-id=\"nav-${zone}\"])`;\nconst VISIBLE_PANE = `:is(${FOCAL_PLANE_PANE_SELECTOR}):not([data-zone-hidden])`;\n/** Two panes or more are side by side (the other panes are siblings in both branches). */\nconst SPLIT = `${CONTENT}:has(${VISIBLE_PANE} ~ ${VISIBLE_PANE})`;\nconst PANES = `:is(${FOCAL_PLANE_PANE_SELECTOR})`;\nconst OBJECTS = `:is([data-fp-object], ${FOCAL_PLANE_PANE_SELECTOR})`;\n/**\n * The popups the focal plane moves, by the stable `data-slot` of their portalled content (Radix `data-state` on the\n * same element). Lifting popups carry the CSS variable Radix publishes as their trigger-relative origin.\n */\nconst POPUPS = {\n lift: [\n ['dropdown-menu-content', '--radix-dropdown-menu-content-transform-origin'],\n ['dropdown-menu-sub-content', '--radix-dropdown-menu-content-transform-origin'],\n ['context-menu-content', '--radix-context-menu-content-transform-origin'],\n ['context-menu-sub-content', '--radix-context-menu-content-transform-origin'],\n ['popover-content', '--radix-popover-content-transform-origin'],\n ['hover-card-content', '--radix-hover-card-content-transform-origin'],\n ['tooltip-content', '--radix-tooltip-content-transform-origin'],\n ['select-content', '--radix-select-content-transform-origin'],\n ['menubar-content', '--radix-menubar-content-transform-origin'],\n ['menubar-sub-content', '--radix-menubar-content-transform-origin'],\n ],\n rise: ['dialog-content', 'alert-dialog-content'],\n} as const;\n/**\n * A MODAL popup is open: a dialog, an alert dialog, a sheet or a drawer, by their content SLOT. Not by `role=\"dialog\"`:\n * a Radix popover's content carries that role too (date pickers, linked-record pickers, the notification centre), and\n * opening one must not step the form you are editing back. Not by `body[data-scroll-locked]` either, which dropdown\n * and context menus also set.\n */\nconst MODAL_SLOTS = ['dialog-content', 'alert-dialog-content', 'sheet-content', 'drawer-content'] as const;\nconst MODAL_OPEN = `:has([data-shell-overlay-layer] :is(${MODAL_SLOTS.map((slot) => `[data-slot=\"${slot}\"]`).join(', ')})[data-state=\"open\"])`;\n\n/** The modal content slots, exported for the tests that pin what counts as modal. */\nexport const FOCAL_PLANE_MODAL_SLOTS: readonly string[] = MODAL_SLOTS;\n\nexport const FOCAL_PLANE_CSS = `\n/* Positioned, never isolated: an isolated root would be one stacking context, and anything positioned outside the\n shell with a lower z-index (a consent prompt) would paint over the shell's own dialogs (#1830). */\n${ROOT} { position: relative; height: 100vh; width: 100vw; overflow: hidden; background: var(--background); }\n\n/* The ambient background: soft fields of the theme's own colours, drifting very slowly. */\n${ROOT} .fp-backdrop { position: absolute; inset: -20%; z-index: 0; pointer-events: none; }\n${ROOT} .fp-backdrop i { position: absolute; border-radius: 50%; filter: blur(70px); opacity: 0.8; }\n${ROOT} .fp-backdrop .fp-a { width: 58%; height: 62%; left: 6%; top: 4%; background: radial-gradient(closest-side, color-mix(in oklab, var(--primary) 38%, var(--background)), transparent); animation: fp-drift-a 48s ease-in-out infinite alternate; }\n${ROOT} .fp-backdrop .fp-b { width: 52%; height: 58%; right: 4%; top: 30%; background: radial-gradient(closest-side, color-mix(in oklab, var(--accent, var(--primary)) 30%, var(--background)), transparent); animation: fp-drift-b 61s ease-in-out infinite alternate; }\n${ROOT} .fp-backdrop .fp-c { width: 46%; height: 50%; left: 34%; bottom: 0; background: radial-gradient(closest-side, color-mix(in oklab, var(--primary) 22%, var(--foreground) 8%), transparent); animation: fp-drift-c 55s ease-in-out infinite alternate; }\n@keyframes fp-drift-a { to { transform: translate(9%, 7%) scale(1.08); } }\n@keyframes fp-drift-b { to { transform: translate(-8%, -6%) scale(0.94); } }\n@keyframes fp-drift-c { to { transform: translate(-6%, -9%) scale(1.1); } }\n\n/* The arrangement: floating windows with a margin and gaps, never edge to edge. */\n${ROOT} .fp-grid { position: absolute; inset: 0; z-index: 1; display: flex; flex-direction: column; gap: 12px; padding: 14px; }\n${ROOT} .fp-row { display: flex; gap: 12px; min-height: 0; min-width: 0; }\n${ROOT} .fp-middle { flex: 1; }\n${ROOT} .fp-column { flex: 1; display: flex; flex-direction: column; gap: 12px; min-width: 0; min-height: 0; }\n${ROOT} .fp-content { flex: 1; min-height: 0; min-width: 0; position: relative; display: flex; flex-direction: column; }\n${ROOT} [data-fp-object]:empty { display: none; }\n${ROOT} [data-fp-object] { position: relative; display: flex; min-height: 0; min-width: 0; }\n${ROOT} [data-fp-object] > * { flex: 1; min-width: 0; min-height: 0; }\n\n/* Every object: seen through the one still camera, at its depth. */\n${ROOT} ${OBJECTS} {\n transform-origin: var(--fp-ox, 50%) var(--fp-oy, 50%);\n transform: perspective(var(--fp-distance)) translate3d(0, 0, var(--fp-z, 0px));\n filter: var(--fp-filter, none);\n transition: transform var(--fp-motion) var(--fp-ease), filter var(--fp-motion) var(--fp-ease), box-shadow var(--fp-motion) var(--fp-ease);\n}\n\n/* Glass: the theme's card colour, translucent, over the background blurred through it. */\n${ROOT} :is([data-fp-object=\"shell\"], ${FOCAL_PLANE_PANE_SELECTOR}) {\n background: color-mix(in oklab, var(--card, var(--background)) var(--fp-glass), transparent);\n -webkit-backdrop-filter: blur(26px) saturate(1.5);\n backdrop-filter: blur(26px) saturate(1.5);\n border: 1px solid color-mix(in oklab, var(--border) 55%, transparent);\n border-radius: 14px;\n box-shadow: 0 18px 44px -22px rgb(0 0 0 / 0.30), 0 1px 3px rgb(0 0 0 / 0.05);\n}\n${ROOT} ${CONTENT} { background: transparent; }\n${ROOT} ${CONTENT} :is([data-content-area=\"${NavigationZone.SECONDARY}\"], [data-content-area=\"${NavigationZone.COMPANION}\"]):not([data-panel-id] *) { margin-left: 12px; }\n\n/* Side by side, the pane you work in rests on the focal plane; every other pane steps back and dims. The focused\n zone comes from the navigation state, written on the root as data-fp-focus. Clicking a pane focuses it (the\n engine does that), which brings it forward. */\n${ZONES.map((zone) => `${ROOT}[data-fp-focus=\"${zone}\"] ${SPLIT} ${VISIBLE_PANE}:not(${zoneMarker(zone)})`).join(', ')} {\n --fp-z: calc(var(--fp-step) * -0.55);\n --fp-filter: brightness(calc(1 - var(--fp-dim) * 0.55)) saturate(calc(1 - var(--fp-dim) * 0.5)) blur(calc(var(--fp-recede-blur) * 0.55));\n}\n\n/* A side pane arrives from depth when it opens. */\n${ROOT} ${CONTENT} :is(${zoneMarker(NavigationZone.SECONDARY)}, ${zoneMarker(NavigationZone.COMPANION)}):is(${FOCAL_PLANE_PANE_SELECTOR}) {\n animation: fp-pane-arrive var(--fp-motion) var(--fp-ease);\n}\n@keyframes fp-pane-arrive {\n from { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -1.2)); opacity: 0; }\n}\n\n/* Ghosts: a discarded pane flying away, and the still image of the panes an expanded pane stands in front of. */\n${ROOT} .fp-ghosts { position: absolute; inset: 0; z-index: 0; pointer-events: none; }\n${ROOT} .fp-ghosts-front { z-index: 2; }\n${ROOT} .fp-ghost {\n position: absolute; box-sizing: border-box; overflow: hidden;\n transform-origin: var(--fp-ox) var(--fp-oy);\n transform: perspective(var(--fp-distance)) translate3d(0, 0, var(--fp-z, 0px));\n filter: var(--fp-filter, none);\n transition: transform var(--fp-motion) var(--fp-ease), filter var(--fp-motion) var(--fp-ease), opacity var(--fp-motion) var(--fp-ease);\n background: color-mix(in oklab, var(--card, var(--background)) var(--fp-glass), transparent);\n border: 1px solid color-mix(in oklab, var(--border) 55%, transparent);\n border-radius: 14px;\n box-shadow: 0 18px 44px -22px rgb(0 0 0 / 0.30);\n}\n\n/* The shell panel under the pointer rises toward the camera; its items zoom a little. */\n${ROOT} [data-fp-object=\"shell\"]:hover { --fp-z: var(--fp-hover-lift); }\n${ROOT} [data-fp-object=\"shell\"] :is(button, a):not(:disabled) { transition: transform 180ms var(--fp-ease); }\n${ROOT} [data-fp-object=\"shell\"] :is(button, a):not(:disabled):hover { transform: scale(1.045); }\n\n/* Behind a modal popup, everything steps back, dims and blurs lightly. A menu is not modal: it only lifts. */\n${ROOT}${MODAL_OPEN} ${OBJECTS} {\n --fp-z: calc(var(--fp-step) * -0.6);\n --fp-filter: brightness(calc(1 - var(--fp-dim) * 0.6)) saturate(0.9) blur(var(--fp-modal-blur));\n}\n\n/* Popups are objects too. Their recipe animations (tw-animate's enter/exit) are replaced by depth KEYFRAMES —\n keyframes, because the overlay library keeps a closing popup mounted only until its exit ANIMATION ends; a\n transition would be cut off. Each popup rests at its true size: depth shows while it travels.\n - A menu, popover or tooltip lifts off its trigger: the library publishes the trigger point as the transform\n origin, and perspective() grows the popup out of it.\n - A dialog (the command palette is one) rises from depth to the focal plane.\n - A sheet arrives from in front of the plane and leaves back into depth.\n Drawers and toasts keep their own motion: their libraries position and stack them with transforms. */\n${POPUPS.lift.map(([slot, origin]) => `${ROOT} [data-shell-overlay-layer] [data-slot=\"${slot}\"] { transform-origin: var(${origin}); }`).join('\\n')}\n${ROOT} [data-shell-overlay-layer] :is(${POPUPS.lift.map(([slot]) => `[data-slot=\"${slot}\"]`).join(', ')}):is([data-state=\"open\"], [data-state=\"delayed-open\"], [data-state=\"instant-open\"]) { animation: fp-lift-in calc(var(--fp-motion) * 0.6) var(--fp-ease) both; }\n${ROOT} [data-shell-overlay-layer] :is(${POPUPS.lift.map(([slot]) => `[data-slot=\"${slot}\"]`).join(', ')})[data-state=\"closed\"] { animation: fp-lift-out calc(var(--fp-motion) * 0.45) var(--fp-ease) both; }\n${ROOT} [data-shell-overlay-layer] :is(${POPUPS.rise.map((slot) => `[data-slot=\"${slot}\"]`).join(', ')})[data-state=\"open\"] { animation: fp-rise-in var(--fp-motion) var(--fp-ease) both; }\n${ROOT} [data-shell-overlay-layer] :is(${POPUPS.rise.map((slot) => `[data-slot=\"${slot}\"]`).join(', ')})[data-state=\"closed\"] { animation: fp-rise-out calc(var(--fp-motion) * 0.7) var(--fp-ease) both; }\n${ROOT} [data-shell-overlay-layer] [data-slot=\"sheet-content\"][data-state=\"open\"] { animation: fp-arrive-in var(--fp-motion) var(--fp-ease) both; }\n${ROOT} [data-shell-overlay-layer] [data-slot=\"sheet-content\"][data-state=\"closed\"] { animation: fp-arrive-out calc(var(--fp-motion) * 0.7) var(--fp-ease) both; }\n/* Popups are glass, a little more opaque than windows (they carry text you act on at once). Tooltips keep their own\n inverse colours. */\n${ROOT} [data-shell-overlay-layer] :is(${[...POPUPS.lift.filter(([slot]) => slot !== 'tooltip-content').map(([slot]) => slot), ...POPUPS.rise, 'sheet-content'].map((slot) => `[data-slot=\"${slot}\"]`).join(', ')}) {\n background: color-mix(in oklab, var(--popover, var(--card, var(--background))) calc(var(--fp-glass) + 26%), transparent);\n -webkit-backdrop-filter: blur(24px) saturate(1.5);\n backdrop-filter: blur(24px) saturate(1.5);\n border-color: color-mix(in oklab, var(--border) 60%, transparent);\n}\n@keyframes fp-lift-in { from { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -0.35)); opacity: 0; } to { transform: none; opacity: 1; } }\n@keyframes fp-lift-out { from { transform: none; opacity: 1; } to { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -0.35)); opacity: 0; } }\n@keyframes fp-rise-in { from { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -1.4)); opacity: 0; } to { transform: none; opacity: 1; } }\n@keyframes fp-rise-out { from { transform: none; opacity: 1; } to { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -1.4)); opacity: 0; } }\n@keyframes fp-arrive-in { from { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * 0.9)); opacity: 0; } to { transform: none; opacity: 1; } }\n@keyframes fp-arrive-out { from { transform: none; opacity: 1; } to { transform: perspective(var(--fp-distance)) translate3d(0, 0, calc(var(--fp-step) * -0.5)); opacity: 0; } }\n\n/* The modal scrim: in the focal plane, stepping back and the light blur above ARE the scrim, so the engine's dark\n overlay (and its own backdrop blur) would double it into a heavy grey. Keep the overlay element (it still catches\n the outside click), just transparent. */\n${ROOT} [data-shell-overlay-layer] :is([data-slot=\"dialog-overlay\"], [data-slot=\"alert-dialog-overlay\"], [data-slot=\"sheet-overlay\"], [data-slot=\"drawer-overlay\"]) {\n background: transparent;\n -webkit-backdrop-filter: none;\n backdrop-filter: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n /* !important: the motion rules above are more specific (the drifting fields, the item zoom), and the reader's\n setting must win over every one of them. */\n ${ROOT} ${OBJECTS}, ${ROOT} .fp-ghost, ${ROOT} [data-fp-object=\"shell\"] :is(button, a), ${ROOT} [data-shell-overlay-layer] [data-slot] { transition-duration: 0ms !important; animation: none !important; }\n ${ROOT} .fp-backdrop i { animation: none !important; }\n}\n`;\n\nlet installed: CSSStyleSheet | null = null;\nlet users = 0;\n\n/**\n * Installs the stylesheet while at least one focal-plane layout is mounted, and removes it when the last one unmounts.\n * Returns the release function. Falls back to a `<style>` element where constructable stylesheets are missing.\n */\nexport function installFocalPlaneStylesheet(doc: Document = document): () => void {\n users += 1;\n if (users === 1) {\n if ('adoptedStyleSheets' in doc && typeof CSSStyleSheet !== 'undefined' && 'replaceSync' in CSSStyleSheet.prototype) {\n installed = new CSSStyleSheet();\n installed.replaceSync(FOCAL_PLANE_CSS);\n doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, installed];\n } else {\n const style = doc.createElement('style');\n style.dataset.focalPlane = '';\n style.textContent = FOCAL_PLANE_CSS;\n doc.head.appendChild(style);\n }\n }\n return () => {\n users -= 1;\n if (users > 0) return;\n if (installed) doc.adoptedStyleSheets = doc.adoptedStyleSheets.filter((sheet) => sheet !== installed);\n doc.head.querySelector('style[data-focal-plane]')?.remove();\n installed = null;\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-pane-depth.d.ts","sourceRoot":"","sources":["../../../src/focal-plane/use-pane-depth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAM3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACtC,QAAQ,EAAE,kBAAkB,EAC5B,aAAa,EAAE,OAAO,GACrB;IAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAqHjC"}
1
+ {"version":3,"file":"use-pane-depth.d.ts","sourceRoot":"","sources":["../../../../src/focal-plane/use-pane-depth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAM3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACtC,QAAQ,EAAE,kBAAkB,EAC5B,aAAa,EAAE,OAAO,GACrB;IAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAqHjC"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-pane-depth.js","sourceRoot":"","sources":["../../../src/focal-plane/use-pane-depth.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useLayoutEffect, useRef, type RefObject } from 'react';\n\nimport { ShellRegion } from '@wildo-ai/presets-components-models';\nimport { NavigationZone } from '@wildo-ai/saas-frontend-lib';\n\nimport { FOCAL_PLANE_PANE_SELECTOR } from './focal-plane-stylesheet';\nimport type { FocalPlaneSettings } from './focal-plane-settings';\nimport { lastStageRects, VANISHING_POINT, type StageRect } from './use-shared-vanishing-point';\n\n/**\n * What the stylesheet cannot do alone, because the engine unmounts or hides a pane at once (#2049 step 2):\n *\n * - **Discard.** A side pane dismissed by its close control is removed from the DOM immediately. The removed node,\n * no longer React's, is re-parented into a ghost layer at the box it last had, and flies away into depth and fades.\n * - **Expand.** An emphasized side pane takes the width, and the engine HIDES the other panes (`hidden`). A still,\n * inert image of each hidden pane is left behind, stepped back, visible through the expanded pane's glass. It is a\n * picture, not a control: stepped back, it shrinks inside the expanded pane's outline, which covers it, so a click\n * could never reach it (an earlier version offered one; a live probe found it unreachable). Returning to side by\n * side is the pane's own restore control, or Escape. The image travels forward and goes as the emphasis ends.\n * - **Swap.** A pane whose content changes in place dips back and returns (`dip`).\n *\n * Ghosts are aria-hidden and inert: they are pictures of panes, never a second copy anyone can use.\n */\nexport function usePaneDepth(\n rootRef: RefObject<HTMLElement | null>,\n settings: FocalPlaneSettings,\n reducedMotion: boolean,\n): { dip: (zone: string) => void } {\n useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root) return undefined;\n const back = root.querySelector<HTMLElement>('.fp-ghosts:not(.fp-ghosts-front)');\n const front = root.querySelector<HTMLElement>('.fp-ghosts-front');\n if (!back || !front) return undefined;\n const behind = new Map<Element, HTMLElement>();\n const motion = reducedMotion ? 0 : settings.motionMs;\n\n const place = (ghost: HTMLElement, rect: StageRect): void => {\n const vx = root.clientWidth * VANISHING_POINT.x;\n const vy = root.clientHeight * VANISHING_POINT.y;\n Object.assign(ghost.style, { left: `${rect.left}px`, top: `${rect.top}px`, width: `${rect.width}px`, height: `${rect.height}px` });\n ghost.style.setProperty('--fp-ox', `${vx - rect.left}px`);\n ghost.style.setProperty('--fp-oy', `${vy - rect.top}px`);\n };\n const inertCopy = (node: Element): HTMLElement => {\n const copy = node.cloneNode(true) as HTMLElement;\n sanitise(copy);\n return copy;\n };\n\n const discard = (node: HTMLElement): void => {\n const rect = lastStageRects.get(node);\n // Moved rather than removed (taken out and put back in one batch): it is still on screen, not discarded.\n if (!rect || motion === 0 || node.isConnected) return;\n const ghost = document.createElement('div');\n ghost.className = 'fp-ghost';\n sanitise(node);\n ghost.appendChild(node);\n place(ghost, rect);\n front.appendChild(ghost);\n requestAnimationFrame(() => requestAnimationFrame(() => {\n ghost.style.setProperty('--fp-z', `${-settings.layerDepthPx * 1.5}px`);\n ghost.style.opacity = '0';\n }));\n setTimeout(() => ghost.remove(), motion + 60);\n };\n\n const syncBehind = (): void => {\n const emphasized = root.querySelector('[data-zone-emphasized]');\n const hidden = emphasized ? [...root.querySelectorAll<HTMLElement>(FOCAL_PLANE_PANE_SELECTOR)].filter((pane) => pane.hasAttribute('data-zone-hidden')) : [];\n for (const [pane, ghost] of behind) {\n if (hidden.includes(pane as HTMLElement)) continue;\n behind.delete(pane);\n ghost.style.setProperty('--fp-z', '0px');\n ghost.style.opacity = '0';\n setTimeout(() => ghost.remove(), motion);\n }\n for (const pane of hidden) {\n if (behind.has(pane)) continue;\n const rect = lastStageRects.get(pane);\n if (!rect) continue;\n const ghost = document.createElement('div');\n ghost.className = 'fp-ghost fp-ghost-behind';\n const copy = inertCopy(pane);\n copy.classList.remove('hidden');\n copy.removeAttribute('data-zone-hidden');\n copy.style.width = '100%';\n copy.style.height = '100%';\n ghost.appendChild(copy);\n place(ghost, rect);\n ghost.style.opacity = '0';\n back.appendChild(ghost);\n behind.set(pane, ghost);\n requestAnimationFrame(() => requestAnimationFrame(() => {\n ghost.style.setProperty('--fp-z', `${-settings.layerDepthPx}px`);\n ghost.style.setProperty('--fp-filter', `brightness(${1 - settings.recedeDim}) saturate(${1 - settings.recedeDim * 0.9})`);\n ghost.style.opacity = '1';\n }));\n }\n };\n\n const observer = new MutationObserver((records) => {\n let emphasisMayHaveChanged = false;\n for (const record of records) {\n if (record.type === 'attributes') {\n emphasisMayHaveChanged = true;\n continue;\n }\n for (const node of record.removedNodes) {\n if (!(node instanceof HTMLElement)) continue;\n // A detached node matches no selector that names its ancestors, so the pane is recognised by the box the\n // stage last measured for it: only objects (a zone, or a resizable panel) have one.\n // Only a SIDE pane is ever dismissed. The primary pane leaves only when the content remounts (a breakpoint\n // flip to the single-zone branch), which is not a discard and must not fly a ghost away.\n if (lastStageRects.has(node) && isSidePane(node)) discard(node);\n }\n emphasisMayHaveChanged = true;\n }\n if (emphasisMayHaveChanged) syncBehind();\n });\n const content = root.querySelector(`[data-component-area=\"${ShellRegion.CONTENT}\"]`) ?? root;\n observer.observe(content, { childList: true, subtree: true, attributes: true, attributeFilter: ['data-zone-hidden', 'data-zone-emphasized'] });\n syncBehind();\n return () => {\n observer.disconnect();\n for (const ghost of behind.values()) ghost.remove();\n };\n }, [rootRef, settings, reducedMotion]);\n\n const dipRef = useRef<(zone: string) => void>(() => undefined);\n useEffect(() => {\n dipRef.current = (zone: string): void => {\n const root = rootRef.current;\n if (!root || reducedMotion) return;\n const pane = root.querySelector<HTMLElement>(`[data-component-area=\"${ShellRegion.CONTENT}\"] :is([data-content-area=\"${zone}\"]:not([data-panel-id] *), [data-panel-id=\"nav-${zone}\"])`);\n if (!pane || typeof pane.animate !== 'function') return;\n // Implicit first and last keyframes: the pane dips from, and returns to, whatever depth it rests at.\n pane.animate(\n [{ offset: 0.45, transform: `perspective(${settings.cameraDistancePx}px) translate3d(0, 0, ${-settings.layerDepthPx * 0.5}px)`, opacity: 0.55 }],\n { duration: settings.motionMs, easing: 'cubic-bezier(0.2, 0.9, 0.25, 1)' },\n );\n };\n }, [rootRef, settings, reducedMotion]);\n return { dip: (zone) => dipRef.current(zone) };\n}\n\nconst SIDE_ZONES: ReadonlySet<string> = new Set([NavigationZone.SECONDARY, NavigationZone.COMPANION]);\nfunction isSidePane(element: HTMLElement): boolean {\n const zone = element.dataset.contentArea ?? element.dataset.panelId?.replace(/^nav-/, '');\n return zone !== undefined && SIDE_ZONES.has(zone);\n}\n\n/**\n * Makes a pane a picture: no ids, no focus, invisible to assistive technology, and none of the markers a query for the\n * REAL pane would find (a document-level lookup of the primary pane must never return its image). Embedded frames and\n * media are dropped rather than loaded a second time.\n */\nfunction sanitise(element: HTMLElement): void {\n element.setAttribute('aria-hidden', 'true');\n element.setAttribute('inert', '');\n for (const node of [element, ...element.querySelectorAll<HTMLElement>('*')]) {\n for (const attribute of ['id', 'data-content-area', 'data-panel-id', 'data-zone-hidden', 'data-zone-emphasized', 'data-component-area']) node.removeAttribute(attribute);\n }\n for (const media of element.querySelectorAll('iframe, video, audio')) media.remove();\n}\n"]}
1
+ {"version":3,"file":"use-pane-depth.js","sourceRoot":"","sources":["../../../../src/focal-plane/use-pane-depth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAC;AAE3E,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAErE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAkB,MAAM,8BAA8B,CAAC;AAE/F;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAsC,EACtC,QAA4B,EAC5B,aAAsB;IAEtB,eAAe,CAAC,GAAG,EAAE;QACnB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,IAAI;YAAE,OAAO,SAAS,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAc,kCAAkC,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAc,kBAAkB,CAAC,CAAC;QAClE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QACtC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;QAC/C,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAErD,MAAM,KAAK,GAAG,CAAC,KAAkB,EAAE,IAAe,EAAQ,EAAE;YAC1D,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,GAAG,eAAe,CAAC,CAAC,CAAC;YAChD,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,GAAG,eAAe,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YACnI,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;YAC1D,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3D,CAAC,CAAC;QACF,MAAM,SAAS,GAAG,CAAC,IAAa,EAAe,EAAE;YAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAgB,CAAC;YACjD,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,CAAC,IAAiB,EAAQ,EAAE;YAC1C,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACtC,yGAAyG;YACzG,IAAI,CAAC,IAAI,IAAI,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW;gBAAE,OAAO;YACtD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC5C,KAAK,CAAC,SAAS,GAAG,UAAU,CAAC;YAC7B,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACxB,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACnB,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACzB,qBAAqB,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,GAAG,EAAE;gBACrD,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,YAAY,GAAG,GAAG,IAAI,CAAC,CAAC;gBACvE,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;YAC5B,CAAC,CAAC,CAAC,CAAC;YACJ,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;QAChD,CAAC,CAAC;QAEF,MAAM,UAAU,GAAG,GAAS,EAAE;YAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAC;YAChE,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAc,yBAAyB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5J,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;gBACnC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAmB,CAAC;oBAAE,SAAS;gBACnD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACpB,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBACzC,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;gBAC1B,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC;YAC3C,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;gBAC1B,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,SAAS;gBAC/B,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACtC,IAAI,CAAC,IAAI;oBAAE,SAAS;gBACpB,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;gBAC5C,KAAK,CAAC,SAAS,GAAG,0BAA0B,CAAC;gBAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;gBAC7B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAChC,IAAI,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC;gBACzC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC;gBAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;gBAC3B,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;gBACxB,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBACnB,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;gBAC1B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACxB,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBACxB,qBAAqB,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,GAAG,EAAE;oBACrD,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,YAAY,IAAI,CAAC,CAAC;oBACjE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,aAAa,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,SAAS,cAAc,CAAC,GAAG,QAAQ,CAAC,SAAS,GAAG,GAAG,GAAG,CAAC,CAAC;oBAC1H,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;gBAC5B,CAAC,CAAC,CAAC,CAAC;YACN,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,CAAC,OAAO,EAAE,EAAE;YAChD,IAAI,sBAAsB,GAAG,KAAK,CAAC;YACnC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBACjC,sBAAsB,GAAG,IAAI,CAAC;oBAC9B,SAAS;gBACX,CAAC;gBACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;oBACvC,IAAI,CAAC,CAAC,IAAI,YAAY,WAAW,CAAC;wBAAE,SAAS;oBAC7C,yGAAyG;oBACzG,oFAAoF;oBACpF,2GAA2G;oBAC3G,yFAAyF;oBACzF,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC;wBAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBAClE,CAAC;gBACD,sBAAsB,GAAG,IAAI,CAAC;YAChC,CAAC;YACD,IAAI,sBAAsB;gBAAE,UAAU,EAAE,CAAC;QAC3C,CAAC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,yBAAyB,WAAW,CAAC,OAAO,IAAI,CAAC,IAAI,IAAI,CAAC;QAC7F,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,kBAAkB,EAAE,sBAAsB,CAAC,EAAE,CAAC,CAAC;QAC/I,UAAU,EAAE,CAAC;QACb,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,UAAU,EAAE,CAAC;YACtB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE;gBAAE,KAAK,CAAC,MAAM,EAAE,CAAC;QACtD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;IAEvC,MAAM,MAAM,GAAG,MAAM,CAAyB,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC/D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,OAAO,GAAG,CAAC,IAAY,EAAQ,EAAE;YACtC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;YAC7B,IAAI,CAAC,IAAI,IAAI,aAAa;gBAAE,OAAO;YACnC,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAc,yBAAyB,WAAW,CAAC,OAAO,8BAA8B,IAAI,kDAAkD,IAAI,KAAK,CAAC,CAAC;YACxL,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,UAAU;gBAAE,OAAO;YACxD,qGAAqG;YACrG,IAAI,CAAC,OAAO,CACV,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,eAAe,QAAQ,CAAC,gBAAgB,yBAAyB,CAAC,QAAQ,CAAC,YAAY,GAAG,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAChJ,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAC3E,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;IACvC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,GAAwB,IAAI,GAAG,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC;AACtG,SAAS,UAAU,CAAC,OAAoB;IACtC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC1F,OAAO,IAAI,KAAK,SAAS,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,SAAS,QAAQ,CAAC,OAAoB;IACpC,OAAO,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAC5C,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAc,GAAG,CAAC,CAAC,EAAE,CAAC;QAC5E,KAAK,MAAM,SAAS,IAAI,CAAC,IAAI,EAAE,mBAAmB,EAAE,eAAe,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,qBAAqB,CAAC;YAAE,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IAC3K,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC,sBAAsB,CAAC;QAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AACvF,CAAC","sourcesContent":["import { useEffect, useLayoutEffect, useRef, type RefObject } from 'react';\n\nimport { ShellRegion } from '@wildo-ai/presets-components-models';\nimport { NavigationZone } from '@wildo-ai/saas-frontend-lib';\n\nimport { FOCAL_PLANE_PANE_SELECTOR } from './focal-plane-stylesheet';\nimport type { FocalPlaneSettings } from './focal-plane-settings';\nimport { lastStageRects, VANISHING_POINT, type StageRect } from './use-shared-vanishing-point';\n\n/**\n * What the stylesheet cannot do alone, because the engine unmounts or hides a pane at once (#2049 step 2):\n *\n * - **Discard.** A side pane dismissed by its close control is removed from the DOM immediately. The removed node,\n * no longer React's, is re-parented into a ghost layer at the box it last had, and flies away into depth and fades.\n * - **Expand.** An emphasized side pane takes the width, and the engine HIDES the other panes (`hidden`). A still,\n * inert image of each hidden pane is left behind, stepped back, visible through the expanded pane's glass. It is a\n * picture, not a control: stepped back, it shrinks inside the expanded pane's outline, which covers it, so a click\n * could never reach it (an earlier version offered one; a live probe found it unreachable). Returning to side by\n * side is the pane's own restore control, or Escape. The image travels forward and goes as the emphasis ends.\n * - **Swap.** A pane whose content changes in place dips back and returns (`dip`).\n *\n * Ghosts are aria-hidden and inert: they are pictures of panes, never a second copy anyone can use.\n */\nexport function usePaneDepth(\n rootRef: RefObject<HTMLElement | null>,\n settings: FocalPlaneSettings,\n reducedMotion: boolean,\n): { dip: (zone: string) => void } {\n useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root) return undefined;\n const back = root.querySelector<HTMLElement>('.fp-ghosts:not(.fp-ghosts-front)');\n const front = root.querySelector<HTMLElement>('.fp-ghosts-front');\n if (!back || !front) return undefined;\n const behind = new Map<Element, HTMLElement>();\n const motion = reducedMotion ? 0 : settings.motionMs;\n\n const place = (ghost: HTMLElement, rect: StageRect): void => {\n const vx = root.clientWidth * VANISHING_POINT.x;\n const vy = root.clientHeight * VANISHING_POINT.y;\n Object.assign(ghost.style, { left: `${rect.left}px`, top: `${rect.top}px`, width: `${rect.width}px`, height: `${rect.height}px` });\n ghost.style.setProperty('--fp-ox', `${vx - rect.left}px`);\n ghost.style.setProperty('--fp-oy', `${vy - rect.top}px`);\n };\n const inertCopy = (node: Element): HTMLElement => {\n const copy = node.cloneNode(true) as HTMLElement;\n sanitise(copy);\n return copy;\n };\n\n const discard = (node: HTMLElement): void => {\n const rect = lastStageRects.get(node);\n // Moved rather than removed (taken out and put back in one batch): it is still on screen, not discarded.\n if (!rect || motion === 0 || node.isConnected) return;\n const ghost = document.createElement('div');\n ghost.className = 'fp-ghost';\n sanitise(node);\n ghost.appendChild(node);\n place(ghost, rect);\n front.appendChild(ghost);\n requestAnimationFrame(() => requestAnimationFrame(() => {\n ghost.style.setProperty('--fp-z', `${-settings.layerDepthPx * 1.5}px`);\n ghost.style.opacity = '0';\n }));\n setTimeout(() => ghost.remove(), motion + 60);\n };\n\n const syncBehind = (): void => {\n const emphasized = root.querySelector('[data-zone-emphasized]');\n const hidden = emphasized ? [...root.querySelectorAll<HTMLElement>(FOCAL_PLANE_PANE_SELECTOR)].filter((pane) => pane.hasAttribute('data-zone-hidden')) : [];\n for (const [pane, ghost] of behind) {\n if (hidden.includes(pane as HTMLElement)) continue;\n behind.delete(pane);\n ghost.style.setProperty('--fp-z', '0px');\n ghost.style.opacity = '0';\n setTimeout(() => ghost.remove(), motion);\n }\n for (const pane of hidden) {\n if (behind.has(pane)) continue;\n const rect = lastStageRects.get(pane);\n if (!rect) continue;\n const ghost = document.createElement('div');\n ghost.className = 'fp-ghost fp-ghost-behind';\n const copy = inertCopy(pane);\n copy.classList.remove('hidden');\n copy.removeAttribute('data-zone-hidden');\n copy.style.width = '100%';\n copy.style.height = '100%';\n ghost.appendChild(copy);\n place(ghost, rect);\n ghost.style.opacity = '0';\n back.appendChild(ghost);\n behind.set(pane, ghost);\n requestAnimationFrame(() => requestAnimationFrame(() => {\n ghost.style.setProperty('--fp-z', `${-settings.layerDepthPx}px`);\n ghost.style.setProperty('--fp-filter', `brightness(${1 - settings.recedeDim}) saturate(${1 - settings.recedeDim * 0.9})`);\n ghost.style.opacity = '1';\n }));\n }\n };\n\n const observer = new MutationObserver((records) => {\n let emphasisMayHaveChanged = false;\n for (const record of records) {\n if (record.type === 'attributes') {\n emphasisMayHaveChanged = true;\n continue;\n }\n for (const node of record.removedNodes) {\n if (!(node instanceof HTMLElement)) continue;\n // A detached node matches no selector that names its ancestors, so the pane is recognised by the box the\n // stage last measured for it: only objects (a zone, or a resizable panel) have one.\n // Only a SIDE pane is ever dismissed. The primary pane leaves only when the content remounts (a breakpoint\n // flip to the single-zone branch), which is not a discard and must not fly a ghost away.\n if (lastStageRects.has(node) && isSidePane(node)) discard(node);\n }\n emphasisMayHaveChanged = true;\n }\n if (emphasisMayHaveChanged) syncBehind();\n });\n const content = root.querySelector(`[data-component-area=\"${ShellRegion.CONTENT}\"]`) ?? root;\n observer.observe(content, { childList: true, subtree: true, attributes: true, attributeFilter: ['data-zone-hidden', 'data-zone-emphasized'] });\n syncBehind();\n return () => {\n observer.disconnect();\n for (const ghost of behind.values()) ghost.remove();\n };\n }, [rootRef, settings, reducedMotion]);\n\n const dipRef = useRef<(zone: string) => void>(() => undefined);\n useEffect(() => {\n dipRef.current = (zone: string): void => {\n const root = rootRef.current;\n if (!root || reducedMotion) return;\n const pane = root.querySelector<HTMLElement>(`[data-component-area=\"${ShellRegion.CONTENT}\"] :is([data-content-area=\"${zone}\"]:not([data-panel-id] *), [data-panel-id=\"nav-${zone}\"])`);\n if (!pane || typeof pane.animate !== 'function') return;\n // Implicit first and last keyframes: the pane dips from, and returns to, whatever depth it rests at.\n pane.animate(\n [{ offset: 0.45, transform: `perspective(${settings.cameraDistancePx}px) translate3d(0, 0, ${-settings.layerDepthPx * 0.5}px)`, opacity: 0.55 }],\n { duration: settings.motionMs, easing: 'cubic-bezier(0.2, 0.9, 0.25, 1)' },\n );\n };\n }, [rootRef, settings, reducedMotion]);\n return { dip: (zone) => dipRef.current(zone) };\n}\n\nconst SIDE_ZONES: ReadonlySet<string> = new Set([NavigationZone.SECONDARY, NavigationZone.COMPANION]);\nfunction isSidePane(element: HTMLElement): boolean {\n const zone = element.dataset.contentArea ?? element.dataset.panelId?.replace(/^nav-/, '');\n return zone !== undefined && SIDE_ZONES.has(zone);\n}\n\n/**\n * Makes a pane a picture: no ids, no focus, invisible to assistive technology, and none of the markers a query for the\n * REAL pane would find (a document-level lookup of the primary pane must never return its image). Embedded frames and\n * media are dropped rather than loaded a second time.\n */\nfunction sanitise(element: HTMLElement): void {\n element.setAttribute('aria-hidden', 'true');\n element.setAttribute('inert', '');\n for (const node of [element, ...element.querySelectorAll<HTMLElement>('*')]) {\n for (const attribute of ['id', 'data-content-area', 'data-panel-id', 'data-zone-hidden', 'data-zone-emphasized', 'data-component-area']) node.removeAttribute(attribute);\n }\n for (const media of element.querySelectorAll('iframe, video, audio')) media.remove();\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-shared-vanishing-point.d.ts","sourceRoot":"","sources":["../../../src/focal-plane/use-shared-vanishing-point.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIxD,uHAAuH;AACvH,eAAO,MAAM,eAAe;;;CAAsB,CAAC;AAEnD,+EAA+E;AAC/E,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,6BAAoC,CAAC;AAEhE;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,IAAI,CAuCpF;AAED,iHAAiH;AACjH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAYnG"}
1
+ {"version":3,"file":"use-shared-vanishing-point.d.ts","sourceRoot":"","sources":["../../../../src/focal-plane/use-shared-vanishing-point.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIxD,uHAAuH;AACvH,eAAO,MAAM,eAAe;;;CAAsB,CAAC;AAEnD,+EAA+E;AAC/E,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,6BAAoC,CAAC;AAEhE;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,IAAI,CAuCpF;AAED,iHAAiH;AACjH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAYnG"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-shared-vanishing-point.js","sourceRoot":"","sources":["../../../src/focal-plane/use-shared-vanishing-point.ts"],"names":[],"mappings":"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","sourcesContent":["import { useLayoutEffect, type RefObject } from 'react';\n\nimport { FOCAL_PLANE_PANE_SELECTOR } from './focal-plane-stylesheet';\n\n/** Where the vanishing point sits in the stage: centred, a little above the middle (the eye line of the prototype). */\nexport const VANISHING_POINT = { x: 0.5, y: 0.42 };\n\n/** An object's laid-out box in the stage (untransformed), as last measured. */\nexport interface StageRect {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\n/**\n * The last laid-out box of every object, kept so a pane that has just been REMOVED or HIDDEN can still be drawn where\n * it was (its ghost flies into depth from there). A zero-size reading never replaces a real one: a hidden pane measures\n * as nothing, and its last visible box is the one that matters.\n */\nexport const lastStageRects = new WeakMap<Element, StageRect>();\n\n/**\n * Keeps every object's `transform-origin` on the stage's ONE vanishing point, so objects that each carry their own\n * `perspective()` are seen through a single still camera (see `focal-plane-stylesheet.ts`).\n *\n * The origin is written as two custom properties on each object (`--fp-ox`, `--fp-oy`): the vanishing point minus the\n * object's own offset in the stage. Offsets are read from `offsetLeft`/`offsetTop`, which ignore transforms, so an object\n * that is currently stepped back still reports where it is laid out. Custom properties written this way are left alone\n * by React, which only manages the style properties it set itself.\n */\nexport function useSharedVanishingPoint(rootRef: RefObject<HTMLElement | null>): void {\n useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root) return undefined;\n let frame = 0;\n // Absent in some environments (a test DOM): the window resize and the mutations below still re-measure.\n const resize = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => schedule());\n const observed = new Set<HTMLElement>();\n const measure = (): void => {\n frame = 0;\n const vx = root.clientWidth * VANISHING_POINT.x;\n const vy = root.clientHeight * VANISHING_POINT.y;\n const objects = new Set(root.querySelectorAll<HTMLElement>(`[data-fp-object], ${FOCAL_PLANE_PANE_SELECTOR}`));\n // Every object is observed, not only the stage: a sidebar collapsing MOVES the content column without resizing\n // the stage, and a moved object with a stale origin would be seen from the wrong point.\n for (const element of objects) if (!observed.has(element)) { resize?.observe(element); observed.add(element); }\n for (const element of observed) if (!objects.has(element)) { resize?.unobserve(element); observed.delete(element); }\n for (const element of objects) {\n const { left, top } = offsetWithin(element, root);\n element.style.setProperty('--fp-ox', `${(vx - left).toFixed(1)}px`);\n element.style.setProperty('--fp-oy', `${(vy - top).toFixed(1)}px`);\n if (element.offsetWidth > 0 && element.offsetHeight > 0) lastStageRects.set(element, { left, top, width: element.offsetWidth, height: element.offsetHeight });\n }\n };\n const schedule = (): void => {\n if (!frame) frame = requestAnimationFrame(measure);\n };\n measure();\n resize?.observe(root);\n const mutations = new MutationObserver(schedule);\n mutations.observe(root, { childList: true, subtree: true });\n window.addEventListener('resize', schedule);\n return () => {\n cancelAnimationFrame(frame);\n resize?.disconnect();\n mutations.disconnect();\n window.removeEventListener('resize', schedule);\n };\n }, [rootRef]);\n}\n\n/** An element's layout offset inside `root`, walking the offset-parent chain (transforms are not part of it). */\nexport function offsetWithin(element: HTMLElement, root: HTMLElement): { left: number; top: number } {\n let left = 0;\n let top = 0;\n let node: HTMLElement | null = element;\n while (node && node !== root) {\n left += node.offsetLeft;\n top += node.offsetTop;\n const parent = node.offsetParent as HTMLElement | null;\n if (!parent || !root.contains(parent) && parent !== root) break;\n node = parent;\n }\n return { left, top };\n}\n"]}
1
+ {"version":3,"file":"use-shared-vanishing-point.js","sourceRoot":"","sources":["../../../../src/focal-plane/use-shared-vanishing-point.ts"],"names":[],"mappings":"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","sourcesContent":["import { useLayoutEffect, type RefObject } from 'react';\n\nimport { FOCAL_PLANE_PANE_SELECTOR } from './focal-plane-stylesheet';\n\n/** Where the vanishing point sits in the stage: centred, a little above the middle (the eye line of the prototype). */\nexport const VANISHING_POINT = { x: 0.5, y: 0.42 };\n\n/** An object's laid-out box in the stage (untransformed), as last measured. */\nexport interface StageRect {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\n/**\n * The last laid-out box of every object, kept so a pane that has just been REMOVED or HIDDEN can still be drawn where\n * it was (its ghost flies into depth from there). A zero-size reading never replaces a real one: a hidden pane measures\n * as nothing, and its last visible box is the one that matters.\n */\nexport const lastStageRects = new WeakMap<Element, StageRect>();\n\n/**\n * Keeps every object's `transform-origin` on the stage's ONE vanishing point, so objects that each carry their own\n * `perspective()` are seen through a single still camera (see `focal-plane-stylesheet.ts`).\n *\n * The origin is written as two custom properties on each object (`--fp-ox`, `--fp-oy`): the vanishing point minus the\n * object's own offset in the stage. Offsets are read from `offsetLeft`/`offsetTop`, which ignore transforms, so an object\n * that is currently stepped back still reports where it is laid out. Custom properties written this way are left alone\n * by React, which only manages the style properties it set itself.\n */\nexport function useSharedVanishingPoint(rootRef: RefObject<HTMLElement | null>): void {\n useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root) return undefined;\n let frame = 0;\n // Absent in some environments (a test DOM): the window resize and the mutations below still re-measure.\n const resize = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => schedule());\n const observed = new Set<HTMLElement>();\n const measure = (): void => {\n frame = 0;\n const vx = root.clientWidth * VANISHING_POINT.x;\n const vy = root.clientHeight * VANISHING_POINT.y;\n const objects = new Set(root.querySelectorAll<HTMLElement>(`[data-fp-object], ${FOCAL_PLANE_PANE_SELECTOR}`));\n // Every object is observed, not only the stage: a sidebar collapsing MOVES the content column without resizing\n // the stage, and a moved object with a stale origin would be seen from the wrong point.\n for (const element of objects) if (!observed.has(element)) { resize?.observe(element); observed.add(element); }\n for (const element of observed) if (!objects.has(element)) { resize?.unobserve(element); observed.delete(element); }\n for (const element of objects) {\n const { left, top } = offsetWithin(element, root);\n element.style.setProperty('--fp-ox', `${(vx - left).toFixed(1)}px`);\n element.style.setProperty('--fp-oy', `${(vy - top).toFixed(1)}px`);\n if (element.offsetWidth > 0 && element.offsetHeight > 0) lastStageRects.set(element, { left, top, width: element.offsetWidth, height: element.offsetHeight });\n }\n };\n const schedule = (): void => {\n if (!frame) frame = requestAnimationFrame(measure);\n };\n measure();\n resize?.observe(root);\n const mutations = new MutationObserver(schedule);\n mutations.observe(root, { childList: true, subtree: true });\n window.addEventListener('resize', schedule);\n return () => {\n cancelAnimationFrame(frame);\n resize?.disconnect();\n mutations.disconnect();\n window.removeEventListener('resize', schedule);\n };\n }, [rootRef]);\n}\n\n/** An element's layout offset inside `root`, walking the offset-parent chain (transforms are not part of it). */\nexport function offsetWithin(element: HTMLElement, root: HTMLElement): { left: number; top: number } {\n let left = 0;\n let top = 0;\n let node: HTMLElement | null = element;\n while (node && node !== root) {\n left += node.offsetLeft;\n top += node.offsetTop;\n const parent = node.offsetParent as HTMLElement | null;\n if (!parent || !root.contains(parent) && parent !== root) break;\n node = parent;\n }\n return { left, top };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"frame-3d-style.d.ts","sourceRoot":"","sources":["../../../src/frame/frame-3d-style.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frame-3d-style.d.ts","sourceRoot":"","sources":["../../../../src/frame/frame-3d-style.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"frame-3d-style.js","sourceRoot":"","sources":["../../../src/frame/frame-3d-style.ts"],"names":[],"mappings":"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","sourcesContent":["import { DesignSystemToken, ShellRegion } from '@wildo-ai/presets-components-models';\n\n/** @wildo_source:part:start presets.3d.frame-style-overrides facet:layer:frontend facet:family:layout-3d facet:audience:app-developer */\n/**\n * What the frame draws under one shell region.\n *\n * A frame style is the 3D frame's OWN vocabulary: it says how a region's slab looks, never how the region\n * itself looks. The region stays the 2D preset's HTML, with its recipes and Tailwind classes untouched; the\n * engine's theme and recipe schemas are not extended for the frame.\n */\nexport enum Frame3DSurfaceKind {\n /** A frosted slab: a translucent tint over the in-scene background, with a rim and an optional shadow. */\n FROSTED = 'frosted',\n /** Nothing is drawn under the region. */\n NONE = 'none',\n}\n\n/** The rim: a thin edge line along the slab, emphasised while the pointer is over the region. */\nexport interface Frame3DRimStyle {\n /** The colour token of the rim. */\n token: DesignSystemToken;\n /** Rim opacity at rest, 0–1. */\n opacity: number;\n /** Rim opacity while the pointer is over the region, 0–1. The only thing hover changes. */\n hoverOpacity: number;\n /** Rim width as a multiple of the `border-width` token. */\n widthScale: number;\n}\n\n/** The slab's shadow, drawn on the scene background just outside the slab. Its colour is black. */\nexport interface Frame3DShadowStyle {\n offsetXPx: number;\n offsetYPx: number;\n /** Blur radius in CSS pixels; 0 draws a hard shadow. */\n blurPx: number;\n /** Shadow opacity, 0–1. */\n opacity: number;\n}\n\n/** How the frame draws under one region kind. */\nexport interface Frame3DRegionStyle {\n surface: Frame3DSurfaceKind;\n /** The colour token the frost is tinted with. Ignored when `tintColor` is set. */\n tintToken: DesignSystemToken;\n /**\n * An explicit CSS colour for the frost instead of a token: a brand colour, or the verification sentinel\n * ({@link createSentinelFrameStyles}). The contrast bound still applies to it.\n */\n tintColor?: string;\n /** Frost opacity over the scene background, 0–1. A glass theme's navigation material replaces it. */\n frost: number;\n /** How much lighter the lit side of the slab is than its shaded side, 0–1. */\n gradient: number;\n /** Corner radius as a multiple of the `radius` token. */\n radiusScale: number;\n rim: Frame3DRimStyle;\n shadow: Frame3DShadowStyle;\n}\n\n/** The in-scene background the slabs sit on: the page's own `backgroundLayer` cannot be sampled by WebGL. */\nexport interface Frame3DBackgroundStyle {\n /** The base colour token. */\n baseToken: DesignSystemToken;\n /** The token of the glow on the lit side. */\n glowToken: DesignSystemToken;\n /** Glow strength: how far the lit side moves from the base colour toward the glow colour, 0–1. */\n glow: number;\n}\n\n/** Everything the frame draws for one theme. `regions` is total over `ShellRegion`: a new region kind must be styled. */\nexport interface Frame3DThemeStyle {\n background: Frame3DBackgroundStyle;\n /**\n * The direction the light comes from, in degrees, y UP: 0 = from the right, 90 = from the top. (A glass\n * navigation material replaces it, converted from the engine's y-down convention.)\n */\n lightAngleDeg: number;\n /**\n * The colour of the light: the lit side of every slab moves toward it. `primary` by default — the colour the\n * background's glow uses too — so the lit side takes a cast of the theme's own light. (A surface token would be\n * the frost's own colour, and a slab lit by itself shows no gradient at all.)\n */\n lightToken: DesignSystemToken;\n /** In dark mode the lit side moves this share of the way it does in light mode (a dimmer light rig), 0–1. */\n darkModeLightStrength: number;\n regions: Record<ShellRegion, Frame3DRegionStyle>;\n}\n\n/**\n * The ids of the themes the framework ships, which the built-in frame styles are keyed on. Theme ids are an\n * open vocabulary (an application can author its own theme); any id not listed here takes the fallback style.\n */\nexport enum Frame3DBuiltInThemeId {\n DEFAULT = 'default',\n COZY = 'cozy',\n DENSE = 'dense',\n EDITORIAL = 'editorial',\n GLASS = 'glass',\n NEO_BRUTALIST = 'neo-brutalist',\n TERMINAL = 'terminal',\n TRADING = 'trading',\n}\n\n/** A partial frame style an application layers over a built-in one; nested objects merge key by key. */\nexport interface Frame3DThemeStyleOverride {\n background?: Partial<Frame3DBackgroundStyle>;\n lightAngleDeg?: number;\n lightToken?: DesignSystemToken;\n darkModeLightStrength?: number;\n regions?: Partial<Record<ShellRegion, Frame3DRegionStyleOverride>>;\n}\n\nexport type Frame3DRegionStyleOverride = Partial<Omit<Frame3DRegionStyle, 'rim' | 'shadow'>> & {\n rim?: Partial<Frame3DRimStyle>;\n shadow?: Partial<Frame3DShadowStyle>;\n};\n\n/**\n * An application's frame-style overrides, passed to `register3DLayout({ frameStyles })`. `all` applies to\n * every theme; `byThemeId` applies to one theme id and is layered after `all`.\n */\nexport interface Frame3DStyleOverrides {\n all?: Frame3DThemeStyleOverride;\n byThemeId?: Partial<Record<string, Frame3DThemeStyleOverride>>;\n}\n/** @wildo_source:part:end presets.3d.frame-style-overrides */\n\n/** The styles a layout's scene ships: one per built-in theme, and the fallback for any other theme id. */\nexport interface Frame3DStyleCatalog {\n byThemeId: Record<Frame3DBuiltInThemeId, Frame3DThemeStyle>;\n fallback: Frame3DThemeStyle;\n}\n\nconst NO_SHADOW: Frame3DShadowStyle = { offsetXPx: 0, offsetYPx: 0, blurPx: 0, opacity: 0 };\n\n/**\n * One theme's region table from a chrome style (the bars and rails) and a content style (the `<main>`). Written\n * as an object literal over every `ShellRegion` member, so a member added to the enum fails to compile here\n * instead of silently falling through to nothing.\n */\nfunction regionStyles(chrome: Frame3DRegionStyle, content: Frame3DRegionStyle): Record<ShellRegion, Frame3DRegionStyle> {\n return {\n [ShellRegion.MENUBAR]: chrome,\n [ShellRegion.SIDEBAR]: chrome,\n [ShellRegion.TOOLBAR]: chrome,\n [ShellRegion.ACTIVITY_BAR]: chrome,\n [ShellRegion.UTILITY_PANEL]: chrome,\n [ShellRegion.STATUS_BAR]: chrome,\n [ShellRegion.CONTENT]: content,\n };\n}\n\nfunction theme(input: {\n radiusScale: number;\n frost: number;\n contentFrost: number;\n gradient: number;\n rim: Frame3DRimStyle;\n shadow: Frame3DShadowStyle;\n glow: number;\n glowToken?: DesignSystemToken;\n lightAngleDeg?: number;\n}): Frame3DThemeStyle {\n const chrome: Frame3DRegionStyle = {\n surface: Frame3DSurfaceKind.FROSTED,\n tintToken: DesignSystemToken.SURFACE_RAISED,\n frost: input.frost,\n gradient: input.gradient,\n radiusScale: input.radiusScale,\n rim: input.rim,\n shadow: input.shadow,\n };\n const content: Frame3DRegionStyle = { ...chrome, tintToken: DesignSystemToken.SURFACE_DEFAULT, frost: input.contentFrost };\n return {\n background: { baseToken: DesignSystemToken.BACKGROUND, glowToken: input.glowToken ?? DesignSystemToken.PRIMARY, glow: input.glow },\n lightAngleDeg: input.lightAngleDeg ?? 110,\n lightToken: DesignSystemToken.PRIMARY,\n darkModeLightStrength: 0.5,\n regions: regionStyles(chrome, content),\n };\n}\n\nconst DEFAULT_STYLE = theme({\n radiusScale: 1,\n frost: 0.5,\n contentFrost: 0.55,\n gradient: 0.06,\n rim: { token: DesignSystemToken.BORDER, opacity: 0.5, hoverOpacity: 0.9, widthScale: 1 },\n shadow: { offsetXPx: 0, offsetYPx: 6, blurPx: 18, opacity: 0.12 },\n glow: 0.08,\n});\n\n/**\n * The INHERIT layout's styles. Each built-in entry expresses its theme's character in the frame's own terms:\n * cozy is softer and rounder, dense and trading are tight and flat, editorial is nearly square and quiet,\n * neo-brutalist is solid with a heavy rim and a hard offset shadow, terminal is square with a primary rim.\n * Colours always come from the tokens; a style only chooses WHICH token and how strongly.\n */\nexport const INHERIT_FRAME_STYLES: Frame3DStyleCatalog = {\n byThemeId: {\n [Frame3DBuiltInThemeId.DEFAULT]: DEFAULT_STYLE,\n [Frame3DBuiltInThemeId.COZY]: theme({\n radiusScale: 1.5,\n frost: 0.6,\n contentFrost: 0.62,\n gradient: 0.08,\n rim: { token: DesignSystemToken.BORDER, opacity: 0.35, hoverOpacity: 0.75, widthScale: 1 },\n shadow: { offsetXPx: 0, offsetYPx: 10, blurPx: 28, opacity: 0.1 },\n glow: 0.1,\n }),\n [Frame3DBuiltInThemeId.DENSE]: theme({\n radiusScale: 0.5,\n frost: 0.4,\n contentFrost: 0.45,\n gradient: 0.03,\n rim: { token: DesignSystemToken.BORDER, opacity: 0.6, hoverOpacity: 0.9, widthScale: 1 },\n shadow: NO_SHADOW,\n glow: 0.04,\n }),\n [Frame3DBuiltInThemeId.EDITORIAL]: theme({\n radiusScale: 0.25,\n frost: 0.3,\n contentFrost: 0.35,\n gradient: 0,\n rim: { token: DesignSystemToken.BORDER, opacity: 0.25, hoverOpacity: 0.5, widthScale: 1 },\n shadow: NO_SHADOW,\n glow: 0.03,\n }),\n [Frame3DBuiltInThemeId.GLASS]: theme({\n radiusScale: 1.25,\n frost: 0.3,\n contentFrost: 0.35,\n gradient: 0.12,\n rim: { token: DesignSystemToken.BORDER_STRONG, opacity: 0.6, hoverOpacity: 1, widthScale: 1 },\n shadow: { offsetXPx: 0, offsetYPx: 8, blurPx: 24, opacity: 0.15 },\n glow: 0.14,\n }),\n [Frame3DBuiltInThemeId.NEO_BRUTALIST]: theme({\n radiusScale: 0,\n frost: 0.92,\n contentFrost: 0.92,\n gradient: 0,\n rim: { token: DesignSystemToken.FOREGROUND, opacity: 1, hoverOpacity: 1, widthScale: 2 },\n shadow: { offsetXPx: 4, offsetYPx: 4, blurPx: 0, opacity: 1 },\n glow: 0,\n }),\n [Frame3DBuiltInThemeId.TERMINAL]: theme({\n radiusScale: 0,\n frost: 0.25,\n contentFrost: 0.3,\n gradient: 0,\n rim: { token: DesignSystemToken.PRIMARY, opacity: 0.5, hoverOpacity: 0.9, widthScale: 1 },\n shadow: NO_SHADOW,\n glow: 0.12,\n }),\n [Frame3DBuiltInThemeId.TRADING]: theme({\n radiusScale: 0.5,\n frost: 0.45,\n contentFrost: 0.5,\n gradient: 0.02,\n rim: { token: DesignSystemToken.BORDER, opacity: 0.45, hoverOpacity: 0.8, widthScale: 1 },\n shadow: NO_SHADOW,\n glow: 0.05,\n }),\n },\n fallback: DEFAULT_STYLE,\n};\n\n/**\n * The HEADER_FIRST layout's styles: the INHERIT styles, lit from straight above — the menubar spans the whole\n * width over the rails in that disposal, so the light falls from the header down.\n */\nexport const HEADER_FIRST_FRAME_STYLES: Frame3DStyleCatalog = withLightAngle(INHERIT_FRAME_STYLES, 90);\n\nfunction withLightAngle(catalog: Frame3DStyleCatalog, lightAngleDeg: number): Frame3DStyleCatalog {\n const byThemeId = {} as Record<Frame3DBuiltInThemeId, Frame3DThemeStyle>;\n for (const id of Object.values(Frame3DBuiltInThemeId)) byThemeId[id] = { ...catalog.byThemeId[id], lightAngleDeg };\n return { byThemeId, fallback: { ...catalog.fallback, lightAngleDeg } };\n}\n\nfunction isBuiltInThemeId(id: string): id is Frame3DBuiltInThemeId {\n return (Object.values(Frame3DBuiltInThemeId) as string[]).includes(id);\n}\n\nfunction mergeTheme(base: Frame3DThemeStyle, override: Frame3DThemeStyleOverride | undefined): Frame3DThemeStyle {\n if (!override) return base;\n const regions = { ...base.regions };\n for (const region of Object.values(ShellRegion)) {\n const regionOverride = override.regions?.[region];\n if (!regionOverride) continue;\n const current = regions[region];\n regions[region] = {\n ...current,\n ...regionOverride,\n rim: { ...current.rim, ...regionOverride.rim },\n shadow: { ...current.shadow, ...regionOverride.shadow },\n };\n }\n return {\n background: { ...base.background, ...override.background },\n lightAngleDeg: override.lightAngleDeg ?? base.lightAngleDeg,\n lightToken: override.lightToken ?? base.lightToken,\n darkModeLightStrength: override.darkModeLightStrength ?? base.darkModeLightStrength,\n regions,\n };\n}\n\n/**\n * The frame style for the active theme: the layout's catalog entry for a built-in theme id (its fallback for any\n * other id), then the application's `all` override, then its override for that theme id.\n */\nexport function resolveFrame3DThemeStyle(catalog: Frame3DStyleCatalog, themeId: string, overrides?: Frame3DStyleOverrides): Frame3DThemeStyle {\n const base = isBuiltInThemeId(themeId) ? catalog.byThemeId[themeId] : catalog.fallback;\n return mergeTheme(mergeTheme(base, overrides?.all), overrides?.byThemeId?.[themeId]);\n}\n\n/**\n * The frame's verification sentinel: a neon green (`#39ff14`) that appears in no theme, token or palette in the\n * framework or the dogfood applications (checked 2026-09-29 by a repository search).\n *\n * That absence is the point. A cover check counts sentinel pixels in a screenshot: one where a region is\n * transparent over its slab is expected, one over a region's CONTENT means the canvas covered it — and a colour\n * a theme could also produce would make that count meaningless.\n */\nexport const FRAME_SENTINEL_COLOR = '#39ff14';\n\n/**\n * Frame-style overrides that draw every region as a flat, square, rimless, shadowless slab in\n * {@link FRAME_SENTINEL_COLOR}, for a cover-and-alignment check: `register3DLayout({ frameStyles:\n * createSentinelFrameStyles() })`. The contrast bound still applies, so run the check where the sentinel passes\n * it against the foreground (a light mode, whose foreground is dark) — and assert the sentinel is actually\n * visible where regions are transparent, or a bound-adjusted colour would read as \"nothing covered\".\n */\nexport function createSentinelFrameStyles(): Frame3DStyleOverrides {\n const sentinel: Frame3DRegionStyleOverride = {\n surface: Frame3DSurfaceKind.FROSTED,\n tintColor: FRAME_SENTINEL_COLOR,\n frost: 1,\n gradient: 0,\n radiusScale: 0,\n rim: { opacity: 0, hoverOpacity: 0 },\n shadow: NO_SHADOW,\n };\n const regions: Partial<Record<ShellRegion, Frame3DRegionStyleOverride>> = {};\n for (const region of Object.values(ShellRegion)) regions[region] = sentinel;\n return { all: { regions } };\n}\n"]}
1
+ {"version":3,"file":"frame-3d-style.js","sourceRoot":"","sources":["../../../../src/frame/frame-3d-style.ts"],"names":[],"mappings":"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","sourcesContent":["import { DesignSystemToken, ShellRegion } from '@wildo-ai/presets-components-models';\n\n/** @wildo_source:part:start presets.3d.frame-style-overrides facet:layer:frontend facet:family:layout-3d facet:audience:app-developer */\n/**\n * What the frame draws under one shell region.\n *\n * A frame style is the 3D frame's OWN vocabulary: it says how a region's slab looks, never how the region\n * itself looks. The region stays the 2D preset's HTML, with its recipes and Tailwind classes untouched; the\n * engine's theme and recipe schemas are not extended for the frame.\n */\nexport enum Frame3DSurfaceKind {\n /** A frosted slab: a translucent tint over the in-scene background, with a rim and an optional shadow. */\n FROSTED = 'frosted',\n /** Nothing is drawn under the region. */\n NONE = 'none',\n}\n\n/** The rim: a thin edge line along the slab, emphasised while the pointer is over the region. */\nexport interface Frame3DRimStyle {\n /** The colour token of the rim. */\n token: DesignSystemToken;\n /** Rim opacity at rest, 0–1. */\n opacity: number;\n /** Rim opacity while the pointer is over the region, 0–1. The only thing hover changes. */\n hoverOpacity: number;\n /** Rim width as a multiple of the `border-width` token. */\n widthScale: number;\n}\n\n/** The slab's shadow, drawn on the scene background just outside the slab. Its colour is black. */\nexport interface Frame3DShadowStyle {\n offsetXPx: number;\n offsetYPx: number;\n /** Blur radius in CSS pixels; 0 draws a hard shadow. */\n blurPx: number;\n /** Shadow opacity, 0–1. */\n opacity: number;\n}\n\n/** How the frame draws under one region kind. */\nexport interface Frame3DRegionStyle {\n surface: Frame3DSurfaceKind;\n /** The colour token the frost is tinted with. Ignored when `tintColor` is set. */\n tintToken: DesignSystemToken;\n /**\n * An explicit CSS colour for the frost instead of a token: a brand colour, or the verification sentinel\n * ({@link createSentinelFrameStyles}). The contrast bound still applies to it.\n */\n tintColor?: string;\n /** Frost opacity over the scene background, 0–1. A glass theme's navigation material replaces it. */\n frost: number;\n /** How much lighter the lit side of the slab is than its shaded side, 0–1. */\n gradient: number;\n /** Corner radius as a multiple of the `radius` token. */\n radiusScale: number;\n rim: Frame3DRimStyle;\n shadow: Frame3DShadowStyle;\n}\n\n/** The in-scene background the slabs sit on: the page's own `backgroundLayer` cannot be sampled by WebGL. */\nexport interface Frame3DBackgroundStyle {\n /** The base colour token. */\n baseToken: DesignSystemToken;\n /** The token of the glow on the lit side. */\n glowToken: DesignSystemToken;\n /** Glow strength: how far the lit side moves from the base colour toward the glow colour, 0–1. */\n glow: number;\n}\n\n/** Everything the frame draws for one theme. `regions` is total over `ShellRegion`: a new region kind must be styled. */\nexport interface Frame3DThemeStyle {\n background: Frame3DBackgroundStyle;\n /**\n * The direction the light comes from, in degrees, y UP: 0 = from the right, 90 = from the top. (A glass\n * navigation material replaces it, converted from the engine's y-down convention.)\n */\n lightAngleDeg: number;\n /**\n * The colour of the light: the lit side of every slab moves toward it. `primary` by default — the colour the\n * background's glow uses too — so the lit side takes a cast of the theme's own light. (A surface token would be\n * the frost's own colour, and a slab lit by itself shows no gradient at all.)\n */\n lightToken: DesignSystemToken;\n /** In dark mode the lit side moves this share of the way it does in light mode (a dimmer light rig), 0–1. */\n darkModeLightStrength: number;\n regions: Record<ShellRegion, Frame3DRegionStyle>;\n}\n\n/**\n * The ids of the themes the framework ships, which the built-in frame styles are keyed on. Theme ids are an\n * open vocabulary (an application can author its own theme); any id not listed here takes the fallback style.\n */\nexport enum Frame3DBuiltInThemeId {\n DEFAULT = 'default',\n COZY = 'cozy',\n DENSE = 'dense',\n EDITORIAL = 'editorial',\n GLASS = 'glass',\n NEO_BRUTALIST = 'neo-brutalist',\n TERMINAL = 'terminal',\n TRADING = 'trading',\n}\n\n/** A partial frame style an application layers over a built-in one; nested objects merge key by key. */\nexport interface Frame3DThemeStyleOverride {\n background?: Partial<Frame3DBackgroundStyle>;\n lightAngleDeg?: number;\n lightToken?: DesignSystemToken;\n darkModeLightStrength?: number;\n regions?: Partial<Record<ShellRegion, Frame3DRegionStyleOverride>>;\n}\n\nexport type Frame3DRegionStyleOverride = Partial<Omit<Frame3DRegionStyle, 'rim' | 'shadow'>> & {\n rim?: Partial<Frame3DRimStyle>;\n shadow?: Partial<Frame3DShadowStyle>;\n};\n\n/**\n * An application's frame-style overrides, passed to `register3DLayout({ frameStyles })`. `all` applies to\n * every theme; `byThemeId` applies to one theme id and is layered after `all`.\n */\nexport interface Frame3DStyleOverrides {\n all?: Frame3DThemeStyleOverride;\n byThemeId?: Partial<Record<string, Frame3DThemeStyleOverride>>;\n}\n/** @wildo_source:part:end presets.3d.frame-style-overrides */\n\n/** The styles a layout's scene ships: one per built-in theme, and the fallback for any other theme id. */\nexport interface Frame3DStyleCatalog {\n byThemeId: Record<Frame3DBuiltInThemeId, Frame3DThemeStyle>;\n fallback: Frame3DThemeStyle;\n}\n\nconst NO_SHADOW: Frame3DShadowStyle = { offsetXPx: 0, offsetYPx: 0, blurPx: 0, opacity: 0 };\n\n/**\n * One theme's region table from a chrome style (the bars and rails) and a content style (the `<main>`). Written\n * as an object literal over every `ShellRegion` member, so a member added to the enum fails to compile here\n * instead of silently falling through to nothing.\n */\nfunction regionStyles(chrome: Frame3DRegionStyle, content: Frame3DRegionStyle): Record<ShellRegion, Frame3DRegionStyle> {\n return {\n [ShellRegion.MENUBAR]: chrome,\n [ShellRegion.SIDEBAR]: chrome,\n [ShellRegion.TOOLBAR]: chrome,\n [ShellRegion.ACTIVITY_BAR]: chrome,\n [ShellRegion.UTILITY_PANEL]: chrome,\n [ShellRegion.STATUS_BAR]: chrome,\n [ShellRegion.CONTENT]: content,\n };\n}\n\nfunction theme(input: {\n radiusScale: number;\n frost: number;\n contentFrost: number;\n gradient: number;\n rim: Frame3DRimStyle;\n shadow: Frame3DShadowStyle;\n glow: number;\n glowToken?: DesignSystemToken;\n lightAngleDeg?: number;\n}): Frame3DThemeStyle {\n const chrome: Frame3DRegionStyle = {\n surface: Frame3DSurfaceKind.FROSTED,\n tintToken: DesignSystemToken.SURFACE_RAISED,\n frost: input.frost,\n gradient: input.gradient,\n radiusScale: input.radiusScale,\n rim: input.rim,\n shadow: input.shadow,\n };\n const content: Frame3DRegionStyle = { ...chrome, tintToken: DesignSystemToken.SURFACE_DEFAULT, frost: input.contentFrost };\n return {\n background: { baseToken: DesignSystemToken.BACKGROUND, glowToken: input.glowToken ?? DesignSystemToken.PRIMARY, glow: input.glow },\n lightAngleDeg: input.lightAngleDeg ?? 110,\n lightToken: DesignSystemToken.PRIMARY,\n darkModeLightStrength: 0.5,\n regions: regionStyles(chrome, content),\n };\n}\n\nconst DEFAULT_STYLE = theme({\n radiusScale: 1,\n frost: 0.5,\n contentFrost: 0.55,\n gradient: 0.06,\n rim: { token: DesignSystemToken.BORDER, opacity: 0.5, hoverOpacity: 0.9, widthScale: 1 },\n shadow: { offsetXPx: 0, offsetYPx: 6, blurPx: 18, opacity: 0.12 },\n glow: 0.08,\n});\n\n/**\n * The INHERIT layout's styles. Each built-in entry expresses its theme's character in the frame's own terms:\n * cozy is softer and rounder, dense and trading are tight and flat, editorial is nearly square and quiet,\n * neo-brutalist is solid with a heavy rim and a hard offset shadow, terminal is square with a primary rim.\n * Colours always come from the tokens; a style only chooses WHICH token and how strongly.\n */\nexport const INHERIT_FRAME_STYLES: Frame3DStyleCatalog = {\n byThemeId: {\n [Frame3DBuiltInThemeId.DEFAULT]: DEFAULT_STYLE,\n [Frame3DBuiltInThemeId.COZY]: theme({\n radiusScale: 1.5,\n frost: 0.6,\n contentFrost: 0.62,\n gradient: 0.08,\n rim: { token: DesignSystemToken.BORDER, opacity: 0.35, hoverOpacity: 0.75, widthScale: 1 },\n shadow: { offsetXPx: 0, offsetYPx: 10, blurPx: 28, opacity: 0.1 },\n glow: 0.1,\n }),\n [Frame3DBuiltInThemeId.DENSE]: theme({\n radiusScale: 0.5,\n frost: 0.4,\n contentFrost: 0.45,\n gradient: 0.03,\n rim: { token: DesignSystemToken.BORDER, opacity: 0.6, hoverOpacity: 0.9, widthScale: 1 },\n shadow: NO_SHADOW,\n glow: 0.04,\n }),\n [Frame3DBuiltInThemeId.EDITORIAL]: theme({\n radiusScale: 0.25,\n frost: 0.3,\n contentFrost: 0.35,\n gradient: 0,\n rim: { token: DesignSystemToken.BORDER, opacity: 0.25, hoverOpacity: 0.5, widthScale: 1 },\n shadow: NO_SHADOW,\n glow: 0.03,\n }),\n [Frame3DBuiltInThemeId.GLASS]: theme({\n radiusScale: 1.25,\n frost: 0.3,\n contentFrost: 0.35,\n gradient: 0.12,\n rim: { token: DesignSystemToken.BORDER_STRONG, opacity: 0.6, hoverOpacity: 1, widthScale: 1 },\n shadow: { offsetXPx: 0, offsetYPx: 8, blurPx: 24, opacity: 0.15 },\n glow: 0.14,\n }),\n [Frame3DBuiltInThemeId.NEO_BRUTALIST]: theme({\n radiusScale: 0,\n frost: 0.92,\n contentFrost: 0.92,\n gradient: 0,\n rim: { token: DesignSystemToken.FOREGROUND, opacity: 1, hoverOpacity: 1, widthScale: 2 },\n shadow: { offsetXPx: 4, offsetYPx: 4, blurPx: 0, opacity: 1 },\n glow: 0,\n }),\n [Frame3DBuiltInThemeId.TERMINAL]: theme({\n radiusScale: 0,\n frost: 0.25,\n contentFrost: 0.3,\n gradient: 0,\n rim: { token: DesignSystemToken.PRIMARY, opacity: 0.5, hoverOpacity: 0.9, widthScale: 1 },\n shadow: NO_SHADOW,\n glow: 0.12,\n }),\n [Frame3DBuiltInThemeId.TRADING]: theme({\n radiusScale: 0.5,\n frost: 0.45,\n contentFrost: 0.5,\n gradient: 0.02,\n rim: { token: DesignSystemToken.BORDER, opacity: 0.45, hoverOpacity: 0.8, widthScale: 1 },\n shadow: NO_SHADOW,\n glow: 0.05,\n }),\n },\n fallback: DEFAULT_STYLE,\n};\n\n/**\n * The HEADER_FIRST layout's styles: the INHERIT styles, lit from straight above — the menubar spans the whole\n * width over the rails in that disposal, so the light falls from the header down.\n */\nexport const HEADER_FIRST_FRAME_STYLES: Frame3DStyleCatalog = withLightAngle(INHERIT_FRAME_STYLES, 90);\n\nfunction withLightAngle(catalog: Frame3DStyleCatalog, lightAngleDeg: number): Frame3DStyleCatalog {\n const byThemeId = {} as Record<Frame3DBuiltInThemeId, Frame3DThemeStyle>;\n for (const id of Object.values(Frame3DBuiltInThemeId)) byThemeId[id] = { ...catalog.byThemeId[id], lightAngleDeg };\n return { byThemeId, fallback: { ...catalog.fallback, lightAngleDeg } };\n}\n\nfunction isBuiltInThemeId(id: string): id is Frame3DBuiltInThemeId {\n return (Object.values(Frame3DBuiltInThemeId) as string[]).includes(id);\n}\n\nfunction mergeTheme(base: Frame3DThemeStyle, override: Frame3DThemeStyleOverride | undefined): Frame3DThemeStyle {\n if (!override) return base;\n const regions = { ...base.regions };\n for (const region of Object.values(ShellRegion)) {\n const regionOverride = override.regions?.[region];\n if (!regionOverride) continue;\n const current = regions[region];\n regions[region] = {\n ...current,\n ...regionOverride,\n rim: { ...current.rim, ...regionOverride.rim },\n shadow: { ...current.shadow, ...regionOverride.shadow },\n };\n }\n return {\n background: { ...base.background, ...override.background },\n lightAngleDeg: override.lightAngleDeg ?? base.lightAngleDeg,\n lightToken: override.lightToken ?? base.lightToken,\n darkModeLightStrength: override.darkModeLightStrength ?? base.darkModeLightStrength,\n regions,\n };\n}\n\n/**\n * The frame style for the active theme: the layout's catalog entry for a built-in theme id (its fallback for any\n * other id), then the application's `all` override, then its override for that theme id.\n */\nexport function resolveFrame3DThemeStyle(catalog: Frame3DStyleCatalog, themeId: string, overrides?: Frame3DStyleOverrides): Frame3DThemeStyle {\n const base = isBuiltInThemeId(themeId) ? catalog.byThemeId[themeId] : catalog.fallback;\n return mergeTheme(mergeTheme(base, overrides?.all), overrides?.byThemeId?.[themeId]);\n}\n\n/**\n * The frame's verification sentinel: a neon green (`#39ff14`) that appears in no theme, token or palette in the\n * framework or the dogfood applications (checked 2026-09-29 by a repository search).\n *\n * That absence is the point. A cover check counts sentinel pixels in a screenshot: one where a region is\n * transparent over its slab is expected, one over a region's CONTENT means the canvas covered it — and a colour\n * a theme could also produce would make that count meaningless.\n */\nexport const FRAME_SENTINEL_COLOR = '#39ff14';\n\n/**\n * Frame-style overrides that draw every region as a flat, square, rimless, shadowless slab in\n * {@link FRAME_SENTINEL_COLOR}, for a cover-and-alignment check: `register3DLayout({ frameStyles:\n * createSentinelFrameStyles() })`. The contrast bound still applies, so run the check where the sentinel passes\n * it against the foreground (a light mode, whose foreground is dark) — and assert the sentinel is actually\n * visible where regions are transparent, or a bound-adjusted colour would read as \"nothing covered\".\n */\nexport function createSentinelFrameStyles(): Frame3DStyleOverrides {\n const sentinel: Frame3DRegionStyleOverride = {\n surface: Frame3DSurfaceKind.FROSTED,\n tintColor: FRAME_SENTINEL_COLOR,\n frost: 1,\n gradient: 0,\n radiusScale: 0,\n rim: { opacity: 0, hoverOpacity: 0 },\n shadow: NO_SHADOW,\n };\n const regions: Partial<Record<ShellRegion, Frame3DRegionStyleOverride>> = {};\n for (const region of Object.values(ShellRegion)) regions[region] = sentinel;\n return { all: { regions } };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"frame-appearance.d.ts","sourceRoot":"","sources":["../../../src/frame/frame-appearance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAgB,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAEzH,OAAO,EAA+C,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACvG,OAAO,EAAgG,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAC9I,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAExG,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,8FAA8F;AAC9F,MAAM,WAAW,mBAAmB;IAClC,qFAAqF;IACrF,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,QAAQ,EAAE,UAAU,CAAC;IACrB,iCAAiC;IACjC,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,UAAU,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,yDAAyD;AACzD,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpE,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,4GAA4G;IAC5G,UAAU,EAAE,UAAU,CAAC;IACvB,0DAA0D;IAC1D,UAAU,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,EAAE,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IACxD,4GAA4G;IAC5G,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAClD,oEAAoE;IACpE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,WAAW,CAAC;IAC9B,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,sGAAsG;IACtG,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,oGAAoG;IACpG,aAAa,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,WAAW,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,CAAC;IACnE,KAAK,EAAE,iBAAiB,CAAC;IACzB,iGAAiG;IACjG,kBAAkB,EAAE,eAAe,GAAG,SAAS,CAAC;IAChD,mGAAmG;IACnG,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IAChF,MAAM,EAAE,OAAO,CAAC;IAChB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,sEAAsE;IACtE,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAmB1C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,GAAG,IAAI,CA6G3F"}
1
+ {"version":3,"file":"frame-appearance.d.ts","sourceRoot":"","sources":["../../../../src/frame/frame-appearance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAgB,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAEzH,OAAO,EAA+C,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACvG,OAAO,EAAgG,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAC9I,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAExG,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,8FAA8F;AAC9F,MAAM,WAAW,mBAAmB;IAClC,qFAAqF;IACrF,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,QAAQ,EAAE,UAAU,CAAC;IACrB,iCAAiC;IACjC,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,UAAU,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,yDAAyD;AACzD,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpE,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,4GAA4G;IAC5G,UAAU,EAAE,UAAU,CAAC;IACvB,0DAA0D;IAC1D,UAAU,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,EAAE,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IACxD,4GAA4G;IAC5G,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAClD,oEAAoE;IACpE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,WAAW,CAAC;IAC9B,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,sGAAsG;IACtG,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,oGAAoG;IACpG,aAAa,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,WAAW,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,CAAC;IACnE,KAAK,EAAE,iBAAiB,CAAC;IACzB,iGAAiG;IACjG,kBAAkB,EAAE,eAAe,GAAG,SAAS,CAAC;IAChD,mGAAmG;IACnG,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IAChF,MAAM,EAAE,OAAO,CAAC;IAChB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,sEAAsE;IACtE,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAmB1C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,GAAG,IAAI,CA6G3F"}