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