@orangecheck/app-design 1.0.0 → 1.1.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 (62) hide show
  1. package/README.md +21 -5
  2. package/dist/chrome.d.mts +31 -42
  3. package/dist/chrome.d.ts +31 -42
  4. package/dist/chrome.js +500 -23
  5. package/dist/chrome.js.map +1 -1
  6. package/dist/chrome.mjs +495 -25
  7. package/dist/chrome.mjs.map +1 -1
  8. package/dist/code.d.mts +52 -0
  9. package/dist/code.d.ts +52 -0
  10. package/dist/code.js +534 -0
  11. package/dist/code.js.map +1 -0
  12. package/dist/code.mjs +522 -0
  13. package/dist/code.mjs.map +1 -0
  14. package/dist/components.d.mts +61 -117
  15. package/dist/components.d.ts +61 -117
  16. package/dist/components.js +2170 -105
  17. package/dist/components.js.map +1 -1
  18. package/dist/components.mjs +2142 -109
  19. package/dist/components.mjs.map +1 -1
  20. package/dist/docs-DhnstueM.d.ts +219 -0
  21. package/dist/docs-DiR6s43s.d.mts +219 -0
  22. package/dist/format.d.mts +12 -0
  23. package/dist/format.d.ts +12 -0
  24. package/dist/format.js +65 -0
  25. package/dist/format.js.map +1 -0
  26. package/dist/format.mjs +58 -0
  27. package/dist/format.mjs.map +1 -0
  28. package/dist/hero-Dn37il-9.d.mts +31 -0
  29. package/dist/hero-Dn37il-9.d.ts +31 -0
  30. package/dist/index.d.mts +10 -3
  31. package/dist/index.d.ts +10 -3
  32. package/dist/index.js +2668 -131
  33. package/dist/index.js.map +1 -1
  34. package/dist/index.mjs +2614 -134
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/mdx.d.mts +58 -0
  37. package/dist/mdx.d.ts +58 -0
  38. package/dist/mdx.js +1712 -0
  39. package/dist/mdx.js.map +1 -0
  40. package/dist/mdx.mjs +1685 -0
  41. package/dist/mdx.mjs.map +1 -0
  42. package/dist/primitives.d.mts +22 -5
  43. package/dist/primitives.d.ts +22 -5
  44. package/dist/primitives.js +51 -5
  45. package/dist/primitives.js.map +1 -1
  46. package/dist/primitives.mjs +51 -7
  47. package/dist/primitives.mjs.map +1 -1
  48. package/dist/session.d.mts +18 -0
  49. package/dist/session.d.ts +18 -0
  50. package/dist/session.js +432 -0
  51. package/dist/session.js.map +1 -0
  52. package/dist/session.mjs +401 -0
  53. package/dist/session.mjs.map +1 -0
  54. package/dist/styles/code.css +97 -0
  55. package/dist/styles/theme.css +2 -0
  56. package/dist/styles/tokens.css +40 -0
  57. package/dist/styles.css +1 -0
  58. package/dist/tool-shell-B1C7ahKE.d.ts +81 -0
  59. package/dist/tool-shell-BDx_N5ai.d.mts +81 -0
  60. package/dist/tools-BggNN5DV.d.ts +131 -0
  61. package/dist/tools-DFIxIj5p.d.mts +131 -0
  62. package/package.json +31 -2
package/dist/chrome.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { X, ChevronDown, Menu, ChevronRight, Sun, Moon, SunMoon } from 'lucide-react';
2
- import Link3 from 'next/link';
3
- import { forwardRef, createContext, useState, useContext, useMemo, useEffect, useId, useRef } from 'react';
1
+ import { X, ChevronDown, Menu, ChevronRight, PanelLeft, Sun, Moon, SunMoon, CircleUser, LogOut, ArrowUpRight } from 'lucide-react';
2
+ import Link5 from 'next/link';
3
+ import { forwardRef, createContext, useState, useContext, useMemo, useEffect, useRef, useId, createElement } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { extendTailwindMerge } from 'tailwind-merge';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -9,6 +9,9 @@ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
9
9
  import * as PopoverPrimitive from '@radix-ui/react-popover';
10
10
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
11
11
  import { cva } from 'class-variance-authority';
12
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
13
+ import 'sonner';
14
+ import { Slot } from '@radix-ui/react-slot';
12
15
  import { useTheme } from 'next-themes';
13
16
 
14
17
  var merge = extendTailwindMerge({
@@ -213,7 +216,10 @@ var FAMILY_GROUPS = [
213
216
  { id: "app", label: "Apps" },
214
217
  { id: "public-good", label: "Public goods" }
215
218
  ];
216
- new Map(FAMILY.map((s) => [s.slug, s]));
219
+ var BY_SLUG = new Map(FAMILY.map((s) => [s.slug, s]));
220
+ function protocolSite(slug) {
221
+ return BY_SLUG.get(slug);
222
+ }
217
223
  function familyByGroup() {
218
224
  return FAMILY_GROUPS.map((g) => ({ ...g, sites: FAMILY.filter((s) => s.group === g.id) }));
219
225
  }
@@ -224,7 +230,7 @@ var LEGAL_LINKS = [
224
230
  { href: `${OCHK_IO}/trademark`, label: "Trademarks" },
225
231
  { href: `${OCHK_IO}/contact`, label: "Contact" }
226
232
  ];
227
- [
233
+ var OCHK_IO_NAV = [
228
234
  {
229
235
  href: `${OCHK_IO}/protocols`,
230
236
  label: "Protocols",
@@ -235,6 +241,16 @@ var LEGAL_LINKS = [
235
241
  { href: `${OCHK_IO}/trust`, label: "Trust" },
236
242
  { href: `${OCHK_IO}/about`, label: "About" }
237
243
  ];
244
+ var OCHK_IO_FOOTER = [
245
+ {
246
+ heading: "Company",
247
+ links: [
248
+ { href: `${OCHK_IO}/about`, label: "About" },
249
+ { href: `${OCHK_IO}/trust`, label: "Trust" },
250
+ { href: "https://github.com/orangecheck", label: "GitHub", external: true }
251
+ ]
252
+ }
253
+ ];
238
254
  var overlayClass = "oca-animate-fade fixed inset-0 z-50 bg-[rgb(10_10_10/0.38)] backdrop-blur-[2px] data-[state=closed]:opacity-0";
239
255
  forwardRef(function DialogContent2({ className, children, hideClose, ...props }, ref) {
240
256
  return /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
@@ -515,16 +531,23 @@ function FamilyMenu({ current, className }) {
515
531
  )
516
532
  ] });
517
533
  }
518
- function NavLink({ item, className, onNavigate }) {
534
+ function NavLink({
535
+ item,
536
+ className,
537
+ onNavigate,
538
+ line = false
539
+ }) {
519
540
  const cls = cn(
520
541
  "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
521
542
  item.active ? "text-foreground" : "text-muted-foreground hover:text-foreground",
543
+ line && "relative after:absolute after:inset-x-3 after:-bottom-[0.625rem] after:h-0.5 after:rounded-full",
544
+ line && item.active && "after:bg-foreground",
522
545
  className
523
546
  );
524
547
  if (item.external) {
525
548
  return /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
526
549
  }
527
- return /* @__PURE__ */ jsx(Link3, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
550
+ return /* @__PURE__ */ jsx(Link5, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
528
551
  }
529
552
  function NavRow({ item, onNavigate }) {
530
553
  const body = /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -535,7 +558,7 @@ function NavRow({ item, onNavigate }) {
535
558
  "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
536
559
  item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
537
560
  );
538
- return item.external ? /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsx(Link3, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
561
+ return item.external ? /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsx(Link5, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
539
562
  }
540
563
  var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
541
564
  function NavDropdown({ item }) {
@@ -577,13 +600,16 @@ function SiteHeader({
577
600
  search,
578
601
  actions,
579
602
  variant = "site",
603
+ navOnPhone = true,
604
+ menu: menuExtra,
580
605
  className
581
606
  }) {
582
607
  const [open, setOpen] = useState(false);
583
608
  const tool = variant === "tool";
584
609
  const size = tool ? 24 : 28;
585
610
  const current = typeof family === "string" ? family : void 0;
586
- const menu = nav.length > 0 || Boolean(family);
611
+ const phoneNav = navOnPhone ? nav : [];
612
+ const menu = phoneNav.length > 0 || Boolean(family) || Boolean(menuExtra);
587
613
  const brandNode = brand ?? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center", children: [
588
614
  /* @__PURE__ */ jsx(Lockup, { size }),
589
615
  product ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -591,7 +617,9 @@ function SiteHeader({
591
617
  /* @__PURE__ */ jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
592
618
  ] }) : null
593
619
  ] });
594
- const navigation = nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map((n) => n.children?.length ? /* @__PURE__ */ jsx(NavDropdown, { item: n }, n.href) : /* @__PURE__ */ jsx(NavLink, { item: n }, n.href)) }) : null;
620
+ const navigation = nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map(
621
+ (n) => n.children?.length ? /* @__PURE__ */ jsx(NavDropdown, { item: n }, n.href) : /* @__PURE__ */ jsx(NavLink, { item: n, line: tool }, n.href)
622
+ ) }) : null;
595
623
  return /* @__PURE__ */ jsx(
596
624
  "header",
597
625
  {
@@ -613,7 +641,7 @@ function SiteHeader({
613
641
  ),
614
642
  children: [
615
643
  /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
616
- /* @__PURE__ */ jsxs(Link3, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
644
+ /* @__PURE__ */ jsxs(Link5, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
617
645
  brandNode,
618
646
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
619
647
  ] }),
@@ -635,7 +663,8 @@ function SiteHeader({
635
663
  ),
636
664
  /* @__PURE__ */ jsxs(SheetContent, { side: "right", className: "pt-16", children: [
637
665
  /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
638
- nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: nav.map(
666
+ menuExtra ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", (phoneNav.length > 0 || family) && "border-b border-border pb-3"), children: menuExtra }) : null,
667
+ phoneNav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: phoneNav.map(
639
668
  (n) => n.children?.length ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col py-2", children: [
640
669
  /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
641
670
  n.children.map((c) => /* @__PURE__ */ jsx(
@@ -657,7 +686,7 @@ function SiteHeader({
657
686
  n.href
658
687
  )
659
688
  ) }) : null,
660
- family ? /* @__PURE__ */ jsxs("details", { className: cn("group", nav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
689
+ family ? /* @__PURE__ */ jsxs("details", { className: cn("group", phoneNav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
661
690
  /* @__PURE__ */ 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: [
662
691
  "All orangecheck sites",
663
692
  /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
@@ -888,12 +917,12 @@ function SignInFrame({
888
917
  children: [
889
918
  /* @__PURE__ */ jsxs("section", { className: "flex flex-col px-4 pb-8 pt-5 sm:px-8 lg:px-14 lg:pt-8", children: [
890
919
  /* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between gap-4", children: [
891
- /* @__PURE__ */ jsxs(Link3, { href: home, className: "w-fit rounded-lg", children: [
920
+ /* @__PURE__ */ jsxs(Link5, { href: home, className: "w-fit rounded-lg", children: [
892
921
  brand ?? /* @__PURE__ */ jsx(Lockup, { size: 28 }),
893
922
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
894
923
  ] }),
895
924
  back === void 0 ? /* @__PURE__ */ jsx(
896
- Link3,
925
+ Link5,
897
926
  {
898
927
  href: home,
899
928
  className: "text-[0.9375rem] text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
@@ -926,15 +955,335 @@ function SignInFrame({
926
955
  }
927
956
  );
928
957
  }
929
- var ShellContext = createContext({});
958
+ function Spinner({ className, label }) {
959
+ return /* @__PURE__ */ jsxs(
960
+ "svg",
961
+ {
962
+ viewBox: "0 0 24 24",
963
+ fill: "none",
964
+ role: label ? "status" : void 0,
965
+ "aria-label": label,
966
+ "aria-hidden": label ? void 0 : true,
967
+ className: cn("size-4 animate-spin", className),
968
+ children: [
969
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeOpacity: "0.2", strokeWidth: "2.5" }),
970
+ /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 0-9-9", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" })
971
+ ]
972
+ }
973
+ );
974
+ }
975
+ forwardRef(function Separator3({ className, orientation = "horizontal", decorative = true, ...props }, ref) {
976
+ return /* @__PURE__ */ jsx(
977
+ SeparatorPrimitive.Root,
978
+ {
979
+ ref,
980
+ decorative,
981
+ orientation,
982
+ className: cn(
983
+ "shrink-0 bg-border",
984
+ orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
985
+ className
986
+ ),
987
+ ...props
988
+ }
989
+ );
990
+ });
991
+ function sharedContext(name, initial) {
992
+ const key = /* @__PURE__ */ Symbol.for(`@orangecheck/app-design/${name}`);
993
+ const store = globalThis;
994
+ return store[key] ?? (store[key] = createContext(initial));
995
+ }
996
+
997
+ // src/lib/density.ts
998
+ var DensityContext = sharedContext("density", "comfortable");
999
+ function DensityProvider({ density, children }) {
1000
+ return createElement(DensityContext.Provider, { value: density }, children);
1001
+ }
1002
+ var ShellContext = sharedContext("shell-place", {});
930
1003
  function useShellPlace() {
931
1004
  return useContext(ShellContext);
932
1005
  }
1006
+ var buttonVariants = cva(
1007
+ [
1008
+ "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-full font-medium",
1009
+ "transition-[background-color,border-color,color,box-shadow,transform] duration-150",
1010
+ "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
1011
+ "active:translate-y-px disabled:pointer-events-none",
1012
+ // Disabled is one look for every variant: a quiet grey pill, never a
1013
+ // faded black or orange slab that reads as broken.
1014
+ "disabled:border disabled:border-border disabled:bg-muted disabled:text-oca-subtle disabled:shadow-none",
1015
+ "[&_svg]:pointer-events-none [&_svg]:size-[1.1em] [&_svg]:shrink-0"
1016
+ ],
1017
+ {
1018
+ variants: {
1019
+ variant: {
1020
+ primary: "bg-primary text-primary-foreground hover:bg-primary/85",
1021
+ secondary: "border border-border bg-secondary text-secondary-foreground hover:border-oca-hairline-strong hover:bg-accent",
1022
+ brand: "bg-brand text-brand-foreground hover:bg-oca-orange-deep",
1023
+ ghost: "text-foreground hover:bg-accent",
1024
+ danger: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
1025
+ link: "h-auto rounded-none px-0 text-foreground underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground",
1026
+ onInk: "bg-white text-oca-ink hover:bg-white/90",
1027
+ onInkOutline: "border border-white/20 text-white hover:bg-white/10"
1028
+ },
1029
+ size: {
1030
+ sm: "h-9 px-4 text-sm",
1031
+ md: "h-11 px-5 text-[0.9375rem]",
1032
+ lg: "h-14 px-7 text-[1.0625rem]",
1033
+ icon: "size-10",
1034
+ "icon-sm": "size-8"
1035
+ }
1036
+ },
1037
+ compoundVariants: [{ variant: "link", className: "h-auto px-0" }],
1038
+ defaultVariants: { variant: "primary", size: "md" }
1039
+ }
1040
+ );
1041
+ var Button = forwardRef(function Button2({ className, variant, size, asChild = false, loading = false, disabled, children, type, ...props }, ref) {
1042
+ const Comp = asChild ? Slot : "button";
1043
+ return /* @__PURE__ */ jsx(
1044
+ Comp,
1045
+ {
1046
+ ref,
1047
+ "data-ui": "button",
1048
+ className: cn(buttonVariants({ variant, size }), className),
1049
+ disabled: asChild ? void 0 : disabled || loading,
1050
+ "aria-busy": loading || void 0,
1051
+ type: asChild ? void 0 : type ?? "button",
1052
+ ...props,
1053
+ children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
1054
+ loading ? /* @__PURE__ */ jsx(Spinner, { className: "size-[1.1em]" }) : null,
1055
+ children
1056
+ ] })
1057
+ }
1058
+ );
1059
+ });
1060
+ function useActiveHeading(ids) {
1061
+ const [active, setActive] = useState(ids[0]);
1062
+ const key = ids.join("|");
1063
+ useEffect(() => {
1064
+ setActive(key.split("|")[0] || void 0);
1065
+ const els = key.split("|").map((id) => document.getElementById(id)).filter((el) => el !== null);
1066
+ if (els.length === 0 || typeof IntersectionObserver === "undefined") return;
1067
+ const io = new IntersectionObserver(
1068
+ (entries) => {
1069
+ const hit = entries.filter((e) => e.isIntersecting).sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)[0];
1070
+ if (hit) setActive(hit.target.id);
1071
+ },
1072
+ { rootMargin: "-80px 0px -65% 0px" }
1073
+ );
1074
+ els.forEach((el) => io.observe(el));
1075
+ return () => io.disconnect();
1076
+ }, [key]);
1077
+ return active;
1078
+ }
1079
+ function useHeadings(selector = "#docs-content", key) {
1080
+ const [items, setItems] = useState([]);
1081
+ useEffect(() => {
1082
+ const read = () => {
1083
+ const root = document.querySelector(selector);
1084
+ if (!root) return setItems([]);
1085
+ setItems(
1086
+ Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
1087
+ id: h.id,
1088
+ // The anchor link's "#" is not part of the name.
1089
+ label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
1090
+ level: h.tagName === "H3" ? 3 : 2
1091
+ }))
1092
+ );
1093
+ };
1094
+ const raf = requestAnimationFrame(read);
1095
+ const t = setTimeout(read, 80);
1096
+ return () => {
1097
+ cancelAnimationFrame(raf);
1098
+ clearTimeout(t);
1099
+ };
1100
+ }, [selector, key]);
1101
+ const activeId = useActiveHeading(items.map((i) => i.id));
1102
+ return { items, activeId };
1103
+ }
1104
+ function OnThisPage({
1105
+ items,
1106
+ activeId,
1107
+ title = "On this page",
1108
+ onNavigate,
1109
+ className
1110
+ }) {
1111
+ const id = useId();
1112
+ if (items.length === 0) return null;
1113
+ return (
1114
+ // With no visible title (a folded list under its own summary) the name is still "On this page".
1115
+ /* @__PURE__ */ jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
1116
+ title ? /* @__PURE__ */ jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
1117
+ /* @__PURE__ */ jsx("ul", { children: items.map((t) => {
1118
+ const on = t.id === activeId;
1119
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
1120
+ "a",
1121
+ {
1122
+ href: `#${t.id}`,
1123
+ onClick: onNavigate,
1124
+ "aria-current": on ? "location" : void 0,
1125
+ className: cn(
1126
+ "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
1127
+ t.level === 3 ? "pl-7" : "pl-4",
1128
+ on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
1129
+ ),
1130
+ children: t.label
1131
+ }
1132
+ ) }, t.id);
1133
+ }) })
1134
+ ] })
1135
+ );
1136
+ }
1137
+ var STATUS_WORDS = /* @__PURE__ */ new Set(["live", "testing", "not-yet", "paused", "good", "caution", "refused"]);
1138
+ var pathOf = (href) => href.split(/[?#]/)[0].replace(/(.)\/$/, "$1");
1139
+ function DocsNav({
1140
+ sections,
1141
+ current,
1142
+ onNavigate,
1143
+ className
1144
+ }) {
1145
+ const here = pathOf(current);
1146
+ const activeSection = useMemo(
1147
+ () => sections.findIndex((s) => s.items.some((i) => pathOf(i.href) === here)),
1148
+ [sections, here]
1149
+ );
1150
+ const [peeked, setPeeked] = useState(() => /* @__PURE__ */ new Set());
1151
+ useEffect(() => setPeeked(/* @__PURE__ */ new Set()), [activeSection]);
1152
+ const activeRef = useRef(null);
1153
+ useEffect(() => {
1154
+ const id = requestAnimationFrame(() => activeRef.current?.scrollIntoView({ block: "nearest" }));
1155
+ return () => cancelAnimationFrame(id);
1156
+ }, [here]);
1157
+ const base = useId();
1158
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Docs", className: cn("flex flex-col gap-0.5", className), children: sections.map((section, si) => {
1159
+ const isActive = si === activeSection;
1160
+ const open = isActive || peeked.has(si);
1161
+ const panel = `${base}-s${si}`;
1162
+ return /* @__PURE__ */ jsxs("div", { children: [
1163
+ /* @__PURE__ */ jsxs(
1164
+ "button",
1165
+ {
1166
+ type: "button",
1167
+ "aria-expanded": open,
1168
+ "aria-controls": panel,
1169
+ onClick: () => {
1170
+ if (isActive) return;
1171
+ setPeeked((p) => {
1172
+ const n = new Set(p);
1173
+ if (n.has(si)) n.delete(si);
1174
+ else n.add(si);
1175
+ return n;
1176
+ });
1177
+ },
1178
+ className: cn(
1179
+ "flex min-h-9 w-full items-center justify-between gap-2 rounded-lg px-2.5 py-1.5 text-left text-[0.875rem] transition-colors",
1180
+ isActive ? "font-medium text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground",
1181
+ isActive && "cursor-default"
1182
+ ),
1183
+ children: [
1184
+ section.label,
1185
+ /* @__PURE__ */ jsx(
1186
+ ChevronRight,
1187
+ {
1188
+ "aria-hidden": true,
1189
+ className: cn("size-3.5 shrink-0 text-oca-subtle transition-transform duration-200", open && "rotate-90")
1190
+ }
1191
+ )
1192
+ ]
1193
+ }
1194
+ ),
1195
+ /* @__PURE__ */ jsx("ul", { id: panel, hidden: !open, className: "mb-2 ml-2.5 mt-0.5 border-l border-border", children: section.items.map((item) => {
1196
+ const on = pathOf(item.href) === here;
1197
+ const badge = typeof item.badge === "string" && STATUS_WORDS.has(item.badge) ? /* @__PURE__ */ jsx(StatusBadge, { status: item.badge }) : item.badge ? /* @__PURE__ */ jsx(Badge, { tone: "muted", children: item.badge }) : null;
1198
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
1199
+ Link5,
1200
+ {
1201
+ href: item.href,
1202
+ ref: on ? activeRef : void 0,
1203
+ onClick: onNavigate,
1204
+ "aria-current": on ? "page" : void 0,
1205
+ className: cn(
1206
+ "-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",
1207
+ on ? "border-foreground font-medium text-foreground" : "border-transparent text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
1208
+ ),
1209
+ children: [
1210
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1", children: item.label }),
1211
+ badge
1212
+ ]
1213
+ }
1214
+ ) }, item.href);
1215
+ }) })
1216
+ ] }, section.label);
1217
+ }) });
1218
+ }
1219
+ var DOCS_HEADER_NAV = OCHK_IO_NAV.map((n) => n.href === DOCS_HREF ? { ...n, active: true } : n);
1220
+ function DocsShell({
1221
+ nav,
1222
+ current,
1223
+ header,
1224
+ search,
1225
+ actions,
1226
+ breadcrumbs,
1227
+ toc,
1228
+ pager,
1229
+ footer,
1230
+ children
1231
+ }) {
1232
+ const [menu, setMenu] = useState(false);
1233
+ useEffect(() => setMenu(false), [current]);
1234
+ const read = useHeadings("#docs-content", current);
1235
+ const items = toc ?? read.items;
1236
+ const activeId = toc ? void 0 : read.activeId;
1237
+ const here = pathOf(current);
1238
+ const place = useMemo(() => {
1239
+ for (const s of nav) {
1240
+ const it = s.items.find((i) => pathOf(i.href) === here);
1241
+ if (it) return { section: s.label, page: it.label };
1242
+ }
1243
+ return null;
1244
+ }, [nav, here]);
1245
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-dvh flex-col bg-background", children: [
1246
+ /* @__PURE__ */ jsx(SkipLink, {}),
1247
+ header ?? /* @__PURE__ */ jsx(SiteHeader, { home: OCHK_IO, family: "docs", nav: DOCS_HEADER_NAV, search, actions }),
1248
+ /* @__PURE__ */ 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__ */ jsx("div", { className: "oca-container flex h-12 items-center gap-2", children: /* @__PURE__ */ jsxs(Sheet, { open: menu, onOpenChange: setMenu, children: [
1249
+ /* @__PURE__ */ 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: [
1250
+ /* @__PURE__ */ jsx(PanelLeft, { "aria-hidden": true, className: "size-[1.125rem] shrink-0" }),
1251
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Docs menu. " }),
1252
+ place ? /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
1253
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
1254
+ /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }),
1255
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: place.page })
1256
+ ] }) : /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Docs" })
1257
+ ] }),
1258
+ /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "w-[min(88vw,22rem)] gap-0 p-0", children: [
1259
+ /* @__PURE__ */ jsx("div", { className: "border-b border-border px-5 py-4 pr-14", children: /* @__PURE__ */ jsx(SheetTitle, { className: "text-[1.0625rem] font-medium", children: "Docs" }) }),
1260
+ /* @__PURE__ */ jsx("div", { className: "overflow-y-auto p-3", children: /* @__PURE__ */ jsx(DocsNav, { sections: nav, current, onNavigate: () => setMenu(false) }) })
1261
+ ] })
1262
+ ] }) }) }),
1263
+ /* @__PURE__ */ jsx("div", { className: "oca-container flex-1", children: /* @__PURE__ */ 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: [
1264
+ /* @__PURE__ */ 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__ */ jsx(DocsNav, { sections: nav, current }) }),
1265
+ /* @__PURE__ */ jsxs("main", { id: "main-content", className: "min-w-0 pb-16 pt-6 md:pt-8", children: [
1266
+ breadcrumbs ? /* @__PURE__ */ jsx("div", { className: "mb-6 max-lg:hidden", children: breadcrumbs }) : null,
1267
+ items.length > 1 ? /* @__PURE__ */ jsxs("details", { className: "group mb-8 rounded-2xl border border-border bg-card xl:hidden", children: [
1268
+ /* @__PURE__ */ 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: [
1269
+ "On this page",
1270
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
1271
+ ] }),
1272
+ /* @__PURE__ */ jsx(OnThisPage, { items, activeId, title: null, className: "px-4 pb-4" })
1273
+ ] }) : null,
1274
+ /* @__PURE__ */ jsx("article", { id: "docs-content", className: "max-w-[46rem]", children }),
1275
+ pager ? /* @__PURE__ */ jsx("div", { className: "mt-16 max-w-[46rem]", children: pager }) : null
1276
+ ] }),
1277
+ /* @__PURE__ */ 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__ */ jsx(OnThisPage, { items, activeId }) : null })
1278
+ ] }) }),
1279
+ footer ?? /* @__PURE__ */ jsx(SiteFooter, { columns: OCHK_IO_FOOTER, family: true, legal: true, signature: false })
1280
+ ] });
1281
+ }
933
1282
  function SideNav({ groups, onNavigate }) {
934
1283
  return /* @__PURE__ */ jsx("nav", { "aria-label": "Pages", className: "flex flex-col gap-5", children: groups.map((g, gi) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
935
1284
  g.label ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
936
1285
  g.items.map((it) => /* @__PURE__ */ jsxs(
937
- Link3,
1286
+ Link5,
938
1287
  {
939
1288
  href: it.href,
940
1289
  onClick: onNavigate,
@@ -969,7 +1318,7 @@ function SectionSwitch({
969
1318
  children: sections.map((sec) => {
970
1319
  const on = sec.id === current.id;
971
1320
  return /* @__PURE__ */ jsx(
972
- Link3,
1321
+ Link5,
973
1322
  {
974
1323
  href: sec.href,
975
1324
  onClick: onNavigate,
@@ -999,7 +1348,7 @@ function TabBar({ items }) {
999
1348
  className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
1000
1349
  style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
1001
1350
  children: items.map((it) => /* @__PURE__ */ jsxs(
1002
- Link3,
1351
+ Link5,
1003
1352
  {
1004
1353
  href: it.href,
1005
1354
  "aria-current": it.active ? "page" : void 0,
@@ -1108,7 +1457,7 @@ function AppShell({
1108
1457
  footer ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
1109
1458
  ] })
1110
1459
  ] }),
1111
- /* @__PURE__ */ jsx(Link3, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
1460
+ /* @__PURE__ */ jsx(Link5, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
1112
1461
  /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: account })
1113
1462
  ] }),
1114
1463
  place.page ? /* @__PURE__ */ jsxs(
@@ -1131,7 +1480,7 @@ function AppShell({
1131
1480
  ] }),
1132
1481
  /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
1133
1482
  /* @__PURE__ */ 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: [
1134
- /* @__PURE__ */ jsx(Link3, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
1483
+ /* @__PURE__ */ jsx(Link5, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
1135
1484
  switcher,
1136
1485
  /* @__PURE__ */ jsx(SideNav, { groups }),
1137
1486
  /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
@@ -1162,9 +1511,16 @@ function AccountMenu({
1162
1511
  "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",
1163
1512
  nameFrom === "lg" ? "lg:pr-3.5" : "sm:pr-3.5"
1164
1513
  ),
1165
- "aria-label": `Account: ${name}`,
1514
+ "aria-label": `${name}, account menu`,
1166
1515
  children: [
1167
- /* @__PURE__ */ jsx("span", { className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background", children: initial }),
1516
+ /* @__PURE__ */ jsx(
1517
+ "span",
1518
+ {
1519
+ "aria-hidden": true,
1520
+ "data-initial": initial,
1521
+ className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background before:content-[attr(data-initial)]"
1522
+ }
1523
+ ),
1168
1524
  /* @__PURE__ */ jsx("span", { className: cn("max-w-[10rem] truncate", nameFrom === "lg" ? "max-lg:hidden" : "max-sm:hidden"), children: name })
1169
1525
  ]
1170
1526
  }
@@ -1176,7 +1532,7 @@ function AccountMenu({
1176
1532
  ] }),
1177
1533
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
1178
1534
  items.map(
1179
- (it, i) => it === "separator" ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxs(Link3, { href: it.href, children: [
1535
+ (it, i) => it === "separator" ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxs(Link5, { href: it.href, children: [
1180
1536
  it.icon,
1181
1537
  it.label
1182
1538
  ] }) }, it.label) : /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
@@ -1209,7 +1565,121 @@ function ThemeToggle({ className }) {
1209
1565
  }
1210
1566
  );
1211
1567
  }
1568
+ var OCHK_APP_ACCOUNT = "https://ochk.app/me/account";
1569
+ function SessionAccountView({
1570
+ state,
1571
+ name,
1572
+ detail,
1573
+ items = [],
1574
+ signInHref,
1575
+ signInLabel = "Sign in",
1576
+ accountHref = OCHK_APP_ACCOUNT,
1577
+ onSignOut,
1578
+ nameFrom = "lg"
1579
+ }) {
1580
+ if (state === "in") {
1581
+ return /* @__PURE__ */ jsx(
1582
+ AccountMenu,
1583
+ {
1584
+ name: name || "Your account",
1585
+ detail,
1586
+ nameFrom,
1587
+ items: [
1588
+ ...items,
1589
+ ...items.length > 0 ? ["separator"] : [],
1590
+ { label: "Your account", href: accountHref, icon: /* @__PURE__ */ jsx(CircleUser, {}) },
1591
+ "separator",
1592
+ { label: "Sign out", onSelect: onSignOut, icon: /* @__PURE__ */ jsx(LogOut, {}) }
1593
+ ]
1594
+ }
1595
+ );
1596
+ }
1597
+ if (state === "unknown") {
1598
+ return /* @__PURE__ */ jsx(Button, { asChild: true, size: "sm", variant: "secondary", children: /* @__PURE__ */ jsx("a", { href: accountHref, children: "Your account" }) });
1599
+ }
1600
+ return (
1601
+ // No box of its own: it sits exactly where the signed-in chip will. While checking it is only unseen.
1602
+ /* @__PURE__ */ jsx("span", { className: state === "checking" ? "contents invisible" : "contents", "aria-hidden": state === "checking" || void 0, children: /* @__PURE__ */ jsx(Button, { asChild: true, size: "sm", variant: "secondary", tabIndex: state === "checking" ? -1 : void 0, children: /* @__PURE__ */ jsx("a", { href: signInHref, children: signInLabel }) }) })
1603
+ );
1604
+ }
1605
+ function ToolShell({
1606
+ protocol: protocol2,
1607
+ tools,
1608
+ home = "/",
1609
+ account,
1610
+ rail = false,
1611
+ railFooter,
1612
+ variant = "tool",
1613
+ banner,
1614
+ footer,
1615
+ children
1616
+ }) {
1617
+ const p = protocolSite(protocol2);
1618
+ const app = variant === "app";
1619
+ const tabs = app ? null : tabsFor([{ items: [...tools] }]);
1620
+ const about = /* @__PURE__ */ jsxs(
1621
+ "a",
1622
+ {
1623
+ href: p.pageHref,
1624
+ className: "inline-flex items-center gap-1 rounded-full px-3 py-2 text-[0.9375rem] text-muted-foreground transition-colors hover:text-foreground",
1625
+ children: [
1626
+ "About ",
1627
+ p.label,
1628
+ /* @__PURE__ */ jsx(ArrowUpRight, { "aria-hidden": true, className: "size-3.5" })
1629
+ ]
1630
+ }
1631
+ );
1632
+ return /* @__PURE__ */ jsx(DensityProvider, { density: "compact", children: /* @__PURE__ */ jsxs(
1633
+ "div",
1634
+ {
1635
+ className: cn(
1636
+ "flex flex-col bg-background",
1637
+ app ? "h-dvh overflow-hidden" : "min-h-dvh",
1638
+ tabs && "max-md:pb-[calc(3.5rem_+_env(safe-area-inset-bottom))]"
1639
+ ),
1640
+ children: [
1641
+ /* @__PURE__ */ jsx(SkipLink, {}),
1642
+ banner,
1643
+ /* @__PURE__ */ jsx(
1644
+ SiteHeader,
1645
+ {
1646
+ variant: "tool",
1647
+ home,
1648
+ product: p.label,
1649
+ family: protocol2,
1650
+ nav: tools.map((t) => ({ href: t.href, label: t.label, active: t.active })),
1651
+ navOnPhone: !tabs,
1652
+ menu: /* @__PURE__ */ jsx("div", { className: "[&>a]:px-3 [&>a]:py-3 [&>a]:text-[1.0625rem]", children: about }),
1653
+ className: cn(rail && "lg:[&_nav[aria-label=Main]]:hidden"),
1654
+ actions: /* @__PURE__ */ jsxs(Fragment, { children: [
1655
+ /* @__PURE__ */ jsx("span", { className: "hidden lg:contents", children: about }),
1656
+ p.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: p.status, className: "max-sm:hidden" }) : null,
1657
+ /* @__PURE__ */ jsx(ThemeToggle, { className: "max-sm:hidden" }),
1658
+ account
1659
+ ] })
1660
+ }
1661
+ ),
1662
+ /* @__PURE__ */ jsxs("div", { className: cn("mx-auto flex w-full", app ? "min-h-0 flex-1" : "max-w-[90rem] flex-1"), children: [
1663
+ rail ? /* @__PURE__ */ jsxs("aside", { className: "sticky top-14 hidden h-[calc(100dvh-3.5rem)] w-60 shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
1664
+ /* @__PURE__ */ jsx(SideNav, { groups: [{ label: "Tools", items: tools.map(({ href, label, icon, active }) => ({ href, label, icon, active })) }] }),
1665
+ railFooter ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-0.5 px-3 text-[0.875rem] text-muted-foreground [&_a:hover]:text-foreground [&_a]:py-1.5 [&_a]:transition-colors", children: railFooter }) : null
1666
+ ] }) : null,
1667
+ /* @__PURE__ */ jsx(
1668
+ "main",
1669
+ {
1670
+ id: "main-content",
1671
+ className: cn("min-w-0 flex-1", app ? "flex min-h-0 flex-col" : "px-4 pb-16 pt-8 md:px-8 md:pt-10"),
1672
+ children: app ? children : /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[72rem]", children })
1673
+ }
1674
+ )
1675
+ ] }),
1676
+ app || footer === false ? null : footer ?? /* @__PURE__ */ jsx(SiteFooter, { compact: true, family: true, legal: true }),
1677
+ tabs ? /* @__PURE__ */ jsx(TabBar, { items: tabs }) : null
1678
+ ]
1679
+ }
1680
+ ) });
1681
+ }
1212
1682
 
1213
- export { AccountMenu, AppShell, FamilyMenu, ShellContext, SignInFrame, SiteBanner, SiteFooter, SiteHeader, SkipLink, ThemeToggle, useShellPlace };
1683
+ export { AccountMenu, AppShell, DOCS_HEADER_NAV, DocsNav, DocsShell, FamilyMenu, OCHK_APP_ACCOUNT, SessionAccountView, ShellContext, SignInFrame, SiteBanner, SiteFooter, SiteHeader, SkipLink, ThemeToggle, ToolShell, useShellPlace };
1214
1684
  //# sourceMappingURL=chrome.mjs.map
1215
1685
  //# sourceMappingURL=chrome.mjs.map