@treasuryspatial/viewer-ui-kit 0.1.40 → 0.1.42

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.
@@ -13,7 +13,8 @@ type ComposerRightRailProps = {
13
13
  title?: string;
14
14
  statusLabel?: string;
15
15
  showEdgeToggle?: boolean;
16
+ topOffsetPx?: number;
16
17
  };
17
- export default function ComposerRightRail({ isVisible, onToggle, activeTab, onTabChange, tabs, title, statusLabel, showEdgeToggle, }: 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;
18
19
  export {};
19
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;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EACxC,SAAS,EACT,QAAQ,EACR,SAAS,EACT,WAAW,EACX,IAAI,EACJ,KAAsB,EACtB,WAAoB,EACpB,cAAsB,GACvB,EAAE,sBAAsB,2CAqExB"}
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', showEdgeToggle = false, }) {
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: [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("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 && 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] }));
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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"LandingShell.d.ts","sourceRoot":"","sources":["../src/LandingShell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAsG1E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,UAAU,CAAC;IACrB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,QAAQ,EACR,OAAO,EACP,aAAqB,EACrB,UAAkB,EAClB,SAAS,GACV,EAAE,iBAAiB,2CAuBnB"}
1
+ {"version":3,"file":"LandingShell.d.ts","sourceRoot":"","sources":["../src/LandingShell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAoI1E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,UAAU,CAAC;IACrB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,QAAQ,EACR,OAAO,EACP,aAAqB,EACrB,UAAkB,EAClB,SAAS,GACV,EAAE,iBAAiB,2CAuBnB"}
@@ -8,13 +8,15 @@ const Root = styled.main `
8
8
  color: var(--brand-text-primary);
9
9
  `;
10
10
  const Section = styled.section `
11
+ min-height: 100vh;
11
12
  display: flex;
12
13
  flex-direction: column;
13
- padding: calc(var(--ui-nav-height) + 28px) 0 56px;
14
+ padding-top: calc(var(--ui-nav-height) + 72px);
15
+ margin-bottom: 50px;
14
16
 
15
17
  @media (min-width: 1024px) {
16
- padding-top: calc(var(--ui-nav-height) + 40px);
17
- padding-bottom: 96px;
18
+ padding-top: calc(var(--ui-nav-height) + 85px);
19
+ padding-bottom: 140px;
18
20
  }
19
21
  `;
20
22
  const Row = styled.div `
@@ -31,6 +33,8 @@ const LeftColumn = styled.div `
31
33
 
32
34
  @media (min-width: 1024px) {
33
35
  width: 50%;
36
+ position: relative;
37
+ z-index: 1;
34
38
  }
35
39
  `;
36
40
  const RightColumn = styled.div `
@@ -41,15 +45,13 @@ const RightColumn = styled.div `
41
45
  }
42
46
  `;
43
47
  const Header = styled.div `
44
- max-width: 65vw;
45
- padding: 72px 24px 0;
48
+ max-width: min(65vw, 720px);
49
+ padding: 108px 24px 0 24px;
46
50
  font-family: var(--ui-font-family, system-ui);
47
51
  font-weight: 400;
48
- color: var(--brand-primary);
49
52
 
50
53
  @media (min-width: 768px) {
51
54
  padding-left: 48px;
52
- font-size: 36px;
53
55
  }
54
56
 
55
57
  @media (min-width: 1024px) {
@@ -57,24 +59,47 @@ const Header = styled.div `
57
59
  }
58
60
  `;
59
61
  const HeaderTitle = styled.div `
60
- font-size: clamp(34px, 3vw + 18px, 61px);
62
+ color: var(--brand-primary);
63
+ font-size: 32px;
61
64
  line-height: 1.02;
62
65
  letter-spacing: -0.03em;
66
+
67
+ @media (min-width: 768px) {
68
+ font-size: 36px;
69
+ }
70
+
71
+ @media (min-width: 1024px) {
72
+ font-size: 42px;
73
+ }
74
+
75
+ @media (min-width: 1440px) {
76
+ font-size: 61px;
77
+ }
63
78
  `;
64
79
  const HeaderStrap = styled.div `
65
- margin-top: 18px;
66
- font-size: clamp(22px, 2vw + 12px, 40px);
80
+ margin-top: 20px;
81
+ color: var(--brand-text-secondary);
82
+ font-size: 25px;
67
83
  line-height: 1.1;
68
84
  letter-spacing: -0.02em;
85
+
86
+ @media (min-width: 1024px) {
87
+ font-size: 35px;
88
+ }
89
+
90
+ @media (min-width: 1440px) {
91
+ font-size: 40px;
92
+ }
69
93
  `;
70
94
  const Body = styled.div `
71
95
  padding: 32px 24px 0;
72
- font-size: 15px;
73
- line-height: 1.8;
74
- color: var(--brand-text-secondary);
96
+ color: var(--brand-text-primary);
97
+ font-family: var(--ui-font-family, system-ui);
98
+ font-size: 16px;
99
+ line-height: 1.45;
75
100
 
76
101
  p {
77
- margin: 0 0 20px;
102
+ margin: 0 0 32px;
78
103
  }
79
104
 
80
105
  p:last-child {
@@ -87,7 +112,12 @@ const Body = styled.div `
87
112
  }
88
113
 
89
114
  @media (min-width: 1024px) {
90
- padding: 24px 84px 0 32px;
115
+ padding: 260px 84px 0 0;
116
+ max-width: 960px;
117
+ }
118
+
119
+ @media (min-width: 1440px) {
120
+ font-size: 20px;
91
121
  }
92
122
  `;
93
123
  export default function LandingShell({ manifest, content, showPoweredBy = false, showLogout = false, className, }) {
package/dist/LoginForm.js CHANGED
@@ -12,7 +12,7 @@ const Row = styled.div `
12
12
  display: flex;
13
13
  `;
14
14
  const LabelCell = styled.div `
15
- background: var(--brand-secondary);
15
+ background: #6b7280;
16
16
  width: 296px;
17
17
  padding: 16px;
18
18
  color: white;
@@ -23,7 +23,7 @@ const Input = styled.input `
23
23
  outline: none;
24
24
  flex: 1;
25
25
  border: none;
26
- background: color-mix(in srgb, var(--brand-panel) 88%, var(--brand-background) 12%);
26
+ background: #f2f2f5;
27
27
  padding: 16px;
28
28
  font-size: 16px;
29
29
  color: var(--brand-text-primary);
@@ -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
  }
@@ -8,14 +8,14 @@ const Root = styled.main `
8
8
  color: var(--brand-text-primary);
9
9
  `;
10
10
  const Shell = styled.section `
11
- min-height: 100vh;
11
+ min-height: calc(100vh - var(--ui-nav-height));
12
12
  display: flex;
13
13
  align-items: center;
14
14
  justify-content: center;
15
- padding: calc(var(--ui-nav-height) + 40px) 24px 40px;
15
+ padding: calc(var(--ui-nav-height) + 16px) 32px 32px;
16
16
 
17
17
  @media (min-width: 768px) {
18
- padding: calc(var(--ui-nav-height) + 48px) 40px 48px;
18
+ padding: calc(var(--ui-nav-height) + 24px) 32px 32px;
19
19
  }
20
20
  `;
21
21
  const Inner = styled.div `
@@ -28,24 +28,24 @@ const Header = styled.header `
28
28
  const Title = styled.h1 `
29
29
  margin: 0;
30
30
  font-family: var(--ui-font-family, system-ui);
31
- font-size: clamp(44px, 7vw, 72px);
32
- line-height: 0.96;
33
- letter-spacing: -0.03em;
31
+ font-size: clamp(54px, 7vw, 72px);
32
+ line-height: 1;
33
+ letter-spacing: -0.02em;
34
34
  font-weight: 400;
35
35
  color: var(--brand-text-primary);
36
36
  `;
37
37
  const Strap = styled.p `
38
38
  margin: 16px 0 0;
39
- max-width: 42ch;
39
+ max-width: 672px;
40
40
  font-size: 18px;
41
- line-height: 1.45;
41
+ line-height: 1.6;
42
42
  color: var(--brand-text-secondary);
43
43
  `;
44
44
  const Body = styled.p `
45
- margin: 18px 0 0;
46
- max-width: 52ch;
47
- font-size: 15px;
48
- line-height: 1.75;
45
+ margin: 20px 0 0;
46
+ max-width: 720px;
47
+ font-size: 16px;
48
+ line-height: 1.7;
49
49
  color: var(--brand-text-secondary);
50
50
  `;
51
51
  const Disclaimer = styled.p `
@@ -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;AAuJF,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,2CAmIrB"}
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"}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
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
5
  import { usePathname, useSearchParams } from 'next/navigation';
@@ -67,11 +67,35 @@ const AuthButton = styled.button `
67
67
  cursor: pointer;
68
68
  padding: 0;
69
69
  white-space: nowrap;
70
- min-width: 12ch;
71
- text-align: left;
70
+ display: inline-grid;
71
+ align-items: center;
72
+ grid-template-areas: 'auth';
72
73
 
73
74
  &:hover {
74
- 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;
82
+ }
83
+
84
+ .auth-logout {
85
+ opacity: 0;
86
+ visibility: hidden;
87
+ }
88
+
89
+ &:hover .auth-default,
90
+ &:focus-visible .auth-default {
91
+ opacity: 0;
92
+ visibility: hidden;
93
+ }
94
+
95
+ &:hover .auth-logout,
96
+ &:focus-visible .auth-logout {
97
+ opacity: 1;
98
+ visibility: visible;
75
99
  }
76
100
  `;
77
101
  const AuthLink = styled(Link) `
@@ -142,7 +166,7 @@ const isRouteActive = (pathname, href) => {
142
166
  return pathname === '/';
143
167
  return pathname === routePath || pathname.startsWith(`${routePath}/`);
144
168
  };
145
- 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', }) {
146
170
  const pathname = usePathname();
147
171
  const searchParams = useSearchParams();
148
172
  const hydrated = useClientHydrated();
@@ -150,7 +174,6 @@ export default function ManifestTopBar({ manifest, variant = 'canvas', showPower
150
174
  const { auth } = useComposerAuthState();
151
175
  const [searchOpen, setSearchOpen] = useState(false);
152
176
  const [searchQuery, setSearchQuery] = useState('');
153
- const [authHovered, setAuthHovered] = useState(false);
154
177
  const searchRef = useRef(null);
155
178
  const inputRef = useRef(null);
156
179
  const navigation = composerData.navigation;
@@ -171,7 +194,7 @@ export default function ManifestTopBar({ manifest, variant = 'canvas', showPower
171
194
  : logoutHref;
172
195
  const handleLogout = useSessionLogout({
173
196
  logoutRoute: logoutEndpoint,
174
- redirectPath: logoutHref,
197
+ redirectPath: loginHref,
175
198
  });
176
199
  useEffect(() => {
177
200
  if (!searchOpen)
@@ -193,13 +216,13 @@ export default function ManifestTopBar({ manifest, variant = 'canvas', showPower
193
216
  if (!showLogout)
194
217
  return null;
195
218
  if (hydrated && auth.isAuthenticated) {
196
- const authLabel = authHovered ? 'logout' : formatDisplayName(auth.name || auth.user);
197
- return (_jsx(AuthButton, { type: "button", onClick: handleLogout, onMouseEnter: () => setAuthHovered(true), onMouseLeave: () => setAuthHovered(false), onFocus: () => setAuthHovered(true), onBlur: () => setAuthHovered(false), "aria-label": authHovered ? 'logout' : authLabel, children: authLabel }));
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" })] }));
198
221
  }
199
222
  if (pathname === logoutHref)
200
223
  return null;
201
224
  return _jsx(AuthLink, { href: loginHref, children: "Login" });
202
- }, [auth.isAuthenticated, auth.name, auth.user, authHovered, handleLogout, hydrated, loginHref, logoutHref, pathname, showLogout]);
225
+ }, [auth.isAuthenticated, auth.name, auth.user, handleLogout, hydrated, loginHref, logoutHref, pathname, showLogout]);
203
226
  const actions = (_jsxs(Actions, { "$variant": variant, children: [_jsx(NavLink, { href: introHref, "$active": isRouteActive(pathname, introHref), children: "Introduction" }), _jsx(NavLink, { href: composeHref, "$active": isRouteActive(pathname, composeHref), children: "Compose" }), authControl, searchEnabled ? (_jsx(SearchWrap, { ref: searchRef, children: _jsx(SearchControl, { "$expanded": searchOpen, onClick: !searchOpen ? () => setSearchOpen(true) : undefined, children: searchOpen ? (_jsxs(_Fragment, { children: [_jsx(SearchInput, { ref: inputRef, type: "text", placeholder: "Search...", value: searchQuery, onChange: (event) => setSearchQuery(event.target.value), onClick: (event) => event.stopPropagation(), onKeyDown: (event) => {
204
227
  if (event.key === 'Escape') {
205
228
  setSearchOpen(false);
@@ -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(47, 74, 60, 0.75));
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(--brand-primary, #318f4e);
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: 58px;
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