@the-portland-company/shell 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chrome.css +53 -0
- package/dist/native.cjs +303 -59
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +62 -2
- package/dist/native.d.ts +62 -2
- package/dist/native.js +301 -60
- package/dist/native.js.map +1 -1
- package/package.json +1 -1
package/dist/chrome.css
CHANGED
|
@@ -296,3 +296,56 @@
|
|
|
296
296
|
--line: #333333;
|
|
297
297
|
--shadow-soft: 0 4px 16px rgba(0, 0, 0, 0.5);
|
|
298
298
|
}
|
|
299
|
+
|
|
300
|
+
/* ---------------------------------------------------------------------------
|
|
301
|
+
Top-bar widget slot — normalizes third-party launchers (e.g. DevNotes) to
|
|
302
|
+
the universal top-bar icon treatment (Global Rules: every icon the exact
|
|
303
|
+
same size, every badge the exact same style; no slot ships its own look).
|
|
304
|
+
Wrap the widget in `.topbar-widget-slot` (shell exports <TopBarWidgetSlot>).
|
|
305
|
+
--------------------------------------------------------------------------- */
|
|
306
|
+
.topbar-widget-slot > button,
|
|
307
|
+
.topbar-widget-slot > div > button:first-of-type,
|
|
308
|
+
.topbar-widget-slot > span > button:first-of-type {
|
|
309
|
+
width: var(--topbar-icon-button-size, 32px);
|
|
310
|
+
height: var(--topbar-icon-button-size, 32px);
|
|
311
|
+
display: inline-flex;
|
|
312
|
+
align-items: center;
|
|
313
|
+
justify-content: center;
|
|
314
|
+
border: 1px solid var(--line);
|
|
315
|
+
border-radius: 9999px;
|
|
316
|
+
background: transparent;
|
|
317
|
+
color: var(--topbar-icon-color, var(--muted));
|
|
318
|
+
opacity: 1;
|
|
319
|
+
position: relative;
|
|
320
|
+
transition: background-color 0.15s ease, color 0.15s ease;
|
|
321
|
+
}
|
|
322
|
+
.topbar-widget-slot > button:hover,
|
|
323
|
+
.topbar-widget-slot > div > button:first-of-type:hover,
|
|
324
|
+
.topbar-widget-slot > span > button:first-of-type:hover {
|
|
325
|
+
background: var(--topbar-icon-hover-bg, transparent);
|
|
326
|
+
color: var(--topbar-icon-hover-color, var(--foreground));
|
|
327
|
+
}
|
|
328
|
+
.topbar-widget-slot button svg {
|
|
329
|
+
width: var(--topbar-icon-size, 20px);
|
|
330
|
+
height: var(--topbar-icon-size, 20px);
|
|
331
|
+
opacity: 1;
|
|
332
|
+
}
|
|
333
|
+
/* Match <TopBarCountBadge>: same offset, size, fill and type as every count. */
|
|
334
|
+
.topbar-widget-slot button [class*="rounded-full"][class*="bg-"],
|
|
335
|
+
.topbar-widget-slot button .dn-badge {
|
|
336
|
+
position: absolute;
|
|
337
|
+
top: -4px;
|
|
338
|
+
right: -4px;
|
|
339
|
+
height: 1rem;
|
|
340
|
+
min-width: 1rem;
|
|
341
|
+
display: inline-flex;
|
|
342
|
+
align-items: center;
|
|
343
|
+
justify-content: center;
|
|
344
|
+
padding: 0 0.25rem;
|
|
345
|
+
border-radius: 9999px;
|
|
346
|
+
background: var(--color-race-red, #e63946);
|
|
347
|
+
color: #fff;
|
|
348
|
+
font-size: 10px;
|
|
349
|
+
font-weight: 400;
|
|
350
|
+
line-height: 1;
|
|
351
|
+
}
|
package/dist/native.cjs
CHANGED
|
@@ -55,7 +55,8 @@ function resolveBrandGlyph(name) {
|
|
|
55
55
|
function topBarIconButtonClass(tone = "default") {
|
|
56
56
|
const toneClass = tone === "danger" || tone === "warning" ? "text-[color:var(--color-race-red)] hover:text-[color:var(--color-race-red)]" : "text-[color:var(--topbar-icon-color,var(--muted))] hover:text-[color:var(--topbar-icon-hover-color,var(--foreground))] hover:bg-[color:var(--topbar-icon-hover-bg,transparent)]";
|
|
57
57
|
return [
|
|
58
|
-
|
|
58
|
+
// `group/tbtip` powers the shared <TopBarTooltip> rendered inside the trigger.
|
|
59
|
+
"group/tbtip relative flex items-center justify-center rounded-full border border-[color:var(--line)] transition",
|
|
59
60
|
"h-[var(--topbar-icon-button-size,32px)] w-[var(--topbar-icon-button-size,32px)]",
|
|
60
61
|
toneClass
|
|
61
62
|
].join(" ");
|
|
@@ -64,6 +65,75 @@ function TopBarCountBadge({ count }) {
|
|
|
64
65
|
if (!(count > 0)) return null;
|
|
65
66
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-[color:var(--color-race-red)] px-1 text-[10px] text-white", children: count > 99 ? "99+" : count });
|
|
66
67
|
}
|
|
68
|
+
function TopBarTooltip({
|
|
69
|
+
title,
|
|
70
|
+
description
|
|
71
|
+
}) {
|
|
72
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
73
|
+
"span",
|
|
74
|
+
{
|
|
75
|
+
role: "tooltip",
|
|
76
|
+
className: "pointer-events-none absolute left-1/2 top-full z-50 mt-2 hidden w-max max-w-56 -translate-x-1/2 flex-col rounded-lg border border-[color:var(--line)] bg-[color:var(--panel-elevated)] px-3 py-2 text-left shadow-[var(--shadow-soft)] group-hover/tbtip:flex",
|
|
77
|
+
children: [
|
|
78
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
79
|
+
"span",
|
|
80
|
+
{
|
|
81
|
+
"aria-hidden": true,
|
|
82
|
+
className: "absolute -top-[5px] left-1/2 h-2.5 w-2.5 -translate-x-1/2 rotate-45 border-l border-t border-[color:var(--line)] bg-[color:var(--panel-elevated)]"
|
|
83
|
+
}
|
|
84
|
+
),
|
|
85
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-[color:var(--foreground)]", children: title }),
|
|
86
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 text-[11px] leading-snug text-[color:var(--muted)]", children: description }) : null
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
function TopBarWidgetSlot({
|
|
92
|
+
title,
|
|
93
|
+
description,
|
|
94
|
+
children
|
|
95
|
+
}) {
|
|
96
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "topbar-widget-slot group/tbtip relative inline-flex", children: [
|
|
97
|
+
children,
|
|
98
|
+
/* @__PURE__ */ jsxRuntime.jsx(TopBarTooltip, { title, description })
|
|
99
|
+
] });
|
|
100
|
+
}
|
|
101
|
+
var THEME_OPTIONS = [
|
|
102
|
+
{ value: "light", label: "Light" },
|
|
103
|
+
{ value: "system", label: "System" },
|
|
104
|
+
{ value: "dark", label: "Dark" }
|
|
105
|
+
];
|
|
106
|
+
function NavThemeControl({
|
|
107
|
+
value,
|
|
108
|
+
onChange
|
|
109
|
+
}) {
|
|
110
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3", children: [
|
|
111
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Appearance" }),
|
|
112
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
113
|
+
"div",
|
|
114
|
+
{
|
|
115
|
+
role: "radiogroup",
|
|
116
|
+
"aria-label": "Appearance",
|
|
117
|
+
className: "flex overflow-hidden rounded-full border border-[color:var(--line)]",
|
|
118
|
+
children: THEME_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
119
|
+
"button",
|
|
120
|
+
{
|
|
121
|
+
type: "button",
|
|
122
|
+
role: "radio",
|
|
123
|
+
"aria-checked": value === opt.value,
|
|
124
|
+
onClick: () => onChange(opt.value),
|
|
125
|
+
className: [
|
|
126
|
+
"flex-1 px-3 py-1.5 text-xs font-semibold transition",
|
|
127
|
+
value === opt.value ? "bg-[color:var(--color-race-red)] text-white" : "text-[color:var(--muted)] hover:bg-[color:var(--panel)] hover:text-[color:var(--foreground)]"
|
|
128
|
+
].join(" "),
|
|
129
|
+
children: opt.label
|
|
130
|
+
},
|
|
131
|
+
opt.value
|
|
132
|
+
))
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
] });
|
|
136
|
+
}
|
|
67
137
|
var NavChromeContext = react.createContext(null);
|
|
68
138
|
function NavChromeProvider({
|
|
69
139
|
fetchJson,
|
|
@@ -128,6 +198,7 @@ function SlotGlyph({
|
|
|
128
198
|
}
|
|
129
199
|
function TopBarPopover({
|
|
130
200
|
label,
|
|
201
|
+
description,
|
|
131
202
|
slot,
|
|
132
203
|
fallbackIcon,
|
|
133
204
|
badge,
|
|
@@ -159,7 +230,6 @@ function TopBarPopover({
|
|
|
159
230
|
{
|
|
160
231
|
type: "button",
|
|
161
232
|
"aria-label": label,
|
|
162
|
-
title: label,
|
|
163
233
|
"aria-expanded": open,
|
|
164
234
|
className: topBarIconButtonClass(tone),
|
|
165
235
|
onClick: () => {
|
|
@@ -171,7 +241,8 @@ function TopBarPopover({
|
|
|
171
241
|
},
|
|
172
242
|
children: [
|
|
173
243
|
/* @__PURE__ */ jsxRuntime.jsx(SlotGlyph, { slot, fallback: fallbackIcon }),
|
|
174
|
-
typeof badge === "number" ? /* @__PURE__ */ jsxRuntime.jsx(TopBarCountBadge, { count: badge }) : null
|
|
244
|
+
typeof badge === "number" ? /* @__PURE__ */ jsxRuntime.jsx(TopBarCountBadge, { count: badge }) : null,
|
|
245
|
+
!open ? /* @__PURE__ */ jsxRuntime.jsx(TopBarTooltip, { title: label, description }) : null
|
|
175
246
|
]
|
|
176
247
|
}
|
|
177
248
|
),
|
|
@@ -285,6 +356,7 @@ function FuelAction({ orgId }) {
|
|
|
285
356
|
TopBarPopover,
|
|
286
357
|
{
|
|
287
358
|
label: "Communications Fuel",
|
|
359
|
+
description: "Remaining SMS and email sending balance for the active organization.",
|
|
288
360
|
slot: "comms-fuel",
|
|
289
361
|
fallbackIcon: BatteryGlyph,
|
|
290
362
|
tone: low ? "warning" : "default",
|
|
@@ -325,7 +397,8 @@ function NotificationsAction({ orgId }) {
|
|
|
325
397
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
326
398
|
TopBarPopover,
|
|
327
399
|
{
|
|
328
|
-
label: "Notifications",
|
|
400
|
+
label: "Alerts & Notifications",
|
|
401
|
+
description: "System alerts and recent activity for the active organization.",
|
|
329
402
|
slot: "notifications",
|
|
330
403
|
fallbackIcon: BellGlyph,
|
|
331
404
|
badge: loading ? 0 : count,
|
|
@@ -388,15 +461,23 @@ function SupportAction() {
|
|
|
388
461
|
}
|
|
389
462
|
};
|
|
390
463
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
391
|
-
/* @__PURE__ */ jsxRuntime.
|
|
464
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
392
465
|
"button",
|
|
393
466
|
{
|
|
394
467
|
type: "button",
|
|
395
468
|
"aria-label": "Support",
|
|
396
|
-
title: "Support",
|
|
397
469
|
className: topBarIconButtonClass(),
|
|
398
470
|
onClick: () => setOpen(true),
|
|
399
|
-
children:
|
|
471
|
+
children: [
|
|
472
|
+
/* @__PURE__ */ jsxRuntime.jsx(SlotGlyph, { slot: "support", fallback: LifeBuoyGlyph }),
|
|
473
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
474
|
+
TopBarTooltip,
|
|
475
|
+
{
|
|
476
|
+
title: "Support",
|
|
477
|
+
description: "Send a support request to the Politogy team."
|
|
478
|
+
}
|
|
479
|
+
)
|
|
480
|
+
]
|
|
400
481
|
}
|
|
401
482
|
),
|
|
402
483
|
open ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -471,24 +552,33 @@ function NavDisplayAction({
|
|
|
471
552
|
value,
|
|
472
553
|
onChange
|
|
473
554
|
}) {
|
|
474
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
475
|
-
|
|
555
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
556
|
+
TopBarPopover,
|
|
476
557
|
{
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
className:
|
|
482
|
-
"
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
558
|
+
label: "Navigation Display",
|
|
559
|
+
description: "Show navigation as a sub-menu, tabs, or both.",
|
|
560
|
+
fallbackIcon: LayoutGlyph,
|
|
561
|
+
panelClassName: "w-44",
|
|
562
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-1", role: "radiogroup", "aria-label": "Navigation display", children: NAV_DISPLAY_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
563
|
+
"button",
|
|
564
|
+
{
|
|
565
|
+
type: "button",
|
|
566
|
+
role: "radio",
|
|
567
|
+
"aria-checked": value === opt.value,
|
|
568
|
+
onClick: () => onChange(opt.value),
|
|
569
|
+
className: [
|
|
570
|
+
"flex w-full items-center justify-between px-4 py-2 text-left text-sm font-medium",
|
|
571
|
+
value === opt.value ? "text-[color:var(--color-race-red)]" : "text-[color:var(--foreground)] hover:bg-[color:var(--panel)]"
|
|
572
|
+
].join(" "),
|
|
573
|
+
children: [
|
|
574
|
+
opt.label,
|
|
575
|
+
value === opt.value ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "\u2713" }) : null
|
|
576
|
+
]
|
|
577
|
+
},
|
|
578
|
+
opt.value
|
|
579
|
+
)) })
|
|
580
|
+
}
|
|
581
|
+
);
|
|
492
582
|
}
|
|
493
583
|
|
|
494
584
|
// src/native/standardNav.ts
|
|
@@ -650,20 +740,20 @@ function NavSidebar({
|
|
|
650
740
|
org.id ? /* @__PURE__ */ jsxRuntime.jsx(OrgIdCopyButton, { id: org.id }) : null
|
|
651
741
|
] }),
|
|
652
742
|
org.organizations && org.organizations.length > 0 && org.onSwitch ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group relative", children: [
|
|
653
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
654
|
-
"
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
}
|
|
666
|
-
),
|
|
743
|
+
/* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex w-full cursor-pointer list-none items-center justify-between gap-2 rounded-md border border-[color:var(--line)] bg-[color:var(--panel-elevated)] px-2.5 py-2 text-left text-[color:var(--foreground)] shadow-sm transition hover:bg-[color:var(--panel)] [&::-webkit-details-marker]:hidden", children: [
|
|
744
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
745
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
746
|
+
"span",
|
|
747
|
+
{
|
|
748
|
+
style: { backgroundColor: orgBg },
|
|
749
|
+
className: "flex h-7 w-7 shrink-0 items-center justify-center overflow-hidden rounded-full text-[11px] font-bold text-white",
|
|
750
|
+
children: org.logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: org.logoUrl, alt: "", className: "h-full w-full object-cover" }) : (org.name ?? "Org").slice(0, 2).toUpperCase()
|
|
751
|
+
}
|
|
752
|
+
),
|
|
753
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-semibold", children: org.name ?? "No organizations" })
|
|
754
|
+
] }),
|
|
755
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {})
|
|
756
|
+
] }),
|
|
667
757
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 right-0 z-40 mt-1 max-h-72 overflow-y-auto rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] py-1 shadow-[var(--shadow-soft)]", children: org.organizations.map((o) => {
|
|
668
758
|
const selected = o.id === org.id;
|
|
669
759
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -699,11 +789,17 @@ function NavSidebar({
|
|
|
699
789
|
{
|
|
700
790
|
type: "button",
|
|
701
791
|
onClick: org.onClick,
|
|
702
|
-
|
|
703
|
-
className: "flex w-full items-center justify-between gap-2 rounded-md px-2.5 py-2 text-left text-white shadow-sm transition hover:opacity-95",
|
|
792
|
+
className: "flex w-full items-center justify-between gap-2 rounded-md border border-[color:var(--line)] bg-[color:var(--panel-elevated)] px-2.5 py-2 text-left text-[color:var(--foreground)] shadow-sm transition hover:bg-[color:var(--panel)]",
|
|
704
793
|
children: [
|
|
705
794
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
706
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
795
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
796
|
+
"span",
|
|
797
|
+
{
|
|
798
|
+
style: { backgroundColor: orgBg },
|
|
799
|
+
className: "flex h-7 w-7 shrink-0 items-center justify-center overflow-hidden rounded-full text-[11px] font-bold text-white",
|
|
800
|
+
children: org.logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: org.logoUrl, alt: "", className: "h-full w-full object-cover" }) : (org.name ?? "Org").slice(0, 2).toUpperCase()
|
|
801
|
+
}
|
|
802
|
+
),
|
|
707
803
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-semibold", children: org.name ?? "No organizations" })
|
|
708
804
|
] }),
|
|
709
805
|
/* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {})
|
|
@@ -954,6 +1050,7 @@ function NavTopBar({
|
|
|
954
1050
|
title,
|
|
955
1051
|
subtitle,
|
|
956
1052
|
user,
|
|
1053
|
+
userMenu,
|
|
957
1054
|
onSignOut,
|
|
958
1055
|
actionsList,
|
|
959
1056
|
actions,
|
|
@@ -977,31 +1074,176 @@ function NavTopBar({
|
|
|
977
1074
|
actionsList && actionsList.length > 0 ? actionsList.map((action) => /* @__PURE__ */ jsxRuntime.jsx(NavTopBarActionButton, { action }, action.key)) : null,
|
|
978
1075
|
actions,
|
|
979
1076
|
themeToggle,
|
|
980
|
-
/* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group relative", children: [
|
|
981
|
-
/* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex cursor-pointer list-none items-center gap-2.5 rounded-full py-1 pl-1 pr-2 transition hover:bg-[color:var(--panel-elevated)] [&::-webkit-details-marker]:hidden", children: [
|
|
1077
|
+
/* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group/acct relative", children: [
|
|
1078
|
+
/* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "group/tbtip relative flex cursor-pointer list-none items-center gap-2.5 rounded-full py-1 pl-1 pr-2 transition hover:bg-[color:var(--panel-elevated)] [&::-webkit-details-marker]:hidden", children: [
|
|
982
1079
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-9 w-9 items-center justify-center overflow-hidden rounded-full bg-[color:var(--color-race-red)] text-xs font-bold text-white", children: user?.avatarUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: user.avatarUrl, alt: "", className: "h-full w-full object-cover" }) : initials }),
|
|
983
1080
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "hidden flex-col leading-tight md:flex", children: [
|
|
984
1081
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-[color:var(--foreground)]", children: user?.name ?? "Signed in" }),
|
|
985
1082
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-[color:var(--muted)]", children: secondary })
|
|
986
1083
|
] }),
|
|
987
|
-
/* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {})
|
|
1084
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {}),
|
|
1085
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "group-open/acct:hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1086
|
+
TopBarTooltip,
|
|
1087
|
+
{
|
|
1088
|
+
title: "My Account",
|
|
1089
|
+
description: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1090
|
+
user?.name ?? "Signed in",
|
|
1091
|
+
user?.email ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1092
|
+
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
1093
|
+
user.email
|
|
1094
|
+
] }) : null,
|
|
1095
|
+
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
1096
|
+
"Profile, organizations, appearance and sign out."
|
|
1097
|
+
] })
|
|
1098
|
+
}
|
|
1099
|
+
) })
|
|
988
1100
|
] }),
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1101
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-0 z-30 mt-2 w-72 overflow-hidden rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] py-1 shadow-[var(--shadow-soft)]", children: [
|
|
1102
|
+
userMenu?.myProfileHref ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1103
|
+
"a",
|
|
1104
|
+
{
|
|
1105
|
+
href: safeHref(userMenu.myProfileHref),
|
|
1106
|
+
className: "flex w-full items-center gap-2.5 px-4 py-2.5 text-left text-sm font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)]",
|
|
1107
|
+
children: [
|
|
1108
|
+
/* @__PURE__ */ jsxRuntime.jsx(ProfileIcon, {}),
|
|
1109
|
+
"My Profile"
|
|
1110
|
+
]
|
|
1111
|
+
}
|
|
1112
|
+
) : null,
|
|
1113
|
+
userMenu?.organizationSettingsHref ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1114
|
+
"a",
|
|
1115
|
+
{
|
|
1116
|
+
href: safeHref(userMenu.organizationSettingsHref),
|
|
1117
|
+
className: "flex w-full items-center gap-2.5 border-t border-[color:var(--line)] px-4 py-2.5 text-left text-sm font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)]",
|
|
1118
|
+
children: [
|
|
1119
|
+
/* @__PURE__ */ jsxRuntime.jsx(BriefcaseIcon, {}),
|
|
1120
|
+
"Organization Settings"
|
|
1121
|
+
]
|
|
1122
|
+
}
|
|
1123
|
+
) : null,
|
|
1124
|
+
userMenu?.roles && userMenu.roles.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-[color:var(--line)] px-4 py-3", children: [
|
|
1125
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Roles & Organizations" }),
|
|
1126
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col gap-1.5", children: userMenu.roles.map((r, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex flex-wrap items-center gap-1.5 text-sm", children: [
|
|
1127
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-md bg-[color:var(--panel)] px-2 py-0.5 text-xs font-bold uppercase tracking-wide text-[color:var(--foreground)]", children: r.role }),
|
|
1128
|
+
r.orgName ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[color:var(--muted)]", children: [
|
|
1129
|
+
"in ",
|
|
1130
|
+
r.orgName
|
|
1131
|
+
] }) : null
|
|
1132
|
+
] }, `${r.role}-${i}`)) })
|
|
1133
|
+
] }) : null,
|
|
1134
|
+
userMenu?.accounts && userMenu.accounts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-[color:var(--line)] px-4 py-3", children: [
|
|
1135
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Accounts" }),
|
|
1136
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col gap-1", children: userMenu.accounts.map((a) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center gap-2.5", children: [
|
|
1137
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1138
|
+
"button",
|
|
1139
|
+
{
|
|
1140
|
+
type: "button",
|
|
1141
|
+
onClick: () => {
|
|
1142
|
+
if (!a.active) userMenu.onSwitchAccount?.(a.id);
|
|
1143
|
+
},
|
|
1144
|
+
className: "flex min-w-0 flex-1 items-center gap-2.5 rounded-lg px-1 py-1 text-left hover:bg-[color:var(--panel)]",
|
|
1145
|
+
children: [
|
|
1146
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full bg-[color:var(--color-race-red)] text-[11px] font-bold text-white", children: a.avatarUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: a.avatarUrl, alt: "", className: "h-full w-full object-cover" }) : (a.name ?? a.email ?? "?").slice(0, 2).toUpperCase() }),
|
|
1147
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col leading-tight", children: [
|
|
1148
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1149
|
+
"span",
|
|
1150
|
+
{
|
|
1151
|
+
className: [
|
|
1152
|
+
"truncate text-sm font-semibold",
|
|
1153
|
+
a.active ? "text-[color:var(--color-race-red)]" : "text-[color:var(--foreground)]"
|
|
1154
|
+
].join(" "),
|
|
1155
|
+
children: a.name ?? a.email ?? a.id.slice(0, 8)
|
|
1156
|
+
}
|
|
1157
|
+
),
|
|
1158
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs text-[color:var(--muted)]", children: a.active ? "Active" : a.email ?? "" })
|
|
1159
|
+
] })
|
|
1160
|
+
]
|
|
1161
|
+
}
|
|
1162
|
+
),
|
|
1163
|
+
!a.active && userMenu.onRemoveAccount ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1164
|
+
"button",
|
|
1165
|
+
{
|
|
1166
|
+
type: "button",
|
|
1167
|
+
"aria-label": `Remove ${a.name ?? a.email ?? "account"}`,
|
|
1168
|
+
onClick: () => userMenu.onRemoveAccount?.(a.id),
|
|
1169
|
+
className: "shrink-0 rounded p-1 text-[color:var(--color-race-red)] hover:bg-[color:var(--panel)]",
|
|
1170
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {})
|
|
1171
|
+
}
|
|
1172
|
+
) : null
|
|
1173
|
+
] }, a.id)) }),
|
|
1174
|
+
userMenu.addAccountHref || userMenu.onAddAccount ? userMenu.addAccountHref ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1175
|
+
"a",
|
|
1176
|
+
{
|
|
1177
|
+
href: safeHref(userMenu.addAccountHref),
|
|
1178
|
+
className: "mt-1.5 flex items-center gap-2.5 rounded-lg px-1 py-1.5 text-sm font-semibold text-[color:var(--color-race-red)] hover:bg-[color:var(--panel)]",
|
|
1179
|
+
children: [
|
|
1180
|
+
/* @__PURE__ */ jsxRuntime.jsx(AddUserIcon, {}),
|
|
1181
|
+
"Add Account"
|
|
1182
|
+
]
|
|
1183
|
+
}
|
|
1184
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1185
|
+
"button",
|
|
1186
|
+
{
|
|
1187
|
+
type: "button",
|
|
1188
|
+
onClick: userMenu.onAddAccount,
|
|
1189
|
+
className: "mt-1.5 flex w-full items-center gap-2.5 rounded-lg px-1 py-1.5 text-left text-sm font-semibold text-[color:var(--color-race-red)] hover:bg-[color:var(--panel)]",
|
|
1190
|
+
children: [
|
|
1191
|
+
/* @__PURE__ */ jsxRuntime.jsx(AddUserIcon, {}),
|
|
1192
|
+
"Add Account"
|
|
1193
|
+
]
|
|
1194
|
+
}
|
|
1195
|
+
) : null
|
|
1196
|
+
] }) : null,
|
|
1197
|
+
userMenu?.theme ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-[color:var(--line)]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1198
|
+
NavThemeControl,
|
|
1199
|
+
{
|
|
1200
|
+
value: userMenu.theme.value,
|
|
1201
|
+
onChange: userMenu.theme.onChange
|
|
1202
|
+
}
|
|
1203
|
+
) }) : null,
|
|
1204
|
+
onSignOut ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1205
|
+
"button",
|
|
1206
|
+
{
|
|
1207
|
+
type: "button",
|
|
1208
|
+
onClick: onSignOut,
|
|
1209
|
+
className: "flex w-full items-center gap-2.5 border-t border-[color:var(--line)] px-4 py-2.5 text-left text-sm font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)] hover:text-[color:var(--color-race-red)]",
|
|
1210
|
+
children: [
|
|
1211
|
+
/* @__PURE__ */ jsxRuntime.jsx(SignOutIcon, {}),
|
|
1212
|
+
"Sign out"
|
|
1213
|
+
]
|
|
1214
|
+
}
|
|
1215
|
+
) : null
|
|
1216
|
+
] })
|
|
1001
1217
|
] })
|
|
1002
1218
|
] })
|
|
1003
1219
|
] });
|
|
1004
1220
|
}
|
|
1221
|
+
function ProfileIcon() {
|
|
1222
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1223
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
|
|
1224
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "7", r: "4" })
|
|
1225
|
+
] });
|
|
1226
|
+
}
|
|
1227
|
+
function BriefcaseIcon() {
|
|
1228
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1229
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "7", width: "20", height: "14", rx: "2", ry: "2" }),
|
|
1230
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16" })
|
|
1231
|
+
] });
|
|
1232
|
+
}
|
|
1233
|
+
function TrashIcon() {
|
|
1234
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: 14, height: 14, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1235
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "3 6 5 6 21 6" }),
|
|
1236
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
1237
|
+
] });
|
|
1238
|
+
}
|
|
1239
|
+
function AddUserIcon() {
|
|
1240
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1241
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }),
|
|
1242
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8.5", cy: "7", r: "4" }),
|
|
1243
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "20", y1: "8", x2: "20", y2: "14" }),
|
|
1244
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "23", y1: "11", x2: "17", y2: "11" })
|
|
1245
|
+
] });
|
|
1246
|
+
}
|
|
1005
1247
|
function SignOutIcon() {
|
|
1006
1248
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1007
1249
|
"svg",
|
|
@@ -1031,7 +1273,8 @@ function NavTopBarActionButton({ action }) {
|
|
|
1031
1273
|
const Glyph = BrandGlyph ?? Icon;
|
|
1032
1274
|
const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1033
1275
|
/* @__PURE__ */ jsxRuntime.jsx(Glyph, { size: 20, className: "text-current" }),
|
|
1034
|
-
typeof action.badge === "number" && action.badge > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-[color:var(--color-race-red)] px-1 text-[10px] text-white", children: action.badge }) : null
|
|
1276
|
+
typeof action.badge === "number" && action.badge > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-[color:var(--color-race-red)] px-1 text-[10px] text-white", children: action.badge }) : null,
|
|
1277
|
+
/* @__PURE__ */ jsxRuntime.jsx(TopBarTooltip, { title: action.label, description: action.description })
|
|
1035
1278
|
] });
|
|
1036
1279
|
const isExternal = action.href ? /^https?:\/\//.test(action.href) : false;
|
|
1037
1280
|
if (action.href) {
|
|
@@ -1040,7 +1283,6 @@ function NavTopBarActionButton({ action }) {
|
|
|
1040
1283
|
{
|
|
1041
1284
|
href: safeHref(action.href),
|
|
1042
1285
|
"aria-label": action.label,
|
|
1043
|
-
title: action.label,
|
|
1044
1286
|
className,
|
|
1045
1287
|
...isExternal ? { target: "_blank", rel: "noreferrer" } : {},
|
|
1046
1288
|
children: content
|
|
@@ -1053,7 +1295,6 @@ function NavTopBarActionButton({ action }) {
|
|
|
1053
1295
|
type: "button",
|
|
1054
1296
|
onClick: action.onClick,
|
|
1055
1297
|
"aria-label": action.label,
|
|
1056
|
-
title: action.label,
|
|
1057
1298
|
className,
|
|
1058
1299
|
children: content
|
|
1059
1300
|
}
|
|
@@ -1173,10 +1414,13 @@ exports.NavChromeProvider = NavChromeProvider;
|
|
|
1173
1414
|
exports.NavDisplayAction = NavDisplayAction;
|
|
1174
1415
|
exports.NavSidebar = NavSidebar;
|
|
1175
1416
|
exports.NavTabStrip = NavTabStrip;
|
|
1417
|
+
exports.NavThemeControl = NavThemeControl;
|
|
1176
1418
|
exports.NavTopBar = NavTopBar;
|
|
1177
1419
|
exports.NotificationsAction = NotificationsAction;
|
|
1178
1420
|
exports.SupportAction = SupportAction;
|
|
1179
1421
|
exports.TopBarCountBadge = TopBarCountBadge;
|
|
1422
|
+
exports.TopBarTooltip = TopBarTooltip;
|
|
1423
|
+
exports.TopBarWidgetSlot = TopBarWidgetSlot;
|
|
1180
1424
|
exports.envChipClasses = envChipClasses;
|
|
1181
1425
|
exports.isNavItemActive = isNavItemActive;
|
|
1182
1426
|
exports.standardPolitogyNav = standardPolitogyNav;
|