@treasuryspatial/viewer-ui-kit 0.1.39 → 0.1.41

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.
@@ -12,7 +12,9 @@ type ComposerRightRailProps = {
12
12
  tabs: ComposerRightRailTab[];
13
13
  title?: string;
14
14
  statusLabel?: string;
15
+ showEdgeToggle?: boolean;
16
+ topOffsetPx?: number;
15
17
  };
16
- export default function ComposerRightRail({ isVisible, onToggle, activeTab, onTabChange, tabs, title, statusLabel, }: ComposerRightRailProps): import("react/jsx-runtime").JSX.Element;
18
+ export default function ComposerRightRail({ isVisible, onToggle, activeTab, onTabChange, tabs, title, statusLabel, showEdgeToggle, topOffsetPx, }: ComposerRightRailProps): import("react/jsx-runtime").JSX.Element;
17
19
  export {};
18
20
  //# sourceMappingURL=ComposerRightRail.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ComposerRightRail.d.ts","sourceRoot":"","sources":["../src/ComposerRightRail.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,CAAC;CACpB,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,oBAAoB,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EACxC,SAAS,EACT,QAAQ,EACR,SAAS,EACT,WAAW,EACX,IAAI,EACJ,KAAsB,EACtB,WAAoB,GACrB,EAAE,sBAAsB,2CAmExB"}
1
+ {"version":3,"file":"ComposerRightRail.d.ts","sourceRoot":"","sources":["../src/ComposerRightRail.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,CAAC;CACpB,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,oBAAoB,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAwDF,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EACxC,SAAS,EACT,QAAQ,EACR,SAAS,EACT,WAAW,EACX,IAAI,EACJ,KAAsB,EACtB,WAAoB,EACpB,cAAsB,EACtB,WAAe,GAChB,EAAE,sBAAsB,2CAiExB"}
@@ -1,10 +1,58 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import styled from 'styled-components';
3
4
  import { RightPanel, RightPanelCollapseToggle, RightPanelShowToggle, } from './layout.js';
4
- export default function ComposerRightRail({ isVisible, onToggle, activeTab, onTabChange, tabs, title = 'image system', statusLabel = 'live', }) {
5
+ const RailHeader = styled.div `
6
+ border-bottom: 1px solid var(--brand-panel-border);
7
+ padding: 16px 18px 14px;
8
+ background: var(--brand-panel);
9
+ `;
10
+ const RailEyebrow = styled.div `
11
+ display: flex;
12
+ align-items: center;
13
+ gap: 6px;
14
+ font-size: 10px;
15
+ text-transform: uppercase;
16
+ letter-spacing: 0.14em;
17
+ color: var(--brand-text-secondary);
18
+ `;
19
+ const RailTabs = styled.div `
20
+ display: flex;
21
+ gap: 8px;
22
+ margin-top: 12px;
23
+ overflow-x: auto;
24
+ padding-bottom: 2px;
25
+
26
+ &::-webkit-scrollbar {
27
+ display: none;
28
+ }
29
+ `;
30
+ const RailTab = styled.button `
31
+ border-radius: 999px;
32
+ min-height: 42px;
33
+ padding: 0 20px;
34
+ border: 1px solid ${(props) => (props.$active ? 'var(--brand-text-primary)' : 'var(--brand-panel-border)')};
35
+ background: ${(props) => (props.$active ? 'var(--brand-text-primary)' : 'var(--brand-background)')};
36
+ color: ${(props) => (props.$active ? 'var(--brand-background)' : 'var(--brand-text-secondary)')};
37
+ font-size: 13px;
38
+ font-weight: 600;
39
+ letter-spacing: 0.01em;
40
+ text-transform: lowercase;
41
+ white-space: nowrap;
42
+ transition: background-color 0.16s ease, color 0.16s ease, border-color 0.16s ease;
43
+
44
+ &:hover {
45
+ color: ${(props) => (props.$active ? 'var(--brand-background)' : 'var(--brand-text-primary)')};
46
+ }
47
+ `;
48
+ const RailBody = styled.div `
49
+ flex: 1;
50
+ min-height: 0;
51
+ overflow-y: auto;
52
+ padding: 18px;
53
+ `;
54
+ export default function ComposerRightRail({ isVisible, onToggle, activeTab, onTabChange, tabs, title = 'image system', statusLabel = 'live', showEdgeToggle = false, topOffsetPx = 0, }) {
5
55
  const active = tabs.find((tab) => tab.id === activeTab) ?? tabs[0] ?? null;
6
56
  const hasStatus = Boolean(statusLabel && statusLabel.trim().length > 0);
7
- return (_jsxs(_Fragment, { children: [isVisible ? (_jsxs(RightPanel, { "$open": isVisible, children: [_jsx(RightPanelCollapseToggle, { type: "button", onClick: onToggle, "aria-label": "Hide right panel", title: "Hide right panel", children: _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" }) }) }), _jsxs("div", { className: "border-b viewer-ui-kit-border px-5 py-4", children: [_jsxs("div", { className: "flex items-center gap-2 text-[11px] uppercase tracking-[0.14em] viewer-ui-kit-text-subtle", children: [_jsx("span", { children: title }), hasStatus ? _jsx("span", { "aria-hidden": "true", children: "/" }) : null, hasStatus ? _jsx("span", { children: statusLabel }) : null] }), _jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: tabs.map((tab) => (_jsx("button", { type: "button", onClick: () => onTabChange(tab.id), className: `rounded-full px-3 py-2 text-[11px] font-semibold uppercase tracking-[0.08em] whitespace-nowrap transition border ${active?.id === tab.id
8
- ? 'bg-[var(--viewer-ui-color-toggle)] text-[var(--viewer-ui-color-toggle-text)] border-[var(--viewer-ui-color-toggle)]'
9
- : 'bg-[var(--viewer-ui-color-tab-bg)] text-[var(--viewer-ui-color-text-muted)] border-[var(--viewer-ui-color-panel-border-subtle)] hover:bg-[var(--viewer-ui-color-button-secondary)] hover:text-[var(--viewer-ui-color-text-strong)]'}`, children: tab.label }, tab.id))) })] }), _jsx("div", { className: "viewer-ui-shell-right-body flex-1 overflow-y-auto px-5 py-5", children: active?.content ?? null })] })) : null, !isVisible ? (_jsx(RightPanelShowToggle, { type: "button", onClick: onToggle, "aria-label": "Show right panel", title: "Show right panel", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M12.707 14.707a1 1 0 010-1.414L9.414 10l3.293-3.293a1 1 0 00-1.414-1.414l-4 4a1 1 0 000 1.414l4 4a1 1 0 001.414 0z", clipRule: "evenodd" }) }) })) : null] }));
57
+ return (_jsxs(_Fragment, { children: [isVisible ? (_jsxs(RightPanel, { "$open": isVisible, "$topOffset": topOffsetPx, children: [showEdgeToggle ? (_jsx(RightPanelCollapseToggle, { type: "button", onClick: onToggle, "aria-label": "Hide right panel", title: "Hide right panel", children: _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" }) }) })) : null, _jsxs(RailHeader, { children: [_jsxs(RailEyebrow, { children: [_jsx("span", { children: title }), hasStatus ? _jsx("span", { "aria-hidden": "true", children: "/" }) : null, hasStatus ? _jsx("span", { children: statusLabel }) : null] }), _jsx(RailTabs, { children: tabs.map((tab) => (_jsx(RailTab, { type: "button", onClick: () => onTabChange(tab.id), "$active": active?.id === tab.id, children: tab.label }, tab.id))) })] }), _jsx(RailBody, { children: active?.content ?? null })] })) : null, !isVisible && showEdgeToggle ? (_jsx(RightPanelShowToggle, { type: "button", onClick: onToggle, "aria-label": "Show right panel", title: "Show right panel", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M12.707 14.707a1 1 0 010-1.414L9.414 10l3.293-3.293a1 1 0 00-1.414-1.414l-4 4a1 1 0 000 1.414l4 4a1 1 0 001.414 0z", clipRule: "evenodd" }) }) })) : null] }));
10
58
  }
package/dist/LoginForm.js CHANGED
@@ -65,5 +65,5 @@ const Notice = styled.p `
65
65
  max-width: 720px;
66
66
  `;
67
67
  export default function LoginForm({ email, password, onEmailChange, onPasswordChange, onSubmit, busy = false, status = null, emailLabel = 'Email', passwordLabel = 'Password', submitLabel = 'Login', busyLabel = 'Logging in…', }) {
68
- return (_jsxs(Form, { onSubmit: onSubmit, autoComplete: "off", children: [_jsxs(Row, { children: [_jsx(LabelCell, { children: emailLabel }), _jsx(Input, { "aria-label": emailLabel, name: "email", placeholder: emailLabel, value: email, onChange: (event) => onEmailChange(event.target.value), autoComplete: "email", "data-lpignore": "true", required: true })] }), _jsxs(Row, { style: { marginTop: '1px' }, children: [_jsx(LabelCell, { children: passwordLabel }), _jsx(Input, { type: "password", "aria-label": passwordLabel, name: "password", placeholder: passwordLabel, required: true, value: password, onChange: (event) => onPasswordChange(event.target.value), autoComplete: "new-password", "data-lpignore": "true" })] }), _jsxs(ButtonRow, { style: { marginTop: '1px' }, children: [_jsx(Button, { type: "submit", "aria-label": submitLabel, disabled: busy || email.trim() === '' || password.trim() === '', children: busy ? busyLabel : submitLabel }), _jsx(Spacer, {})] }), status ? _jsx(Notice, { style: { color: 'var(--viewer-ui-color-text-error, #b91c1c)' }, children: status }) : null] }));
68
+ return (_jsxs(Form, { onSubmit: onSubmit, autoComplete: "on", children: [_jsxs(Row, { children: [_jsx(LabelCell, { children: emailLabel }), _jsx(Input, { "aria-label": emailLabel, name: "email", placeholder: emailLabel, value: email, onChange: (event) => onEmailChange(event.target.value), autoComplete: "username", "data-lpignore": "true", required: true })] }), _jsxs(Row, { style: { marginTop: '1px' }, children: [_jsx(LabelCell, { children: passwordLabel }), _jsx(Input, { type: "password", "aria-label": passwordLabel, name: "password", placeholder: passwordLabel, required: true, value: password, onChange: (event) => onPasswordChange(event.target.value), autoComplete: "current-password", "data-lpignore": "true" })] }), _jsxs(ButtonRow, { style: { marginTop: '1px' }, children: [_jsx(Button, { type: "submit", "aria-label": submitLabel, disabled: busy || email.trim() === '' || password.trim() === '', children: busy ? busyLabel : submitLabel }), _jsx(Spacer, {})] }), status ? _jsx(Notice, { style: { color: 'var(--viewer-ui-color-text-error, #b91c1c)' }, children: status }) : null] }));
69
69
  }
@@ -4,11 +4,10 @@ export type ManifestTopBarProps = {
4
4
  variant?: 'landing' | 'canvas';
5
5
  showPoweredBy?: boolean;
6
6
  showLogout?: boolean;
7
- showPanelToggle?: boolean;
8
7
  showSubtitle?: boolean;
9
8
  logoutCookieNames?: string[];
10
9
  logoutEndpoint?: string;
11
10
  logoutHref?: string;
12
11
  };
13
- export default function ManifestTopBar({ manifest, variant, showPoweredBy, showLogout, showPanelToggle, showSubtitle, logoutCookieNames, logoutEndpoint, logoutHref, }: ManifestTopBarProps): import("react/jsx-runtime").JSX.Element;
12
+ export default function ManifestTopBar({ manifest, variant, showPoweredBy, showLogout, showSubtitle, logoutCookieNames, logoutEndpoint, logoutHref, }: ManifestTopBarProps): import("react/jsx-runtime").JSX.Element;
14
13
  //# sourceMappingURL=ManifestTopBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ManifestTopBar.d.ts","sourceRoot":"","sources":["../src/ManifestTopBar.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAY/D,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,UAAU,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAiKF,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EACrC,QAAQ,EACR,OAAkB,EAClB,aAAqB,EACrB,UAAkB,EAClB,eAAuB,EACvB,YAAoB,EACpB,iBAAiB,EACjB,cAAmC,EACnC,UAAqB,GACtB,EAAE,mBAAmB,2CA4HrB"}
1
+ {"version":3,"file":"ManifestTopBar.d.ts","sourceRoot":"","sources":["../src/ManifestTopBar.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAY/D,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,UAAU,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AA+KF,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EACrC,QAAQ,EACR,OAAkB,EAClB,aAAqB,EACrB,UAAkB,EAClB,YAAoB,EACpB,iBAAiB,EACjB,cAAmC,EACnC,UAAqB,GACtB,EAAE,mBAAmB,2CA+HrB"}
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useEffect, useMemo, useRef, useState } from 'react';
4
4
  import Link from 'next/link';
5
- import { usePathname, useRouter, useSearchParams } from 'next/navigation';
5
+ import { usePathname, useSearchParams } from 'next/navigation';
6
6
  import { buildLoginHref, useClientHydrated, useComposerAuthState, useSessionLogout, useSurfaceComposerData, } from '@treasuryspatial/viewer-react';
7
7
  import styled from 'styled-components';
8
8
  import TopBar from './TopBar.js';
@@ -67,21 +67,35 @@ const AuthButton = styled.button `
67
67
  cursor: pointer;
68
68
  padding: 0;
69
69
  white-space: nowrap;
70
+ display: inline-grid;
71
+ align-items: center;
72
+ grid-template-areas: 'auth';
70
73
 
71
74
  &:hover {
72
- color: var(--brand-primary);
75
+ color: var(--brand-text-primary);
76
+ }
77
+
78
+ .auth-default,
79
+ .auth-logout {
80
+ grid-area: auth;
81
+ transition: opacity 0.16s ease;
73
82
  }
74
83
 
75
- .auth-hover {
76
- display: none;
84
+ .auth-logout {
85
+ opacity: 0;
86
+ visibility: hidden;
77
87
  }
78
88
 
79
- &:hover .auth-default {
80
- display: none;
89
+ &:hover .auth-default,
90
+ &:focus-visible .auth-default {
91
+ opacity: 0;
92
+ visibility: hidden;
81
93
  }
82
94
 
83
- &:hover .auth-hover {
84
- display: inline;
95
+ &:hover .auth-logout,
96
+ &:focus-visible .auth-logout {
97
+ opacity: 1;
98
+ visibility: visible;
85
99
  }
86
100
  `;
87
101
  const AuthLink = styled(Link) `
@@ -152,9 +166,8 @@ const isRouteActive = (pathname, href) => {
152
166
  return pathname === '/';
153
167
  return pathname === routePath || pathname.startsWith(`${routePath}/`);
154
168
  };
155
- export default function ManifestTopBar({ manifest, variant = 'canvas', showPoweredBy = false, showLogout = false, showPanelToggle = false, showSubtitle = false, logoutCookieNames, logoutEndpoint = '/api/auth/logout', logoutHref = '/login', }) {
169
+ export default function ManifestTopBar({ manifest, variant = 'canvas', showPoweredBy = false, showLogout = false, showSubtitle = false, logoutCookieNames, logoutEndpoint = '/api/auth/logout', logoutHref = '/login', }) {
156
170
  const pathname = usePathname();
157
- const router = useRouter();
158
171
  const searchParams = useSearchParams();
159
172
  const hydrated = useClientHydrated();
160
173
  const composerData = useSurfaceComposerData();
@@ -181,8 +194,7 @@ export default function ManifestTopBar({ manifest, variant = 'canvas', showPower
181
194
  : logoutHref;
182
195
  const handleLogout = useSessionLogout({
183
196
  logoutRoute: logoutEndpoint,
184
- redirectPath: logoutHref,
185
- onRedirect: (path) => router.push(path),
197
+ redirectPath: loginHref,
186
198
  });
187
199
  useEffect(() => {
188
200
  if (!searchOpen)
@@ -204,7 +216,8 @@ export default function ManifestTopBar({ manifest, variant = 'canvas', showPower
204
216
  if (!showLogout)
205
217
  return null;
206
218
  if (hydrated && auth.isAuthenticated) {
207
- return (_jsxs(AuthButton, { type: "button", onClick: handleLogout, children: [_jsx("span", { className: "auth-default", children: formatDisplayName(auth.name || auth.user) }), _jsx("span", { className: "auth-hover", children: "logout" })] }));
219
+ const authLabel = formatDisplayName(auth.name || auth.user);
220
+ return (_jsxs(AuthButton, { type: "button", onClick: handleLogout, "aria-label": "logout", children: [_jsx("span", { className: "auth-default", children: authLabel }), _jsx("span", { className: "auth-logout", children: "logout" })] }));
208
221
  }
209
222
  if (pathname === logoutHref)
210
223
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"MetricsPanelContent.d.ts","sourceRoot":"","sources":["../src/MetricsPanelContent.tsx"],"names":[],"mappings":"AAEA,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;AAKD,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,2CA4D1B"}
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,7 +1,63 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import styled from 'styled-components';
3
4
  const formatMeters = (value) => `${value.toFixed(2)} m`;
4
5
  const formatDegrees = (value) => `${value.toFixed(1)}°`;
6
+ const Root = styled.div `
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: 18px;
10
+ `;
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
+ `;
5
61
  export default function MetricsPanelContent({ cameraMetrics, distanceToFloor, distanceToCeiling, distanceToNorth, distanceToSouth, distanceToEast, distanceToWest, compassAngle, pitchAngle, }) {
6
62
  const sections = [
7
63
  {
@@ -37,5 +93,5 @@ export default function MetricsPanelContent({ cameraMetrics, distanceToFloor, di
37
93
  }
38
94
  : null,
39
95
  ].filter(Boolean);
40
- return (_jsxs("div", { className: "space-y-5", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("div", { className: "text-[16px] font-semibold tracking-[0.01em] viewer-ui-kit-text", children: "viewer metrics" }), _jsx("div", { className: "text-[10px] uppercase tracking-[0.18em] viewer-ui-kit-text-subtle", children: "live scene telemetry" })] }), _jsx("div", { className: "space-y-5 text-[12px]", children: sections.map((section) => (_jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "text-[10px] uppercase tracking-[0.18em] viewer-ui-kit-text-subtle", children: section.title }), section.metrics.map((metric) => (_jsxs("div", { className: "flex justify-between gap-4 border-b viewer-ui-kit-border-subtle pb-2 last:border-b-0 last:pb-0", children: [_jsx("span", { className: "viewer-ui-kit-text-muted", children: metric.label }), _jsx("span", { className: "font-mono viewer-ui-kit-text", children: metric.value })] }, metric.label)))] }, section.title))) })] }));
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))) })] }));
41
97
  }
package/dist/ModeBar.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { ReactNode } from 'react';
2
1
  export type ModeTab = {
3
2
  id: string;
4
3
  label: string;
@@ -12,15 +11,14 @@ export type ModeBarProps = {
12
11
  tabs: ModeTab[];
13
12
  tone?: 'green' | 'ochre';
14
13
  heightPx?: number;
15
- collapsed?: boolean;
16
- showToggle?: boolean;
17
14
  lockedLabel?: string;
18
15
  onSelect?: (modeId: string) => void;
19
- onTogglePanels?: () => void;
20
- toggleButton?: ReactNode;
21
16
  hidden?: boolean;
22
17
  className?: string;
18
+ showPanelToggle?: boolean;
19
+ panelsCollapsed?: boolean;
20
+ onTogglePanels?: () => void;
23
21
  };
24
22
  export declare const MODE_BAR_HEIGHT_PX = 34;
25
- export default function ModeBar({ active, topOffsetPx, tabs, tone, heightPx, collapsed, showToggle, lockedLabel, onSelect, onTogglePanels, toggleButton, hidden, className, }: ModeBarProps): import("react/jsx-runtime").JSX.Element | null;
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;
26
24
  //# sourceMappingURL=ModeBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ModeBar.d.ts","sourceRoot":"","sources":["../src/ModeBar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAqGvC,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,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,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,SAAiB,EACjB,UAAkB,EAClB,WAA2B,EAC3B,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,MAAc,EACd,SAAS,GACV,EAAE,YAAY,kDA4Ed"}
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"}
package/dist/ModeBar.js CHANGED
@@ -11,6 +11,17 @@ const Root = styled.div `
11
11
  background: var(--viewer-ui-color-bg-base, var(--brand-panel, #f6f3eb));
12
12
  border-bottom: 1px solid var(--viewer-ui-color-panel-border, rgba(47, 74, 60, 0.35));
13
13
  `;
14
+ const ToggleOverlay = styled.div `
15
+ position: absolute;
16
+ left: 50%;
17
+ top: calc(100% + 8px);
18
+ transform: translateX(-50%);
19
+ z-index: 80;
20
+ display: flex;
21
+ align-items: center;
22
+ gap: 8px;
23
+ pointer-events: auto;
24
+ `;
14
25
  const Tabs = styled.div `
15
26
  height: 100%;
16
27
  display: flex;
@@ -32,73 +43,56 @@ const TabLink = styled.a `
32
43
  align-items: center;
33
44
  text-decoration: none;
34
45
  font-size: 13px;
35
- font-weight: 700;
46
+ font-weight: 600;
36
47
  letter-spacing: 0.04em;
37
48
  text-transform: lowercase;
38
- transition: color 0.16s ease, background-color 0.16s ease;
49
+ transition: color 0.16s ease, background-color 0.16s ease, border-color 0.16s ease;
39
50
  background: ${(props) => props.$active
40
51
  ? props.$tone === 'green'
41
- ? 'var(--viewer-ui-color-button-secondary)'
42
- : 'var(--viewer-ui-color-button-primary)'
52
+ ? 'rgba(49, 143, 78, 0.12)'
53
+ : 'rgba(15, 23, 42, 0.08)'
43
54
  : 'var(--viewer-ui-color-tab-bg, rgba(47, 74, 60, 0.08))'};
44
55
  color: ${(props) => props.$active
45
- ? 'var(--viewer-ui-color-text-strong, #efe9de)'
56
+ ? props.$tone === 'green'
57
+ ? 'var(--viewer-ui-color-button-primary, #318f4e)'
58
+ : 'var(--viewer-ui-color-button-secondary, #0b1320)'
46
59
  : 'var(--viewer-ui-color-text-muted, rgba(47, 74, 60, 0.75))'};
47
60
 
48
61
  &:hover {
49
- color: var(--viewer-ui-color-text-strong, #efe9de);
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)'};
50
67
  }
51
68
  `;
52
- const ToggleCluster = styled.div `
53
- position: absolute;
54
- left: 50%;
55
- bottom: -1px;
56
- transform: translate(-50%, 100%);
57
- display: flex;
58
- align-items: center;
59
- gap: 8px;
69
+ 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));
60
75
  `;
61
- const ToggleTextButton = styled.button `
76
+ const ToggleText = styled.button `
62
77
  border: 0;
63
78
  background: transparent;
64
79
  font-size: 11px;
65
80
  text-transform: uppercase;
66
- letter-spacing: 0.06em;
67
- color: var(--viewer-ui-color-text-muted, rgba(239, 233, 222, 0.6));
68
- transition: color 0.16s ease;
81
+ letter-spacing: 0.14em;
82
+ color: var(--brand-text-secondary);
69
83
  cursor: pointer;
70
84
  padding: 0;
85
+ white-space: nowrap;
71
86
 
72
87
  &:hover {
73
- color: var(--viewer-ui-color-text-strong, #efe9de);
88
+ color: var(--brand-text-primary);
74
89
  }
75
90
  `;
76
- const LockedLabel = styled.span `
77
- margin-left: 8px;
78
- font-size: 9px;
79
- letter-spacing: 0.2em;
80
- text-transform: uppercase;
81
- color: var(--viewer-ui-color-text-muted, rgba(47, 74, 60, 0.75));
82
- `;
83
- const CollapsedRoot = styled.div `
84
- position: fixed;
85
- left: 50%;
86
- top: 0;
87
- z-index: 70;
88
- transform: translateX(-50%);
89
- display: flex;
90
- align-items: center;
91
- gap: 8px;
92
- `;
93
91
  export const MODE_BAR_HEIGHT_PX = 34;
94
- export default function ModeBar({ active, topOffsetPx, tabs, tone = 'green', heightPx = MODE_BAR_HEIGHT_PX, collapsed = false, showToggle = false, lockedLabel = 'coming soon', onSelect, onTogglePanels, toggleButton, hidden = false, className, }) {
95
- const renderedToggleButton = toggleButton ?? (_jsx("button", { type: "button", className: "collapse-toggle collapse-toggle--edge-top", onClick: onTogglePanels, "aria-label": collapsed ? 'Show panels' : 'Hide panels', children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: collapsed ? (_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" })) }) }));
96
- if (hidden && !showToggle) {
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, }) {
93
+ if (hidden) {
97
94
  return null;
98
95
  }
99
- if (collapsed && showToggle) {
100
- return (_jsxs(CollapsedRoot, { className: className, children: [renderedToggleButton, _jsx(ToggleTextButton, { type: "button", onClick: onTogglePanels, "aria-label": "Show all panels", children: "show all panels" })] }));
101
- }
102
96
  return (_jsxs(Root, { className: className, "$topOffsetPx": topOffsetPx, "$heightPx": heightPx, children: [_jsx(Tabs, { children: tabs.map((tab, index) => {
103
97
  const statusLabel = tab.status === 'coming-soon' || tab.locked ? lockedLabel : null;
104
98
  return (_jsxs(TabLink, { "$active": tab.id === active, "$tone": tone, "$index": index, href: tab.href ?? '#', onClick: (event) => {
@@ -107,5 +101,5 @@ export default function ModeBar({ active, topOffsetPx, tabs, tone = 'green', hei
107
101
  }
108
102
  onSelect?.(tab.id);
109
103
  }, children: [_jsx("span", { children: tab.label }), statusLabel ? _jsx(LockedLabel, { children: statusLabel }) : null] }, tab.id));
110
- }) }), showToggle ? (_jsxs(ToggleCluster, { children: [renderedToggleButton, _jsx(ToggleTextButton, { type: "button", onClick: onTogglePanels, "aria-label": "Toggle panels", children: "toggle panels" })] })) : null] }));
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] }));
111
105
  }
package/dist/TopBar.d.ts CHANGED
@@ -5,7 +5,8 @@ export type TopBarProps = {
5
5
  brand: ReactNode;
6
6
  center?: ReactNode;
7
7
  actions?: ReactNode;
8
+ bottomOverlay?: ReactNode;
8
9
  className?: string;
9
10
  };
10
- export default function TopBar({ compact, hidden, brand, center, actions, className, }: TopBarProps): import("react/jsx-runtime").JSX.Element;
11
+ export default function TopBar({ compact, hidden, brand, center, actions, bottomOverlay, className, }: TopBarProps): import("react/jsx-runtime").JSX.Element;
11
12
  //# sourceMappingURL=TopBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TopBar.d.ts","sourceRoot":"","sources":["../src/TopBar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAkDvC,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,OAAe,EACf,MAAc,EACd,KAAK,EACL,MAAM,EACN,OAAO,EACP,SAAS,GACV,EAAE,WAAW,2CAUb"}
1
+ {"version":3,"file":"TopBar.d.ts","sourceRoot":"","sources":["../src/TopBar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA8DvC,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,OAAe,EACf,MAAc,EACd,KAAK,EACL,MAAM,EACN,OAAO,EACP,aAAa,EACb,SAAS,GACV,EAAE,WAAW,2CAWb"}
package/dist/TopBar.js CHANGED
@@ -13,11 +13,12 @@ const Root = styled.nav `
13
13
  color: var(--viewer-ui-color-text-strong, var(--brand-text-primary, #1f2937));
14
14
  transform: ${(props) => (props.$hidden ? 'translateY(-100%)' : 'translateY(0)')};
15
15
  transition: transform 0.22s ease;
16
+ overflow: visible;
16
17
  `;
17
18
  const Inner = styled.div `
18
19
  height: 100%;
19
20
  display: grid;
20
- grid-template-columns: minmax(0, 1fr) auto;
21
+ grid-template-columns: ${(props) => (props.$hasCenter ? 'minmax(0, 1fr) auto minmax(0, 1fr)' : 'minmax(0, 1fr) auto')};
21
22
  align-items: center;
22
23
  gap: 16px;
23
24
  padding: 0 16px;
@@ -32,7 +33,7 @@ const BrandSlot = styled.div `
32
33
  align-items: center;
33
34
  `;
34
35
  const CenterSlot = styled.div `
35
- display: none;
36
+ display: flex;
36
37
  justify-content: center;
37
38
  align-items: center;
38
39
  min-width: 0;
@@ -43,6 +44,16 @@ const ActionsSlot = styled.div `
43
44
  justify-content: flex-end;
44
45
  align-items: center;
45
46
  `;
46
- export default function TopBar({ compact = false, hidden = false, brand, center, actions, className, }) {
47
- return (_jsx(Root, { className: className, "$compact": compact, "$hidden": hidden, children: _jsxs(Inner, { children: [_jsx(BrandSlot, { children: brand }), _jsx(CenterSlot, { children: center }), _jsx(ActionsSlot, { children: actions })] }) }));
47
+ const BottomOverlay = styled.div `
48
+ position: absolute;
49
+ left: 50%;
50
+ bottom: -1px;
51
+ transform: translate(-50%, 100%);
52
+ z-index: 60;
53
+ display: ${(props) => (props.$compact ? 'flex' : 'none')};
54
+ align-items: center;
55
+ gap: 8px;
56
+ `;
57
+ export default function TopBar({ compact = false, hidden = false, brand, center, actions, bottomOverlay, className, }) {
58
+ return (_jsxs(Root, { className: className, "$compact": compact, "$hidden": hidden, children: [_jsxs(Inner, { "$hasCenter": Boolean(center), children: [_jsx(BrandSlot, { children: brand }), center ? _jsx(CenterSlot, { children: center }) : null, _jsx(ActionsSlot, { children: actions })] }), bottomOverlay ? _jsx(BottomOverlay, { "$compact": compact, children: bottomOverlay }) : null] }));
48
59
  }
package/dist/layout.d.ts CHANGED
@@ -20,6 +20,7 @@ export declare const PanelCollapseToggle: import("styled-components/dist/types")
20
20
  export declare const PanelShowToggle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>>, never>, never>> & string;
21
21
  export declare const RightPanel: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, {
22
22
  $open: boolean;
23
+ $topOffset?: number;
23
24
  }>> & string;
24
25
  export declare const RightPanelCollapseToggle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>>, never>, never>> & string;
25
26
  export declare const RightPanelShowToggle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>>, never>, never>> & string;
@@ -1 +1 @@
1
- {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM,6NAKlB,CAAC;AAEF,eAAO,MAAM,WAAW;iBAAiC,MAAM;YAM9D,CAAC;AAEF,eAAO,MAAM,eAAe,6NAK3B,CAAC;AAEF,eAAO,MAAM,YAAY;WAAyB,OAAO;YAexD,CAAC;AAEF,eAAO,MAAM,WAAW,6NAOvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,6NAI9B,CAAC;AAEF,eAAO,MAAM,cAAc,6NAK1B,CAAC;AAEF,eAAO,MAAM,UAAU,qOAItB,CAAC;AAEF,eAAO,MAAM,aAAa,yOAIzB,CAAC;AAEF,eAAO,MAAM,eAAe;YAAyB,SAAS,GAAG,OAAO,GAAG,OAAO;YA4BjF,CAAC;AAEF,eAAO,MAAM,SAAS,6NASrB,CAAC;AAEF,eAAO,MAAM,WAAW,6NAOvB,CAAC;AAEF,eAAO,MAAM,mBAAmB,wbAM/B,CAAC;AAEF,eAAO,MAAM,eAAe,wbAM3B,CAAC;AAEF,eAAO,MAAM,UAAU;WAAyB,OAAO;YActD,CAAC;AAEF,eAAO,MAAM,wBAAwB,wbAMpC,CAAC;AAEF,eAAO,MAAM,oBAAoB,wbAMhC,CAAC;AAEF,eAAO,MAAM,gBAAgB;iBAA6B,MAAM;YAO/D,CAAC;AAEF,eAAO,MAAM,aAAa,6NAYzB,CAAC;AAEF,eAAO,MAAM,eAAe,6NAK3B,CAAC;AAEF,eAAO,MAAM,cAAc,+NAK1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,yOAa7B,CAAC;AAEF,eAAO,MAAM,aAAa,6NAGzB,CAAC;AAEF,eAAO,MAAM,YAAY,6NAKxB,CAAC;AAEF,eAAO,MAAM,kBAAkB,6NAI9B,CAAC;AAEF,eAAO,MAAM,eAAe,yOAa3B,CAAC;AAEF,eAAO,MAAM,gBAAgB;iBAA6B,OAAO;YAYhE,CAAC"}
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM,6NAKlB,CAAC;AAEF,eAAO,MAAM,WAAW;iBAAiC,MAAM;YAM9D,CAAC;AAEF,eAAO,MAAM,eAAe,6NAK3B,CAAC;AAEF,eAAO,MAAM,YAAY;WAAyB,OAAO;YAexD,CAAC;AAEF,eAAO,MAAM,WAAW,6NAOvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,6NAI9B,CAAC;AAEF,eAAO,MAAM,cAAc,6NAK1B,CAAC;AAEF,eAAO,MAAM,UAAU,qOAItB,CAAC;AAEF,eAAO,MAAM,aAAa,yOAIzB,CAAC;AAEF,eAAO,MAAM,eAAe;YAAyB,SAAS,GAAG,OAAO,GAAG,OAAO;YA4BjF,CAAC;AAEF,eAAO,MAAM,SAAS,6NASrB,CAAC;AAEF,eAAO,MAAM,WAAW,6NAOvB,CAAC;AAEF,eAAO,MAAM,mBAAmB,wbAM/B,CAAC;AAEF,eAAO,MAAM,eAAe,wbAM3B,CAAC;AAEF,eAAO,MAAM,UAAU;WAAyB,OAAO;iBAAe,MAAM;YAc3E,CAAC;AAEF,eAAO,MAAM,wBAAwB,wbAMpC,CAAC;AAEF,eAAO,MAAM,oBAAoB,wbAMhC,CAAC;AAEF,eAAO,MAAM,gBAAgB;iBAA6B,MAAM;YAO/D,CAAC;AAEF,eAAO,MAAM,aAAa,6NAYzB,CAAC;AAEF,eAAO,MAAM,eAAe,6NAK3B,CAAC;AAEF,eAAO,MAAM,cAAc,+NAK1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,yOAa7B,CAAC;AAEF,eAAO,MAAM,aAAa,6NAGzB,CAAC;AAEF,eAAO,MAAM,YAAY,6NAKxB,CAAC;AAEF,eAAO,MAAM,kBAAkB,6NAI9B,CAAC;AAEF,eAAO,MAAM,eAAe,yOAa3B,CAAC;AAEF,eAAO,MAAM,gBAAgB;iBAA6B,OAAO;YAYhE,CAAC"}
package/dist/layout.js CHANGED
@@ -126,8 +126,8 @@ export const PanelShowToggle = styled.button.attrs({ className: 'collapse-toggle
126
126
  export const RightPanel = styled.aside `
127
127
  position: absolute;
128
128
  right: 0;
129
- top: 0;
130
- bottom: 0;
129
+ top: ${(props) => props.$topOffset ?? 0}px;
130
+ height: calc(100% - ${(props) => props.$topOffset ?? 0}px);
131
131
  width: var(--ui-metrics-width);
132
132
  background: var(--brand-panel);
133
133
  border-left: 1px solid var(--brand-panel-border);
@@ -135,7 +135,7 @@ export const RightPanel = styled.aside `
135
135
  display: flex;
136
136
  flex-direction: column;
137
137
  transform: translateX(${(props) => (props.$open ? '0' : '105%')});
138
- transition: transform 0.3s ease;
138
+ transition: transform 0.3s ease, top 0.3s ease, height 0.3s ease;
139
139
  z-index: 30;
140
140
  `;
141
141
  export const RightPanelCollapseToggle = styled.button.attrs({ className: 'collapse-toggle collapse-toggle--edge-left' }) `