@treasuryspatial/viewer-ui-kit 0.1.41 → 0.1.56

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 (90) hide show
  1. package/dist/AdminLayout.js +1 -1
  2. package/dist/AdminShell.d.ts +6 -1
  3. package/dist/AdminShell.d.ts.map +1 -1
  4. package/dist/AdminShell.js +45 -3
  5. package/dist/ChooserActionCard.d.ts +10 -0
  6. package/dist/ChooserActionCard.d.ts.map +1 -0
  7. package/dist/ChooserActionCard.js +39 -0
  8. package/dist/ComposerRightRail.d.ts +3 -1
  9. package/dist/ComposerRightRail.d.ts.map +1 -1
  10. package/dist/ComposerRightRail.js +11 -43
  11. package/dist/ConfiguratorShell.js +1 -1
  12. package/dist/LandingShell.d.ts +2 -1
  13. package/dist/LandingShell.d.ts.map +1 -1
  14. package/dist/LandingShell.js +162 -32
  15. package/dist/LoginForm.js +2 -2
  16. package/dist/LoginShell.d.ts +2 -1
  17. package/dist/LoginShell.d.ts.map +1 -1
  18. package/dist/LoginShell.js +38 -15
  19. package/dist/ManifestTopBar.d.ts +7 -1
  20. package/dist/ManifestTopBar.d.ts.map +1 -1
  21. package/dist/ManifestTopBar.js +249 -38
  22. package/dist/MetricsPanel.d.ts +1 -1
  23. package/dist/MetricsPanel.d.ts.map +1 -1
  24. package/dist/MetricsPanel.js +19 -29
  25. package/dist/MetricsPanelContent.d.ts +38 -17
  26. package/dist/MetricsPanelContent.d.ts.map +1 -1
  27. package/dist/MetricsPanelContent.js +84 -90
  28. package/dist/ModeBar.d.ts +6 -2
  29. package/dist/ModeBar.d.ts.map +1 -1
  30. package/dist/ModeBar.js +49 -82
  31. package/dist/ModuleSelectorPanel.d.ts +2 -1
  32. package/dist/ModuleSelectorPanel.d.ts.map +1 -1
  33. package/dist/ModuleSelectorPanel.js +47 -49
  34. package/dist/PanelSkin.d.ts.map +1 -1
  35. package/dist/PanelSkin.js +1598 -312
  36. package/dist/PanelSystem.d.ts +45 -0
  37. package/dist/PanelSystem.d.ts.map +1 -0
  38. package/dist/PanelSystem.js +450 -0
  39. package/dist/PanelTabs.d.ts.map +1 -1
  40. package/dist/PanelTabs.js +8 -34
  41. package/dist/PanelToggleDock.d.ts +10 -0
  42. package/dist/PanelToggleDock.d.ts.map +1 -0
  43. package/dist/PanelToggleDock.js +40 -0
  44. package/dist/PromptPackChooserPanel.d.ts +12 -11
  45. package/dist/PromptPackChooserPanel.d.ts.map +1 -1
  46. package/dist/PromptPackChooserPanel.js +103 -63
  47. package/dist/SceneInspectorPanel.d.ts +42 -0
  48. package/dist/SceneInspectorPanel.d.ts.map +1 -0
  49. package/dist/SceneInspectorPanel.js +135 -0
  50. package/dist/ScienceDataPanelContent.d.ts +16 -0
  51. package/dist/ScienceDataPanelContent.d.ts.map +1 -0
  52. package/dist/ScienceDataPanelContent.js +31 -0
  53. package/dist/ScienceMetricsPanelContent.d.ts +53 -0
  54. package/dist/ScienceMetricsPanelContent.d.ts.map +1 -0
  55. package/dist/ScienceMetricsPanelContent.js +415 -0
  56. package/dist/SpatialHud.d.ts +18 -0
  57. package/dist/SpatialHud.d.ts.map +1 -0
  58. package/dist/SpatialHud.js +120 -0
  59. package/dist/StreetviewModeSurface.d.ts +40 -0
  60. package/dist/StreetviewModeSurface.d.ts.map +1 -0
  61. package/dist/StreetviewModeSurface.js +358 -0
  62. package/dist/SurfaceSwitcher.d.ts +11 -0
  63. package/dist/SurfaceSwitcher.d.ts.map +1 -0
  64. package/dist/SurfaceSwitcher.js +46 -0
  65. package/dist/TopBar.d.ts +2 -0
  66. package/dist/TopBar.d.ts.map +1 -1
  67. package/dist/TopBar.js +3 -1
  68. package/dist/UnknownModeSurface.d.ts +6 -0
  69. package/dist/UnknownModeSurface.d.ts.map +1 -0
  70. package/dist/UnknownModeSurface.js +41 -0
  71. package/dist/index.d.ts +19 -0
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +12 -0
  74. package/dist/landingTokens.d.ts +7 -0
  75. package/dist/landingTokens.d.ts.map +1 -0
  76. package/dist/landingTokens.js +6 -0
  77. package/dist/layout.d.ts +27 -27
  78. package/dist/layout.d.ts.map +1 -1
  79. package/dist/layout.js +33 -27
  80. package/dist/mapMetrics.d.ts +88 -0
  81. package/dist/mapMetrics.d.ts.map +1 -0
  82. package/dist/mapMetrics.js +1 -0
  83. package/dist/panelPrimitives.d.ts +11 -0
  84. package/dist/panelPrimitives.d.ts.map +1 -0
  85. package/dist/panelPrimitives.js +41 -0
  86. package/dist/topbarLogoPolicy.d.ts +14 -0
  87. package/dist/topbarLogoPolicy.d.ts.map +1 -0
  88. package/dist/topbarLogoPolicy.js +41 -0
  89. package/dist/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +18 -5
@@ -2,6 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useMemo, useState } from 'react';
4
4
  import styled from 'styled-components';
5
+ import { panelEyebrowCss, panelPillButtonCss, panelSectionTitleCss } from './panelPrimitives.js';
5
6
  const Panel = styled.div `
6
7
  position: fixed;
7
8
  right: 0;
@@ -9,9 +10,9 @@ const Panel = styled.div `
9
10
  transform: translateY(-50%) ${(props) => (props.$visible ? 'translateX(0)' : 'translateX(100%)')};
10
11
  width: var(--ui-metrics-width);
11
12
  height: 70vh;
12
- background: rgba(255, 255, 255, 0.96);
13
- border-left: 1px solid var(--brand-panel-border);
14
- box-shadow: 0 16px 32px rgba(15, 23, 42, 0.12);
13
+ background: var(--viewer-ui-color-surface);
14
+ border-left: 1px solid var(--viewer-ui-color-panel-border);
15
+ box-shadow: none;
15
16
  transition: transform 0.3s ease;
16
17
  z-index: 40;
17
18
  display: flex;
@@ -19,14 +20,12 @@ const Panel = styled.div `
19
20
  `;
20
21
  const Header = styled.div `
21
22
  padding: 16px 20px;
22
- border-bottom: 1px solid var(--brand-panel-border);
23
+ border-bottom: 1px solid var(--viewer-ui-color-panel-border);
23
24
  display: flex;
24
25
  align-items: center;
25
26
  justify-content: space-between;
26
- font-size: 11px;
27
- text-transform: uppercase;
28
- letter-spacing: 0.08em;
29
- color: var(--brand-text-secondary);
27
+ ${panelEyebrowCss}
28
+ color: var(--viewer-ui-color-text-muted);
30
29
  `;
31
30
  const TabRow = styled.div `
32
31
  display: flex;
@@ -34,13 +33,10 @@ const TabRow = styled.div `
34
33
  padding: 12px 20px 0;
35
34
  `;
36
35
  const TabButton = styled.button `
37
- border-radius: 999px;
38
- padding: 6px 12px;
39
- font-size: 11px;
40
- text-transform: lowercase;
41
- border: none;
42
- background: ${(props) => (props.$active ? 'var(--brand-primary)' : 'rgba(15, 23, 42, 0.08)')};
43
- color: ${(props) => (props.$active ? '#ffffff' : 'var(--brand-text-secondary)')};
36
+ ${panelPillButtonCss}
37
+ min-height: 30px;
38
+ padding: 0 12px;
39
+ font-size: 10px;
44
40
  cursor: pointer;
45
41
  `;
46
42
  const Body = styled.div `
@@ -57,21 +53,18 @@ const MetricGrid = styled.div `
57
53
  gap: 12px;
58
54
  `;
59
55
  const MetricCard = styled.div `
60
- border-radius: 12px;
61
- border: 1px solid var(--brand-panel-border);
56
+ border-radius: 8px;
57
+ border: 1px solid var(--viewer-ui-color-panel-border-subtle);
62
58
  padding: 8px 10px;
63
- background: rgba(15, 23, 42, 0.04);
59
+ background: var(--viewer-ui-color-surface);
64
60
  `;
65
61
  const MetricLabel = styled.div `
66
- font-size: 10px;
67
- text-transform: uppercase;
68
- letter-spacing: 0.08em;
69
- color: var(--brand-text-secondary);
62
+ ${panelEyebrowCss}
70
63
  `;
71
64
  const MetricValue = styled.div `
72
65
  font-size: 13px;
73
66
  font-weight: 600;
74
- color: var(--brand-text-primary);
67
+ color: var(--viewer-ui-color-text-strong);
75
68
  `;
76
69
  const ToggleWrapper = styled.div `
77
70
  position: fixed;
@@ -83,13 +76,10 @@ const ToggleWrapper = styled.div `
83
76
  `;
84
77
  const Divider = styled.div `
85
78
  height: 1px;
86
- background: var(--brand-panel-border);
79
+ background: var(--viewer-ui-color-panel-border-subtle);
87
80
  `;
88
81
  const SectionTitle = styled.div `
89
- font-size: 12px;
90
- text-transform: uppercase;
91
- letter-spacing: 0.08em;
92
- color: var(--brand-text-secondary);
82
+ ${panelSectionTitleCss}
93
83
  `;
94
84
  export default function MetricsPanel({ isVisible, onToggle, distanceToFloor, distanceToCeiling, distanceToNorth, distanceToSouth, distanceToEast, distanceToWest, compassAngle, pitchAngle, moduleLabel, moduleSummary, renderInputs, }) {
95
85
  const [activeTab, setActiveTab] = useState('inputs');
@@ -103,5 +93,5 @@ export default function MetricsPanel({ isVisible, onToggle, distanceToFloor, dis
103
93
  { label: 'compass', value: `${compassAngle.toFixed(1)} deg` },
104
94
  { label: 'pitch', value: `${pitchAngle.toFixed(1)} deg` },
105
95
  ], [distanceToFloor, distanceToCeiling, distanceToNorth, distanceToSouth, distanceToEast, distanceToWest, compassAngle, pitchAngle]);
106
- return (_jsxs(_Fragment, { children: [_jsx(ToggleWrapper, { "$visible": isVisible, children: _jsx("button", { type: "button", onClick: onToggle, className: "collapse-toggle collapse-toggle--edge-right", title: isVisible ? 'Hide metrics' : 'Show metrics', children: isVisible ? (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z", clipRule: "evenodd" }) })) : (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z", clipRule: "evenodd" }) })) }) }), _jsxs(Panel, { "$visible": isVisible, children: [_jsxs(Header, { children: [_jsx("span", { children: "analytics" }), _jsx("span", { children: "live" })] }), _jsxs(TabRow, { children: [_jsx(TabButton, { type: "button", "$active": activeTab === 'inputs', onClick: () => setActiveTab('inputs'), children: "inputs" }), _jsx(TabButton, { type: "button", "$active": activeTab === 'outputs', onClick: () => setActiveTab('outputs'), children: "outputs" })] }), _jsxs(Body, { children: [activeTab === 'inputs' ? (_jsxs(_Fragment, { children: [moduleLabel ? (_jsxs("div", { children: [_jsx(SectionTitle, { children: "module" }), _jsx("div", { style: { fontSize: '16px', fontWeight: 600, marginTop: 6 }, children: moduleLabel }), moduleSummary ? (_jsx("div", { style: { fontSize: '12px', color: 'var(--brand-text-secondary)', marginTop: 6 }, children: moduleSummary })) : null] })) : null, renderInputs ? (_jsxs("div", { children: [_jsx(SectionTitle, { children: "render inputs" }), _jsx("div", { style: { marginTop: 8, fontSize: '12px', color: 'var(--brand-text-secondary)' }, children: renderInputs.presetLabel ? `Preset: ${renderInputs.presetLabel}` : 'Preset: default' }), renderInputs.presetSummary ? (_jsx("div", { style: { marginTop: 4, fontSize: '11px', color: 'var(--brand-text-secondary)' }, children: renderInputs.presetSummary })) : null, renderInputs.lightingRig ? (_jsxs("div", { style: { marginTop: 6, fontSize: '11px', color: 'var(--brand-text-secondary)' }, children: ["Lighting rig: ", renderInputs.lightingRig] })) : null, typeof renderInputs.toneMappingExposure === 'number' ? (_jsxs("div", { style: { marginTop: 4, fontSize: '11px', color: 'var(--brand-text-secondary)' }, children: ["Exposure: ", renderInputs.toneMappingExposure.toFixed(2)] })) : null, renderInputs.sky ? (_jsxs("div", { style: { marginTop: 8 }, children: [_jsx(SectionTitle, { children: "sky & environment" }), _jsxs("div", { style: { marginTop: 6, fontSize: '12px', color: 'var(--brand-text-secondary)' }, children: [renderInputs.sky.label, renderInputs.sky.mode ? ` · ${renderInputs.sky.mode}` : ''] }), renderInputs.sky.description ? (_jsx("div", { style: { marginTop: 4, fontSize: '11px', color: 'var(--brand-text-secondary)' }, children: renderInputs.sky.description })) : null, renderInputs.sky.src ? (_jsx("div", { style: { marginTop: 4, fontSize: '10px', color: 'var(--brand-text-secondary)' }, children: renderInputs.sky.src })) : null, typeof renderInputs.sky.exposure === 'number' ? (_jsxs("div", { style: { marginTop: 4, fontSize: '11px', color: 'var(--brand-text-secondary)' }, children: ["Sky exposure: ", renderInputs.sky.exposure.toFixed(2)] })) : null] })) : null] })) : null] })) : (_jsxs(_Fragment, { children: [_jsx(SectionTitle, { children: "spatial metrics" }), _jsx(MetricGrid, { children: metrics.map((metric) => (_jsxs(MetricCard, { children: [_jsx(MetricLabel, { children: metric.label }), _jsx(MetricValue, { children: metric.value })] }, metric.label))) })] })), _jsx(Divider, {})] })] })] }));
96
+ return (_jsxs(_Fragment, { children: [_jsx(ToggleWrapper, { "$visible": isVisible, children: _jsx("button", { type: "button", onClick: onToggle, className: "collapse-toggle collapse-toggle--edge-right", title: isVisible ? 'Hide metrics' : 'Show metrics', children: isVisible ? (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z", clipRule: "evenodd" }) })) : (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z", clipRule: "evenodd" }) })) }) }), _jsxs(Panel, { "$visible": isVisible, children: [_jsxs(Header, { children: [_jsx("span", { children: "analytics" }), _jsx("span", { children: "live" })] }), _jsxs(TabRow, { children: [_jsx(TabButton, { type: "button", "$active": activeTab === 'inputs', onClick: () => setActiveTab('inputs'), children: "inputs" }), _jsx(TabButton, { type: "button", "$active": activeTab === 'outputs', onClick: () => setActiveTab('outputs'), children: "outputs" })] }), _jsxs(Body, { children: [activeTab === 'inputs' ? (_jsxs(_Fragment, { children: [moduleLabel ? (_jsxs("div", { children: [_jsx(SectionTitle, { children: "module" }), _jsx("div", { style: { fontSize: '16px', fontWeight: 600, marginTop: 6 }, children: moduleLabel }), moduleSummary ? (_jsx("div", { style: { fontSize: '12px', color: 'var(--viewer-ui-color-text-muted)', marginTop: 6 }, children: moduleSummary })) : null] })) : null, renderInputs ? (_jsxs("div", { children: [_jsx(SectionTitle, { children: "render inputs" }), _jsx("div", { style: { marginTop: 8, fontSize: '12px', color: 'var(--viewer-ui-color-text-muted)' }, children: renderInputs.presetLabel ? `Preset: ${renderInputs.presetLabel}` : 'Preset: default' }), renderInputs.presetSummary ? (_jsx("div", { style: { marginTop: 4, fontSize: '11px', color: 'var(--viewer-ui-color-text-muted)' }, children: renderInputs.presetSummary })) : null, renderInputs.lightingRig ? (_jsxs("div", { style: { marginTop: 6, fontSize: '11px', color: 'var(--viewer-ui-color-text-muted)' }, children: ["Lighting rig: ", renderInputs.lightingRig] })) : null, typeof renderInputs.toneMappingExposure === 'number' ? (_jsxs("div", { style: { marginTop: 4, fontSize: '11px', color: 'var(--viewer-ui-color-text-muted)' }, children: ["Exposure: ", renderInputs.toneMappingExposure.toFixed(2)] })) : null, renderInputs.sky ? (_jsxs("div", { style: { marginTop: 8 }, children: [_jsx(SectionTitle, { children: "sky & environment" }), _jsxs("div", { style: { marginTop: 6, fontSize: '12px', color: 'var(--viewer-ui-color-text-muted)' }, children: [renderInputs.sky.label, renderInputs.sky.mode ? ` · ${renderInputs.sky.mode}` : ''] }), renderInputs.sky.description ? (_jsx("div", { style: { marginTop: 4, fontSize: '11px', color: 'var(--viewer-ui-color-text-muted)' }, children: renderInputs.sky.description })) : null, renderInputs.sky.src ? (_jsx("div", { style: { marginTop: 4, fontSize: '10px', color: 'var(--viewer-ui-color-text-muted)' }, children: renderInputs.sky.src })) : null, typeof renderInputs.sky.exposure === 'number' ? (_jsxs("div", { style: { marginTop: 4, fontSize: '11px', color: 'var(--viewer-ui-color-text-muted)' }, children: ["Sky exposure: ", renderInputs.sky.exposure.toFixed(2)] })) : null] })) : null] })) : null] })) : (_jsxs(_Fragment, { children: [_jsx(SectionTitle, { children: "spatial metrics" }), _jsx(MetricGrid, { children: metrics.map((metric) => (_jsxs(MetricCard, { children: [_jsx(MetricLabel, { children: metric.label }), _jsx(MetricValue, { children: metric.value })] }, metric.label))) })] })), _jsx(Divider, {})] })] })] }));
107
97
  }
@@ -1,21 +1,42 @@
1
+ type MetricsFeedKind = 'runtime' | 'viewer' | 'geometry' | 'render' | 'map';
2
+ type ToolMetricDefinition = {
3
+ id: string;
4
+ label: string;
5
+ summary?: string;
6
+ source: {
7
+ kind: MetricsFeedKind;
8
+ path: string;
9
+ };
10
+ format?: 'text' | 'number' | 'count';
11
+ digits?: number;
12
+ prefix?: string;
13
+ suffix?: string;
14
+ emptyLabel?: string;
15
+ };
16
+ type ToolMetricGroupDefinition = {
17
+ id: string;
18
+ label: string;
19
+ summary?: string;
20
+ metrics: ToolMetricDefinition[];
21
+ };
22
+ type ToolMetricsDefinition = {
23
+ title?: string;
24
+ summary?: string;
25
+ groups: ToolMetricGroupDefinition[];
26
+ };
27
+ type ToolMetricsFeeds = Partial<Record<MetricsFeedKind, Record<string, unknown>>>;
1
28
  interface MetricsPanelContentProps {
2
- cameraMetrics: {
3
- position: {
4
- x: number;
5
- y: number;
6
- z: number;
7
- };
8
- heightAboveFloor: number;
9
- } | null;
10
- distanceToFloor: number;
11
- distanceToCeiling: number;
12
- distanceToNorth: number;
13
- distanceToSouth: number;
14
- distanceToEast: number;
15
- distanceToWest: number;
16
- compassAngle: number;
17
- pitchAngle: number;
29
+ modeId: string;
30
+ modeLabel: string;
31
+ moduleLabel?: string | null;
32
+ moduleSummary?: string | null;
33
+ promptPackLabel?: string | null;
34
+ promptPackDescription?: string | null;
35
+ renderCount?: number;
36
+ imageSetCount?: number;
37
+ toolMetrics?: ToolMetricsDefinition | null;
38
+ feeds?: ToolMetricsFeeds | null;
18
39
  }
19
- export default function MetricsPanelContent({ cameraMetrics, distanceToFloor, distanceToCeiling, distanceToNorth, distanceToSouth, distanceToEast, distanceToWest, compassAngle, pitchAngle, }: MetricsPanelContentProps): import("react/jsx-runtime").JSX.Element;
40
+ export default function MetricsPanelContent({ modeId, modeLabel, moduleLabel, moduleSummary, promptPackLabel, promptPackDescription, renderCount, imageSetCount, toolMetrics, feeds, }: MetricsPanelContentProps): import("react/jsx-runtime").JSX.Element;
20
41
  export {};
21
42
  //# sourceMappingURL=MetricsPanelContent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MetricsPanelContent.d.ts","sourceRoot":"","sources":["../src/MetricsPanelContent.tsx"],"names":[],"mappings":"AAIA,UAAU,wBAAwB;IAChC,aAAa,EAAE;QAAE,QAAQ,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClG,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAqED,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,EAC1C,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAY,EACZ,UAAU,GACX,EAAE,wBAAwB,2CAyD1B"}
1
+ {"version":3,"file":"MetricsPanelContent.d.ts","sourceRoot":"","sources":["../src/MetricsPanelContent.tsx"],"names":[],"mappings":"AAKA,KAAK,eAAe,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE5E,KAAK,oBAAoB,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QACN,IAAI,EAAE,eAAe,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,oBAAoB,EAAE,CAAC;CACjC,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,yBAAyB,EAAE,CAAC;CACrC,CAAC;AAEF,KAAK,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAElF,UAAU,wBAAwB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC3C,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACjC;AAgED,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,EAC1C,MAAM,EACN,SAAS,EACT,WAAW,EACX,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,WAAe,EACf,aAAiB,EACjB,WAAW,EACX,KAAK,GACN,EAAE,wBAAwB,2CAwJ1B"}
@@ -1,97 +1,91 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import styled from 'styled-components';
4
- const formatMeters = (value) => `${value.toFixed(2)} m`;
5
- const formatDegrees = (value) => `${value.toFixed(1)}°`;
6
- const Root = styled.div `
7
- display: flex;
8
- flex-direction: column;
9
- gap: 18px;
4
+ const Root = styled.div.attrs({ className: 'viewer-ui-panel-sections' }) ``;
5
+ const Section = styled.section.attrs({ className: 'panel-section' }) ``;
6
+ const SectionHeader = styled.div.attrs({ className: 'panel-section-header' }) ``;
7
+ const SectionHeaderCopy = styled.div `
8
+ min-width: 0;
10
9
  `;
11
- const Header = styled.div `
12
- display: flex;
13
- flex-direction: column;
14
- gap: 4px;
15
- `;
16
- const Title = styled.div `
17
- font-size: 17px;
18
- font-weight: 600;
19
- letter-spacing: 0.01em;
20
- color: var(--brand-text-primary);
21
- `;
22
- const Eyebrow = styled.div `
23
- font-size: 10px;
24
- text-transform: uppercase;
25
- letter-spacing: 0.18em;
26
- color: var(--brand-text-secondary);
27
- `;
28
- const Section = styled.div `
29
- display: flex;
30
- flex-direction: column;
31
- gap: 10px;
32
- `;
33
- const SectionTitle = styled.div `
34
- font-size: 10px;
35
- text-transform: uppercase;
36
- letter-spacing: 0.18em;
37
- color: var(--brand-text-secondary);
38
- `;
39
- const MetricRow = styled.div `
40
- display: flex;
41
- align-items: baseline;
42
- justify-content: space-between;
43
- gap: 20px;
44
- padding-bottom: 10px;
45
- border-bottom: 1px solid var(--brand-panel-border);
46
-
47
- &:last-child {
48
- border-bottom: 0;
49
- padding-bottom: 0;
50
- }
51
- `;
52
- const MetricLabel = styled.span `
53
- font-size: 13px;
54
- color: var(--brand-text-secondary);
55
- `;
56
- const MetricValue = styled.span `
57
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;
58
- font-size: 13px;
59
- color: var(--brand-text-primary);
60
- `;
61
- export default function MetricsPanelContent({ cameraMetrics, distanceToFloor, distanceToCeiling, distanceToNorth, distanceToSouth, distanceToEast, distanceToWest, compassAngle, pitchAngle, }) {
62
- const sections = [
63
- {
64
- title: 'camera',
65
- metrics: [
66
- {
67
- label: 'height above floor',
68
- value: cameraMetrics ? formatMeters(cameraMetrics.heightAboveFloor) : formatMeters(distanceToFloor),
69
- },
70
- { label: 'compass angle', value: formatDegrees(compassAngle) },
71
- { label: 'pitch angle', value: formatDegrees(pitchAngle) },
72
- ],
73
- },
10
+ const SectionList = styled.div.attrs({ className: 'panel-section-list' }) ``;
11
+ const MetricRow = styled.div.attrs({ className: 'panel-section-row' }) ``;
12
+ const MetricMeta = styled.div.attrs({ className: 'panel-section-row-copy' }) ``;
13
+ const MetricLabel = styled.span.attrs({ className: 'panel-section-row-label' }) ``;
14
+ const MetricHelp = styled.span.attrs({ className: 'panel-section-row-help' }) ``;
15
+ const MetricValue = styled.span.attrs({ className: 'panel-section-row-value' }) ``;
16
+ const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
17
+ const resolvePathValue = (root, path) => {
18
+ if (!root || !path.trim())
19
+ return null;
20
+ const parts = path.split('.').map((part) => part.trim()).filter(Boolean);
21
+ let current = root;
22
+ for (const part of parts) {
23
+ if (!isRecord(current))
24
+ return null;
25
+ current = current[part];
26
+ }
27
+ return current ?? null;
28
+ };
29
+ const formatMetricValue = (metric, value) => {
30
+ if (value === null || value === undefined || value === '') {
31
+ return metric.emptyLabel?.trim() || 'not emitted';
32
+ }
33
+ if (typeof value === 'number' && Number.isFinite(value)) {
34
+ if (metric.prefix === '$') {
35
+ const digits = metric.digits ?? 0;
36
+ return new Intl.NumberFormat('en-US', {
37
+ style: 'currency',
38
+ currency: 'USD',
39
+ minimumFractionDigits: digits,
40
+ maximumFractionDigits: digits,
41
+ }).format(value);
42
+ }
43
+ if (metric.format === 'count') {
44
+ return `${metric.prefix ?? ''}${Math.round(value)}${metric.suffix ?? ''}`;
45
+ }
46
+ const digits = metric.digits ?? (Number.isInteger(value) ? 0 : 2);
47
+ return `${metric.prefix ?? ''}${value.toFixed(digits)}${metric.suffix ?? ''}`;
48
+ }
49
+ if (typeof value === 'boolean') {
50
+ return value ? `${metric.prefix ?? ''}yes${metric.suffix ?? ''}` : `${metric.prefix ?? ''}no${metric.suffix ?? ''}`;
51
+ }
52
+ return `${metric.prefix ?? ''}${String(value)}${metric.suffix ?? ''}`;
53
+ };
54
+ export default function MetricsPanelContent({ modeId, modeLabel, moduleLabel, moduleSummary, promptPackLabel, promptPackDescription, renderCount = 0, imageSetCount = 0, toolMetrics, feeds, }) {
55
+ const supportsDerivedMetrics = modeId === 'design' || modeId === 'map' || modeId === 'streetmix' || modeId === 'streetview';
56
+ const manifestGroups = Array.isArray(toolMetrics?.groups) ? toolMetrics.groups : [];
57
+ const hasManifestMetrics = manifestGroups.length > 0;
58
+ const runtimeFeed = isRecord(feeds?.runtime) ? feeds.runtime : null;
59
+ const mapFeed = isRecord(feeds?.map) ? feeds.map : null;
60
+ const mapMetrics = mapFeed ? feeds?.map : null;
61
+ const hasMapFeed = Boolean(mapFeed && Object.keys(mapFeed).length > 0);
62
+ const manifestUsesMapFeed = manifestGroups.some((group) => Array.isArray(group.metrics) ? group.metrics.some((metric) => metric.source.kind === 'map') : false);
63
+ const mapMetricsSourceLabel = hasMapFeed && mapMetrics?.source?.trim() ? mapMetrics.source.trim() : 'derived';
64
+ const eyebrowLabel = hasManifestMetrics
65
+ ? 'manifest-driven feeds'
66
+ : modeId === 'map' && hasMapFeed
67
+ ? 'runtime + map feed'
68
+ : 'runtime context only';
69
+ const runtimeRows = [
70
+ { label: 'mode', value: modeLabel },
71
+ { label: 'module', value: moduleLabel?.trim() || 'none' },
72
+ { label: 'prompt system', value: promptPackLabel?.trim() || 'default' },
73
+ { label: 'renders', value: `${renderCount}` },
74
+ { label: 'image sets', value: `${imageSetCount}` },
74
75
  {
75
- title: 'clearances',
76
- metrics: [
77
- { label: 'floor', value: formatMeters(distanceToFloor) },
78
- { label: 'ceiling', value: formatMeters(distanceToCeiling) },
79
- { label: 'north', value: formatMeters(distanceToNorth) },
80
- { label: 'south', value: formatMeters(distanceToSouth) },
81
- { label: 'east', value: formatMeters(distanceToEast) },
82
- { label: 'west', value: formatMeters(distanceToWest) },
83
- ],
76
+ label: 'geometry status',
77
+ value: typeof runtimeFeed?.geometryStatus === 'string' && runtimeFeed.geometryStatus.trim()
78
+ ? runtimeFeed.geometryStatus
79
+ : modeId === 'imagine'
80
+ ? 'blank canvas'
81
+ : 'idle',
84
82
  },
85
- cameraMetrics
86
- ? {
87
- title: 'position',
88
- metrics: [
89
- { label: 'x', value: formatMeters(cameraMetrics.position.x) },
90
- { label: 'y', value: formatMeters(cameraMetrics.position.y) },
91
- { label: 'z', value: formatMeters(cameraMetrics.position.z) },
92
- ],
93
- }
94
- : null,
95
- ].filter(Boolean);
96
- return (_jsxs(Root, { children: [_jsxs(Header, { children: [_jsx(Title, { children: "viewer metrics" }), _jsx(Eyebrow, { children: "live scene telemetry" })] }), _jsx("div", { children: sections.map((section) => (_jsxs(Section, { children: [_jsx(SectionTitle, { children: section.title }), section.metrics.map((metric) => (_jsxs(MetricRow, { children: [_jsx(MetricLabel, { children: metric.label }), _jsx(MetricValue, { children: metric.value })] }, metric.label)))] }, section.title))) })] }));
83
+ ];
84
+ return (_jsxs(Root, { children: [_jsx(Section, { "data-panel-id": "metrics-overview", children: _jsx(SectionHeader, { children: _jsxs(SectionHeaderCopy, { children: [_jsx("h3", { children: toolMetrics?.title?.trim() || 'surface metrics' }), _jsx("p", { children: eyebrowLabel }), toolMetrics?.summary?.trim() ? _jsx("p", { children: toolMetrics.summary }) : null] }) }) }), _jsxs(Section, { "data-panel-id": "metrics-context", children: [_jsx(SectionHeader, { children: _jsxs(SectionHeaderCopy, { children: [_jsx("h3", { children: "surface context" }), moduleSummary?.trim() ? _jsx("p", { children: moduleSummary }) : null, promptPackDescription?.trim() ? _jsx("p", { children: promptPackDescription }) : null] }) }), _jsx(SectionList, { children: runtimeRows.map((metric) => (_jsxs(MetricRow, { children: [_jsx(MetricMeta, { children: _jsx(MetricLabel, { children: metric.label }) }), _jsx(MetricValue, { children: metric.value })] }, metric.label))) })] }), !hasManifestMetrics ? (_jsx(Section, { "data-panel-id": "metrics-contract-warning", children: _jsx(SectionHeader, { children: _jsxs(SectionHeaderCopy, { children: [_jsx("h3", { children: modeId === 'map' ? 'map metrics contract missing' : 'tool metrics not declared' }), _jsx("p", { children: modeId === 'map'
85
+ ? 'This map tool is receiving live site metrics, but its manifest does not declare canonical groups against the shared map feed. Add manifest metrics instead of relying on frontend-only cards.'
86
+ : 'This tool manifest does not declare canonical metrics feeds. Composer is only showing shared runtime context and will not invent tool-specific metrics from frontend heuristics.' })] }) }) })) : null, modeId === 'map' && manifestUsesMapFeed && !hasMapFeed ? (_jsx(Section, { "data-panel-id": "metrics-map-feed-warning", children: _jsx(SectionHeader, { children: _jsxs(SectionHeaderCopy, { children: [_jsx("h3", { children: "map feed missing" }), _jsx("p", { children: "This panel has manifest-declared map metrics, but no canonical `feeds.map` payload was provided. This is a metrics wiring bug, not absent site data." })] }) }) })) : null, manifestGroups.map((group) => (_jsxs(Section, { "data-panel-id": `metrics-${group.id}`, children: [_jsx(SectionHeader, { children: _jsxs(SectionHeaderCopy, { children: [_jsx("h3", { children: group.label }), group.summary?.trim() ? _jsx("p", { children: group.summary }) : null] }) }), group.metrics.length > 0 ? (_jsx(SectionList, { children: group.metrics.map((metric) => {
87
+ const feedRoot = isRecord(feeds?.[metric.source.kind]) ? feeds?.[metric.source.kind] : null;
88
+ const value = resolvePathValue(feedRoot, metric.source.path);
89
+ return (_jsxs(MetricRow, { children: [_jsxs(MetricMeta, { children: [_jsx(MetricLabel, { children: metric.label }), metric.summary?.trim() ? _jsx(MetricHelp, { children: metric.summary }) : null] }), _jsx(MetricValue, { children: formatMetricValue(metric, value) })] }, metric.id));
90
+ }) })) : (_jsx("div", { className: "panel-section-empty", children: "This metrics group has no declared fields." }))] }, group.id))), _jsxs(Section, { "data-panel-id": "metrics-status", children: [_jsx(SectionHeader, { children: _jsx(SectionHeaderCopy, { children: _jsx("h3", { children: modeId === 'map' ? 'metrics' : supportsDerivedMetrics || hasManifestMetrics ? 'status' : 'metrics' }) }) }), _jsx(SectionList, { children: modeId === 'map' && hasMapFeed ? (_jsxs(MetricRow, { children: [_jsx(MetricMeta, { children: _jsx(MetricLabel, { children: "source" }) }), _jsx(MetricValue, { children: mapMetricsSourceLabel })] })) : (_jsxs(MetricRow, { children: [_jsx(MetricMeta, { children: _jsx(MetricLabel, { children: hasManifestMetrics ? 'source' : supportsDerivedMetrics ? 'availability' : 'state' }) }), _jsx(MetricValue, { children: hasManifestMetrics ? 'manifest + runtime' : supportsDerivedMetrics ? 'pending' : 'none' })] })) })] })] }));
97
91
  }
package/dist/ModeBar.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export declare const MODE_BAR_HEIGHT_PX = 42;
2
+ export declare const MODE_BAR_WITH_UTILITIES_HEIGHT_PX = 42;
1
3
  export type ModeTab = {
2
4
  id: string;
3
5
  label: string;
@@ -18,7 +20,9 @@ export type ModeBarProps = {
18
20
  showPanelToggle?: boolean;
19
21
  panelsCollapsed?: boolean;
20
22
  onTogglePanels?: () => void;
23
+ inline?: boolean;
24
+ id?: string;
25
+ ariaLabel?: string;
21
26
  };
22
- export declare const MODE_BAR_HEIGHT_PX = 34;
23
- export default function ModeBar({ active, topOffsetPx, tabs, tone, heightPx, lockedLabel, onSelect, hidden, className, showPanelToggle, panelsCollapsed, onTogglePanels, }: ModeBarProps): import("react/jsx-runtime").JSX.Element | null;
27
+ export default function ModeBar({ active, topOffsetPx, tabs, tone: _tone, heightPx, lockedLabel, onSelect, hidden, className, showPanelToggle, panelsCollapsed, onTogglePanels, inline, id, ariaLabel, }: ModeBarProps): import("react/jsx-runtime").JSX.Element | null;
24
28
  //# sourceMappingURL=ModeBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ModeBar.d.ts","sourceRoot":"","sources":["../src/ModeBar.tsx"],"names":[],"mappings":"AAoGA,MAAM,MAAM,OAAO,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,EAC9B,MAAM,EACN,WAAW,EACX,IAAI,EACJ,IAAc,EACd,QAA6B,EAC7B,WAA2B,EAC3B,QAAQ,EACR,MAAc,EACd,SAAS,EACT,eAAuB,EACvB,eAAuB,EACvB,cAAc,GACf,EAAE,YAAY,kDA6Dd"}
1
+ {"version":3,"file":"ModeBar.d.ts","sourceRoot":"","sources":["../src/ModeBar.tsx"],"names":[],"mappings":"AAWA,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,iCAAiC,KAAqB,CAAC;AAmDpE,MAAM,MAAM,OAAO,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,EAC9B,MAAM,EACN,WAAW,EACX,IAAI,EACJ,IAAI,EAAE,KAAe,EACrB,QAAQ,EACR,WAA2B,EAC3B,QAAQ,EACR,MAAc,EACd,SAAS,EACT,eAAuB,EACvB,eAAuB,EACvB,cAAc,EACd,MAAc,EACd,EAAE,EACF,SAA2B,GAC5B,EAAE,YAAY,kDAmDd"}
package/dist/ModeBar.js CHANGED
@@ -1,105 +1,72 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import styled from 'styled-components';
4
+ import { panelSystemFeatureToggleCss, panelSystemToggleBarCss, panelSystemVarsCss, } from './PanelSystem.js';
5
+ import PanelToggleDock from './PanelToggleDock.js';
6
+ export const MODE_BAR_HEIGHT_PX = 42;
7
+ export const MODE_BAR_WITH_UTILITIES_HEIGHT_PX = MODE_BAR_HEIGHT_PX;
4
8
  const Root = styled.div `
5
- position: fixed;
9
+ ${panelSystemVarsCss}
10
+ position: ${(props) => (props.$inline ? 'relative' : 'fixed')};
6
11
  left: 0;
7
12
  right: 0;
8
13
  z-index: 70;
9
- top: ${(props) => `${Math.max(0, props.$topOffsetPx)}px`};
14
+ top: ${(props) => (props.$inline ? 'auto' : `${Math.max(0, props.$topOffsetPx)}px`)};
15
+ width: ${(props) => (props.$inline ? '100vw' : 'auto')};
10
16
  height: ${(props) => `${props.$heightPx}px`};
11
- background: var(--viewer-ui-color-bg-base, var(--brand-panel, #f6f3eb));
12
- border-bottom: 1px solid var(--viewer-ui-color-panel-border, rgba(47, 74, 60, 0.35));
17
+ display: flex;
18
+ flex-direction: column;
19
+ overflow: visible;
20
+ background: rgba(255, 255, 255, 0.95);
21
+ border-bottom: 1px solid var(--panel-system-border);
22
+ backdrop-filter: blur(12px);
23
+ font-family: var(--index-panel-font, var(--viewer-ui-font-body));
13
24
  `;
14
- const ToggleOverlay = styled.div `
15
- position: absolute;
16
- left: 50%;
17
- top: calc(100% + 8px);
18
- transform: translateX(-50%);
19
- z-index: 80;
25
+ const Content = styled.div `
26
+ flex: 0 0 ${() => `${MODE_BAR_HEIGHT_PX}px`};
20
27
  display: flex;
21
28
  align-items: center;
22
- gap: 8px;
23
- pointer-events: auto;
29
+ justify-content: center;
30
+ min-width: 0;
31
+ padding: 0 20px;
24
32
  `;
25
33
  const Tabs = styled.div `
26
- height: 100%;
27
- display: flex;
28
- align-items: stretch;
34
+ ${panelSystemToggleBarCss}
35
+ flex: 0 1 auto;
36
+ justify-content: center;
37
+ max-width: 100%;
38
+ min-width: 0;
29
39
  `;
30
40
  const TabLink = styled.a `
31
- position: relative;
32
- z-index: ${(props) => (props.$active ? 10 : 0)};
33
- margin-left: ${(props) => (props.$index === 0 ? '0' : '-18px')};
34
- border-left: ${(props) => (props.$index === 0 ? '1px solid var(--viewer-ui-color-panel-border)' : '0')};
35
- border-right: 1px solid var(--viewer-ui-color-panel-border);
36
- border-bottom: 1px solid var(--viewer-ui-color-panel-border);
37
- border-radius: 0 0 18px 0;
38
- box-shadow: inset 0 0 0 1px var(--viewer-ui-color-panel-border-subtle);
39
- flex: 1 1 0;
40
- min-width: 0;
41
- display: inline-flex;
42
- justify-content: center;
43
- align-items: center;
44
- text-decoration: none;
45
- font-size: 13px;
46
- font-weight: 600;
47
- letter-spacing: 0.04em;
48
- text-transform: lowercase;
49
- transition: color 0.16s ease, background-color 0.16s ease, border-color 0.16s ease;
50
- background: ${(props) => props.$active
51
- ? props.$tone === 'green'
52
- ? 'rgba(49, 143, 78, 0.12)'
53
- : 'rgba(15, 23, 42, 0.08)'
54
- : 'var(--viewer-ui-color-tab-bg, rgba(47, 74, 60, 0.08))'};
55
- color: ${(props) => props.$active
56
- ? props.$tone === 'green'
57
- ? 'var(--viewer-ui-color-button-primary, #318f4e)'
58
- : 'var(--viewer-ui-color-button-secondary, #0b1320)'
59
- : 'var(--viewer-ui-color-text-muted, rgba(47, 74, 60, 0.75))'};
60
-
61
- &:hover {
62
- color: ${(props) => props.$active
63
- ? props.$tone === 'green'
64
- ? 'var(--viewer-ui-color-button-primary, #318f4e)'
65
- : 'var(--viewer-ui-color-button-secondary, #0b1320)'
66
- : 'var(--viewer-ui-color-text-strong, #0f172a)'};
67
- }
41
+ ${panelSystemFeatureToggleCss}
42
+ gap: 8px;
68
43
  `;
69
44
  const LockedLabel = styled.span `
70
- margin-left: 8px;
71
- font-size: 9px;
72
- letter-spacing: 0.2em;
73
- text-transform: uppercase;
74
- color: var(--viewer-ui-color-text-muted, rgba(47, 74, 60, 0.75));
75
- `;
76
- const ToggleText = styled.button `
77
- border: 0;
78
- background: transparent;
79
45
  font-size: 11px;
80
- text-transform: uppercase;
81
- letter-spacing: 0.14em;
82
- color: var(--brand-text-secondary);
83
- cursor: pointer;
84
- padding: 0;
85
- white-space: nowrap;
86
-
87
- &:hover {
88
- color: var(--brand-text-primary);
89
- }
46
+ letter-spacing: 0;
47
+ text-transform: none;
48
+ color: currentColor;
49
+ opacity: 0.72;
50
+ flex: 0 0 auto;
90
51
  `;
91
- export const MODE_BAR_HEIGHT_PX = 34;
92
- export default function ModeBar({ active, topOffsetPx, tabs, tone = 'green', heightPx = MODE_BAR_HEIGHT_PX, lockedLabel = 'coming soon', onSelect, hidden = false, className, showPanelToggle = false, panelsCollapsed = false, onTogglePanels, }) {
52
+ export default function ModeBar({ active, topOffsetPx, tabs, tone: _tone = 'green', heightPx, lockedLabel = 'coming soon', onSelect, hidden = false, className, showPanelToggle = false, panelsCollapsed = false, onTogglePanels, inline = false, id, ariaLabel = 'Composer mode', }) {
93
53
  if (hidden) {
94
54
  return null;
95
55
  }
96
- return (_jsxs(Root, { className: className, "$topOffsetPx": topOffsetPx, "$heightPx": heightPx, children: [_jsx(Tabs, { children: tabs.map((tab, index) => {
97
- const statusLabel = tab.status === 'coming-soon' || tab.locked ? lockedLabel : null;
98
- return (_jsxs(TabLink, { "$active": tab.id === active, "$tone": tone, "$index": index, href: tab.href ?? '#', onClick: (event) => {
99
- if (!tab.href) {
100
- event.preventDefault();
101
- }
102
- onSelect?.(tab.id);
103
- }, children: [_jsx("span", { children: tab.label }), statusLabel ? _jsx(LockedLabel, { children: statusLabel }) : null] }, tab.id));
104
- }) }), showPanelToggle && onTogglePanels ? (_jsxs(ToggleOverlay, { children: [_jsx("button", { type: "button", className: "collapse-toggle collapse-toggle--edge-top", onClick: onTogglePanels, "aria-label": panelsCollapsed ? 'Show panels' : 'Toggle panels', children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: panelsCollapsed ? (_jsx("path", { fillRule: "evenodd", d: "M5.23 7.21a.75.75 0 011.06.02L10 10.94l3.71-3.71a.75.75 0 111.06 1.06l-4.24 4.24a.75.75 0 01-1.06 0L5.25 8.27a.75.75 0 01-.02-1.06z", clipRule: "evenodd" })) : (_jsx("path", { fillRule: "evenodd", d: "M5.23 12.79a.75.75 0 001.06-.02L10 9.06l3.71 3.71a.75.75 0 001.06-1.06L10.53 7.47a.75.75 0 00-1.06 0L4.23 11.75a.75.75 0 001 1.04z", clipRule: "evenodd" })) }) }), _jsx(ToggleText, { type: "button", onClick: onTogglePanels, children: panelsCollapsed ? 'show panels' : 'toggle panels' })] })) : null] }));
56
+ const hasPanelUtility = Boolean(showPanelToggle && onTogglePanels);
57
+ const resolvedHeightPx = heightPx ?? MODE_BAR_HEIGHT_PX;
58
+ return (_jsxs(Root, { id: id, className: className, "$topOffsetPx": topOffsetPx, "$heightPx": resolvedHeightPx, "$inline": inline, children: [_jsx(Content, { children: _jsx(Tabs, { role: "radiogroup", "aria-label": ariaLabel, children: tabs.map((tab, index) => {
59
+ const isDisabled = tab.status === 'coming-soon' || tab.locked;
60
+ const statusLabel = isDisabled ? lockedLabel : null;
61
+ const isActive = tab.id === active;
62
+ return (_jsxs(TabLink, { role: "radio", "aria-checked": isActive, "aria-disabled": isDisabled ? 'true' : undefined, "data-active": isActive ? 'true' : 'false', "data-index": index, href: tab.href ?? '#', onClick: (event) => {
63
+ if (!tab.href || isDisabled) {
64
+ event.preventDefault();
65
+ }
66
+ if (isDisabled) {
67
+ return;
68
+ }
69
+ onSelect?.(tab.id);
70
+ }, children: [_jsx("span", { children: tab.label }), statusLabel ? _jsx(LockedLabel, { children: statusLabel }) : null] }, tab.id));
71
+ }) }) }), _jsx(PanelToggleDock, { placement: "absolute", topOffsetPx: resolvedHeightPx, collapsed: panelsCollapsed, hidden: !hasPanelUtility, onToggle: onTogglePanels })] }));
105
72
  }
@@ -19,7 +19,8 @@ type ModuleSelectorPanelProps = {
19
19
  uploadDescription?: string;
20
20
  uploadSlot?: ReactNode;
21
21
  uploadMeta?: ReactNode;
22
+ supplementarySlot?: ReactNode;
22
23
  };
23
- export default function ModuleSelectorPanel({ title, description, status, error, modules, activeModuleId, onSelectModule, emptyLabel, uploadTitle, uploadDescription, uploadSlot, uploadMeta, }: ModuleSelectorPanelProps): import("react/jsx-runtime").JSX.Element;
24
+ export default function ModuleSelectorPanel({ title, description: _description, status, error, modules, activeModuleId, onSelectModule, emptyLabel, uploadTitle, uploadDescription: _uploadDescription, uploadSlot, uploadMeta: _uploadMeta, supplementarySlot, }: ModuleSelectorPanelProps): import("react/jsx-runtime").JSX.Element;
24
25
  export {};
25
26
  //# sourceMappingURL=ModuleSelectorPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ModuleSelectorPanel.d.ts","sourceRoot":"","sources":["../src/ModuleSelectorPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,oBAAoB,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1D,KAAK,wBAAwB,GAAG;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB,CAAC;AA0GF,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,EAC1C,KAA+B,EAC/B,WAAW,EACX,MAAgB,EAChB,KAAK,EACL,OAAO,EACP,cAAc,EACd,cAAc,EACd,UAAoC,EACpC,WAAsB,EACtB,iBAAiB,EACjB,UAAU,EACV,UAAU,GACX,EAAE,wBAAwB,2CAyC1B"}
1
+ {"version":3,"file":"ModuleSelectorPanel.d.ts","sourceRoot":"","sources":["../src/ModuleSelectorPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUvC,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,oBAAoB,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1D,KAAK,wBAAwB,GAAG;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iBAAiB,CAAC,EAAE,SAAS,CAAC;CAC/B,CAAC;AAoGF,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,EAC1C,KAA+B,EAC/B,WAAW,EAAE,YAAY,EACzB,MAAgB,EAChB,KAAK,EACL,OAAO,EACP,cAAc,EACd,cAAc,EACd,UAAoC,EACpC,WAAsB,EACtB,iBAAiB,EAAE,kBAAkB,EACrC,UAAU,EACV,UAAU,EAAE,WAAW,EACvB,iBAAiB,GAClB,EAAE,wBAAwB,2CAuC1B"}