@the-portland-company/shell 0.14.3 → 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/native.cjs CHANGED
@@ -52,6 +52,534 @@ function resolveBrandGlyph(name) {
52
52
  if (!name) return null;
53
53
  return GLYPHS[name.trim().toLowerCase()] ?? null;
54
54
  }
55
+ function topBarIconButtonClass(tone = "default") {
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
+ return [
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",
60
+ "h-[var(--topbar-icon-button-size,32px)] w-[var(--topbar-icon-button-size,32px)]",
61
+ toneClass
62
+ ].join(" ");
63
+ }
64
+ function TopBarCountBadge({ count }) {
65
+ if (!(count > 0)) return null;
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 });
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
+ }
137
+ var NavChromeContext = react.createContext(null);
138
+ function NavChromeProvider({
139
+ fetchJson,
140
+ children
141
+ }) {
142
+ return /* @__PURE__ */ jsxRuntime.jsx(NavChromeContext.Provider, { value: { fetchJson }, children });
143
+ }
144
+ function useNavChrome(component) {
145
+ const ctx = react.useContext(NavChromeContext);
146
+ if (!ctx) {
147
+ throw new Error(
148
+ `${component} must be rendered inside <NavChromeProvider> (inject the chrome API fetcher there).`
149
+ );
150
+ }
151
+ return ctx;
152
+ }
153
+ function useChromeOrgs() {
154
+ const { fetchJson } = useNavChrome("useChromeOrgs");
155
+ const [orgs, setOrgs] = react.useState(null);
156
+ const [loading, setLoading] = react.useState(true);
157
+ const [error, setError] = react.useState(false);
158
+ react.useEffect(() => {
159
+ let cancelled = false;
160
+ setLoading(true);
161
+ setError(false);
162
+ fetchJson("orgs").then((data) => {
163
+ if (cancelled) return;
164
+ const list = data?.orgs ?? [];
165
+ setOrgs(list);
166
+ }).catch(() => {
167
+ if (!cancelled) setError(true);
168
+ }).finally(() => {
169
+ if (!cancelled) setLoading(false);
170
+ });
171
+ return () => {
172
+ cancelled = true;
173
+ };
174
+ }, [fetchJson]);
175
+ return { orgs, loading, error };
176
+ }
177
+ function ValueSkeleton({ className }) {
178
+ return /* @__PURE__ */ jsxRuntime.jsx(
179
+ "span",
180
+ {
181
+ "aria-hidden": true,
182
+ className: [
183
+ "inline-block animate-pulse rounded bg-[color:var(--panel-elevated)]",
184
+ className ?? "h-4 w-16"
185
+ ].join(" ")
186
+ }
187
+ );
188
+ }
189
+ function SlotGlyph({
190
+ slot,
191
+ fallback: Fallback,
192
+ size = 20
193
+ }) {
194
+ const glyphName = useTopBarIconSlotGlyph(slot ?? "apps");
195
+ const BrandGlyph = slot ? resolveBrandGlyph(glyphName) : null;
196
+ const Glyph = BrandGlyph ?? Fallback;
197
+ return /* @__PURE__ */ jsxRuntime.jsx(Glyph, { size, className: "text-current" });
198
+ }
199
+ function TopBarPopover({
200
+ label,
201
+ description,
202
+ slot,
203
+ fallbackIcon,
204
+ badge,
205
+ tone,
206
+ onOpen,
207
+ children,
208
+ panelClassName
209
+ }) {
210
+ const [open, setOpen] = react.useState(false);
211
+ const rootRef = react.useRef(null);
212
+ react.useEffect(() => {
213
+ if (!open) return;
214
+ const onDocClick = (e) => {
215
+ if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
216
+ };
217
+ const onKey = (e) => {
218
+ if (e.key === "Escape") setOpen(false);
219
+ };
220
+ document.addEventListener("mousedown", onDocClick);
221
+ document.addEventListener("keydown", onKey);
222
+ return () => {
223
+ document.removeEventListener("mousedown", onDocClick);
224
+ document.removeEventListener("keydown", onKey);
225
+ };
226
+ }, [open]);
227
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: rootRef, className: "relative", children: [
228
+ /* @__PURE__ */ jsxRuntime.jsxs(
229
+ "button",
230
+ {
231
+ type: "button",
232
+ "aria-label": label,
233
+ "aria-expanded": open,
234
+ className: topBarIconButtonClass(tone),
235
+ onClick: () => {
236
+ setOpen((v) => {
237
+ const next = !v;
238
+ if (next) onOpen?.();
239
+ return next;
240
+ });
241
+ },
242
+ children: [
243
+ /* @__PURE__ */ jsxRuntime.jsx(SlotGlyph, { slot, fallback: fallbackIcon }),
244
+ typeof badge === "number" ? /* @__PURE__ */ jsxRuntime.jsx(TopBarCountBadge, { count: badge }) : null,
245
+ !open ? /* @__PURE__ */ jsxRuntime.jsx(TopBarTooltip, { title: label, description }) : null
246
+ ]
247
+ }
248
+ ),
249
+ open ? /* @__PURE__ */ jsxRuntime.jsx(
250
+ "div",
251
+ {
252
+ className: [
253
+ "absolute right-0 z-40 mt-2 overflow-hidden rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] shadow-[var(--shadow-soft)]",
254
+ panelClassName ?? "w-80"
255
+ ].join(" "),
256
+ children
257
+ }
258
+ ) : null
259
+ ] });
260
+ }
261
+ function BatteryGlyph({ size = 20, className }) {
262
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className, "aria-hidden": true, children: [
263
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "1", y: "6", width: "18", height: "12", rx: "2", ry: "2" }),
264
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "23", y1: "10", x2: "23", y2: "14" }),
265
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "5", y1: "10", x2: "5", y2: "14" }),
266
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "10", x2: "9", y2: "14" })
267
+ ] });
268
+ }
269
+ function BellGlyph({ size = 20, className }) {
270
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className, "aria-hidden": true, children: [
271
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" }),
272
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M13.73 21a2 2 0 0 1-3.46 0" })
273
+ ] });
274
+ }
275
+ function LifeBuoyGlyph({ size = 20, className }) {
276
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className, "aria-hidden": true, children: [
277
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
278
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "4" }),
279
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "4.93", y1: "4.93", x2: "9.17", y2: "9.17" }),
280
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "14.83", y1: "14.83", x2: "19.07", y2: "19.07" }),
281
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "14.83", y1: "9.17", x2: "19.07", y2: "4.93" }),
282
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "4.93", y1: "19.07", x2: "9.17", y2: "14.83" })
283
+ ] });
284
+ }
285
+ function LayoutGlyph({ size = 20, className }) {
286
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className, "aria-hidden": true, children: [
287
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
288
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "9", x2: "21", y2: "9" }),
289
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "21", x2: "9", y2: "9" })
290
+ ] });
291
+ }
292
+ function FuelRow({
293
+ label,
294
+ channel,
295
+ loading
296
+ }) {
297
+ const remaining = channel?.remainingUnits ?? 0;
298
+ const total = channel ? Math.max(channel.rawBalanceUnits, channel.remainingUnits) : 0;
299
+ const ratio = total > 0 ? Math.min(100, Math.max(0, remaining / total * 100)) : 0;
300
+ const low = channel?.lowFuel ?? false;
301
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
302
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
303
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-[color:var(--foreground)]", children: label }),
304
+ loading ? /* @__PURE__ */ jsxRuntime.jsx(ValueSkeleton, { className: "h-3.5 w-14" }) : /* @__PURE__ */ jsxRuntime.jsxs(
305
+ "span",
306
+ {
307
+ className: [
308
+ "text-xs font-semibold tabular-nums",
309
+ low ? "text-[color:var(--color-race-red)]" : "text-[color:var(--muted)]"
310
+ ].join(" "),
311
+ children: [
312
+ remaining.toLocaleString(),
313
+ " left"
314
+ ]
315
+ }
316
+ )
317
+ ] }),
318
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 w-full overflow-hidden rounded-full bg-[color:var(--panel)]", children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full animate-pulse bg-[color:var(--line)]" }) : /* @__PURE__ */ jsxRuntime.jsx(
319
+ "div",
320
+ {
321
+ className: [
322
+ "h-full rounded-full transition-[width]",
323
+ low ? "bg-[color:var(--color-race-red)]" : "bg-[color:var(--color-ok,#00A651)]"
324
+ ].join(" "),
325
+ style: { width: `${ratio}%` }
326
+ }
327
+ ) })
328
+ ] });
329
+ }
330
+ function FuelAction({ orgId }) {
331
+ const { fetchJson } = useNavChrome("FuelAction");
332
+ const [fuel, setFuel] = react.useState(null);
333
+ const [loading, setLoading] = react.useState(true);
334
+ const [error, setError] = react.useState(false);
335
+ react.useEffect(() => {
336
+ let cancelled = false;
337
+ setLoading(true);
338
+ setError(false);
339
+ setFuel(null);
340
+ fetchJson("communications/fuel-status", {
341
+ headers: orgId ? { "x-contacts-org": orgId } : void 0
342
+ }).then((data) => {
343
+ if (cancelled) return;
344
+ setFuel(data?.fuel ?? null);
345
+ }).catch(() => {
346
+ if (!cancelled) setError(true);
347
+ }).finally(() => {
348
+ if (!cancelled) setLoading(false);
349
+ });
350
+ return () => {
351
+ cancelled = true;
352
+ };
353
+ }, [fetchJson, orgId]);
354
+ const low = !!fuel && (fuel.signal.lowFuel || fuel.broadcast.lowFuel);
355
+ return /* @__PURE__ */ jsxRuntime.jsx(
356
+ TopBarPopover,
357
+ {
358
+ label: "Communications Fuel",
359
+ description: "Remaining SMS and email sending balance for the active organization.",
360
+ slot: "comms-fuel",
361
+ fallbackIcon: BatteryGlyph,
362
+ tone: low ? "warning" : "default",
363
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3", children: [
364
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-3 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Communications Fuel" }),
365
+ error || !loading && !fuel ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-[color:var(--muted)]", children: "Fuel balance is unavailable right now." }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
366
+ /* @__PURE__ */ jsxRuntime.jsx(FuelRow, { label: "SMS Signal", channel: fuel?.signal ?? null, loading }),
367
+ /* @__PURE__ */ jsxRuntime.jsx(FuelRow, { label: "Email Broadcast", channel: fuel?.broadcast ?? null, loading })
368
+ ] })
369
+ ] })
370
+ }
371
+ );
372
+ }
373
+ function NotificationsAction({ orgId }) {
374
+ const { fetchJson } = useNavChrome("NotificationsAction");
375
+ const [payload, setPayload] = react.useState(null);
376
+ const [loading, setLoading] = react.useState(true);
377
+ const [error, setError] = react.useState(false);
378
+ react.useEffect(() => {
379
+ let cancelled = false;
380
+ setLoading(true);
381
+ setError(false);
382
+ setPayload(null);
383
+ fetchJson("notifications", {
384
+ headers: orgId ? { "x-contacts-org": orgId } : void 0
385
+ }).then((data) => {
386
+ if (!cancelled) setPayload(data);
387
+ }).catch(() => {
388
+ if (!cancelled) setError(true);
389
+ }).finally(() => {
390
+ if (!cancelled) setLoading(false);
391
+ });
392
+ return () => {
393
+ cancelled = true;
394
+ };
395
+ }, [fetchJson, orgId]);
396
+ const count = (payload?.alerts.length ?? 0) + (payload?.replies.length ?? 0);
397
+ return /* @__PURE__ */ jsxRuntime.jsx(
398
+ TopBarPopover,
399
+ {
400
+ label: "Alerts & Notifications",
401
+ description: "System alerts and recent activity for the active organization.",
402
+ slot: "notifications",
403
+ fallbackIcon: BellGlyph,
404
+ badge: loading ? 0 : count,
405
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3", children: [
406
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Notifications" }),
407
+ loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 py-1", children: [
408
+ /* @__PURE__ */ jsxRuntime.jsx(ValueSkeleton, { className: "h-4 w-full" }),
409
+ /* @__PURE__ */ jsxRuntime.jsx(ValueSkeleton, { className: "h-4 w-3/4" })
410
+ ] }) : error ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-[color:var(--muted)]", children: "Notifications are unavailable right now." }) : count === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-1 text-sm text-[color:var(--muted)]", children: "You\u2019re all caught up." }) : /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "flex max-h-80 flex-col gap-1 overflow-y-auto", children: [
411
+ payload?.alerts.map((a) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
412
+ "a",
413
+ {
414
+ href: a.href ?? "#",
415
+ className: "block rounded-lg px-2 py-2 hover:bg-[color:var(--panel)]",
416
+ children: [
417
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-[color:var(--foreground)]", children: a.title }),
418
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-[color:var(--muted)]", children: a.description })
419
+ ]
420
+ }
421
+ ) }, a.id)),
422
+ payload?.replies.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "rounded-lg px-2 py-2 hover:bg-[color:var(--panel)]", children: [
423
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-[color:var(--foreground)]", children: r.name }),
424
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs text-[color:var(--muted)]", children: r.preview })
425
+ ] }, r.id))
426
+ ] })
427
+ ] })
428
+ }
429
+ );
430
+ }
431
+ function SupportAction() {
432
+ const { fetchJson } = useNavChrome("SupportAction");
433
+ const [open, setOpen] = react.useState(false);
434
+ const [message, setMessage] = react.useState("");
435
+ const [state, setState] = react.useState("idle");
436
+ const close = react.useCallback(() => {
437
+ setOpen(false);
438
+ setState("idle");
439
+ setMessage("");
440
+ }, []);
441
+ react.useEffect(() => {
442
+ if (!open) return;
443
+ const onKey = (e) => {
444
+ if (e.key === "Escape") close();
445
+ };
446
+ document.addEventListener("keydown", onKey);
447
+ return () => document.removeEventListener("keydown", onKey);
448
+ }, [open, close]);
449
+ const submit = async () => {
450
+ if (!message.trim() || state === "sending") return;
451
+ setState("sending");
452
+ try {
453
+ await fetchJson("support", {
454
+ method: "POST",
455
+ headers: { "Content-Type": "application/json" },
456
+ body: JSON.stringify({ message: message.trim() })
457
+ });
458
+ setState("sent");
459
+ } catch {
460
+ setState("error");
461
+ }
462
+ };
463
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
464
+ /* @__PURE__ */ jsxRuntime.jsxs(
465
+ "button",
466
+ {
467
+ type: "button",
468
+ "aria-label": "Support",
469
+ className: topBarIconButtonClass(),
470
+ onClick: () => setOpen(true),
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
+ ]
481
+ }
482
+ ),
483
+ open ? /* @__PURE__ */ jsxRuntime.jsx(
484
+ "div",
485
+ {
486
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",
487
+ role: "dialog",
488
+ "aria-modal": "true",
489
+ "aria-label": "Support request",
490
+ onMouseDown: (e) => {
491
+ if (e.target === e.currentTarget) close();
492
+ },
493
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full max-w-md rounded-2xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] p-6 shadow-[var(--shadow-soft)]", children: [
494
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-bold tracking-[-0.01em] text-[color:var(--foreground)]", children: "Contact Support" }),
495
+ state === "sent" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
496
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-sm text-[color:var(--muted)]", children: "Your request was sent. The team will reply by email." }),
497
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-5 flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(
498
+ "button",
499
+ {
500
+ type: "button",
501
+ onClick: close,
502
+ className: "rounded-full bg-[color:var(--color-race-red)] px-4 py-2 text-sm font-semibold text-white hover:opacity-90",
503
+ children: "Done"
504
+ }
505
+ ) })
506
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
507
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-[color:var(--muted)]", children: "Describe the problem or question. Your account details ride along automatically." }),
508
+ /* @__PURE__ */ jsxRuntime.jsx(
509
+ "textarea",
510
+ {
511
+ value: message,
512
+ onChange: (e) => setMessage(e.target.value),
513
+ rows: 5,
514
+ placeholder: "How can we help?",
515
+ className: "mt-4 w-full resize-y rounded-lg border border-[color:var(--line)] bg-[color:var(--panel)] px-3 py-2 text-sm text-[color:var(--foreground)] placeholder:text-[color:var(--muted)] focus:outline-none focus:ring-2 focus:ring-[color:var(--color-race-red)]"
516
+ }
517
+ ),
518
+ state === "error" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-[color:var(--color-race-red)]", children: "Sending failed \u2014 try again." }) : null,
519
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex justify-end gap-2", children: [
520
+ /* @__PURE__ */ jsxRuntime.jsx(
521
+ "button",
522
+ {
523
+ type: "button",
524
+ onClick: close,
525
+ className: "rounded-full border border-[color:var(--line)] px-4 py-2 text-sm font-semibold text-[color:var(--foreground)] hover:bg-[color:var(--panel)]",
526
+ children: "Cancel"
527
+ }
528
+ ),
529
+ /* @__PURE__ */ jsxRuntime.jsx(
530
+ "button",
531
+ {
532
+ type: "button",
533
+ onClick: submit,
534
+ disabled: !message.trim() || state === "sending",
535
+ className: "rounded-full bg-[color:var(--color-race-red)] px-4 py-2 text-sm font-semibold text-white transition hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50",
536
+ children: state === "sending" ? "Sending\u2026" : "Send request"
537
+ }
538
+ )
539
+ ] })
540
+ ] })
541
+ ] })
542
+ }
543
+ ) : null
544
+ ] });
545
+ }
546
+ var NAV_DISPLAY_OPTIONS = [
547
+ { value: "menu", label: "Sub Menu" },
548
+ { value: "tabs", label: "Tabs Only" },
549
+ { value: "both", label: "Both" }
550
+ ];
551
+ function NavDisplayAction({
552
+ value,
553
+ onChange
554
+ }) {
555
+ return /* @__PURE__ */ jsxRuntime.jsx(
556
+ TopBarPopover,
557
+ {
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
+ );
582
+ }
55
583
 
56
584
  // src/native/standardNav.ts
57
585
  var CONTACTS_DEFAULT_CHILDREN = [
@@ -211,16 +739,67 @@ function NavSidebar({
211
739
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Organization" }),
212
740
  org.id ? /* @__PURE__ */ jsxRuntime.jsx(OrgIdCopyButton, { id: org.id }) : null
213
741
  ] }),
214
- /* @__PURE__ */ jsxRuntime.jsxs(
742
+ org.organizations && org.organizations.length > 0 && org.onSwitch ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group relative", children: [
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
+ ] }),
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) => {
758
+ const selected = o.id === org.id;
759
+ return /* @__PURE__ */ jsxRuntime.jsxs(
760
+ "button",
761
+ {
762
+ type: "button",
763
+ onClick: (e) => {
764
+ e.currentTarget.closest("details")?.removeAttribute("open");
765
+ if (!selected) org.onSwitch?.(o.id);
766
+ },
767
+ "aria-current": selected ? "true" : void 0,
768
+ className: [
769
+ "flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm",
770
+ selected ? "font-semibold text-[color:var(--color-race-red)]" : "font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)]"
771
+ ].join(" "),
772
+ children: [
773
+ /* @__PURE__ */ jsxRuntime.jsx(
774
+ "span",
775
+ {
776
+ style: { backgroundColor: o.brandColor || ORG_PILL_DEFAULT },
777
+ className: "flex h-6 w-6 shrink-0 items-center justify-center overflow-hidden rounded-full text-[10px] font-bold text-white",
778
+ children: o.logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: o.logoUrl, alt: "", className: "h-full w-full object-cover" }) : (o.name ?? "Org").slice(0, 2).toUpperCase()
779
+ }
780
+ ),
781
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: o.name ?? o.id.slice(0, 8) })
782
+ ]
783
+ },
784
+ o.id
785
+ );
786
+ }) })
787
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(
215
788
  "button",
216
789
  {
217
790
  type: "button",
218
791
  onClick: org.onClick,
219
- style: { backgroundColor: orgBg },
220
- 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)]",
221
793
  children: [
222
794
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-2.5", children: [
223
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center overflow-hidden rounded-full bg-white/20 text-[11px] font-bold text-white", 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() }),
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
+ ),
224
803
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-semibold", children: org.name ?? "No organizations" })
225
804
  ] }),
226
805
  /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {})
@@ -471,6 +1050,7 @@ function NavTopBar({
471
1050
  title,
472
1051
  subtitle,
473
1052
  user,
1053
+ userMenu,
474
1054
  onSignOut,
475
1055
  actionsList,
476
1056
  actions,
@@ -494,31 +1074,176 @@ function NavTopBar({
494
1074
  actionsList && actionsList.length > 0 ? actionsList.map((action) => /* @__PURE__ */ jsxRuntime.jsx(NavTopBarActionButton, { action }, action.key)) : null,
495
1075
  actions,
496
1076
  themeToggle,
497
- /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group relative", children: [
498
- /* @__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: [
499
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 }),
500
1080
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "hidden flex-col leading-tight md:flex", children: [
501
1081
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-[color:var(--foreground)]", children: user?.name ?? "Signed in" }),
502
1082
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-[color:var(--muted)]", children: secondary })
503
1083
  ] }),
504
- /* @__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
+ ) })
505
1100
  ] }),
506
- onSignOut ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 z-30 mt-2 w-44 overflow-hidden rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] py-1 shadow-[var(--shadow-soft)]", children: /* @__PURE__ */ jsxRuntime.jsxs(
507
- "button",
508
- {
509
- type: "button",
510
- onClick: onSignOut,
511
- className: "flex w-full items-center gap-2.5 px-4 py-2 text-left text-sm font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)] hover:text-[color:var(--color-race-red)]",
512
- children: [
513
- /* @__PURE__ */ jsxRuntime.jsx(SignOutIcon, {}),
514
- "Sign out"
515
- ]
516
- }
517
- ) }) : null
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
+ ] })
518
1217
  ] })
519
1218
  ] })
520
1219
  ] });
521
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
+ }
522
1247
  function SignOutIcon() {
523
1248
  return /* @__PURE__ */ jsxRuntime.jsxs(
524
1249
  "svg",
@@ -542,19 +1267,14 @@ function SignOutIcon() {
542
1267
  }
543
1268
  function NavTopBarActionButton({ action }) {
544
1269
  const Icon = action.icon;
545
- const tone = action.tone ?? "default";
546
- 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)]";
547
- const className = [
548
- "relative flex items-center justify-center rounded-full border border-[color:var(--line)] transition",
549
- "h-[var(--topbar-icon-button-size,32px)] w-[var(--topbar-icon-button-size,32px)]",
550
- toneClass
551
- ].join(" ");
1270
+ const className = topBarIconButtonClass(action.tone ?? "default");
552
1271
  const glyphName = useTopBarIconSlotGlyph(action.slot ?? "apps");
553
1272
  const BrandGlyph = action.slot ? resolveBrandGlyph(glyphName) : null;
554
1273
  const Glyph = BrandGlyph ?? Icon;
555
1274
  const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
556
1275
  /* @__PURE__ */ jsxRuntime.jsx(Glyph, { size: 20, className: "text-current" }),
557
- 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 })
558
1278
  ] });
559
1279
  const isExternal = action.href ? /^https?:\/\//.test(action.href) : false;
560
1280
  if (action.href) {
@@ -563,7 +1283,6 @@ function NavTopBarActionButton({ action }) {
563
1283
  {
564
1284
  href: safeHref(action.href),
565
1285
  "aria-label": action.label,
566
- title: action.label,
567
1286
  className,
568
1287
  ...isExternal ? { target: "_blank", rel: "noreferrer" } : {},
569
1288
  children: content
@@ -576,7 +1295,6 @@ function NavTopBarActionButton({ action }) {
576
1295
  type: "button",
577
1296
  onClick: action.onClick,
578
1297
  "aria-label": action.label,
579
- title: action.label,
580
1298
  className,
581
1299
  children: content
582
1300
  }
@@ -690,12 +1408,23 @@ function NavAppShell({ sidebar, topBar, children }) {
690
1408
  ] });
691
1409
  }
692
1410
 
1411
+ exports.FuelAction = FuelAction;
693
1412
  exports.NavAppShell = NavAppShell;
1413
+ exports.NavChromeProvider = NavChromeProvider;
1414
+ exports.NavDisplayAction = NavDisplayAction;
694
1415
  exports.NavSidebar = NavSidebar;
695
1416
  exports.NavTabStrip = NavTabStrip;
1417
+ exports.NavThemeControl = NavThemeControl;
696
1418
  exports.NavTopBar = NavTopBar;
1419
+ exports.NotificationsAction = NotificationsAction;
1420
+ exports.SupportAction = SupportAction;
1421
+ exports.TopBarCountBadge = TopBarCountBadge;
1422
+ exports.TopBarTooltip = TopBarTooltip;
1423
+ exports.TopBarWidgetSlot = TopBarWidgetSlot;
697
1424
  exports.envChipClasses = envChipClasses;
698
1425
  exports.isNavItemActive = isNavItemActive;
699
1426
  exports.standardPolitogyNav = standardPolitogyNav;
1427
+ exports.topBarIconButtonClass = topBarIconButtonClass;
1428
+ exports.useChromeOrgs = useChromeOrgs;
700
1429
  //# sourceMappingURL=native.cjs.map
701
1430
  //# sourceMappingURL=native.cjs.map