@orangecheck/app-design 1.2.3 → 1.4.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.
Files changed (47) hide show
  1. package/dist/chrome.d.mts +8 -3
  2. package/dist/chrome.d.ts +8 -3
  3. package/dist/chrome.js +605 -553
  4. package/dist/chrome.js.map +1 -1
  5. package/dist/chrome.mjs +605 -555
  6. package/dist/chrome.mjs.map +1 -1
  7. package/dist/code.js +3 -1
  8. package/dist/code.js.map +1 -1
  9. package/dist/code.mjs +3 -1
  10. package/dist/code.mjs.map +1 -1
  11. package/dist/components.d.mts +3 -3
  12. package/dist/components.d.ts +3 -3
  13. package/dist/components.js +730 -666
  14. package/dist/components.js.map +1 -1
  15. package/dist/components.mjs +731 -667
  16. package/dist/components.mjs.map +1 -1
  17. package/dist/{docs-Dxg4Tp_q.d.ts → docs-BB9gK4KF.d.ts} +18 -4
  18. package/dist/{docs-wJBfLS08.d.mts → docs-D-T-nHiu.d.mts} +18 -4
  19. package/dist/index.d.mts +4 -4
  20. package/dist/index.d.ts +4 -4
  21. package/dist/index.js +1549 -1406
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +1548 -1407
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/mdx.d.mts +6 -2
  26. package/dist/mdx.d.ts +6 -2
  27. package/dist/mdx.js +168 -74
  28. package/dist/mdx.js.map +1 -1
  29. package/dist/mdx.mjs +169 -75
  30. package/dist/mdx.mjs.map +1 -1
  31. package/dist/primitives.d.mts +9 -3
  32. package/dist/primitives.d.ts +9 -3
  33. package/dist/primitives.js +7 -6
  34. package/dist/primitives.js.map +1 -1
  35. package/dist/primitives.mjs +7 -6
  36. package/dist/primitives.mjs.map +1 -1
  37. package/dist/session.d.mts +4 -3
  38. package/dist/session.d.ts +4 -3
  39. package/dist/session.js +27 -3
  40. package/dist/session.js.map +1 -1
  41. package/dist/session.mjs +27 -3
  42. package/dist/session.mjs.map +1 -1
  43. package/dist/styles/swagger.css +252 -0
  44. package/dist/styles/tokens.css +2 -0
  45. package/dist/{tool-shell-kqGWMTep.d.mts → tool-shell-D8Q8XX11.d.mts} +8 -5
  46. package/dist/{tool-shell-DLSwUxTD.d.ts → tool-shell-gmlj47Ie.d.ts} +8 -5
  47. package/package.json +1 -1
package/dist/chrome.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var lucideReact = require('lucide-react');
4
- var Link5 = require('next/link');
4
+ var Link = require('next/link');
5
5
  var react = require('react');
6
6
  var clsx = require('clsx');
7
7
  var tailwindMerge = require('tailwind-merge');
@@ -10,11 +10,12 @@ var DialogPrimitive = require('@radix-ui/react-dialog');
10
10
  var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
11
11
  var PopoverPrimitive = require('@radix-ui/react-popover');
12
12
  var TooltipPrimitive = require('@radix-ui/react-tooltip');
13
+ var nextThemes = require('next-themes');
13
14
  var classVarianceAuthority = require('class-variance-authority');
14
15
  var SeparatorPrimitive = require('@radix-ui/react-separator');
15
16
  require('sonner');
16
17
  var reactSlot = require('@radix-ui/react-slot');
17
- var nextThemes = require('next-themes');
18
+ var router = require('next/compat/router');
18
19
 
19
20
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
20
21
 
@@ -36,7 +37,7 @@ function _interopNamespace(e) {
36
37
  return Object.freeze(n);
37
38
  }
38
39
 
39
- var Link5__default = /*#__PURE__*/_interopDefault(Link5);
40
+ var Link__default = /*#__PURE__*/_interopDefault(Link);
40
41
  var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
41
42
  var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(DropdownMenuPrimitive);
42
43
  var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
@@ -435,6 +436,17 @@ var DropdownMenuLabel = react.forwardRef(function DropdownMenuLabel2({ className
435
436
  var DropdownMenuSeparator = react.forwardRef(function DropdownMenuSeparator2({ className, ...props }, ref) {
436
437
  return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Separator, { ref, className: cn("my-1.5 h-px bg-border", className), ...props });
437
438
  });
439
+ function sharedContext(name, initial) {
440
+ const key = /* @__PURE__ */ Symbol.for(`@orangecheck/app-design/${name}`);
441
+ const store = globalThis;
442
+ return store[key] ?? (store[key] = react.createContext(initial));
443
+ }
444
+
445
+ // src/lib/shell-context.ts
446
+ var ShellContext = sharedContext("shell-place", {});
447
+ function useShellPlace() {
448
+ return react.useContext(ShellContext);
449
+ }
438
450
  var GOOD_DOT = "border-border bg-card text-foreground before:size-1.5 before:shrink-0 before:rounded-full before:bg-success before:content-['']";
439
451
  var badgeVariants = classVarianceAuthority.cva(
440
452
  "inline-flex h-6 shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 text-[0.8125rem] font-medium leading-none",
@@ -561,191 +573,483 @@ function FamilyMenu({ current, className }) {
561
573
  )
562
574
  ] });
563
575
  }
564
- function NavLink({
565
- item,
566
- className,
567
- onNavigate,
568
- line = false
569
- }) {
570
- const cls = cn(
571
- "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
572
- item.active ? "text-foreground" : "text-muted-foreground hover:text-foreground",
573
- line && "relative after:absolute after:inset-x-3 after:-bottom-[0.625rem] after:h-0.5 after:rounded-full",
574
- line && item.active && "after:bg-foreground",
575
- className
576
- );
577
- if (item.external) {
578
- return /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
579
- }
580
- return /* @__PURE__ */ jsxRuntime.jsx(Link5__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
581
- }
582
- function NavRow({ item, onNavigate }) {
583
- const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
584
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] font-medium leading-6 text-foreground", children: item.label }),
585
- item.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: item.description }) : null
586
- ] });
587
- const cls = cn(
588
- "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
589
- item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
590
- );
591
- return item.external ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsxRuntime.jsx(Link5__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
592
- }
593
- var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
594
- function NavDropdown({ item }) {
595
- const [open, setOpen] = react.useState(false);
596
- const active = item.active || item.children?.some((c) => c.active);
597
- return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
598
- /* @__PURE__ */ jsxRuntime.jsxs(
599
- PopoverTrigger,
576
+ function SideNav({ groups, onNavigate }) {
577
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Pages", className: "flex flex-col gap-5", children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
578
+ g.label ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
579
+ g.items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
580
+ Link__default.default,
600
581
  {
582
+ href: it.href,
583
+ onClick: onNavigate,
584
+ "aria-current": it.active ? "page" : void 0,
601
585
  className: cn(
602
- "group inline-flex items-center gap-1 rounded-full py-2 pl-3 pr-2.5 text-[0.9375rem] transition-colors md:max-lg:pl-2.5 md:max-lg:pr-2",
603
- active ? "text-foreground" : "text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
586
+ "flex h-9 items-center gap-3 rounded-xl px-3 text-[0.9375rem] transition-colors",
587
+ "[&_svg]:size-[1.0625rem] [&_svg]:shrink-0",
588
+ it.active ? "bg-card text-foreground shadow-sm ring-1 ring-border [&_svg]:text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground"
604
589
  ),
605
590
  children: [
606
- item.label,
607
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180" })
591
+ it.icon,
592
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: it.label }),
593
+ it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: it.badge }) : null
608
594
  ]
609
- }
610
- ),
611
- /* @__PURE__ */ jsxRuntime.jsxs(PopoverContent, { align: "center", sideOffset: 10, className: "w-[min(calc(100vw-2rem),26rem)] p-2", children: [
612
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col", children: item.children?.map((c) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(NavRow, { item: c, onNavigate: () => setOpen(false) }) }, c.href)) }),
613
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1.5 border-t border-border px-1 pt-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(
614
- NavLink,
615
- {
616
- item: { ...item, label: seeAll(item), children: void 0 },
617
- className: "block rounded-xl px-2 py-2 text-[0.875rem]",
618
- onNavigate: () => setOpen(false)
619
- }
620
- ) })
621
- ] })
622
- ] });
595
+ },
596
+ it.href
597
+ ))
598
+ ] }, g.label ?? gi)) });
623
599
  }
624
- function SiteHeader({
625
- home = "/",
626
- brand,
627
- product,
628
- family,
629
- nav = [],
630
- search,
631
- actions,
632
- variant = "site",
633
- navOnPhone = true,
634
- menu: menuExtra,
635
- className
600
+ function SectionSwitch({
601
+ sections,
602
+ current,
603
+ onNavigate
636
604
  }) {
637
- const [open, setOpen] = react.useState(false);
638
- const tool = variant === "tool";
639
- const size = tool ? 24 : 28;
640
- const current = typeof family === "string" ? family : void 0;
641
- const phoneNav = navOnPhone ? nav : [];
642
- const menu = phoneNav.length > 0 || Boolean(family) || Boolean(menuExtra);
643
- const brandNode = brand ?? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center", children: [
644
- /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size }),
645
- product ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
646
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "mx-3 h-5 w-px bg-oca-hairline-strong" }),
647
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
648
- ] }) : null
649
- ] });
650
- const navigation = nav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map(
651
- (n) => n.children?.length ? /* @__PURE__ */ jsxRuntime.jsx(NavDropdown, { item: n }, n.href) : (
652
- // Between md and lg the family menu and the actions share the row: tighter.
653
- /* @__PURE__ */ jsxRuntime.jsx(NavLink, { item: n, line: tool, className: tool ? void 0 : "md:max-lg:px-2.5" }, n.href)
654
- )
655
- ) }) : null;
605
+ const cols = sections.length <= 3 ? sections.length : 2;
656
606
  return /* @__PURE__ */ jsxRuntime.jsx(
657
- "header",
607
+ "nav",
658
608
  {
659
- className: cn(
660
- "sticky top-0 z-40 w-full border-b bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90",
661
- tool ? "border-border" : "border-transparent",
662
- className
663
- ),
664
- children: /* @__PURE__ */ jsxRuntime.jsxs(
609
+ "aria-label": "Sections",
610
+ className: cn("grid gap-1 bg-muted p-1", cols === sections.length ? "rounded-full" : "rounded-[1.25rem]"),
611
+ style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
612
+ children: sections.map((sec) => {
613
+ const on = sec.id === current.id;
614
+ return /* @__PURE__ */ jsxRuntime.jsx(
615
+ Link__default.default,
616
+ {
617
+ href: sec.href,
618
+ onClick: onNavigate,
619
+ "aria-current": on ? "true" : void 0,
620
+ className: cn(
621
+ "flex h-8 min-w-0 items-center justify-center rounded-full px-1.5 text-[0.8125rem] font-medium transition-colors",
622
+ on ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
623
+ ),
624
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: sec.label })
625
+ },
626
+ sec.id
627
+ );
628
+ })
629
+ }
630
+ );
631
+ }
632
+ function TabBar({ items }) {
633
+ return /* @__PURE__ */ jsxRuntime.jsx(
634
+ "nav",
635
+ {
636
+ "aria-label": "Pages",
637
+ "data-oca-tabbar": "",
638
+ className: "fixed inset-x-0 bottom-0 z-40 border-t border-border bg-background/90 pb-[env(safe-area-inset-bottom)] backdrop-blur-md md:hidden",
639
+ children: /* @__PURE__ */ jsxRuntime.jsx(
665
640
  "div",
666
641
  {
667
- className: cn(
668
- "flex items-center justify-between gap-4",
669
- tool ? "h-14 px-4 md:px-6" : "oca-container h-16 md:h-[4.5rem] md:max-lg:gap-2",
670
- // Three columns, the outer two each at least their content: the
671
- // navigation stays centred whatever the actions hold, so it does
672
- // not shift when they change (signed out to signed in).
673
- !tool && nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
674
- ),
675
- children: [
676
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
677
- /* @__PURE__ */ jsxRuntime.jsxs(Link5__default.default, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
678
- brandNode,
679
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " home" })
680
- ] }),
681
- family ? /* @__PURE__ */ jsxRuntime.jsx(FamilyMenu, { current, className: "max-md:hidden" }) : null,
682
- tool && navigation ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-5", children: navigation }) : null
683
- ] }),
684
- !tool ? navigation : null,
685
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
686
- search,
687
- actions,
688
- menu ? /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open, onOpenChange: setOpen, children: [
689
- /* @__PURE__ */ jsxRuntime.jsx(
690
- SheetTrigger,
642
+ className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
643
+ style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
644
+ children: items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
645
+ Link__default.default,
646
+ {
647
+ href: it.href,
648
+ "aria-current": it.active ? "page" : void 0,
649
+ className: cn(
650
+ "flex min-w-0 flex-col items-center justify-center gap-1 rounded-2xl text-[0.6875rem] leading-none outline-none transition-colors [-webkit-tap-highlight-color:transparent] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
651
+ it.active ? "text-foreground" : "text-muted-foreground hover:text-foreground"
652
+ ),
653
+ children: [
654
+ /* @__PURE__ */ jsxRuntime.jsxs(
655
+ "span",
691
656
  {
692
- className: "inline-flex size-10 items-center justify-center rounded-full text-foreground hover:bg-accent md:hidden",
693
- "aria-label": "Open menu",
694
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
657
+ className: cn(
658
+ "relative flex h-7 w-12 items-center justify-center rounded-full transition-[background-color,box-shadow] duration-200",
659
+ "[&_svg]:size-[1.125rem] [&_svg]:shrink-0",
660
+ it.active ? "bg-card shadow-sm ring-1 ring-border [&_svg]:stroke-2" : "[&_svg]:stroke-[1.75]"
661
+ ),
662
+ children: [
663
+ it.icon,
664
+ it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute right-2.5 top-0.5 size-2 rounded-full bg-oca-orange ring-2 ring-background" }) : null
665
+ ]
695
666
  }
696
667
  ),
697
- /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "right", className: "pt-16", children: [
698
- /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
699
- menuExtra ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col", (phoneNav.length > 0 || family) && "border-b border-border pb-3"), children: menuExtra }) : null,
700
- phoneNav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: phoneNav.map(
701
- (n) => n.children?.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col py-2", children: [
702
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
703
- n.children.map((c) => /* @__PURE__ */ jsxRuntime.jsx(
704
- NavLink,
705
- {
706
- item: c,
707
- className: "rounded-xl px-3 py-2.5 text-[1.0625rem]",
708
- onNavigate: () => setOpen(false)
709
- },
710
- c.href
711
- ))
712
- ] }, n.href) : /* @__PURE__ */ jsxRuntime.jsx(
713
- NavLink,
714
- {
715
- item: n,
716
- className: "rounded-xl px-3 py-3 text-[1.0625rem]",
717
- onNavigate: () => setOpen(false)
718
- },
719
- n.href
720
- )
721
- ) }) : null,
722
- family ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: cn("group", phoneNav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
723
- /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between rounded-xl px-3 py-2.5 text-[1.0625rem] [&::-webkit-details-marker]:hidden", children: [
724
- "All orangecheck sites",
725
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
726
- ] }),
727
- /* @__PURE__ */ jsxRuntime.jsx(FamilyList, { current, onNavigate: () => setOpen(false), stack: true, className: "mt-2" })
728
- ] }) : null
729
- ] })
730
- ] }) : null
731
- ] })
732
- ]
668
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-full truncate px-0.5", children: it.label }),
669
+ it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: it.badge }) : null
670
+ ]
671
+ },
672
+ it.href
673
+ ))
733
674
  }
734
675
  )
735
676
  }
736
677
  );
737
678
  }
738
- function SkipLink({ href = "#main-content", children = "Skip to content" }) {
739
- return /* @__PURE__ */ jsxRuntime.jsx(
740
- "a",
741
- {
742
- href,
743
- className: "sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-3 focus:z-50 focus:rounded-full focus:border focus:border-border focus:bg-card focus:px-4 focus:py-2 focus:text-[0.9375rem] focus:font-medium focus:text-foreground focus:shadow-md",
744
- children
745
- }
746
- );
747
- }
748
- var BANNER_TONE = {
679
+ function tabsFor(groups) {
680
+ const items = groups.flatMap((g) => g.items);
681
+ return items.length >= 2 && items.length <= 5 && items.every((it) => it.icon) ? items : null;
682
+ }
683
+ var activeItem = (groups) => groups.flatMap((g) => g.items).find((it) => it.active);
684
+ var warned = /* @__PURE__ */ new Set();
685
+ function warnDuplicateLabels(groups) {
686
+ if (typeof process === "undefined" || process.env.NODE_ENV === "production") return;
687
+ const seen = /* @__PURE__ */ new Set();
688
+ for (const it of groups.flatMap((g) => g.items)) {
689
+ if (seen.has(it.label) && !warned.has(it.label)) {
690
+ warned.add(it.label);
691
+ console.warn(`AppShell: two pages are labelled "${it.label}"; give each its own name.`);
692
+ }
693
+ seen.add(it.label);
694
+ }
695
+ }
696
+ function AppShell({
697
+ nav,
698
+ sections,
699
+ activeSection,
700
+ page: pageOverride,
701
+ persistent = [],
702
+ home = "/",
703
+ family,
704
+ account,
705
+ banner,
706
+ footer,
707
+ children,
708
+ className
709
+ }) {
710
+ const [open, setOpen] = react.useState(false);
711
+ const current = sections && sections.length > 0 ? sections.find((sec) => sec.id === activeSection) ?? sections.find((sec) => activeItem(sec.groups)) ?? sections[0] : void 0;
712
+ const groups = current ? [...current.groups, ...persistent] : [...nav ?? [], ...persistent];
713
+ warnDuplicateLabels(groups);
714
+ const tabs = current ? null : tabsFor(groups);
715
+ const page = activeItem(groups);
716
+ const place = react.useMemo(
717
+ () => ({
718
+ section: current ? current.title ?? current.label : void 0,
719
+ page: pageOverride ?? page?.label
720
+ }),
721
+ [current, page?.label, pageOverride]
722
+ );
723
+ const familyMenu = family ? /* @__PURE__ */ jsxRuntime.jsx(FamilyMenu, { current: typeof family === "string" ? family : void 0 }) : null;
724
+ const switcher = sections && current && sections.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(SectionSwitch, { sections, current, onNavigate: () => setOpen(false) }) : null;
725
+ return /* @__PURE__ */ jsxRuntime.jsx(ShellContext.Provider, { value: place, children: /* @__PURE__ */ jsxRuntime.jsxs(
726
+ "div",
727
+ {
728
+ className: cn(
729
+ "min-h-dvh bg-background",
730
+ tabs && "max-md:pb-[calc(3.5rem_+_env(safe-area-inset-bottom))]",
731
+ className
732
+ ),
733
+ children: [
734
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sticky top-0 z-40 border-b border-border bg-background/90 backdrop-blur-md lg:hidden", children: [
735
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-14 items-center gap-2 px-3", children: [
736
+ /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open, onOpenChange: setOpen, children: [
737
+ /* @__PURE__ */ jsxRuntime.jsx(
738
+ SheetTrigger,
739
+ {
740
+ className: cn(
741
+ "inline-flex size-10 items-center justify-center rounded-full hover:bg-accent",
742
+ // The tab bar holds every page; the sheet is left for a footer.
743
+ tabs && !footer && "max-md:hidden"
744
+ ),
745
+ "aria-label": "Open navigation",
746
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
747
+ }
748
+ ),
749
+ /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "left", className: "flex flex-col gap-6 overflow-y-auto p-4 pt-16", children: [
750
+ /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
751
+ switcher,
752
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: tabs ? "max-md:hidden" : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups, onNavigate: () => setOpen(false) }) }),
753
+ footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
754
+ ] })
755
+ ] }),
756
+ /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 22 }) }),
757
+ familyMenu,
758
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex items-center", children: account })
759
+ ] }),
760
+ place.page ? /* @__PURE__ */ jsxRuntime.jsxs(
761
+ "div",
762
+ {
763
+ className: cn(
764
+ "flex h-9 items-center gap-1.5 border-t border-border px-4 text-[0.875rem]",
765
+ // The active tab already names the page.
766
+ tabs && !pageOverride && "max-md:hidden"
767
+ ),
768
+ children: [
769
+ place.section ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
770
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
771
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-muted-foreground" })
772
+ ] }) : null,
773
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: place.page })
774
+ ]
775
+ }
776
+ ) : null
777
+ ] }),
778
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
779
+ /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "sticky top-0 hidden h-dvh w-[17rem] shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
780
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
781
+ /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 26 }) }),
782
+ familyMenu
783
+ ] }),
784
+ switcher,
785
+ /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups }),
786
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
787
+ ] }),
788
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
789
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden h-[4.5rem] items-center justify-end gap-3 px-8 lg:flex", children: account }),
790
+ banner ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pb-2 pt-4 md:px-8 lg:pt-0", children: banner }) : null,
791
+ /* @__PURE__ */ jsxRuntime.jsx("main", { id: "main-content", className: "flex-1 px-4 pb-16 pt-6 md:px-8 lg:pt-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto w-full max-w-[72rem]", children }) })
792
+ ] })
793
+ ] }),
794
+ tabs ? /* @__PURE__ */ jsxRuntime.jsx(TabBar, { items: tabs }) : null
795
+ ]
796
+ }
797
+ ) });
798
+ }
799
+ function AccountMenu({
800
+ name,
801
+ detail,
802
+ items,
803
+ nameFrom = "sm"
804
+ }) {
805
+ const initial = name.trim().charAt(0).toUpperCase() || "\xB7";
806
+ return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
807
+ /* @__PURE__ */ jsxRuntime.jsxs(
808
+ DropdownMenuTrigger,
809
+ {
810
+ className: cn(
811
+ "inline-flex h-10 items-center gap-2.5 rounded-full border border-border bg-card pl-1 pr-1 text-[0.9375rem] outline-none transition-colors hover:border-oca-hairline-strong focus-visible:ring-2 focus-visible:ring-ring",
812
+ nameFrom === "lg" ? "lg:pr-3.5" : "sm:pr-3.5"
813
+ ),
814
+ "aria-label": `${name}, account menu`,
815
+ children: [
816
+ /* @__PURE__ */ jsxRuntime.jsx(
817
+ "span",
818
+ {
819
+ "aria-hidden": true,
820
+ "data-initial": initial,
821
+ className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background before:content-[attr(data-initial)]"
822
+ }
823
+ ),
824
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("max-w-[10rem] truncate", nameFrom === "lg" ? "max-lg:hidden" : "max-sm:hidden"), children: name })
825
+ ]
826
+ }
827
+ ),
828
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "end", className: "w-64", children: [
829
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuLabel, { className: "flex flex-col gap-0.5", children: [
830
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: name }),
831
+ detail ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono text-[0.75rem]", children: detail }) : null
832
+ ] }),
833
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
834
+ items.map(
835
+ (it, i) => it === "separator" ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxRuntime.jsxs(Link__default.default, { href: it.href, children: [
836
+ it.icon,
837
+ it.label
838
+ ] }) }, it.label) : /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
839
+ it.icon,
840
+ it.label
841
+ ] }, it.label)
842
+ )
843
+ ] })
844
+ ] });
845
+ }
846
+ function ThemeToggle({ className }) {
847
+ const { theme, setTheme } = nextThemes.useTheme();
848
+ const [mounted, setMounted] = react.useState(false);
849
+ react.useEffect(() => setMounted(true), []);
850
+ const current = mounted ? theme ?? "system" : "system";
851
+ const next = current === "light" ? "dark" : current === "dark" ? "system" : "light";
852
+ const Icon = current === "light" ? lucideReact.Sun : current === "dark" ? lucideReact.Moon : lucideReact.SunMoon;
853
+ return /* @__PURE__ */ jsxRuntime.jsx(
854
+ "button",
855
+ {
856
+ type: "button",
857
+ onClick: () => setTheme(next),
858
+ "aria-label": `Theme: ${current}. Switch to ${next}`,
859
+ title: `Theme: ${current}`,
860
+ className: cn(
861
+ "inline-flex size-10 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
862
+ className
863
+ ),
864
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-[1.125rem]" })
865
+ }
866
+ );
867
+ }
868
+ function NavLink({
869
+ item,
870
+ className,
871
+ onNavigate,
872
+ line = false
873
+ }) {
874
+ const cls = cn(
875
+ "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
876
+ item.active ? "text-foreground" : "text-muted-foreground hover:text-foreground",
877
+ line && "relative after:absolute after:inset-x-3 after:-bottom-[0.625rem] after:h-0.5 after:rounded-full",
878
+ line && item.active && "after:bg-foreground",
879
+ className
880
+ );
881
+ if (item.external) {
882
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
883
+ }
884
+ return /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
885
+ }
886
+ function NavRow({ item, onNavigate }) {
887
+ const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
888
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] font-medium leading-6 text-foreground", children: item.label }),
889
+ item.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: item.description }) : null
890
+ ] });
891
+ const cls = cn(
892
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
893
+ item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
894
+ );
895
+ return item.external ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
896
+ }
897
+ var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
898
+ function NavDropdown({ item }) {
899
+ const [open, setOpen] = react.useState(false);
900
+ const active = item.active || item.children?.some((c) => c.active);
901
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
902
+ /* @__PURE__ */ jsxRuntime.jsxs(
903
+ PopoverTrigger,
904
+ {
905
+ className: cn(
906
+ "group inline-flex items-center gap-1 rounded-full py-2 pl-3 pr-2.5 text-[0.9375rem] transition-colors md:max-lg:pl-2.5 md:max-lg:pr-2",
907
+ active ? "text-foreground" : "text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
908
+ ),
909
+ children: [
910
+ item.label,
911
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180" })
912
+ ]
913
+ }
914
+ ),
915
+ /* @__PURE__ */ jsxRuntime.jsxs(PopoverContent, { align: "center", sideOffset: 10, className: "w-[min(calc(100vw-2rem),26rem)] p-2", children: [
916
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col", children: item.children?.map((c) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(NavRow, { item: c, onNavigate: () => setOpen(false) }) }, c.href)) }),
917
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1.5 border-t border-border px-1 pt-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(
918
+ NavLink,
919
+ {
920
+ item: { ...item, label: seeAll(item), children: void 0 },
921
+ className: "block rounded-xl px-2 py-2 text-[0.875rem]",
922
+ onNavigate: () => setOpen(false)
923
+ }
924
+ ) })
925
+ ] })
926
+ ] });
927
+ }
928
+ function SiteHeader({
929
+ home = "/",
930
+ brand,
931
+ product,
932
+ family,
933
+ nav = [],
934
+ search,
935
+ actions,
936
+ variant = "site",
937
+ navOnPhone = true,
938
+ menu: menuExtra,
939
+ className
940
+ }) {
941
+ const [open, setOpen] = react.useState(false);
942
+ const tool = variant === "tool";
943
+ const size = tool ? 24 : 28;
944
+ const current = typeof family === "string" ? family : void 0;
945
+ const phoneNav = navOnPhone ? nav : [];
946
+ const menu = phoneNav.length > 0 || Boolean(family) || Boolean(menuExtra);
947
+ const brandNode = brand ?? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center", children: [
948
+ /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size }),
949
+ product ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
950
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "mx-3 h-5 w-px bg-oca-hairline-strong" }),
951
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
952
+ ] }) : null
953
+ ] });
954
+ const navigation = nav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map(
955
+ (n) => n.children?.length ? /* @__PURE__ */ jsxRuntime.jsx(NavDropdown, { item: n }, n.href) : (
956
+ // Between md and lg the family menu and the actions share the row: tighter.
957
+ /* @__PURE__ */ jsxRuntime.jsx(NavLink, { item: n, line: tool, className: tool ? void 0 : "md:max-lg:px-2.5" }, n.href)
958
+ )
959
+ ) }) : null;
960
+ return /* @__PURE__ */ jsxRuntime.jsx(
961
+ "header",
962
+ {
963
+ className: cn(
964
+ "sticky top-0 z-40 w-full border-b bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90",
965
+ tool ? "border-border" : "border-transparent",
966
+ className
967
+ ),
968
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
969
+ "div",
970
+ {
971
+ className: cn(
972
+ "flex items-center justify-between gap-4",
973
+ tool ? "h-14 px-4 md:px-6" : "oca-container h-16 md:h-[4.5rem] md:max-lg:gap-2",
974
+ // Three columns, the outer two each at least their content: the
975
+ // navigation stays centred whatever the actions hold, so it does
976
+ // not shift when they change (signed out to signed in).
977
+ !tool && nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
978
+ ),
979
+ children: [
980
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
981
+ /* @__PURE__ */ jsxRuntime.jsxs(Link__default.default, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
982
+ brandNode,
983
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " home" })
984
+ ] }),
985
+ family ? /* @__PURE__ */ jsxRuntime.jsx(FamilyMenu, { current, className: "max-md:hidden" }) : null,
986
+ tool && navigation ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-5", children: navigation }) : null
987
+ ] }),
988
+ !tool ? navigation : null,
989
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
990
+ search,
991
+ actions,
992
+ menu ? /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open, onOpenChange: setOpen, children: [
993
+ /* @__PURE__ */ jsxRuntime.jsx(
994
+ SheetTrigger,
995
+ {
996
+ className: "inline-flex size-10 items-center justify-center rounded-full text-foreground hover:bg-accent md:hidden",
997
+ "aria-label": "Open menu",
998
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
999
+ }
1000
+ ),
1001
+ /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "right", className: "pt-16", children: [
1002
+ /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
1003
+ menuExtra ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col", (phoneNav.length > 0 || family) && "border-b border-border pb-3"), children: menuExtra }) : null,
1004
+ phoneNav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: phoneNav.map(
1005
+ (n) => n.children?.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col py-2", children: [
1006
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
1007
+ n.children.map((c) => /* @__PURE__ */ jsxRuntime.jsx(
1008
+ NavLink,
1009
+ {
1010
+ item: c,
1011
+ className: "rounded-xl px-3 py-2.5 text-[1.0625rem]",
1012
+ onNavigate: () => setOpen(false)
1013
+ },
1014
+ c.href
1015
+ ))
1016
+ ] }, n.href) : /* @__PURE__ */ jsxRuntime.jsx(
1017
+ NavLink,
1018
+ {
1019
+ item: n,
1020
+ className: "rounded-xl px-3 py-3 text-[1.0625rem]",
1021
+ onNavigate: () => setOpen(false)
1022
+ },
1023
+ n.href
1024
+ )
1025
+ ) }) : null,
1026
+ family ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: cn("group", phoneNav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
1027
+ /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between rounded-xl px-3 py-2.5 text-[1.0625rem] [&::-webkit-details-marker]:hidden", children: [
1028
+ "All orangecheck sites",
1029
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
1030
+ ] }),
1031
+ /* @__PURE__ */ jsxRuntime.jsx(FamilyList, { current, onNavigate: () => setOpen(false), stack: true, className: "mt-2" })
1032
+ ] }) : null
1033
+ ] })
1034
+ ] }) : null
1035
+ ] })
1036
+ ]
1037
+ }
1038
+ )
1039
+ }
1040
+ );
1041
+ }
1042
+ function SkipLink({ href = "#main-content", children = "Skip to content" }) {
1043
+ return /* @__PURE__ */ jsxRuntime.jsx(
1044
+ "a",
1045
+ {
1046
+ href,
1047
+ className: "sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-3 focus:z-50 focus:rounded-full focus:border focus:border-border focus:bg-card focus:px-4 focus:py-2 focus:text-[0.9375rem] focus:font-medium focus:text-foreground focus:shadow-md",
1048
+ children
1049
+ }
1050
+ );
1051
+ }
1052
+ var BANNER_TONE = {
749
1053
  neutral: "border-border bg-muted",
750
1054
  brand: "border-[color-mix(in_oklab,var(--oca-orange)_30%,var(--border))] bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--background))]",
751
1055
  danger: "border-[color-mix(in_oklab,var(--destructive)_35%,var(--border))] bg-[color-mix(in_oklab,var(--destructive)_8%,var(--background))]"
@@ -776,7 +1080,7 @@ function SiteBanner({
776
1080
  var FOOT_LINK = "inline-flex min-h-11 items-center transition-colors hover:text-foreground md:min-h-0";
777
1081
  function LegalRow({ links }) {
778
1082
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:items-center sm:justify-between", children: [
779
- /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Legal", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-wrap gap-x-5", children: links.map((l) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: l.href.startsWith("/") ? /* @__PURE__ */ jsxRuntime.jsx(Link5__default.default, { href: l.href, className: FOOT_LINK, children: l.label }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href: l.href, className: FOOT_LINK, children: l.label }) }, l.href)) }) }),
1083
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Legal", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-wrap gap-x-5", children: links.map((l) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: l.href.startsWith("/") ? /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: l.href, className: FOOT_LINK, children: l.label }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href: l.href, className: FOOT_LINK, children: l.label }) }, l.href)) }) }),
780
1084
  /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
781
1085
  "\xA9 ",
782
1086
  (/* @__PURE__ */ new Date()).getFullYear(),
@@ -866,6 +1170,25 @@ function SiteFooter({
866
1170
  ] }) }) : null
867
1171
  ] });
868
1172
  }
1173
+ function OchkIoFooter({ columns = OCHK_IO_FOOTER, className }) {
1174
+ return /* @__PURE__ */ jsxRuntime.jsx(
1175
+ SiteFooter,
1176
+ {
1177
+ columns,
1178
+ family: true,
1179
+ legal: true,
1180
+ fineprint: "Open protocols on Bitcoin. Anyone can check the result.",
1181
+ meta: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
1182
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
1183
+ "Open-source work on orangecheck is ",
1184
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: "supported by OpenSats." })
1185
+ ] }),
1186
+ /* @__PURE__ */ jsxRuntime.jsx(ThemeToggle, { className: "-mx-3" })
1187
+ ] }),
1188
+ className
1189
+ }
1190
+ );
1191
+ }
869
1192
  function IsoCheck({ size = 360, settle = false, shadow = true, tilt = false, title, className }) {
870
1193
  const ref = react.useRef(null);
871
1194
  react.useEffect(() => {
@@ -951,12 +1274,12 @@ function SignInFrame({
951
1274
  children: [
952
1275
  /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col px-4 pb-8 pt-5 sm:px-8 lg:px-14 lg:pt-8", children: [
953
1276
  /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex items-center justify-between gap-4", children: [
954
- /* @__PURE__ */ jsxRuntime.jsxs(Link5__default.default, { href: home, className: "w-fit rounded-lg", children: [
1277
+ /* @__PURE__ */ jsxRuntime.jsxs(Link__default.default, { href: home, className: "w-fit rounded-lg", children: [
955
1278
  brand ?? /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 28 }),
956
1279
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " home" })
957
1280
  ] }),
958
1281
  back === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
959
- Link5__default.default,
1282
+ Link__default.default,
960
1283
  {
961
1284
  href: home,
962
1285
  className: "text-[0.9375rem] text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
@@ -1022,21 +1345,10 @@ react.forwardRef(function Separator3({ className, orientation = "horizontal", de
1022
1345
  }
1023
1346
  );
1024
1347
  });
1025
- function sharedContext(name, initial) {
1026
- const key = /* @__PURE__ */ Symbol.for(`@orangecheck/app-design/${name}`);
1027
- const store = globalThis;
1028
- return store[key] ?? (store[key] = react.createContext(initial));
1029
- }
1030
-
1031
- // src/lib/density.ts
1032
1348
  var DensityContext = sharedContext("density", "comfortable");
1033
1349
  function DensityProvider({ density, children }) {
1034
1350
  return react.createElement(DensityContext.Provider, { value: density }, children);
1035
1351
  }
1036
- var ShellContext = sharedContext("shell-place", {});
1037
- function useShellPlace() {
1038
- return react.useContext(ShellContext);
1039
- }
1040
1352
  var buttonVariants = classVarianceAuthority.cva(
1041
1353
  [
1042
1354
  "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-full font-medium",
@@ -1168,6 +1480,7 @@ function OnThisPage({
1168
1480
  ] })
1169
1481
  );
1170
1482
  }
1483
+ var InDocsContext = sharedContext("in-docs", false);
1171
1484
  var STATUS_WORDS = /* @__PURE__ */ new Set(["live", "testing", "not-yet", "paused", "good", "caution", "refused"]);
1172
1485
  var pathOf = (href) => href.split(/[?#]/)[0].replace(/(.)\/$/, "$1");
1173
1486
  function DocsNav({
@@ -1223,394 +1536,131 @@ function DocsNav({
1223
1536
  className: cn("size-3.5 shrink-0 text-oca-subtle transition-transform duration-200", open && "rotate-90")
1224
1537
  }
1225
1538
  )
1226
- ]
1227
- }
1228
- ),
1229
- /* @__PURE__ */ jsxRuntime.jsx("ul", { id: panel, hidden: !open, className: "mb-2 ml-2.5 mt-0.5 border-l border-border", children: section.items.map((item) => {
1230
- const on = pathOf(item.href) === here;
1231
- const badge = typeof item.badge === "string" && STATUS_WORDS.has(item.badge) ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: item.badge }) : item.badge ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: item.badge }) : null;
1232
- return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
1233
- Link5__default.default,
1234
- {
1235
- href: item.href,
1236
- ref: on ? activeRef : void 0,
1237
- onClick: onNavigate,
1238
- "aria-current": on ? "page" : void 0,
1239
- className: cn(
1240
- "-ml-px flex min-h-9 items-center gap-2 border-l-2 py-1.5 pl-3.5 pr-2 text-[0.875rem] leading-snug transition-colors",
1241
- on ? "border-foreground font-medium text-foreground" : "border-transparent text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
1242
- ),
1243
- children: [
1244
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1", children: item.label }),
1245
- badge
1246
- ]
1247
- }
1248
- ) }, item.href);
1249
- }) })
1250
- ] }, section.label);
1251
- }) });
1252
- }
1253
- var DOCS_HEADER_NAV = OCHK_IO_NAV.map((n) => n.href === DOCS_HREF ? { ...n, active: true } : n);
1254
- function DocsShell({
1255
- nav,
1256
- current,
1257
- header,
1258
- search,
1259
- actions,
1260
- breadcrumbs,
1261
- toc,
1262
- pager,
1263
- footer,
1264
- children
1265
- }) {
1266
- const [menu, setMenu] = react.useState(false);
1267
- react.useEffect(() => setMenu(false), [current]);
1268
- const read = useHeadings("#docs-content", current);
1269
- const items = toc ?? read.items;
1270
- const activeId = toc ? void 0 : read.activeId;
1271
- const here = pathOf(current);
1272
- const place = react.useMemo(() => {
1273
- for (const s of nav) {
1274
- const it = s.items.find((i) => pathOf(i.href) === here);
1275
- if (it) return { section: s.label, page: it.label };
1276
- }
1277
- return null;
1278
- }, [nav, here]);
1279
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-dvh flex-col bg-background", children: [
1280
- /* @__PURE__ */ jsxRuntime.jsx(SkipLink, {}),
1281
- header ?? /* @__PURE__ */ jsxRuntime.jsx(SiteHeader, { home: OCHK_IO, family: "docs", nav: DOCS_HEADER_NAV, search, actions }),
1282
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-16 z-30 border-b border-border bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90 md:top-[4.5rem] lg:hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container flex h-12 items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open: menu, onOpenChange: setMenu, children: [
1283
- /* @__PURE__ */ jsxRuntime.jsxs(SheetTrigger, { className: "-ml-2 inline-flex h-10 min-w-0 items-center gap-2 rounded-full px-2.5 text-[0.875rem] hover:bg-accent", children: [
1284
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeft, { "aria-hidden": true, className: "size-[1.125rem] shrink-0" }),
1285
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Docs menu. " }),
1286
- place ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
1287
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
1288
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }),
1289
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: place.page })
1290
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Docs" })
1291
- ] }),
1292
- /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "left", className: "w-[min(88vw,22rem)] gap-0 p-0", children: [
1293
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-border px-5 py-4 pr-14", children: /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "text-[1.0625rem] font-medium", children: "Docs" }) }),
1294
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto p-3", children: /* @__PURE__ */ jsxRuntime.jsx(DocsNav, { sections: nav, current, onNavigate: () => setMenu(false) }) })
1295
- ] })
1296
- ] }) }) }),
1297
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lg:grid lg:grid-cols-[13.5rem_minmax(0,1fr)] lg:gap-x-10 xl:grid-cols-[13.5rem_minmax(0,1fr)_11rem]", children: [
1298
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto overscroll-contain py-8 pr-1 lg:block", children: /* @__PURE__ */ jsxRuntime.jsx(DocsNav, { sections: nav, current }) }),
1299
- /* @__PURE__ */ jsxRuntime.jsxs("main", { id: "main-content", className: "min-w-0 pb-16 pt-6 md:pt-8", children: [
1300
- breadcrumbs ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-6 max-lg:hidden", children: breadcrumbs }) : null,
1301
- items.length > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group mb-8 rounded-2xl border border-border bg-card xl:hidden", children: [
1302
- /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex min-h-12 cursor-pointer list-none items-center justify-between px-4 text-[0.9375rem] font-medium [&::-webkit-details-marker]:hidden", children: [
1303
- "On this page",
1304
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
1305
- ] }),
1306
- /* @__PURE__ */ jsxRuntime.jsx(OnThisPage, { items, activeId, title: null, className: "px-4 pb-4" })
1307
- ] }) : null,
1308
- /* @__PURE__ */ jsxRuntime.jsx("article", { id: "docs-content", className: "max-w-[46rem]", children }),
1309
- pager ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-16 max-w-[46rem]", children: pager }) : null
1310
- ] }),
1311
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto py-10 xl:block", children: items.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(OnThisPage, { items, activeId }) : null })
1312
- ] }) }),
1313
- footer ?? /* @__PURE__ */ jsxRuntime.jsx(SiteFooter, { columns: OCHK_IO_FOOTER, family: true, legal: true, signature: false })
1314
- ] });
1315
- }
1316
- function SideNav({ groups, onNavigate }) {
1317
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Pages", className: "flex flex-col gap-5", children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
1318
- g.label ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
1319
- g.items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
1320
- Link5__default.default,
1321
- {
1322
- href: it.href,
1323
- onClick: onNavigate,
1324
- "aria-current": it.active ? "page" : void 0,
1325
- className: cn(
1326
- "flex h-9 items-center gap-3 rounded-xl px-3 text-[0.9375rem] transition-colors",
1327
- "[&_svg]:size-[1.0625rem] [&_svg]:shrink-0",
1328
- it.active ? "bg-card text-foreground shadow-sm ring-1 ring-border [&_svg]:text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground"
1329
- ),
1330
- children: [
1331
- it.icon,
1332
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: it.label }),
1333
- it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: it.badge }) : null
1334
- ]
1335
- },
1336
- it.href
1337
- ))
1338
- ] }, g.label ?? gi)) });
1339
- }
1340
- function SectionSwitch({
1341
- sections,
1342
- current,
1343
- onNavigate
1344
- }) {
1345
- const cols = sections.length <= 3 ? sections.length : 2;
1346
- return /* @__PURE__ */ jsxRuntime.jsx(
1347
- "nav",
1348
- {
1349
- "aria-label": "Sections",
1350
- className: cn("grid gap-1 bg-muted p-1", cols === sections.length ? "rounded-full" : "rounded-[1.25rem]"),
1351
- style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
1352
- children: sections.map((sec) => {
1353
- const on = sec.id === current.id;
1354
- return /* @__PURE__ */ jsxRuntime.jsx(
1355
- Link5__default.default,
1356
- {
1357
- href: sec.href,
1358
- onClick: onNavigate,
1359
- "aria-current": on ? "true" : void 0,
1360
- className: cn(
1361
- "flex h-8 min-w-0 items-center justify-center rounded-full px-1.5 text-[0.8125rem] font-medium transition-colors",
1362
- on ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
1363
- ),
1364
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: sec.label })
1365
- },
1366
- sec.id
1367
- );
1368
- })
1369
- }
1370
- );
1371
- }
1372
- function TabBar({ items }) {
1373
- return /* @__PURE__ */ jsxRuntime.jsx(
1374
- "nav",
1375
- {
1376
- "aria-label": "Pages",
1377
- "data-oca-tabbar": "",
1378
- className: "fixed inset-x-0 bottom-0 z-40 border-t border-border bg-background/90 pb-[env(safe-area-inset-bottom)] backdrop-blur-md md:hidden",
1379
- children: /* @__PURE__ */ jsxRuntime.jsx(
1380
- "div",
1381
- {
1382
- className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
1383
- style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
1384
- children: items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
1385
- Link5__default.default,
1386
- {
1387
- href: it.href,
1388
- "aria-current": it.active ? "page" : void 0,
1389
- className: cn(
1390
- "flex min-w-0 flex-col items-center justify-center gap-1 rounded-2xl text-[0.6875rem] leading-none outline-none transition-colors [-webkit-tap-highlight-color:transparent] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
1391
- it.active ? "text-foreground" : "text-muted-foreground hover:text-foreground"
1392
- ),
1393
- children: [
1394
- /* @__PURE__ */ jsxRuntime.jsxs(
1395
- "span",
1396
- {
1397
- className: cn(
1398
- "relative flex h-7 w-12 items-center justify-center rounded-full transition-[background-color,box-shadow] duration-200",
1399
- "[&_svg]:size-[1.125rem] [&_svg]:shrink-0",
1400
- it.active ? "bg-card shadow-sm ring-1 ring-border [&_svg]:stroke-2" : "[&_svg]:stroke-[1.75]"
1401
- ),
1402
- children: [
1403
- it.icon,
1404
- it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute right-2.5 top-0.5 size-2 rounded-full bg-oca-orange ring-2 ring-background" }) : null
1405
- ]
1406
- }
1407
- ),
1408
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-full truncate px-0.5", children: it.label }),
1409
- it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: it.badge }) : null
1410
- ]
1411
- },
1412
- it.href
1413
- ))
1539
+ ]
1414
1540
  }
1415
- )
1416
- }
1417
- );
1418
- }
1419
- function tabsFor(groups) {
1420
- const items = groups.flatMap((g) => g.items);
1421
- return items.length >= 2 && items.length <= 5 && items.every((it) => it.icon) ? items : null;
1422
- }
1423
- var activeItem = (groups) => groups.flatMap((g) => g.items).find((it) => it.active);
1424
- var warned = /* @__PURE__ */ new Set();
1425
- function warnDuplicateLabels(groups) {
1426
- if (typeof process === "undefined" || process.env.NODE_ENV === "production") return;
1427
- const seen = /* @__PURE__ */ new Set();
1428
- for (const it of groups.flatMap((g) => g.items)) {
1429
- if (seen.has(it.label) && !warned.has(it.label)) {
1430
- warned.add(it.label);
1431
- console.warn(`AppShell: two pages are labelled "${it.label}"; give each its own name.`);
1432
- }
1433
- seen.add(it.label);
1434
- }
1541
+ ),
1542
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { id: panel, hidden: !open, className: "mb-2 ml-2.5 mt-0.5 border-l border-border", children: section.items.map((item) => {
1543
+ const on = pathOf(item.href) === here;
1544
+ const badge = typeof item.badge === "string" && STATUS_WORDS.has(item.badge) ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: item.badge }) : item.badge ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: item.badge }) : null;
1545
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
1546
+ Link__default.default,
1547
+ {
1548
+ href: item.href,
1549
+ ref: on ? activeRef : void 0,
1550
+ onClick: onNavigate,
1551
+ "aria-current": on ? "page" : void 0,
1552
+ className: cn(
1553
+ "-ml-px flex min-h-9 items-center gap-2 border-l-2 py-1.5 pl-3.5 pr-2 text-[0.875rem] leading-snug transition-colors",
1554
+ on ? "border-foreground font-medium text-foreground" : "border-transparent text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
1555
+ ),
1556
+ children: [
1557
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1", children: item.label }),
1558
+ badge
1559
+ ]
1560
+ }
1561
+ ) }, item.href);
1562
+ }) })
1563
+ ] }, section.label);
1564
+ }) });
1435
1565
  }
1436
- function AppShell({
1566
+ var DOCS_HEADER_NAV = OCHK_IO_NAV.map((n) => n.href === DOCS_HREF ? { ...n, active: true } : n);
1567
+ function DocsShell({
1437
1568
  nav,
1438
- sections,
1439
- activeSection,
1440
- page: pageOverride,
1441
- persistent = [],
1442
- home = "/",
1443
- account,
1444
- banner,
1569
+ current,
1570
+ navCurrent,
1571
+ header,
1572
+ search,
1573
+ actions,
1574
+ breadcrumbs,
1575
+ toc,
1576
+ pager,
1445
1577
  footer,
1446
- children,
1447
- className
1578
+ children
1448
1579
  }) {
1449
- const [open, setOpen] = react.useState(false);
1450
- const current = sections && sections.length > 0 ? sections.find((sec) => sec.id === activeSection) ?? sections.find((sec) => activeItem(sec.groups)) ?? sections[0] : void 0;
1451
- const groups = current ? [...current.groups, ...persistent] : [...nav ?? [], ...persistent];
1452
- warnDuplicateLabels(groups);
1453
- const tabs = current ? null : tabsFor(groups);
1454
- const page = activeItem(groups);
1455
- const place = react.useMemo(
1456
- () => ({
1457
- section: current ? current.title ?? current.label : void 0,
1458
- page: pageOverride ?? page?.label
1459
- }),
1460
- [current, page?.label, pageOverride]
1461
- );
1462
- const switcher = sections && current && sections.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(SectionSwitch, { sections, current, onNavigate: () => setOpen(false) }) : null;
1463
- return /* @__PURE__ */ jsxRuntime.jsx(ShellContext.Provider, { value: place, children: /* @__PURE__ */ jsxRuntime.jsxs(
1464
- "div",
1465
- {
1466
- className: cn(
1467
- "min-h-dvh bg-background",
1468
- tabs && "max-md:pb-[calc(3.5rem_+_env(safe-area-inset-bottom))]",
1469
- className
1470
- ),
1471
- children: [
1472
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sticky top-0 z-40 border-b border-border bg-background/90 backdrop-blur-md lg:hidden", children: [
1473
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-14 items-center gap-2 px-3", children: [
1474
- /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open, onOpenChange: setOpen, children: [
1475
- /* @__PURE__ */ jsxRuntime.jsx(
1476
- SheetTrigger,
1477
- {
1478
- className: cn(
1479
- "inline-flex size-10 items-center justify-center rounded-full hover:bg-accent",
1480
- // The tab bar holds every page; the sheet is left for a footer.
1481
- tabs && !footer && "max-md:hidden"
1482
- ),
1483
- "aria-label": "Open navigation",
1484
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
1485
- }
1486
- ),
1487
- /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "left", className: "flex flex-col gap-6 overflow-y-auto p-4 pt-16", children: [
1488
- /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
1489
- switcher,
1490
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: tabs ? "max-md:hidden" : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups, onNavigate: () => setOpen(false) }) }),
1491
- footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
1492
- ] })
1493
- ] }),
1494
- /* @__PURE__ */ jsxRuntime.jsx(Link5__default.default, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 22 }) }),
1495
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex items-center", children: account })
1496
- ] }),
1497
- place.page ? /* @__PURE__ */ jsxRuntime.jsxs(
1498
- "div",
1499
- {
1500
- className: cn(
1501
- "flex h-9 items-center gap-1.5 border-t border-border px-4 text-[0.875rem]",
1502
- // The active tab already names the page.
1503
- tabs && !pageOverride && "max-md:hidden"
1504
- ),
1505
- children: [
1506
- place.section ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1507
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
1508
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-muted-foreground" })
1509
- ] }) : null,
1510
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: place.page })
1511
- ]
1512
- }
1513
- ) : null
1514
- ] }),
1515
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
1516
- /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "sticky top-0 hidden h-dvh w-[17rem] shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
1517
- /* @__PURE__ */ jsxRuntime.jsx(Link5__default.default, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 26 }) }),
1518
- switcher,
1519
- /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups }),
1520
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
1521
- ] }),
1522
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
1523
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden h-[4.5rem] items-center justify-end gap-3 px-8 lg:flex", children: account }),
1524
- banner ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pb-2 pt-4 md:px-8 lg:pt-0", children: banner }) : null,
1525
- /* @__PURE__ */ jsxRuntime.jsx("main", { id: "main-content", className: "flex-1 px-4 pb-16 pt-6 md:px-8 lg:pt-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto w-full max-w-[72rem]", children }) })
1526
- ] })
1527
- ] }),
1528
- tabs ? /* @__PURE__ */ jsxRuntime.jsx(TabBar, { items: tabs }) : null
1529
- ]
1580
+ const [menu, setMenu] = react.useState(false);
1581
+ react.useEffect(() => setMenu(false), [current]);
1582
+ const read = useHeadings("#docs-content", current);
1583
+ const items = toc ?? read.items;
1584
+ const activeId = toc ? void 0 : read.activeId;
1585
+ const marked = navCurrent ?? current;
1586
+ const here = pathOf(marked);
1587
+ const place = react.useMemo(() => {
1588
+ for (const s of nav) {
1589
+ const it = s.items.find((i) => pathOf(i.href) === here);
1590
+ if (it) return { section: s.label, page: it.label };
1530
1591
  }
1531
- ) });
1532
- }
1533
- function AccountMenu({
1534
- name,
1535
- detail,
1536
- items,
1537
- nameFrom = "sm"
1538
- }) {
1539
- const initial = name.trim().charAt(0).toUpperCase() || "\xB7";
1540
- return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
1541
- /* @__PURE__ */ jsxRuntime.jsxs(
1542
- DropdownMenuTrigger,
1543
- {
1544
- className: cn(
1545
- "inline-flex h-10 items-center gap-2.5 rounded-full border border-border bg-card pl-1 pr-1 text-[0.9375rem] outline-none transition-colors hover:border-oca-hairline-strong focus-visible:ring-2 focus-visible:ring-ring",
1546
- nameFrom === "lg" ? "lg:pr-3.5" : "sm:pr-3.5"
1547
- ),
1548
- "aria-label": `${name}, account menu`,
1549
- children: [
1550
- /* @__PURE__ */ jsxRuntime.jsx(
1551
- "span",
1552
- {
1553
- "aria-hidden": true,
1554
- "data-initial": initial,
1555
- className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background before:content-[attr(data-initial)]"
1556
- }
1557
- ),
1558
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("max-w-[10rem] truncate", nameFrom === "lg" ? "max-lg:hidden" : "max-sm:hidden"), children: name })
1559
- ]
1560
- }
1561
- ),
1562
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "end", className: "w-64", children: [
1563
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuLabel, { className: "flex flex-col gap-0.5", children: [
1564
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: name }),
1565
- detail ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono text-[0.75rem]", children: detail }) : null
1592
+ return null;
1593
+ }, [nav, here]);
1594
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-dvh flex-col bg-background", children: [
1595
+ /* @__PURE__ */ jsxRuntime.jsx(SkipLink, {}),
1596
+ header ?? /* @__PURE__ */ jsxRuntime.jsx(SiteHeader, { home: OCHK_IO, family: "docs", nav: DOCS_HEADER_NAV, search, actions }),
1597
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-16 z-30 border-b border-border bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90 md:top-[4.5rem] lg:hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container flex h-12 items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open: menu, onOpenChange: setMenu, children: [
1598
+ /* @__PURE__ */ jsxRuntime.jsxs(SheetTrigger, { className: "-ml-2 inline-flex h-10 min-w-0 items-center gap-2 rounded-full px-2.5 text-[0.875rem] hover:bg-accent", children: [
1599
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeft, { "aria-hidden": true, className: "size-[1.125rem] shrink-0" }),
1600
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Docs menu. " }),
1601
+ place ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
1602
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
1603
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }),
1604
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: place.page })
1605
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Docs" })
1566
1606
  ] }),
1567
- /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
1568
- items.map(
1569
- (it, i) => it === "separator" ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxRuntime.jsxs(Link5__default.default, { href: it.href, children: [
1570
- it.icon,
1571
- it.label
1572
- ] }) }, it.label) : /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
1573
- it.icon,
1574
- it.label
1575
- ] }, it.label)
1576
- )
1577
- ] })
1607
+ /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "left", className: "w-[min(88vw,22rem)] gap-0 p-0", children: [
1608
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-border px-5 py-4 pr-14", children: /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "text-[1.0625rem] font-medium", children: "Docs" }) }),
1609
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto p-3", children: /* @__PURE__ */ jsxRuntime.jsx(DocsNav, { sections: nav, current: marked, onNavigate: () => setMenu(false) }) })
1610
+ ] })
1611
+ ] }) }) }),
1612
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lg:grid lg:grid-cols-[13.5rem_minmax(0,1fr)] lg:gap-x-10 xl:grid-cols-[13.5rem_minmax(0,1fr)_11rem]", children: [
1613
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto overscroll-contain py-8 pr-1 lg:block", children: /* @__PURE__ */ jsxRuntime.jsx(DocsNav, { sections: nav, current: marked }) }),
1614
+ /* @__PURE__ */ jsxRuntime.jsxs("main", { id: "main-content", className: "min-w-0 pb-16 pt-6 md:pt-8", children: [
1615
+ breadcrumbs ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-6 max-lg:hidden", children: breadcrumbs }) : null,
1616
+ items.length > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group mb-8 rounded-2xl border border-border bg-card xl:hidden", children: [
1617
+ /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex min-h-12 cursor-pointer list-none items-center justify-between px-4 text-[0.9375rem] font-medium [&::-webkit-details-marker]:hidden", children: [
1618
+ "On this page",
1619
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
1620
+ ] }),
1621
+ /* @__PURE__ */ jsxRuntime.jsx(OnThisPage, { items, activeId, title: null, className: "px-4 pb-4" })
1622
+ ] }) : null,
1623
+ /* @__PURE__ */ jsxRuntime.jsx("article", { id: "docs-content", className: "max-w-[46rem]", children: /* @__PURE__ */ jsxRuntime.jsx(InDocsContext.Provider, { value: true, children }) }),
1624
+ pager ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-16 max-w-[46rem]", children: pager }) : null
1625
+ ] }),
1626
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto py-10 xl:block", children: items.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(OnThisPage, { items, activeId }) : null })
1627
+ ] }) }),
1628
+ footer ?? /* @__PURE__ */ jsxRuntime.jsx(OchkIoFooter, {})
1578
1629
  ] });
1579
1630
  }
1580
- function ThemeToggle({ className }) {
1581
- const { theme, setTheme } = nextThemes.useTheme();
1582
- const [mounted, setMounted] = react.useState(false);
1583
- react.useEffect(() => setMounted(true), []);
1584
- const current = mounted ? theme ?? "system" : "system";
1585
- const next = current === "light" ? "dark" : current === "dark" ? "system" : "light";
1586
- const Icon = current === "light" ? lucideReact.Sun : current === "dark" ? lucideReact.Moon : lucideReact.SunMoon;
1587
- return /* @__PURE__ */ jsxRuntime.jsx(
1588
- "button",
1589
- {
1590
- type: "button",
1591
- onClick: () => setTheme(next),
1592
- "aria-label": `Theme: ${current}. Switch to ${next}`,
1593
- title: `Theme: ${current}`,
1594
- className: cn(
1595
- "inline-flex size-10 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
1596
- className
1597
- ),
1598
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-[1.125rem]" })
1599
- }
1600
- );
1601
- }
1602
1631
  var OCHK_APP_ACCOUNT = "https://ochk.app/me/account";
1632
+ function onHistory(change) {
1633
+ window.addEventListener("popstate", change);
1634
+ return () => window.removeEventListener("popstate", change);
1635
+ }
1636
+ function herePath() {
1637
+ const { href, origin, pathname, search } = window.location;
1638
+ const path = pathname + search;
1639
+ return new URL(path, href).origin === origin ? path : "/";
1640
+ }
1641
+ function routePath(router) {
1642
+ if (!router || router.pathname.includes("[")) return null;
1643
+ return router.basePath && router.pathname === "/" ? router.basePath : router.basePath + router.pathname;
1644
+ }
1645
+ function useSignInHref(path) {
1646
+ const router$1 = router.useRouter();
1647
+ const here = react.useSyncExternalStore(onHistory, herePath, () => routePath(router$1));
1648
+ if (!path) return void 0;
1649
+ return here ? `${path}?return_to=${encodeURIComponent(here)}` : path;
1650
+ }
1603
1651
  function SessionAccountView({
1604
1652
  state,
1605
1653
  name,
1606
1654
  detail,
1607
1655
  items = [],
1608
1656
  signInHref,
1657
+ signInPath,
1609
1658
  signInLabel = "Sign in",
1610
1659
  accountHref = OCHK_APP_ACCOUNT,
1611
1660
  onSignOut,
1612
1661
  nameFrom = "lg"
1613
1662
  }) {
1663
+ const inPlace = useSignInHref(signInPath);
1614
1664
  if (state === "in") {
1615
1665
  return /* @__PURE__ */ jsxRuntime.jsx(
1616
1666
  AccountMenu,
@@ -1633,13 +1683,13 @@ function SessionAccountView({
1633
1683
  }
1634
1684
  return (
1635
1685
  // No box of its own: it sits exactly where the signed-in chip will. While checking it is only unseen.
1636
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: state === "checking" ? "contents invisible" : "contents", "aria-hidden": state === "checking" || void 0, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, size: "sm", variant: "secondary", tabIndex: state === "checking" ? -1 : void 0, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: signInHref, children: signInLabel }) }) })
1686
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: state === "checking" ? "contents invisible" : "contents", "aria-hidden": state === "checking" || void 0, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, size: "sm", variant: "secondary", tabIndex: state === "checking" ? -1 : void 0, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: signInHref ?? inPlace ?? "https://ochk.io/signin", children: signInLabel }) }) })
1637
1687
  );
1638
1688
  }
1639
1689
  function ToolShell({
1640
1690
  protocol: protocol2,
1641
1691
  tools,
1642
- home = "/",
1692
+ home,
1643
1693
  account,
1644
1694
  rail = false,
1645
1695
  railFooter,
@@ -1678,7 +1728,7 @@ function ToolShell({
1678
1728
  SiteHeader,
1679
1729
  {
1680
1730
  variant: "tool",
1681
- home,
1731
+ home: home ?? p.pageHref,
1682
1732
  product: p.label,
1683
1733
  family: protocol2,
1684
1734
  nav: tools.map((t) => ({ href: t.href, label: t.label, active: t.active })),
@@ -1721,6 +1771,7 @@ exports.DocsNav = DocsNav;
1721
1771
  exports.DocsShell = DocsShell;
1722
1772
  exports.FamilyMenu = FamilyMenu;
1723
1773
  exports.OCHK_APP_ACCOUNT = OCHK_APP_ACCOUNT;
1774
+ exports.OchkIoFooter = OchkIoFooter;
1724
1775
  exports.SessionAccountView = SessionAccountView;
1725
1776
  exports.ShellContext = ShellContext;
1726
1777
  exports.SignInFrame = SignInFrame;
@@ -1731,5 +1782,6 @@ exports.SkipLink = SkipLink;
1731
1782
  exports.ThemeToggle = ThemeToggle;
1732
1783
  exports.ToolShell = ToolShell;
1733
1784
  exports.useShellPlace = useShellPlace;
1785
+ exports.useSignInHref = useSignInHref;
1734
1786
  //# sourceMappingURL=chrome.js.map
1735
1787
  //# sourceMappingURL=chrome.js.map