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