@orangecheck/ui 0.5.0 → 0.6.1

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/index.js CHANGED
@@ -4,6 +4,7 @@ var lucideReact = require('lucide-react');
4
4
  var Link = require('next/link');
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
+ var authClient = require('@orangecheck/auth-client');
7
8
 
8
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
10
 
@@ -178,10 +179,13 @@ function EcosystemSwitcher({
178
179
  )
179
180
  ] });
180
181
  }
181
- var ENTRIES2 = [
182
+
183
+ // src/family-properties.ts
184
+ var FAMILY_PROPERTIES = [
182
185
  {
183
186
  slug: "home",
184
- href: "https://ochk.io",
187
+ origin: "https://ochk.io",
188
+ hostname: "ochk.io",
185
189
  label: "orangecheck",
186
190
  sub: "umbrella \xB7 sign-in",
187
191
  docsHref: "https://docs.ochk.io",
@@ -189,7 +193,8 @@ var ENTRIES2 = [
189
193
  },
190
194
  {
191
195
  slug: "docs",
192
- href: "https://docs.ochk.io",
196
+ origin: "https://docs.ochk.io",
197
+ hostname: "docs.ochk.io",
193
198
  label: "oc\xB7docs",
194
199
  sub: "unified reference",
195
200
  docsHref: "https://docs.ochk.io",
@@ -197,7 +202,8 @@ var ENTRIES2 = [
197
202
  },
198
203
  {
199
204
  slug: "me",
200
- href: "https://me.ochk.io",
205
+ origin: "https://me.ochk.io",
206
+ hostname: "me.ochk.io",
201
207
  label: "oc\xB7me",
202
208
  sub: "earn \u2014 consumer identity",
203
209
  docsHref: "https://docs.ochk.io/me",
@@ -205,7 +211,8 @@ var ENTRIES2 = [
205
211
  },
206
212
  {
207
213
  slug: "vault",
208
- href: "https://vault.ochk.io",
214
+ origin: "https://vault.ochk.io",
215
+ hostname: "vault.ochk.io",
209
216
  label: "oc\xB7vault",
210
217
  sub: "keep \u2014 encrypted secrets",
211
218
  docsHref: "https://docs.ochk.io/vault",
@@ -213,7 +220,8 @@ var ENTRIES2 = [
213
220
  },
214
221
  {
215
222
  slug: "fleet",
216
- href: "https://fleet.ochk.io",
223
+ origin: "https://fleet.ochk.io",
224
+ hostname: "fleet.ochk.io",
217
225
  label: "oc\xB7fleet",
218
226
  sub: "managed \u2014 agent fleet",
219
227
  docsHref: "https://docs.ochk.io/fleet",
@@ -221,7 +229,8 @@ var ENTRIES2 = [
221
229
  },
222
230
  {
223
231
  slug: "attest",
224
- href: "https://attest.ochk.io",
232
+ origin: "https://attest.ochk.io",
233
+ hostname: "attest.ochk.io",
225
234
  label: "oc\xB7attest",
226
235
  sub: "am \u2014 sybil resistance",
227
236
  docsHref: "https://docs.ochk.io/attest",
@@ -229,7 +238,8 @@ var ENTRIES2 = [
229
238
  },
230
239
  {
231
240
  slug: "lock",
232
- href: "https://lock.ochk.io",
241
+ origin: "https://lock.ochk.io",
242
+ hostname: "lock.ochk.io",
233
243
  label: "oc\xB7lock",
234
244
  sub: "whisper \u2014 encryption",
235
245
  docsHref: "https://docs.ochk.io/lock",
@@ -237,7 +247,8 @@ var ENTRIES2 = [
237
247
  },
238
248
  {
239
249
  slug: "vote",
240
- href: "https://vote.ochk.io",
250
+ origin: "https://vote.ochk.io",
251
+ hostname: "vote.ochk.io",
241
252
  label: "oc\xB7vote",
242
253
  sub: "decide \u2014 polls",
243
254
  docsHref: "https://docs.ochk.io/vote",
@@ -245,7 +256,8 @@ var ENTRIES2 = [
245
256
  },
246
257
  {
247
258
  slug: "stamp",
248
- href: "https://stamp.ochk.io",
259
+ origin: "https://stamp.ochk.io",
260
+ hostname: "stamp.ochk.io",
249
261
  label: "oc\xB7stamp",
250
262
  sub: "declare \u2014 block-anchored",
251
263
  docsHref: "https://docs.ochk.io/stamp",
@@ -253,7 +265,8 @@ var ENTRIES2 = [
253
265
  },
254
266
  {
255
267
  slug: "agent",
256
- href: "https://agent.ochk.io",
268
+ origin: "https://agent.ochk.io",
269
+ hostname: "agent.ochk.io",
257
270
  label: "oc\xB7agent",
258
271
  sub: "delegate \u2014 scoped auth",
259
272
  docsHref: "https://docs.ochk.io/agent",
@@ -261,13 +274,21 @@ var ENTRIES2 = [
261
274
  },
262
275
  {
263
276
  slug: "pledge",
264
- href: "https://pledge.ochk.io",
277
+ origin: "https://pledge.ochk.io",
278
+ hostname: "pledge.ochk.io",
265
279
  label: "oc\xB7pledge",
266
280
  sub: "swear \u2014 bonded commitment",
267
281
  docsHref: "https://docs.ochk.io/pledge",
268
282
  category: "protocol"
269
283
  }
270
284
  ];
285
+ var SITE_STATE_LABEL = {
286
+ alpha: "alpha",
287
+ beta: "beta"
288
+ };
289
+ function findFamilyProperty(slug) {
290
+ return FAMILY_PROPERTIES.find((p) => p.slug === slug);
291
+ }
271
292
  var SECTIONS = [
272
293
  { category: "hub", label: "hub" },
273
294
  { category: "product", label: "products" },
@@ -286,6 +307,18 @@ function CategoryChip({ category }) {
286
307
  }
287
308
  );
288
309
  }
310
+ function SiteStateBadge({ state }) {
311
+ if (state === "live") return null;
312
+ return /* @__PURE__ */ jsxRuntime.jsx(
313
+ "span",
314
+ {
315
+ "aria-label": `site lifecycle: ${state}`,
316
+ className: "text-muted-foreground/70 ml-1 hidden font-mono text-[9px] font-medium tracking-widest uppercase sm:inline-block",
317
+ "data-oc-site-state": state,
318
+ children: SITE_STATE_LABEL[state]
319
+ }
320
+ );
321
+ }
289
322
  function MenuCategoryChip({ category }) {
290
323
  if (category === "hub") return null;
291
324
  const isProduct = category === "product";
@@ -293,7 +326,7 @@ function MenuCategoryChip({ category }) {
293
326
  "span",
294
327
  {
295
328
  "aria-hidden": true,
296
- className: "inline-block rounded-sm px-1 py-[1px] font-mono text-[9px] font-medium tracking-widest uppercase " + (isProduct ? "bg-primary/10 text-primary" : "bg-muted/60 text-muted-foreground/80"),
329
+ className: "inline-block shrink-0 rounded-sm px-1 py-[1px] font-mono text-[9px] font-medium tracking-widest uppercase " + (isProduct ? "bg-primary/10 text-primary" : "bg-muted/60 text-muted-foreground/80"),
297
330
  children: isProduct ? "pro" : "spec"
298
331
  }
299
332
  );
@@ -301,6 +334,7 @@ function MenuCategoryChip({ category }) {
301
334
  function OcLogoDropdown({
302
335
  current,
303
336
  homeHref = "/",
337
+ siteState = "live",
304
338
  children,
305
339
  className,
306
340
  triggerClassName,
@@ -309,7 +343,7 @@ function OcLogoDropdown({
309
343
  const [open, setOpen] = react.useState(false);
310
344
  const containerRef = react.useRef(null);
311
345
  const menuId = react.useId();
312
- const currentCategory = ENTRIES2.find((e) => e.slug === current)?.category ?? "hub";
346
+ const currentCategory = findFamilyProperty(current)?.category ?? "hub";
313
347
  react.useEffect(() => {
314
348
  if (!open) return;
315
349
  function onDoc(e) {
@@ -333,6 +367,7 @@ function OcLogoDropdown({
333
367
  className: "relative " + (className ?? ""),
334
368
  "data-oc-logo-dropdown": "",
335
369
  "data-oc-current-category": currentCategory,
370
+ "data-oc-site-state": siteState,
336
371
  children: [
337
372
  /* @__PURE__ */ jsxRuntime.jsxs(
338
373
  "button",
@@ -349,6 +384,7 @@ function OcLogoDropdown({
349
384
  children: [
350
385
  children,
351
386
  /* @__PURE__ */ jsxRuntime.jsx(CategoryChip, { category: currentCategory }),
387
+ /* @__PURE__ */ jsxRuntime.jsx(SiteStateBadge, { state: siteState }),
352
388
  /* @__PURE__ */ jsxRuntime.jsx(
353
389
  lucideReact.ChevronDown,
354
390
  {
@@ -369,61 +405,56 @@ function OcLogoDropdown({
369
405
  "data-oc-logo-dropdown-popover": "",
370
406
  children: [
371
407
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-primary border-b px-4 py-2", children: "\xA7 the orangecheck family" }),
372
- /* @__PURE__ */ jsxRuntime.jsx(
373
- "div",
374
- {
375
- className: "max-h-[min(28rem,70vh)] overflow-y-auto py-1",
376
- role: "none",
377
- children: SECTIONS.map(({ category, label }) => {
378
- const sectionEntries = ENTRIES2.filter((e) => e.category === category);
379
- if (sectionEntries.length === 0) return null;
380
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "none", "data-oc-section": category, children: [
381
- /* @__PURE__ */ jsxRuntime.jsx(
382
- "div",
383
- {
384
- role: "separator",
385
- "aria-hidden": true,
386
- className: "text-muted-foreground/60 px-4 pt-2.5 pb-1 font-mono text-[9px] font-medium tracking-widest uppercase " + (category === "hub" ? "" : "border-t mt-1"),
387
- children: label
388
- }
389
- ),
390
- /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "none", className: "pb-1", children: sectionEntries.map((e) => {
391
- const isActive = e.slug === current;
392
- const href = isActive ? homeHref : e.href;
393
- return /* @__PURE__ */ jsxRuntime.jsx("li", { role: "none", children: /* @__PURE__ */ jsxRuntime.jsxs(
394
- Link__default.default,
395
- {
396
- href,
397
- role: "menuitem",
398
- onClick: () => setOpen(false),
399
- "aria-current": isActive ? "page" : void 0,
400
- className: "group flex items-center gap-2 px-4 py-2 transition-colors " + (isActive ? "bg-primary/8 border-primary -ml-px border-l-2" : "hover:bg-muted -ml-px border-l-2 border-transparent"),
401
- "data-oc-logo-dropdown-item": isActive ? "current" : "sibling",
402
- "data-oc-entry-category": e.category,
403
- children: [
404
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
405
- /* @__PURE__ */ jsxRuntime.jsx(
406
- "span",
407
- {
408
- className: "font-display text-[12px] font-semibold tracking-tight " + (isActive ? "text-primary" : "text-foreground group-hover:text-primary transition-colors"),
409
- children: e.label
410
- }
411
- ),
412
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground mt-0.5 font-mono text-[10px] tracking-wide", children: e.sub })
413
- ] }),
414
- /* @__PURE__ */ jsxRuntime.jsx(MenuCategoryChip, { category: e.category }),
415
- isActive ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-primary inline-flex shrink-0 items-center gap-1 font-mono text-[10px] tracking-widest uppercase", children: [
416
- "home",
417
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3" })
418
- ] }) : null
419
- ]
420
- }
421
- ) }, e.slug);
422
- }) })
423
- ] }, category);
424
- })
425
- }
426
- ),
408
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[min(28rem,70vh)] overflow-y-auto py-1", role: "none", children: SECTIONS.map(({ category, label }) => {
409
+ const sectionEntries = FAMILY_PROPERTIES.filter(
410
+ (e) => e.category === category
411
+ );
412
+ if (sectionEntries.length === 0) return null;
413
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "none", "data-oc-section": category, children: [
414
+ /* @__PURE__ */ jsxRuntime.jsx(
415
+ "div",
416
+ {
417
+ role: "separator",
418
+ "aria-hidden": true,
419
+ className: "text-muted-foreground/60 px-4 pt-2.5 pb-1 font-mono text-[9px] font-medium tracking-widest uppercase " + (category === "hub" ? "" : "border-t mt-1"),
420
+ children: label
421
+ }
422
+ ),
423
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "none", className: "pb-1", children: sectionEntries.map((e) => {
424
+ const isActive = e.slug === current;
425
+ const href = isActive ? homeHref : e.origin;
426
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { role: "none", children: /* @__PURE__ */ jsxRuntime.jsxs(
427
+ Link__default.default,
428
+ {
429
+ href,
430
+ role: "menuitem",
431
+ onClick: () => setOpen(false),
432
+ "aria-current": isActive ? "page" : void 0,
433
+ className: "group flex items-center gap-2 px-4 py-2 transition-colors " + (isActive ? "bg-primary/8 border-primary -ml-px border-l-2" : "hover:bg-muted -ml-px border-l-2 border-transparent"),
434
+ "data-oc-logo-dropdown-item": isActive ? "current" : "sibling",
435
+ "data-oc-entry-category": e.category,
436
+ children: [
437
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
438
+ /* @__PURE__ */ jsxRuntime.jsx(
439
+ "span",
440
+ {
441
+ className: "font-display text-[12px] font-semibold tracking-tight " + (isActive ? "text-primary" : "text-foreground group-hover:text-primary transition-colors"),
442
+ children: e.label
443
+ }
444
+ ),
445
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground mt-0.5 font-mono text-[10px] tracking-wide", children: e.sub })
446
+ ] }),
447
+ /* @__PURE__ */ jsxRuntime.jsx(MenuCategoryChip, { category: e.category }),
448
+ isActive ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-primary inline-flex shrink-0 items-center gap-1 font-mono text-[10px] tracking-widest uppercase", children: [
449
+ "home",
450
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3" })
451
+ ] }) : null
452
+ ]
453
+ }
454
+ ) }, e.slug);
455
+ }) })
456
+ ] }, category);
457
+ }) }),
427
458
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t px-4 py-2 font-mono text-[10px] tracking-widest uppercase", children: /* @__PURE__ */ jsxRuntime.jsx(
428
459
  Link__default.default,
429
460
  {
@@ -440,6 +471,289 @@ function OcLogoDropdown({
440
471
  }
441
472
  );
442
473
  }
474
+ function shortenDid(s) {
475
+ if (s.length <= 14) return s;
476
+ return `${s.slice(0, 7)}\u2026${s.slice(-5)}`;
477
+ }
478
+ function OcAccountMenu(props) {
479
+ const session = authClient.useOcSession();
480
+ return /* @__PURE__ */ jsxRuntime.jsx(
481
+ OcAccountMenuView,
482
+ {
483
+ ...props,
484
+ session: {
485
+ status: session.status,
486
+ account: session.account ? {
487
+ didOc: session.account.didOc,
488
+ displayName: session.account.displayName ?? null
489
+ } : null,
490
+ signOut: session.signOut,
491
+ refresh: session.refresh
492
+ }
493
+ }
494
+ );
495
+ }
496
+ function OcAccountMenuView({
497
+ current,
498
+ signInUrl = "/signin",
499
+ signInLabel = "sign in",
500
+ menuItems,
501
+ showFamilyDashboard,
502
+ build,
503
+ siteState,
504
+ className,
505
+ triggerClassName,
506
+ popoverClassName,
507
+ session
508
+ }) {
509
+ const { status, account, signOut, refresh } = session;
510
+ const [hydrated, setHydrated] = react.useState(false);
511
+ const [open, setOpen] = react.useState(false);
512
+ const wrapRef = react.useRef(null);
513
+ const property = findFamilyProperty(current);
514
+ const hostname = property?.hostname ?? `${current}.ochk.io`;
515
+ const isHome = current === "home";
516
+ const familyDashboardEnabled = showFamilyDashboard ?? !isHome;
517
+ react.useEffect(() => setHydrated(true), []);
518
+ react.useEffect(() => {
519
+ const onWake = () => {
520
+ if (document.visibilityState === "visible") void refresh();
521
+ };
522
+ const onFocus = () => void refresh();
523
+ document.addEventListener("visibilitychange", onWake);
524
+ window.addEventListener("focus", onFocus);
525
+ return () => {
526
+ document.removeEventListener("visibilitychange", onWake);
527
+ window.removeEventListener("focus", onFocus);
528
+ };
529
+ }, [refresh]);
530
+ react.useEffect(() => {
531
+ if (!open) return;
532
+ const onClick = (e) => {
533
+ if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
534
+ };
535
+ const onKey = (e) => {
536
+ if (e.key === "Escape") setOpen(false);
537
+ };
538
+ document.addEventListener("mousedown", onClick);
539
+ document.addEventListener("keydown", onKey);
540
+ return () => {
541
+ document.removeEventListener("mousedown", onClick);
542
+ document.removeEventListener("keydown", onKey);
543
+ };
544
+ }, [open]);
545
+ const signInTrigger = /* @__PURE__ */ jsxRuntime.jsx(
546
+ "a",
547
+ {
548
+ href: signInUrl,
549
+ "aria-label": signInLabel,
550
+ "data-oc-account-menu-signin": "",
551
+ className: triggerClassName ?? "border-input bg-background hover:bg-accent inline-flex h-8 items-center justify-center rounded-md border px-3 font-mono text-[11px] font-semibold tracking-widest uppercase transition-colors",
552
+ children: signInLabel
553
+ }
554
+ );
555
+ if (!hydrated || status === "loading") {
556
+ return signInTrigger;
557
+ }
558
+ if (status !== "authenticated" || !account) {
559
+ return signInTrigger;
560
+ }
561
+ const displayName = account.displayName ?? null;
562
+ const label = displayName ?? shortenDid(account.didOc);
563
+ return /* @__PURE__ */ jsxRuntime.jsxs(
564
+ "div",
565
+ {
566
+ ref: wrapRef,
567
+ className: "relative inline-block " + (className ?? ""),
568
+ "data-oc-account-menu": "",
569
+ children: [
570
+ /* @__PURE__ */ jsxRuntime.jsxs(
571
+ "button",
572
+ {
573
+ type: "button",
574
+ onClick: () => setOpen((v) => !v),
575
+ "aria-haspopup": "menu",
576
+ "aria-expanded": open,
577
+ "aria-label": `Signed in as ${account.didOc}. Open account menu.`,
578
+ className: triggerClassName ?? "border-primary/40 bg-card hover:bg-accent inline-flex h-8 items-center gap-1.5 rounded-md border px-3 font-mono text-[11px] tracking-wide transition-colors",
579
+ "data-oc-account-menu-trigger": "",
580
+ children: [
581
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-primary inline-block size-1.5 rounded-full", "aria-hidden": true }),
582
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground", children: label }),
583
+ /* @__PURE__ */ jsxRuntime.jsx(
584
+ "svg",
585
+ {
586
+ width: "9",
587
+ height: "9",
588
+ viewBox: "0 0 10 10",
589
+ "aria-hidden": true,
590
+ className: "opacity-60 transition-transform " + (open ? "rotate-180" : "rotate-0"),
591
+ children: /* @__PURE__ */ jsxRuntime.jsx(
592
+ "path",
593
+ {
594
+ d: "M2 4 L5 7 L8 4",
595
+ stroke: "currentColor",
596
+ strokeWidth: "1.5",
597
+ fill: "none",
598
+ strokeLinecap: "round"
599
+ }
600
+ )
601
+ }
602
+ )
603
+ ]
604
+ }
605
+ ),
606
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
607
+ "div",
608
+ {
609
+ role: "menu",
610
+ "aria-label": "Account menu",
611
+ className: popoverClassName ?? "border-border bg-popover text-popover-foreground absolute top-[calc(100%+6px)] right-0 z-50 w-[min(18rem,calc(100vw-1rem))] border shadow-xl",
612
+ "data-oc-account-menu-popover": "",
613
+ children: [
614
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-border border-b p-3", children: [
615
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-primary mb-1 font-mono text-[10px] tracking-widest uppercase", children: [
616
+ "\xA7 signed in \xB7 ",
617
+ hostname
618
+ ] }),
619
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-foreground/90 font-mono text-[11px] leading-tight break-all", children: account.didOc }),
620
+ displayName ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/80 mt-1 font-mono text-[10px] tracking-wide", children: displayName }) : null
621
+ ] }),
622
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-1", children: [
623
+ menuItems?.map((item) => {
624
+ const onClick = () => setOpen(false);
625
+ const cls = "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors";
626
+ const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
627
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
628
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item.label }),
629
+ item.external ? /* @__PURE__ */ jsxRuntime.jsx(
630
+ "span",
631
+ {
632
+ className: "text-muted-foreground/70 text-[10px]",
633
+ "aria-hidden": true,
634
+ children: "\u2197"
635
+ }
636
+ ) : null
637
+ ] });
638
+ return item.external ? /* @__PURE__ */ jsxRuntime.jsx(
639
+ "a",
640
+ {
641
+ href: item.href,
642
+ target: "_blank",
643
+ rel: "noreferrer",
644
+ onClick,
645
+ role: "menuitem",
646
+ className: cls,
647
+ "data-oc-account-menu-item": "",
648
+ children: inner
649
+ },
650
+ item.href
651
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
652
+ Link__default.default,
653
+ {
654
+ href: item.href,
655
+ onClick,
656
+ role: "menuitem",
657
+ className: cls,
658
+ "data-oc-account-menu-item": "",
659
+ children: inner
660
+ },
661
+ item.href
662
+ );
663
+ }),
664
+ familyDashboardEnabled ? /* @__PURE__ */ jsxRuntime.jsxs(
665
+ "a",
666
+ {
667
+ href: "https://ochk.io/dashboard",
668
+ target: "_blank",
669
+ rel: "noreferrer",
670
+ onClick: () => setOpen(false),
671
+ role: "menuitem",
672
+ className: "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors",
673
+ "data-oc-account-menu-item": "",
674
+ "data-oc-account-menu-family-dashboard": "",
675
+ children: [
676
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
677
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "family dashboard" }),
678
+ /* @__PURE__ */ jsxRuntime.jsx(
679
+ "span",
680
+ {
681
+ className: "text-muted-foreground/70 text-[10px]",
682
+ "aria-hidden": true,
683
+ children: "\u2197"
684
+ }
685
+ )
686
+ ]
687
+ }
688
+ ) : null,
689
+ /* @__PURE__ */ jsxRuntime.jsxs(
690
+ "button",
691
+ {
692
+ type: "button",
693
+ role: "menuitem",
694
+ onClick: () => {
695
+ setOpen(false);
696
+ void signOut();
697
+ },
698
+ className: "hover:bg-accent flex w-full items-center gap-2 px-3 py-2 text-left font-mono text-[11px] tracking-wide transition-colors",
699
+ "data-oc-account-menu-item": "",
700
+ "data-oc-account-menu-signout": "",
701
+ children: [
702
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
703
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "sign out" })
704
+ ]
705
+ }
706
+ )
707
+ ] }),
708
+ build ? /* @__PURE__ */ jsxRuntime.jsx(BuildFooter, { hostname, build, state: siteState }) : null
709
+ ]
710
+ }
711
+ )
712
+ ]
713
+ }
714
+ );
715
+ }
716
+ function BuildFooter({
717
+ hostname,
718
+ build,
719
+ state
720
+ }) {
721
+ const sha = build.sha;
722
+ const showSha = !!sha && sha !== "dev";
723
+ const commitUrl = showSha && build.repo ? `https://github.com/${build.repo}/commit/${sha}` : null;
724
+ return /* @__PURE__ */ jsxRuntime.jsxs(
725
+ "div",
726
+ {
727
+ className: "text-muted-foreground/60 border-border border-t px-3 py-2 font-mono text-[9.5px] tracking-widest uppercase",
728
+ "data-oc-account-menu-build": "",
729
+ children: [
730
+ hostname,
731
+ state && state !== "live" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
732
+ " \xB7 ",
733
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/80", children: state })
734
+ ] }) : null,
735
+ " ",
736
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground/80", children: [
737
+ "v",
738
+ build.version,
739
+ showSha ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
740
+ " \xB7 ",
741
+ commitUrl ? /* @__PURE__ */ jsxRuntime.jsx(
742
+ "a",
743
+ {
744
+ href: commitUrl,
745
+ target: "_blank",
746
+ rel: "noreferrer",
747
+ className: "hover:text-foreground/90 underline decoration-dotted underline-offset-2",
748
+ children: sha
749
+ }
750
+ ) : sha
751
+ ] }) : null
752
+ ] })
753
+ ]
754
+ }
755
+ );
756
+ }
443
757
  function AppShell({
444
758
  eyebrow,
445
759
  title,
@@ -566,9 +880,14 @@ function StatTile({ children, ...item }) {
566
880
  exports.AppShell = AppShell;
567
881
  exports.EcosystemSwitcher = EcosystemSwitcher;
568
882
  exports.EmptyState = EmptyState;
883
+ exports.FAMILY_PROPERTIES = FAMILY_PROPERTIES;
884
+ exports.OcAccountMenu = OcAccountMenu;
885
+ exports.OcAccountMenuView = OcAccountMenuView;
569
886
  exports.OcLogoDropdown = OcLogoDropdown;
887
+ exports.SITE_STATE_LABEL = SITE_STATE_LABEL;
570
888
  exports.SectionHeader = SectionHeader;
571
889
  exports.StatGrid = StatGrid;
572
890
  exports.StatTile = StatTile;
891
+ exports.findFamilyProperty = findFamilyProperty;
573
892
  //# sourceMappingURL=index.js.map
574
893
  //# sourceMappingURL=index.js.map