@orangecheck/app-design 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) 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 +502 -24
  5. package/dist/chrome.js.map +1 -1
  6. package/dist/chrome.mjs +497 -26
  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 +2178 -106
  17. package/dist/components.js.map +1 -1
  18. package/dist/components.mjs +2150 -110
  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/family.js +2 -1
  23. package/dist/family.js.map +1 -1
  24. package/dist/family.mjs +2 -1
  25. package/dist/family.mjs.map +1 -1
  26. package/dist/format.d.mts +12 -0
  27. package/dist/format.d.ts +12 -0
  28. package/dist/format.js +65 -0
  29. package/dist/format.js.map +1 -0
  30. package/dist/format.mjs +58 -0
  31. package/dist/format.mjs.map +1 -0
  32. package/dist/hero-Dn37il-9.d.mts +31 -0
  33. package/dist/hero-Dn37il-9.d.ts +31 -0
  34. package/dist/index.d.mts +10 -3
  35. package/dist/index.d.ts +10 -3
  36. package/dist/index.js +2675 -131
  37. package/dist/index.js.map +1 -1
  38. package/dist/index.mjs +2621 -134
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/mdx.d.mts +58 -0
  41. package/dist/mdx.d.ts +58 -0
  42. package/dist/mdx.js +1719 -0
  43. package/dist/mdx.js.map +1 -0
  44. package/dist/mdx.mjs +1692 -0
  45. package/dist/mdx.mjs.map +1 -0
  46. package/dist/primitives.d.mts +22 -5
  47. package/dist/primitives.d.ts +22 -5
  48. package/dist/primitives.js +51 -5
  49. package/dist/primitives.js.map +1 -1
  50. package/dist/primitives.mjs +51 -7
  51. package/dist/primitives.mjs.map +1 -1
  52. package/dist/session.d.mts +18 -0
  53. package/dist/session.d.ts +18 -0
  54. package/dist/session.js +432 -0
  55. package/dist/session.js.map +1 -0
  56. package/dist/session.mjs +401 -0
  57. package/dist/session.mjs.map +1 -0
  58. package/dist/styles/code.css +97 -0
  59. package/dist/styles/theme.css +2 -0
  60. package/dist/styles/tokens.css +40 -0
  61. package/dist/styles.css +1 -0
  62. package/dist/tool-shell-B1C7ahKE.d.ts +81 -0
  63. package/dist/tool-shell-BDx_N5ai.d.mts +81 -0
  64. package/dist/tools-BggNN5DV.d.ts +131 -0
  65. package/dist/tools-DFIxIj5p.d.mts +131 -0
  66. package/package.json +31 -2
@@ -1,9 +1,10 @@
1
- import { forwardRef, createContext, createElement, useRef, useState, useEffect, useContext, Children, isValidElement, cloneElement, useCallback, Component, useId, Fragment as Fragment$1 } from 'react';
1
+ import { forwardRef, createContext, useContext, useState, useEffect, createElement, useRef, Children, isValidElement, cloneElement, useCallback, useMemo, Component, useId, useSyncExternalStore, Fragment as Fragment$1 } from 'react';
2
2
  import { clsx } from 'clsx';
3
3
  import { extendTailwindMerge } from 'tailwind-merge';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import { cva } from 'class-variance-authority';
6
- import { ChevronDown, Check, Copy, ArrowUpRight, CircleDashed, CircleMinus, Clock, CircleX, CircleCheck } from 'lucide-react';
6
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
7
+ import { ChevronDown, Check, Search, Copy, ArrowUpRight, ArrowRight, ChevronRight, CornerDownLeft, Download, FileText, Upload, ArrowLeft, Lock, CircleDashed, CircleMinus, Clock, CircleX, CircleCheck } from 'lucide-react';
7
8
  import { Slot } from '@radix-ui/react-slot';
8
9
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
9
10
  import 'sonner';
@@ -13,6 +14,7 @@ import * as LabelPrimitive from '@radix-ui/react-label';
13
14
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
14
15
  import * as SelectPrimitive from '@radix-ui/react-select';
15
16
  import * as SwitchPrimitive from '@radix-ui/react-switch';
17
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
16
18
 
17
19
  var merge = extendTailwindMerge({
18
20
  extend: {
@@ -276,6 +278,7 @@ function useActiveHeading(ids) {
276
278
  const [active, setActive] = useState(ids[0]);
277
279
  const key = ids.join("|");
278
280
  useEffect(() => {
281
+ setActive(key.split("|")[0] || void 0);
279
282
  const els = key.split("|").map((id) => document.getElementById(id)).filter((el) => el !== null);
280
283
  if (els.length === 0 || typeof IntersectionObserver === "undefined") return;
281
284
  const io = new IntersectionObserver(
@@ -425,6 +428,487 @@ function StepGrid({ items, look = "cards", className }) {
425
428
  ] }) }, i)
426
429
  ) });
427
430
  }
431
+ var KIND = {
432
+ package: "text-oca-code-package",
433
+ tag: "text-oca-code-tag",
434
+ link: "text-oca-code-link"
435
+ };
436
+ function PackageCard({ items, className }) {
437
+ return /* @__PURE__ */ jsx(
438
+ "div",
439
+ {
440
+ className: cn(
441
+ "grid gap-x-10 gap-y-7 rounded-[1.25rem] border border-oca-ink-line bg-oca-ink-card p-6 text-oca-ink-foreground md:grid-cols-2 md:p-9",
442
+ className
443
+ ),
444
+ children: items.map((it, i) => {
445
+ const code = /* @__PURE__ */ jsx("span", { className: cn("text-[0.9375rem]", KIND[it.kind ?? "package"]), children: it.code });
446
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
447
+ /* @__PURE__ */ jsx("h3", { className: "text-[1.125rem] font-semibold tracking-[-0.01em] text-oca-ink-title", children: it.title }),
448
+ it.href ? /* @__PURE__ */ jsx("a", { href: it.href, className: "w-fit underline decoration-transparent underline-offset-4 hover:decoration-current", children: code }) : code,
449
+ it.note ? /* @__PURE__ */ jsxs("p", { className: "text-[0.9375rem] leading-relaxed text-oca-ink-subtle", children: [
450
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "// " }),
451
+ it.note
452
+ ] }) : null
453
+ ] }, i);
454
+ })
455
+ }
456
+ );
457
+ }
458
+
459
+ // src/code/highlight.ts
460
+ var TOKEN_CLASS = {
461
+ keyword: "oca-k",
462
+ string: "oca-s",
463
+ number: "oca-n",
464
+ function: "oca-f",
465
+ type: "oca-y",
466
+ property: "oca-p",
467
+ comment: "oca-c",
468
+ tag: "oca-g",
469
+ url: "oca-u"
470
+ };
471
+ var ALIASES = {
472
+ ts: "js",
473
+ typescript: "js",
474
+ tsx: "js",
475
+ js: "js",
476
+ javascript: "js",
477
+ jsx: "js",
478
+ mjs: "js",
479
+ cjs: "js",
480
+ json: "json",
481
+ jsonc: "json",
482
+ json5: "json",
483
+ bash: "shell",
484
+ sh: "shell",
485
+ shell: "shell",
486
+ zsh: "shell",
487
+ console: "shell",
488
+ terminal: "shell",
489
+ py: "python",
490
+ python: "python",
491
+ yaml: "yaml",
492
+ yml: "yaml",
493
+ diff: "diff"
494
+ };
495
+ function grammarOf(lang) {
496
+ return lang && ALIASES[lang.toLowerCase()] || "plain";
497
+ }
498
+ function collector() {
499
+ const tokens = [];
500
+ const emit = (text, kind) => {
501
+ if (!text) return;
502
+ const last = tokens[tokens.length - 1];
503
+ if (last && last.kind === kind) last.text += text;
504
+ else tokens.push(kind ? { text, kind } : { text });
505
+ };
506
+ return { emit, tokens };
507
+ }
508
+ function at(re, src, i) {
509
+ re.lastIndex = i;
510
+ const m = re.exec(src);
511
+ return m ? m[0] : null;
512
+ }
513
+ var WS = /[ \t]+/y;
514
+ var NEWLINE = /\r?\n/y;
515
+ var JS_KEYWORDS = new Set(
516
+ "abstract as async await break case catch class const continue debugger declare default delete do else enum export extends finally for from function get if implements import in infer instanceof interface is keyof let module namespace new of override private protected public readonly return satisfies set static super switch this throw try type typeof unique var void while with yield".split(" ")
517
+ );
518
+ var JS_CONSTANTS = /* @__PURE__ */ new Set(["true", "false", "null", "undefined", "NaN", "Infinity"]);
519
+ var TS_PRIMITIVES = /* @__PURE__ */ new Set(["string", "number", "boolean", "bigint", "symbol", "object", "unknown", "any", "never"]);
520
+ var isConstant = (m) => /^[A-Z][A-Z\d_]+$/.test(m) && (m.includes("_") || m.length > 4);
521
+ var JS_LINE_COMMENT = /\/\/[^\n]*/y;
522
+ var JS_BLOCK_COMMENT = /\/\*[\s\S]*?(?:\*\/|$)/y;
523
+ var JS_TEMPLATE = /`(?:\\[\s\S]|[^\\`])*`?/y;
524
+ var JS_STRING = /'(?:\\.|[^\\'\n])*'?|"(?:\\.|[^\\"\n])*"?/y;
525
+ var JS_NUMBER = /(?:0[xX][\da-fA-F_]+|0[bB][01_]+|0[oO][0-7_]+|\d[\d_]*(?:\.[\d_]+)?(?:[eE][+-]?\d+)?|\.\d[\d_]*(?:[eE][+-]?\d+)?)n?/y;
526
+ var JS_IDENT = /[A-Za-z_$][\w$]*/y;
527
+ var JS_DECORATOR = /@[A-Za-z_$][\w$.]*/y;
528
+ var JS_CALL_AFTER = /\s*(?:<[\w$\s,.[\]|&'"]*>)?\s*\(/y;
529
+ var JS_TAG = /<\/?(?=[A-Za-z])/y;
530
+ var JS_TAG_NAME = /[A-Za-z][\w$.:-]*/y;
531
+ var JS_PUNCT = /=>|\.\.\.|[{}()[\];,.<>=+\-*/%!?:&|^~#]/y;
532
+ var JSX_BEFORE = /* @__PURE__ */ new Set(["(", ",", "=", "?", ":", "{", "[", ";", ">", "&&", "||", "=>", "return"]);
533
+ function scanJs(src, emit, jsx35) {
534
+ let i = 0;
535
+ let prev = "";
536
+ let tagDepth = 0;
537
+ let braceInTag = 0;
538
+ const sig = (t) => {
539
+ prev = t;
540
+ };
541
+ while (i < src.length) {
542
+ let m;
543
+ if ((m = at(WS, src, i)) || (m = at(NEWLINE, src, i))) {
544
+ emit(m);
545
+ i += m.length;
546
+ continue;
547
+ }
548
+ if ((m = at(JS_LINE_COMMENT, src, i)) || (m = at(JS_BLOCK_COMMENT, src, i))) {
549
+ emit(m, "comment");
550
+ i += m.length;
551
+ continue;
552
+ }
553
+ if ((m = at(JS_TEMPLATE, src, i)) || (m = at(JS_STRING, src, i))) {
554
+ emit(m, "string");
555
+ i += m.length;
556
+ sig('"');
557
+ continue;
558
+ }
559
+ if (jsx35 && tagDepth === 0 && (m = at(JS_TAG, src, i)) && (prev === "" || JSX_BEFORE.has(prev))) {
560
+ const name = at(JS_TAG_NAME, src, i + m.length);
561
+ if (name) {
562
+ emit(m);
563
+ emit(name, "tag");
564
+ i += m.length + name.length;
565
+ tagDepth = 1;
566
+ braceInTag = 0;
567
+ sig("tag");
568
+ continue;
569
+ }
570
+ }
571
+ if (jsx35 && tagDepth > 0 && braceInTag === 0) {
572
+ if (src.startsWith("/>", i) || src[i] === ">") {
573
+ const close = src[i] === ">" ? ">" : "/>";
574
+ emit(close);
575
+ i += close.length;
576
+ tagDepth = 0;
577
+ sig(">");
578
+ continue;
579
+ }
580
+ if ((m = at(JS_IDENT, src, i)) && /^\s*=/.test(src.slice(i + m.length, i + m.length + 4))) {
581
+ emit(m, "property");
582
+ i += m.length;
583
+ continue;
584
+ }
585
+ if (m = at(JS_IDENT, src, i)) {
586
+ emit(m, "property");
587
+ i += m.length;
588
+ continue;
589
+ }
590
+ if (src[i] === "{") braceInTag = 1;
591
+ } else if (jsx35 && tagDepth > 0 && braceInTag > 0) {
592
+ if (src[i] === "{") braceInTag++;
593
+ else if (src[i] === "}") braceInTag--;
594
+ }
595
+ if (m = at(JS_DECORATOR, src, i)) {
596
+ emit(m, "function");
597
+ i += m.length;
598
+ sig("@");
599
+ continue;
600
+ }
601
+ if (m = at(JS_IDENT, src, i)) {
602
+ const end = i + m.length;
603
+ let kind;
604
+ if (prev !== "." && JS_CONSTANTS.has(m)) kind = "number";
605
+ else if (prev !== "." && JS_KEYWORDS.has(m)) kind = "keyword";
606
+ else if (at(JS_CALL_AFTER, src, end) !== null) kind = "function";
607
+ else if (prev !== "." && TS_PRIMITIVES.has(m)) kind = "type";
608
+ else if (isConstant(m)) kind = "number";
609
+ else if (/^[A-Z]/.test(m)) kind = "type";
610
+ emit(m, kind);
611
+ i = end;
612
+ sig(kind === "keyword" ? m : "id");
613
+ continue;
614
+ }
615
+ if (m = at(JS_NUMBER, src, i)) {
616
+ emit(m, "number");
617
+ i += m.length;
618
+ sig("0");
619
+ continue;
620
+ }
621
+ if (m = at(JS_PUNCT, src, i)) {
622
+ emit(m);
623
+ i += m.length;
624
+ sig(m === "." ? "." : m);
625
+ continue;
626
+ }
627
+ emit(src[i]);
628
+ i++;
629
+ }
630
+ }
631
+ var JSON_STRING = /"(?:\\.|[^\\"\n])*"?/y;
632
+ var JSON_KEY_AFTER = /\s*:/y;
633
+ var JSON_NUMBER = /-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/y;
634
+ var JSON_WORD = /true|false|null/y;
635
+ function scanJson(src, emit) {
636
+ let i = 0;
637
+ while (i < src.length) {
638
+ let m;
639
+ if ((m = at(JS_LINE_COMMENT, src, i)) || (m = at(JS_BLOCK_COMMENT, src, i))) {
640
+ emit(m, "comment");
641
+ } else if (m = at(JSON_STRING, src, i)) {
642
+ emit(m, at(JSON_KEY_AFTER, src, i + m.length) !== null ? "property" : "string");
643
+ } else if ((m = at(JSON_NUMBER, src, i)) || (m = at(JSON_WORD, src, i))) {
644
+ emit(m, "number");
645
+ } else {
646
+ m = src[i];
647
+ emit(m);
648
+ }
649
+ i += m.length;
650
+ }
651
+ }
652
+ var SH_KEYWORDS = new Set(
653
+ "if then else elif fi for in do done case esac while until function return export local select time".split(" ")
654
+ );
655
+ var SH_PROMPT = /\$ (?=\S)/y;
656
+ var SH_COMMENT = /#[^\n]*/y;
657
+ var SH_SINGLE = /'[^']*'?/y;
658
+ var SH_DOUBLE = /"(?:\\.|[^\\"])*"?/y;
659
+ var SH_VAR = /\$(?:\{[^}\n]*\}?|[A-Za-z_][\w]*|[@*#?$!\d])/y;
660
+ var SH_URL = /https?:\/\/[^\s'"`)]+/y;
661
+ var SH_FLAG = /--?[A-Za-z][\w-]*/y;
662
+ var SH_ASSIGN = /[A-Za-z_][\w]*(?==)/y;
663
+ var SH_VALUE = /=[^\s|&;()<>'"`$]*/y;
664
+ var SH_WORD = /[^\s|&;()<>'"`$#]+/y;
665
+ var SH_OPERATOR = /\|\||&&|[|;&]|\$\(|[()<>]/y;
666
+ function scanShell(src, emit) {
667
+ let i = 0;
668
+ let command = true;
669
+ let lineStart = true;
670
+ while (i < src.length) {
671
+ let m;
672
+ if (m = at(NEWLINE, src, i)) {
673
+ emit(m);
674
+ i += m.length;
675
+ command = !/\\\s*$/.test(src.slice(0, i - m.length));
676
+ lineStart = true;
677
+ continue;
678
+ }
679
+ if (m = at(WS, src, i)) {
680
+ emit(m);
681
+ i += m.length;
682
+ continue;
683
+ }
684
+ if (lineStart && (m = at(SH_PROMPT, src, i))) {
685
+ emit(m, "comment");
686
+ i += m.length;
687
+ lineStart = false;
688
+ continue;
689
+ }
690
+ lineStart = false;
691
+ if ((m = at(SH_COMMENT, src, i)) && (i === 0 || /\s/.test(src[i - 1]))) {
692
+ emit(m, "comment");
693
+ i += m.length;
694
+ continue;
695
+ }
696
+ if ((m = at(SH_SINGLE, src, i)) || (m = at(SH_DOUBLE, src, i))) {
697
+ emit(m, "string");
698
+ i += m.length;
699
+ command = false;
700
+ continue;
701
+ }
702
+ if (m = at(SH_OPERATOR, src, i)) {
703
+ emit(m);
704
+ i += m.length;
705
+ command = m !== ")" && m !== ">" && m !== "<";
706
+ continue;
707
+ }
708
+ if (m = at(SH_VAR, src, i)) {
709
+ emit(m, "type");
710
+ i += m.length;
711
+ command = false;
712
+ continue;
713
+ }
714
+ if (m = at(SH_URL, src, i)) {
715
+ emit(m, "url");
716
+ i += m.length;
717
+ command = false;
718
+ continue;
719
+ }
720
+ if (command && (m = at(SH_ASSIGN, src, i))) {
721
+ emit(m, "property");
722
+ i += m.length;
723
+ const v = at(SH_VALUE, src, i);
724
+ emit(v);
725
+ i += v.length;
726
+ continue;
727
+ }
728
+ if ((m = at(SH_FLAG, src, i)) && !command) {
729
+ emit(m, "keyword");
730
+ i += m.length;
731
+ continue;
732
+ }
733
+ if (m = at(SH_WORD, src, i)) {
734
+ if (command && SH_KEYWORDS.has(m)) emit(m, "keyword");
735
+ else if (command) {
736
+ emit(m, "function");
737
+ command = m === "sudo" || m === "npx" || m === "env" || m === "time";
738
+ i += m.length;
739
+ continue;
740
+ } else emit(m);
741
+ i += m.length;
742
+ continue;
743
+ }
744
+ emit(src[i]);
745
+ i++;
746
+ }
747
+ }
748
+ var PY_KEYWORDS = new Set(
749
+ "and as assert async await break class continue def del elif else except finally for from global if import in is lambda match case nonlocal not or pass raise return try while with yield self cls".split(" ")
750
+ );
751
+ var PY_CONSTANTS = /* @__PURE__ */ new Set(["True", "False", "None"]);
752
+ var PY_TYPES = /* @__PURE__ */ new Set(["int", "str", "bool", "float", "bytes", "list", "dict", "tuple", "set", "object"]);
753
+ var PY_COMMENT = /#[^\n]*/y;
754
+ var PY_TRIPLE = /[rRbBuUfF]{0,2}(?:"""[\s\S]*?(?:"""|$)|'''[\s\S]*?(?:'''|$))/y;
755
+ var PY_STRING = /[rRbBuUfF]{0,2}(?:'(?:\\.|[^\\'\n])*'?|"(?:\\.|[^\\"\n])*"?)/y;
756
+ var PY_NUMBER = /(?:0[xX][\da-fA-F_]+|\d[\d_]*(?:\.[\d_]*)?(?:[eE][+-]?\d+)?j?)/y;
757
+ var PY_IDENT = /[A-Za-z_]\w*/y;
758
+ var PY_DECORATOR = /@[A-Za-z_][\w.]*/y;
759
+ var PY_CALL_AFTER = /\s*\(/y;
760
+ function scanPython(src, emit) {
761
+ let i = 0;
762
+ let prev = "";
763
+ while (i < src.length) {
764
+ let m;
765
+ if ((m = at(WS, src, i)) || (m = at(NEWLINE, src, i))) {
766
+ emit(m);
767
+ i += m.length;
768
+ continue;
769
+ }
770
+ if (m = at(PY_COMMENT, src, i)) {
771
+ emit(m, "comment");
772
+ } else if ((m = at(PY_TRIPLE, src, i)) || (m = at(PY_STRING, src, i))) {
773
+ if (/^[A-Za-z]+$/.test(m)) {
774
+ emit(m);
775
+ } else emit(m, "string");
776
+ prev = '"';
777
+ } else if (m = at(PY_DECORATOR, src, i)) {
778
+ emit(m, "function");
779
+ prev = "@";
780
+ } else if (m = at(PY_IDENT, src, i)) {
781
+ let kind;
782
+ if (PY_CONSTANTS.has(m)) kind = "number";
783
+ else if (prev !== "." && PY_KEYWORDS.has(m)) kind = "keyword";
784
+ else if (prev === "def" || at(PY_CALL_AFTER, src, i + m.length) !== null) kind = "function";
785
+ else if (prev === "class" || /^[A-Z][a-z]/.test(m) || PY_TYPES.has(m)) kind = "type";
786
+ else if (isConstant(m)) kind = "number";
787
+ emit(m, kind);
788
+ prev = kind === "keyword" ? m : "id";
789
+ } else if (m = at(PY_NUMBER, src, i)) {
790
+ emit(m, "number");
791
+ prev = "0";
792
+ } else {
793
+ m = src[i];
794
+ emit(m);
795
+ prev = m;
796
+ }
797
+ i += m.length;
798
+ }
799
+ }
800
+ var YAML_KEY = /[ \t]*(?:- )?[\w.$/-]+(?=[ \t]*:(?:\s|$))/y;
801
+ var YAML_VALUE_WORD = /(?:true|false|null|yes|no|~|-?\d+(?:\.\d+)?)(?=\s*(?:#|$))/y;
802
+ function scanYaml(src, emit) {
803
+ let i = 0;
804
+ let lineStart = true;
805
+ while (i < src.length) {
806
+ let m;
807
+ if (m = at(NEWLINE, src, i)) {
808
+ emit(m);
809
+ i += m.length;
810
+ lineStart = true;
811
+ continue;
812
+ }
813
+ if (lineStart && (m = at(YAML_KEY, src, i))) {
814
+ const dash = m.match(/^([ \t]*(?:- )?)/)[1];
815
+ emit(dash);
816
+ emit(m.slice(dash.length), "property");
817
+ i += m.length;
818
+ lineStart = false;
819
+ continue;
820
+ }
821
+ lineStart = false;
822
+ if ((m = at(SH_COMMENT, src, i)) && (i === 0 || /\s/.test(src[i - 1]))) emit(m, "comment");
823
+ else if ((m = at(SH_SINGLE, src, i)) || (m = at(JSON_STRING, src, i))) emit(m, "string");
824
+ else if (m = at(YAML_VALUE_WORD, src, i)) emit(m, "number");
825
+ else if (m = at(SH_URL, src, i)) emit(m, "url");
826
+ else {
827
+ m = src[i];
828
+ emit(m);
829
+ }
830
+ i += m.length;
831
+ }
832
+ }
833
+ function toLines(tokens) {
834
+ const lines = [[]];
835
+ for (const t of tokens) {
836
+ const parts = t.text.split(/\r?\n/);
837
+ parts.forEach((part, j) => {
838
+ if (j > 0) lines.push([]);
839
+ if (part) lines[lines.length - 1].push(t.kind ? { text: part, kind: t.kind } : { text: part });
840
+ });
841
+ }
842
+ return lines;
843
+ }
844
+ function highlight(code, lang) {
845
+ const src = code.replace(/\r?\n$/, "");
846
+ const grammar = grammarOf(lang);
847
+ const { emit, tokens } = collector();
848
+ const name = (lang ?? "").toLowerCase();
849
+ switch (grammar) {
850
+ case "js":
851
+ scanJs(src, emit, name === "tsx" || name === "jsx");
852
+ break;
853
+ case "json":
854
+ scanJson(src, emit);
855
+ break;
856
+ case "shell":
857
+ scanShell(src, emit);
858
+ break;
859
+ case "python":
860
+ scanPython(src, emit);
861
+ break;
862
+ case "yaml":
863
+ scanYaml(src, emit);
864
+ break;
865
+ default:
866
+ emit(src);
867
+ }
868
+ return toLines(tokens);
869
+ }
870
+ function readDiff(code) {
871
+ const diff = /* @__PURE__ */ new Map();
872
+ const lines = code.replace(/\r?\n$/, "").split(/\r?\n/);
873
+ const out = lines.map((line, i) => {
874
+ const c = line[0];
875
+ if (c === "+" || c === "-") {
876
+ diff.set(i + 1, c === "+" ? "add" : "remove");
877
+ return line.slice(1);
878
+ }
879
+ return c === " " ? line.slice(1) : line;
880
+ });
881
+ return { code: out.join("\n"), diff };
882
+ }
883
+ function parseLineRanges(spec) {
884
+ if (!spec) return /* @__PURE__ */ new Set();
885
+ if (typeof spec !== "string") return new Set(spec);
886
+ const out = /* @__PURE__ */ new Set();
887
+ for (const part of spec.split(",")) {
888
+ const m = part.trim().match(/^(\d+)(?:\s*-\s*(\d+))?$/);
889
+ if (!m) continue;
890
+ const a = Number(m[1]);
891
+ const b = m[2] ? Number(m[2]) : a;
892
+ for (let n = Math.min(a, b); n <= Math.max(a, b) && n - a < 1e4; n++) out.add(n);
893
+ }
894
+ return out;
895
+ }
896
+ var ESCAPE = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" };
897
+ function escapeHtml(s) {
898
+ return s.replace(/[&<>"]/g, (c) => ESCAPE[c]);
899
+ }
900
+ function linesToHtml(lines, marks = {}) {
901
+ return lines.map((line, i) => {
902
+ const n = i + 1;
903
+ const attrs = [
904
+ 'data-line=""',
905
+ marks.highlight?.has(n) ? 'data-mark=""' : "",
906
+ marks.diff?.has(n) ? `data-diff="${marks.diff.get(n)}"` : ""
907
+ ].filter(Boolean).join(" ");
908
+ const body = line.map((t) => t.kind ? `<span class="${TOKEN_CLASS[t.kind]}">${escapeHtml(t.text)}</span>` : escapeHtml(t.text)).join("");
909
+ return `<span ${attrs}>${body}</span>`;
910
+ }).join("\n");
911
+ }
428
912
  function ScrollFade({ fade = "var(--card)", className, innerClassName, children, ...props }) {
429
913
  const ref = useRef(null);
430
914
  const [edges, setEdges] = useState({ left: false, right: false });
@@ -483,7 +967,73 @@ function ScrollFade({ fade = "var(--card)", className, innerClassName, children,
483
967
  )
484
968
  ] });
485
969
  }
486
- var ShellContext = createContext({});
970
+
971
+ // src/format/index.ts
972
+ var EXPLORER = "https://mempool.space";
973
+ function explorerUrl(kind, value, network = "mainnet") {
974
+ const net = network === "mainnet" ? "" : `/${network}`;
975
+ return `${EXPLORER}${net}/${kind}/${encodeURIComponent(String(value))}`;
976
+ }
977
+ function shortenMiddle(value, head = 8, tail = 6) {
978
+ return value.length <= head + tail + 1 ? value : `${value.slice(0, head)}\u2026${value.slice(-tail)}`;
979
+ }
980
+ function formatBlockHeight(height) {
981
+ return Math.trunc(height).toLocaleString("en-US");
982
+ }
983
+ function blocksToDuration(blocks, minutesPerBlock = 10) {
984
+ const minutes = Math.max(0, Math.round(blocks * minutesPerBlock));
985
+ if (minutes < 60) return `about ${minutes} minute${minutes === 1 ? "" : "s"}`;
986
+ const units = [
987
+ [60 * 24 * 7, "week"],
988
+ [60 * 24, "day"],
989
+ [60, "hour"],
990
+ [1, "minute"]
991
+ ];
992
+ const parts = [];
993
+ let rest = minutes;
994
+ for (const [size, word] of units) {
995
+ const n = Math.floor(rest / size);
996
+ if (n > 0 && parts.length < 2) {
997
+ parts.push(`${n} ${word}${n === 1 ? "" : "s"}`);
998
+ rest -= n * size;
999
+ } else if (parts.length > 0) break;
1000
+ }
1001
+ return `about ${parts.join(" ")}`;
1002
+ }
1003
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
1004
+ function formatUtc(at2, opts = {}) {
1005
+ const d = typeof at2 === "number" ? new Date(at2 * 1e3) : new Date(at2);
1006
+ if (Number.isNaN(d.getTime())) return "\u2014";
1007
+ const day = `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]} ${d.getUTCFullYear()}`;
1008
+ if (opts.date) return day;
1009
+ const hh = String(d.getUTCHours()).padStart(2, "0");
1010
+ const mm = String(d.getUTCMinutes()).padStart(2, "0");
1011
+ return `${day}, ${hh}:${mm} UTC`;
1012
+ }
1013
+ function formatBytes(bytes) {
1014
+ if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
1015
+ if (bytes < 1024) return `${bytes} B`;
1016
+ const units = ["KB", "MB", "GB", "TB"];
1017
+ let v = bytes / 1024;
1018
+ let u = 0;
1019
+ while (v >= 1024 && u < units.length - 1) {
1020
+ v /= 1024;
1021
+ u++;
1022
+ }
1023
+ return `${v < 10 ? v.toFixed(1).replace(/\.0$/, "") : Math.round(v)} ${units[u]}`;
1024
+ }
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] = createContext(initial));
1029
+ }
1030
+
1031
+ // src/lib/density.ts
1032
+ var DensityContext = sharedContext("density", "comfortable");
1033
+ function useDensity() {
1034
+ return useContext(DensityContext);
1035
+ }
1036
+ var ShellContext = sharedContext("shell-place", {});
487
1037
  function useShellPlace() {
488
1038
  return useContext(ShellContext);
489
1039
  }
@@ -538,6 +1088,18 @@ forwardRef(function Separator2({ className, orientation = "horizontal", decorati
538
1088
  }
539
1089
  );
540
1090
  });
1091
+ function Kbd({ className, ...props }) {
1092
+ return /* @__PURE__ */ jsx(
1093
+ "kbd",
1094
+ {
1095
+ className: cn(
1096
+ "inline-flex h-5 min-w-5 items-center justify-center rounded-md border border-border bg-card px-1.5 font-mono text-[11px] text-muted-foreground",
1097
+ className
1098
+ ),
1099
+ ...props
1100
+ }
1101
+ );
1102
+ }
541
1103
  var buttonVariants = cva(
542
1104
  [
543
1105
  "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-full font-medium",
@@ -611,26 +1173,30 @@ function PageHeader({
611
1173
  ] });
612
1174
  }
613
1175
  var InStatGrid = createContext(false);
614
- function StatCard({ label, value, hint, className }) {
1176
+ function StatCard({ label, value, hint, size, className }) {
615
1177
  const inGrid = useContext(InStatGrid);
1178
+ const density = useDensity();
1179
+ const sm = (size ?? (density === "compact" ? "sm" : "md")) === "sm";
616
1180
  return /* @__PURE__ */ jsxs(
617
1181
  "div",
618
1182
  {
619
1183
  "data-ui": "stat",
620
1184
  className: cn(
621
- "rounded-[1.25rem] border border-border bg-card p-5 md:p-6",
1185
+ "border border-border bg-card",
1186
+ sm ? "rounded-2xl p-4" : "rounded-[1.25rem] p-5 md:p-6",
622
1187
  // In a grid, label, value and hint each share a row with their
623
1188
  // neighbours, so values line up whatever wraps above them.
624
1189
  inGrid ? "row-span-3 grid grid-rows-subgrid gap-1.5" : "flex flex-col gap-2",
625
1190
  className
626
1191
  ),
627
1192
  children: [
628
- /* @__PURE__ */ jsx("span", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: label }),
1193
+ /* @__PURE__ */ jsx("span", { className: cn("leading-snug text-muted-foreground", sm ? "text-[0.8125rem]" : "text-[0.875rem]"), children: label }),
629
1194
  /* @__PURE__ */ jsx(
630
1195
  "span",
631
1196
  {
632
1197
  className: cn(
633
- "break-words oca-tabular text-[1.5rem] leading-tight tracking-[-0.02em] md:text-[1.75rem]",
1198
+ "break-words oca-tabular leading-tight tracking-[-0.02em]",
1199
+ sm ? "text-[1.25rem]" : "text-[1.5rem] md:text-[1.75rem]",
634
1200
  inGrid && "self-end"
635
1201
  ),
636
1202
  children: value
@@ -692,6 +1258,7 @@ function StatGrid({ columns, empty, isEmpty, className, children, ...props }) {
692
1258
  const items = Children.toArray(children).filter(isValidElement);
693
1259
  const n = items.length;
694
1260
  const allZero = n > 0 && items.every((el) => "raw" in el.props && (el.props.raw === 0 || el.props.raw === null));
1261
+ const compact = useDensity() === "compact";
695
1262
  if (isEmpty ?? allZero) return /* @__PURE__ */ jsx(EmptyLine, { className, children: empty ?? "Nothing here yet." });
696
1263
  const lg = columns ?? statColumns(n);
697
1264
  const md = lg > 4 ? 3 : lg;
@@ -701,7 +1268,8 @@ function StatGrid({ columns, empty, isEmpty, className, children, ...props }) {
701
1268
  "div",
702
1269
  {
703
1270
  className: cn(
704
- "grid gap-3 md:gap-4",
1271
+ "grid",
1272
+ compact ? "gap-2.5 md:gap-3" : "gap-3 md:gap-4",
705
1273
  n === 1 ? "grid-cols-1" : "grid-cols-2",
706
1274
  MD_COLS[md],
707
1275
  LG_COLS[lg],
@@ -720,11 +1288,40 @@ function StatGrid({ columns, empty, isEmpty, className, children, ...props }) {
720
1288
  }
721
1289
  ) });
722
1290
  }
723
- function KeyValueList({ items, className }) {
724
- return /* @__PURE__ */ jsx("dl", { className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: items.map((it, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 px-5 py-3.5 sm:flex-row sm:items-baseline sm:gap-6", children: [
725
- /* @__PURE__ */ jsx("dt", { className: "shrink-0 text-[0.875rem] text-muted-foreground sm:w-48", children: it.label }),
726
- /* @__PURE__ */ jsx("dd", { className: cn("min-w-0 break-words text-[0.9375rem]", it.mono && "font-mono text-[0.875rem]"), children: it.value })
727
- ] }, i)) });
1291
+ function KeyValueList({
1292
+ items,
1293
+ dense,
1294
+ className
1295
+ }) {
1296
+ const density = useDensity();
1297
+ const tight = dense ?? density === "compact";
1298
+ return (
1299
+ // The rows go side by side when the list itself is wide enough, wherever it sits: a narrow card stacks them.
1300
+ /* @__PURE__ */ jsx("dl", { className: cn("@container divide-y divide-border border border-border bg-card", tight ? "rounded-2xl" : "rounded-[1.25rem]", className), children: items.map((it, i) => /* @__PURE__ */ jsxs(
1301
+ "div",
1302
+ {
1303
+ className: cn(
1304
+ "flex flex-col gap-1 @md:flex-row @md:items-baseline",
1305
+ tight ? "px-4 py-2.5 @md:gap-5" : "px-5 py-3.5 @md:gap-6"
1306
+ ),
1307
+ children: [
1308
+ /* @__PURE__ */ jsx("dt", { className: cn("shrink-0 text-muted-foreground", tight ? "text-[0.8125rem] @md:w-36" : "text-[0.875rem] @md:w-48"), children: it.label }),
1309
+ /* @__PURE__ */ jsx(
1310
+ "dd",
1311
+ {
1312
+ className: cn(
1313
+ "min-w-0 break-words",
1314
+ tight ? "text-[0.875rem]" : "text-[0.9375rem]",
1315
+ it.mono && (tight ? "font-mono text-[0.8125rem]" : "font-mono text-[0.875rem]")
1316
+ ),
1317
+ children: it.value
1318
+ }
1319
+ )
1320
+ ]
1321
+ },
1322
+ i
1323
+ )) })
1324
+ );
728
1325
  }
729
1326
  function DataTable({
730
1327
  columns,
@@ -733,8 +1330,11 @@ function DataTable({
733
1330
  empty,
734
1331
  caption,
735
1332
  phone = "cards",
1333
+ dense,
736
1334
  className
737
1335
  }) {
1336
+ const density = useDensity();
1337
+ const tight = dense ?? density === "compact";
738
1338
  if (rows.length === 0 && empty) return /* @__PURE__ */ jsx(Fragment, { children: empty });
739
1339
  const primary = columns.find((c) => c.primary) ?? columns[0];
740
1340
  const right = (c) => c.numeric || c.align === "end";
@@ -742,11 +1342,12 @@ function DataTable({
742
1342
  "div",
743
1343
  {
744
1344
  className: cn(
745
- "overflow-hidden rounded-[1.25rem] border border-border bg-card",
1345
+ "overflow-hidden border border-border bg-card",
1346
+ tight ? "rounded-2xl" : "rounded-[1.25rem]",
746
1347
  phone === "cards" && "max-sm:hidden",
747
1348
  className
748
1349
  ),
749
- children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-left text-[0.9375rem]", children: [
1350
+ children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxs("table", { className: cn("w-full border-collapse text-left", tight ? "text-[0.875rem]" : "text-[0.9375rem]"), children: [
750
1351
  caption ? /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }) : null,
751
1352
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { className: "border-b border-border", children: columns.map((c) => /* @__PURE__ */ jsx(
752
1353
  "th",
@@ -754,7 +1355,8 @@ function DataTable({
754
1355
  scope: "col",
755
1356
  style: { width: c.width, minWidth: c.minWidth },
756
1357
  className: cn(
757
- "whitespace-nowrap px-5 py-3 text-[0.8125rem] font-medium text-muted-foreground",
1358
+ "whitespace-nowrap text-[0.8125rem] font-medium text-muted-foreground",
1359
+ tight ? "px-4 py-2.5" : "px-5 py-3",
758
1360
  right(c) && "text-right",
759
1361
  c.wide && "hidden md:table-cell"
760
1362
  ),
@@ -767,7 +1369,8 @@ function DataTable({
767
1369
  {
768
1370
  style: { minWidth: c.minWidth },
769
1371
  className: cn(
770
- "px-5 py-3.5 align-middle",
1372
+ "align-middle",
1373
+ tight ? "px-4 py-2" : "px-5 py-3.5",
771
1374
  right(c) && "text-right",
772
1375
  c.numeric && "whitespace-nowrap oca-tabular",
773
1376
  c.wide && "hidden md:table-cell"
@@ -787,8 +1390,12 @@ function DataTable({
787
1390
  "ul",
788
1391
  {
789
1392
  "aria-label": caption,
790
- className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card sm:hidden", className),
791
- children: rows.map((r, i) => /* @__PURE__ */ jsxs("li", { className: "flex flex-col gap-2.5 px-4 py-4", children: [
1393
+ className: cn(
1394
+ "divide-y divide-border border border-border bg-card sm:hidden",
1395
+ tight ? "rounded-2xl" : "rounded-[1.25rem]",
1396
+ className
1397
+ ),
1398
+ children: rows.map((r, i) => /* @__PURE__ */ jsxs("li", { className: cn("flex flex-col gap-2.5 px-4", tight ? "py-3" : "py-4"), children: [
792
1399
  /* @__PURE__ */ jsx("div", { className: "min-w-0 break-words text-[0.9375rem] font-medium", children: primary?.cell(r) }),
793
1400
  rest.length > 0 ? /* @__PURE__ */ jsx("dl", { className: "grid grid-cols-[minmax(5.5rem,auto)_minmax(0,1fr)] gap-x-4 gap-y-1.5 text-[0.875rem]", children: rest.map((c) => /* @__PURE__ */ jsxs("div", { className: "contents", children: [
794
1401
  /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: c.header }),
@@ -835,13 +1442,14 @@ function Notice({
835
1442
  title,
836
1443
  children,
837
1444
  action,
1445
+ role,
838
1446
  className
839
1447
  }) {
840
1448
  const kind = NOTICE_KIND[tone];
841
1449
  return /* @__PURE__ */ jsxs(
842
1450
  "div",
843
1451
  {
844
- role: tone === "danger" || tone === "warning" ? "alert" : "note",
1452
+ role: role ?? (tone === "danger" || tone === "warning" ? "alert" : "note"),
845
1453
  "data-tone": kind,
846
1454
  className: cn(
847
1455
  "flex flex-col gap-3 rounded-2xl border border-border bg-card px-5 py-4 sm:flex-row sm:items-start sm:justify-between",
@@ -891,45 +1499,66 @@ function LoadingBlock({
891
1499
  }
892
1500
  return /* @__PURE__ */ jsx("div", { role: "status", "aria-label": label, className: cn("flex flex-col gap-3", className), children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-16 rounded-2xl" }, i)) });
893
1501
  }
894
- function middle(v, head, tail) {
895
- return v.length <= head + tail + 1 ? v : `${v.slice(0, head)}\u2026${v.slice(-tail)}`;
1502
+ async function wipeIfUnchanged(expected) {
1503
+ try {
1504
+ if (await navigator.clipboard.readText() !== expected) return;
1505
+ } catch {
1506
+ }
1507
+ try {
1508
+ await navigator.clipboard.writeText("");
1509
+ } catch {
1510
+ }
896
1511
  }
897
1512
  function useCopy(timeoutMs = 1600) {
898
1513
  const [copied, setCopied] = useState(false);
899
1514
  const t = useRef(null);
900
- useEffect(() => () => {
901
- if (t.current) clearTimeout(t.current);
902
- }, []);
1515
+ const wipe = useRef(null);
1516
+ useEffect(
1517
+ () => () => {
1518
+ if (t.current) clearTimeout(t.current);
1519
+ },
1520
+ []
1521
+ );
903
1522
  const copy = useCallback(
904
- async (text) => {
1523
+ async (text, opts = {}) => {
905
1524
  try {
906
1525
  await navigator.clipboard.writeText(text);
907
1526
  setCopied(true);
908
1527
  if (t.current) clearTimeout(t.current);
909
1528
  t.current = setTimeout(() => setCopied(false), timeoutMs);
1529
+ if (opts.clearAfter && opts.clearAfter > 0) {
1530
+ if (wipe.current) clearTimeout(wipe.current);
1531
+ wipe.current = setTimeout(() => void wipeIfUnchanged(text), opts.clearAfter);
1532
+ }
1533
+ return true;
910
1534
  } catch {
911
1535
  setCopied(false);
1536
+ return false;
912
1537
  }
913
1538
  },
914
1539
  [timeoutMs]
915
1540
  );
916
1541
  return { copied, copy };
917
1542
  }
918
- function CopyButton({ value, label = "Copy", className }) {
1543
+ function CopyButton({ value, label = "Copy", clearAfter, onCopied, className }) {
919
1544
  const { copied, copy } = useCopy();
1545
+ const done = copied ? clearAfter ? `Copied. Cleared in ${Math.round(clearAfter / 1e3)} seconds` : "Copied" : "";
920
1546
  return /* @__PURE__ */ jsxs(
921
1547
  "button",
922
1548
  {
923
1549
  type: "button",
924
- onClick: () => void copy(value),
1550
+ onClick: async () => {
1551
+ if (await copy(typeof value === "function" ? value() : value, { clearAfter })) onCopied?.();
1552
+ },
925
1553
  "aria-label": copied ? "Copied" : label,
1554
+ title: label,
926
1555
  className: cn(
927
1556
  "inline-flex size-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
928
1557
  className
929
1558
  ),
930
1559
  children: [
931
1560
  copied ? /* @__PURE__ */ jsx(Check, { className: "size-4 text-success" }) : /* @__PURE__ */ jsx(Copy, { className: "size-4" }),
932
- /* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", children: copied ? "Copied" : "" })
1561
+ /* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", children: done })
933
1562
  ]
934
1563
  }
935
1564
  );
@@ -940,12 +1569,27 @@ function HashChip({
940
1569
  tail = 6,
941
1570
  copy = true,
942
1571
  href,
1572
+ explorer,
1573
+ network = "mainnet",
943
1574
  className
944
1575
  }) {
945
- const shown = middle(value, head, tail);
1576
+ const shown = shortenMiddle(value, head, tail);
1577
+ const link = href ?? (explorer ? explorerUrl(explorer, value, network) : void 0);
1578
+ const offsite = !!link && /^https?:\/\//.test(link);
946
1579
  const text = /* @__PURE__ */ jsx("span", { title: value, className: "font-mono text-[0.875rem]", children: shown });
947
1580
  return /* @__PURE__ */ jsxs("span", { className: cn("inline-flex max-w-full items-center gap-1", className), children: [
948
- href ? /* @__PURE__ */ jsx("a", { href, className: "underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground", children: text }) : text,
1581
+ link ? /* @__PURE__ */ jsxs(
1582
+ "a",
1583
+ {
1584
+ href: link,
1585
+ ...offsite ? { target: "_blank", rel: "noreferrer" } : {},
1586
+ className: "underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground",
1587
+ children: [
1588
+ text,
1589
+ offsite ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (opens in a new tab)" }) : null
1590
+ ]
1591
+ }
1592
+ ) : text,
949
1593
  copy ? /* @__PURE__ */ jsx(CopyButton, { value, label: "Copy full value" }) : null
950
1594
  ] });
951
1595
  }
@@ -999,96 +1643,269 @@ function ActivityList({ items, empty, className }) {
999
1643
  return /* @__PURE__ */ jsx("li", { children: it.href ? /* @__PURE__ */ jsx("a", { href: it.href, className: "block transition-colors hover:bg-accent/60", children: body }) : body }, it.id);
1000
1644
  }) });
1001
1645
  }
1002
- var KIND = {
1003
- package: "text-oca-code-package",
1004
- tag: "text-oca-code-tag",
1005
- link: "text-oca-code-link"
1646
+ var LANG_NAME = {
1647
+ ts: "TypeScript",
1648
+ typescript: "TypeScript",
1649
+ tsx: "TSX",
1650
+ js: "JavaScript",
1651
+ javascript: "JavaScript",
1652
+ jsx: "JSX",
1653
+ mjs: "JavaScript",
1654
+ json: "JSON",
1655
+ jsonc: "JSON",
1656
+ bash: "Shell",
1657
+ sh: "Shell",
1658
+ shell: "Shell",
1659
+ zsh: "Shell",
1660
+ console: "Terminal",
1661
+ terminal: "Terminal",
1662
+ python: "Python",
1663
+ py: "Python",
1664
+ yaml: "YAML",
1665
+ yml: "YAML",
1666
+ diff: "Diff",
1667
+ text: "Text"
1006
1668
  };
1007
- function PackageCard({ items, className }) {
1008
- return /* @__PURE__ */ jsx(
1009
- "div",
1010
- {
1011
- className: cn(
1012
- "grid gap-x-10 gap-y-7 rounded-[1.25rem] border border-oca-ink-line bg-oca-ink-card p-6 text-oca-ink-foreground md:grid-cols-2 md:p-9",
1013
- className
1014
- ),
1015
- children: items.map((it, i) => {
1016
- const code = /* @__PURE__ */ jsx("span", { className: cn("text-[0.9375rem]", KIND[it.kind ?? "package"]), children: it.code });
1017
- return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
1018
- /* @__PURE__ */ jsx("h3", { className: "text-[1.125rem] font-semibold tracking-[-0.01em] text-oca-ink-title", children: it.title }),
1019
- it.href ? /* @__PURE__ */ jsx("a", { href: it.href, className: "w-fit underline decoration-transparent underline-offset-4 hover:decoration-current", children: code }) : code,
1020
- it.note ? /* @__PURE__ */ jsxs("p", { className: "text-[0.9375rem] leading-relaxed text-oca-ink-subtle", children: [
1021
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "// " }),
1022
- it.note
1023
- ] }) : null
1024
- ] }, i);
1025
- })
1026
- }
1027
- );
1669
+ function languageName(lang) {
1670
+ return lang ? LANG_NAME[lang.toLowerCase()] ?? lang : void 0;
1671
+ }
1672
+ function forClipboard(text, lang) {
1673
+ if (grammarOf(lang) !== "shell") return text;
1674
+ const lines = text.split("\n");
1675
+ if (!lines.some((l) => l.startsWith("$ "))) return text;
1676
+ return lines.filter((l) => l.startsWith("$ ")).map((l) => l.slice(2)).join("\n");
1677
+ }
1678
+ function linesFromDom(pre) {
1679
+ if (!pre) return null;
1680
+ const lines = pre.querySelectorAll("[data-line]");
1681
+ if (lines.length === 0) return pre.textContent ?? "";
1682
+ return Array.from(lines).filter((l) => l.getAttribute("data-diff") !== "remove").map((l) => l.textContent ?? "").join("\n");
1683
+ }
1684
+ function prepare(code, lang, marks, diff) {
1685
+ const d = diff ? readDiff(code) : null;
1686
+ const src = d ? d.code : code.replace(/\r?\n$/, "");
1687
+ const lines = highlight(src, lang === "diff" ? void 0 : lang);
1688
+ const kept = d ? src.split("\n").filter((_, i) => d.diff.get(i + 1) !== "remove") : null;
1689
+ return {
1690
+ html: linesToHtml(lines, { highlight: parseLineRanges(marks), diff: d?.diff }),
1691
+ copy: kept ? kept.join("\n") : src,
1692
+ lines: lines.length,
1693
+ diff: !!d
1694
+ };
1695
+ }
1696
+ function Well({
1697
+ preRef,
1698
+ html,
1699
+ children,
1700
+ lang,
1701
+ lines,
1702
+ maxLines,
1703
+ diff,
1704
+ lineNumbers
1705
+ }) {
1706
+ const foldable = maxLines !== void 0 && lines > maxLines + 2;
1707
+ const [open, setOpen] = useState(false);
1708
+ const folded = foldable && !open;
1709
+ const lined = html !== void 0;
1710
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1711
+ /* @__PURE__ */ jsx(
1712
+ "div",
1713
+ {
1714
+ className: cn(folded && "overflow-hidden"),
1715
+ style: folded ? { maxHeight: `calc(${maxLines} * 1.625em + 2rem)` } : void 0,
1716
+ children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--oca-code-surface)", children: /* @__PURE__ */ jsx(
1717
+ "pre",
1718
+ {
1719
+ ref: preRef,
1720
+ "data-diff": diff ? "" : void 0,
1721
+ "data-line-numbers": lineNumbers ? "" : void 0,
1722
+ className: cn(
1723
+ "oca-code w-max min-w-full py-4 font-mono text-[0.875rem] leading-[1.625] text-oca-ink-muted [font-variant-ligatures:none]",
1724
+ !lined && "px-5"
1725
+ ),
1726
+ children: lined ? /* @__PURE__ */ jsx("code", { className: "block", "data-lang": lang, dangerouslySetInnerHTML: { __html: html } }) : /* @__PURE__ */ jsx("code", { className: "block", "data-lang": lang, children })
1727
+ }
1728
+ ) })
1729
+ }
1730
+ ),
1731
+ foldable ? /* @__PURE__ */ jsx(
1732
+ "div",
1733
+ {
1734
+ className: cn("flex justify-center px-5 pb-4", folded && "absolute inset-x-0 bottom-0 pt-16"),
1735
+ style: folded ? { background: "linear-gradient(to top, var(--oca-code-surface) 40%, transparent)" } : void 0,
1736
+ children: /* @__PURE__ */ jsx(
1737
+ "button",
1738
+ {
1739
+ type: "button",
1740
+ onClick: () => setOpen((v) => !v),
1741
+ "aria-expanded": open,
1742
+ className: "rounded-full border border-white/20 px-4 py-1.5 text-[0.8125rem] text-white transition-colors hover:bg-white/10",
1743
+ children: open ? "Show less" : `Show all ${lines} lines`
1744
+ }
1745
+ )
1746
+ }
1747
+ ) : null
1748
+ ] });
1028
1749
  }
1750
+ var FRAME = "overflow-hidden rounded-[1.25rem] border border-[var(--oca-code-line)] bg-[var(--oca-code-surface)]";
1751
+ var COPY_ON_INK = "text-oca-ink-subtle hover:bg-white/10 hover:text-white";
1029
1752
  function CodeBlock({
1030
1753
  code,
1754
+ html,
1755
+ children,
1756
+ lang,
1031
1757
  caption,
1032
1758
  copy = true,
1759
+ clearAfter,
1033
1760
  maxLines,
1761
+ highlight: marks,
1762
+ diff,
1763
+ lineNumbers,
1764
+ actions,
1034
1765
  className
1035
1766
  }) {
1036
- const lines = code.split("\n").length;
1037
- const foldable = maxLines !== void 0 && lines > maxLines + 2;
1038
- const [open, setOpen] = useState(false);
1039
- const folded = foldable && !open;
1767
+ const preRef = useRef(null);
1768
+ const isDiff = diff || lang === "diff";
1769
+ const markKey = typeof marks === "string" ? marks : marks?.join(",");
1770
+ const prepared = useMemo(
1771
+ () => html === void 0 && children === void 0 && code !== void 0 ? prepare(code, lang, markKey, !!isDiff) : null,
1772
+ [code, html, children, lang, markKey, isDiff]
1773
+ );
1774
+ const markup = prepared?.html ?? html;
1775
+ const lines = prepared?.lines ?? (html !== void 0 ? html.split("\n").length : code?.split("\n").length ?? 0);
1776
+ const read = () => forClipboard(prepared?.copy ?? linesFromDom(preRef.current) ?? code ?? "", lang);
1777
+ return /* @__PURE__ */ jsxs("figure", { className: cn(FRAME, className), children: [
1778
+ /* @__PURE__ */ jsxs("figcaption", { className: "flex h-11 items-center justify-between gap-3 border-b border-[var(--oca-code-line)] pl-5 pr-2", children: [
1779
+ /* @__PURE__ */ jsx("span", { className: "truncate text-[0.8125rem] text-oca-ink-subtle", children: caption ?? languageName(lang) ?? "Code" }),
1780
+ /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
1781
+ actions,
1782
+ copy ? /* @__PURE__ */ jsx(CopyButton, { value: read, label: "Copy code", clearAfter, className: COPY_ON_INK }) : null
1783
+ ] })
1784
+ ] }),
1785
+ /* @__PURE__ */ jsx(
1786
+ Well,
1787
+ {
1788
+ preRef,
1789
+ html: markup,
1790
+ lang,
1791
+ lines,
1792
+ maxLines,
1793
+ diff: prepared ? prepared.diff : isDiff,
1794
+ lineNumbers,
1795
+ children
1796
+ }
1797
+ )
1798
+ ] });
1799
+ }
1800
+ var tabListeners = /* @__PURE__ */ new Map();
1801
+ var tabMemory = /* @__PURE__ */ new Map();
1802
+ var storeKey = (k) => `oca-code-tab:${k}`;
1803
+ function readTab(key) {
1804
+ if (tabMemory.has(key)) return tabMemory.get(key);
1805
+ try {
1806
+ return window.localStorage.getItem(storeKey(key));
1807
+ } catch {
1808
+ return null;
1809
+ }
1810
+ }
1811
+ function writeTab(key, value) {
1812
+ tabMemory.set(key, value);
1813
+ try {
1814
+ window.localStorage.setItem(storeKey(key), value);
1815
+ } catch {
1816
+ }
1817
+ tabListeners.get(key)?.forEach((l) => l());
1818
+ }
1819
+ function useSyncedTab(key) {
1820
+ const subscribe = useCallback(
1821
+ (cb) => {
1822
+ if (!key) return () => {
1823
+ };
1824
+ const set = tabListeners.get(key) ?? /* @__PURE__ */ new Set();
1825
+ set.add(cb);
1826
+ tabListeners.set(key, set);
1827
+ return () => {
1828
+ set.delete(cb);
1829
+ };
1830
+ },
1831
+ [key]
1832
+ );
1833
+ const value = useSyncExternalStore(
1834
+ subscribe,
1835
+ () => key ? readTab(key) : null,
1836
+ () => null
1837
+ );
1838
+ return [value, (v) => key && writeTab(key, v)];
1839
+ }
1840
+ function CodeTabs({
1841
+ items,
1842
+ syncKey,
1843
+ defaultValue,
1844
+ maxLines,
1845
+ className
1846
+ }) {
1847
+ const [synced, setSynced] = useSyncedTab(syncKey);
1848
+ const [local, setLocal] = useState(null);
1849
+ const labels = items.map((it) => it.label);
1850
+ const pick = [local, synced, defaultValue].find((v) => !!v && labels.includes(v)) ?? labels[0] ?? "";
1851
+ const active = items.find((it) => it.label === pick);
1852
+ const prepared = useMemo(() => items.map((it) => prepare(it.code, it.lang, void 0, it.lang === "diff")), [items]);
1040
1853
  return /* @__PURE__ */ jsxs(
1041
- "figure",
1854
+ TabsPrimitive.Root,
1042
1855
  {
1043
- className: cn(
1044
- "overflow-hidden rounded-[1.25rem] border border-[var(--oca-code-line)] bg-[var(--oca-code-surface)]",
1045
- className
1046
- ),
1856
+ value: pick,
1857
+ onValueChange: (v) => {
1858
+ setLocal(v);
1859
+ setSynced(v);
1860
+ },
1861
+ className: cn(FRAME, className),
1047
1862
  children: [
1048
- /* @__PURE__ */ jsxs("figcaption", { className: "flex h-11 items-center justify-between gap-3 border-b border-[var(--oca-code-line)] pl-5 pr-2", children: [
1049
- /* @__PURE__ */ jsx("span", { className: "truncate text-[0.8125rem] text-oca-ink-subtle", children: caption ?? "Code" }),
1050
- copy ? /* @__PURE__ */ jsx(
1051
- CopyButton,
1052
- {
1053
- value: code,
1054
- label: "Copy code",
1055
- className: "text-oca-ink-subtle hover:bg-white/10 hover:text-white"
1056
- }
1057
- ) : null
1058
- ] }),
1059
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1060
- /* @__PURE__ */ jsx(
1061
- "div",
1062
- {
1063
- className: cn(folded && "overflow-hidden"),
1064
- style: folded ? { maxHeight: `calc(${maxLines} * 1.625em + 2.5rem)` } : void 0,
1065
- children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--oca-code-surface)", children: /* @__PURE__ */ jsx("pre", { className: "w-max min-w-full p-5 font-mono text-[0.875rem] leading-[1.625] text-oca-ink-muted [font-variant-ligatures:none]", children: /* @__PURE__ */ jsx("code", { children: code }) }) })
1066
- }
1067
- ),
1068
- foldable ? /* @__PURE__ */ jsx(
1069
- "div",
1863
+ /* @__PURE__ */ jsxs("div", { className: "flex h-11 items-center justify-between gap-3 border-b border-[var(--oca-code-line)] pl-2 pr-2", children: [
1864
+ /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--oca-code-surface)", className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(TabsPrimitive.List, { "aria-label": "Versions", className: "flex w-max items-center gap-0.5", children: items.map((it) => /* @__PURE__ */ jsx(
1865
+ TabsPrimitive.Trigger,
1070
1866
  {
1867
+ value: it.label,
1071
1868
  className: cn(
1072
- "flex justify-center px-5 pb-4",
1073
- folded && "absolute inset-x-0 bottom-0 pt-16"
1869
+ "relative inline-flex h-11 items-center whitespace-nowrap px-3 text-[0.8125rem] text-oca-ink-subtle outline-none transition-colors",
1870
+ "hover:text-white focus-visible:text-white focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
1871
+ "data-[state=active]:text-white",
1872
+ "after:absolute after:inset-x-3 after:bottom-0 after:h-0.5 after:rounded-full after:bg-transparent data-[state=active]:after:bg-oca-orange"
1074
1873
  ),
1075
- style: folded ? { background: "linear-gradient(to top, var(--oca-code-surface) 40%, transparent)" } : void 0,
1076
- children: /* @__PURE__ */ jsx(
1077
- "button",
1078
- {
1079
- type: "button",
1080
- onClick: () => setOpen((v) => !v),
1081
- className: "rounded-full border border-white/20 px-4 py-1.5 text-[0.8125rem] text-white transition-colors hover:bg-white/10",
1082
- children: open ? "Show less" : `Show all ${lines} lines`
1083
- }
1084
- )
1874
+ children: it.label
1875
+ },
1876
+ it.label
1877
+ )) }) }),
1878
+ active ? /* @__PURE__ */ jsx(
1879
+ CopyButton,
1880
+ {
1881
+ value: () => forClipboard(prepared[items.indexOf(active)]?.copy ?? active.code, active.lang),
1882
+ label: `Copy ${active.label}`,
1883
+ className: COPY_ON_INK
1085
1884
  }
1086
1885
  ) : null
1087
- ] })
1886
+ ] }),
1887
+ items.map((it, i) => /* @__PURE__ */ jsx(TabsPrimitive.Content, { value: it.label, className: "outline-none", tabIndex: -1, children: /* @__PURE__ */ jsx(
1888
+ Well,
1889
+ {
1890
+ html: prepared[i].html,
1891
+ lang: it.lang,
1892
+ lines: prepared[i].lines,
1893
+ maxLines,
1894
+ diff: prepared[i].diff
1895
+ }
1896
+ ) }, it.label))
1088
1897
  ]
1089
1898
  }
1090
1899
  );
1091
1900
  }
1901
+ function InstallTabs({ pkg, dev = false, className }) {
1902
+ const items = [
1903
+ { label: "npm", code: `npm install ${dev ? "--save-dev " : ""}${pkg}`, lang: "bash" },
1904
+ { label: "yarn", code: `yarn add ${dev ? "--dev " : ""}${pkg}`, lang: "bash" },
1905
+ { label: "pnpm", code: `pnpm add ${dev ? "--save-dev " : ""}${pkg}`, lang: "bash" }
1906
+ ];
1907
+ return /* @__PURE__ */ jsx(CodeTabs, { items, syncKey: "package-manager", className });
1908
+ }
1092
1909
  function SplitBar({
1093
1910
  segments,
1094
1911
  caption,
@@ -1932,7 +2749,8 @@ var FAMILY = [
1932
2749
  group: "app",
1933
2750
  line: "Builders find co-founders and backers.",
1934
2751
  status: "testing",
1935
- protocols: ["attest"]
2752
+ // Signs in with an orangecheck account and a wallet; uses none of the six directly.
2753
+ protocols: []
1936
2754
  },
1937
2755
  {
1938
2756
  slug: "me-demo",
@@ -2016,20 +2834,33 @@ function ProtocolGrid({
2016
2834
  ] }),
2017
2835
  p.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: p.status }) : null
2018
2836
  ] }),
2019
- /* @__PURE__ */ jsx("h3", { className: "oca-display-3", children: /* @__PURE__ */ jsx("a", { href: link === "tool" ? p.toolHref : p.pageHref, className: STRETCH, children: p.label }) }),
2837
+ /* @__PURE__ */ jsx("h3", { className: "oca-display-3", children: /* @__PURE__ */ jsx(
2838
+ "a",
2839
+ {
2840
+ href: link === "tool" ? p.toolHref : link === "docs" ? `${DOCS_HREF}/${p.slug}` : p.pageHref,
2841
+ className: STRETCH,
2842
+ children: p.label
2843
+ }
2844
+ ) }),
2020
2845
  /* @__PURE__ */ jsx("p", { className: "oca-body", children: p.line }),
2021
2846
  /* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center justify-between gap-3 pt-2 text-[0.875rem] text-muted-foreground", children: [
2022
2847
  /* @__PURE__ */ jsxs("span", { className: "oca-tabular", children: [
2023
2848
  "Nostr kind ",
2024
2849
  p.kinds
2025
2850
  ] }),
2026
- /* @__PURE__ */ jsx(
2851
+ link === "tool" ? /* @__PURE__ */ jsx(
2027
2852
  ArrowUpRight,
2028
2853
  {
2029
2854
  "aria-hidden": true,
2030
2855
  className: "size-4 transition-transform duration-200 group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:text-foreground"
2031
2856
  }
2032
- )
2857
+ ) : /* @__PURE__ */ jsx(
2858
+ ArrowRight,
2859
+ {
2860
+ "aria-hidden": true,
2861
+ className: "size-4 transition-transform duration-200 group-hover:translate-x-0.5 group-hover:text-foreground"
2862
+ }
2863
+ )
2033
2864
  ] })
2034
2865
  ] }) }, slug);
2035
2866
  }) });
@@ -2068,8 +2899,24 @@ var fieldBase = [
2068
2899
  "disabled:cursor-not-allowed disabled:opacity-55",
2069
2900
  "aria-[invalid=true]:border-destructive aria-[invalid=true]:focus:ring-[color-mix(in_oklab,var(--destructive)_14%,transparent)]"
2070
2901
  ];
2071
- var Input = forwardRef(function Input2({ className, type = "text", ...props }, ref) {
2072
- return /* @__PURE__ */ jsx("input", { ref, type, "data-ui": "input", className: cn(fieldBase, "h-11 px-3.5", className), ...props });
2902
+ var FIELD_SIZE = {
2903
+ md: "h-11 px-3.5",
2904
+ sm: "h-9 rounded-[0.625rem] px-3 md:text-[0.875rem]"
2905
+ };
2906
+ var Input = forwardRef(function Input2({ className, type = "text", size, ...props }, ref) {
2907
+ const density = useDensity();
2908
+ const s = size ?? (density === "compact" ? "sm" : "md");
2909
+ return /* @__PURE__ */ jsx(
2910
+ "input",
2911
+ {
2912
+ ref,
2913
+ type,
2914
+ "data-ui": "input",
2915
+ "data-size": s,
2916
+ className: cn(fieldBase, FIELD_SIZE[s], className),
2917
+ ...props
2918
+ }
2919
+ );
2073
2920
  });
2074
2921
  var Textarea = forwardRef(
2075
2922
  function Textarea2({ className, ...props }, ref) {
@@ -2126,12 +2973,19 @@ function Field({ label, hint, optional, error, children, className, hideLabel, a
2126
2973
  error ? /* @__PURE__ */ jsx("p", { id: errorId, role: "alert", className: "text-[0.8125rem] leading-snug text-destructive", children: error }) : null
2127
2974
  ] });
2128
2975
  }
2129
- forwardRef(function SelectTrigger2({ className, children, ...props }, ref) {
2976
+ var SelectFieldContext = sharedContext("select-field", null);
2977
+ forwardRef(function SelectTrigger2({ className, children, size, ...props }, ref) {
2978
+ const density = useDensity();
2979
+ const field = useContext(SelectFieldContext);
2980
+ const s = size ?? (density === "compact" ? "sm" : "md");
2130
2981
  return /* @__PURE__ */ jsxs(
2131
2982
  SelectPrimitive.Trigger,
2132
2983
  {
2133
2984
  ref,
2134
- className: cn(fieldBase, "flex h-11 items-center justify-between gap-2 px-3.5 text-left", className),
2985
+ id: field?.id,
2986
+ "aria-describedby": field?.["aria-describedby"],
2987
+ "aria-invalid": field?.["aria-invalid"],
2988
+ className: cn(fieldBase, FIELD_SIZE[s], "flex items-center justify-between gap-2 text-left", className),
2135
2989
  ...props,
2136
2990
  children: [
2137
2991
  /* @__PURE__ */ jsx("span", { className: "truncate", children }),
@@ -2480,6 +3334,7 @@ function VerifyReport({
2480
3334
  facts,
2481
3335
  notChecked,
2482
3336
  actions,
3337
+ as: Heading = "h2",
2483
3338
  className
2484
3339
  }) {
2485
3340
  return /* @__PURE__ */ jsxs(
@@ -2490,7 +3345,7 @@ function VerifyReport({
2490
3345
  children: [
2491
3346
  /* @__PURE__ */ jsxs("header", { className: "flex flex-col items-start gap-3 p-6 md:p-8", children: [
2492
3347
  /* @__PURE__ */ jsx(StatusBadge, { status: verdict }),
2493
- /* @__PURE__ */ jsx("h3", { className: "oca-display-3", children: title }),
3348
+ /* @__PURE__ */ jsx(Heading, { className: "oca-display-3", children: title }),
2494
3349
  summary ? /* @__PURE__ */ jsx("p", { className: "oca-body max-w-[40rem]", children: summary }) : null
2495
3350
  ] }),
2496
3351
  /* @__PURE__ */ jsx("ul", { "aria-label": "Checks", className: "divide-y divide-border border-t border-border", children: checks.map((c, i) => {
@@ -2590,7 +3445,1192 @@ function SignMessage({
2590
3445
  )
2591
3446
  ] });
2592
3447
  }
3448
+ var isInternal = (href) => href.startsWith("/") || href.startsWith("#");
3449
+ function DocLink({ href, className, children, ...rest }) {
3450
+ return isInternal(href) ? /* @__PURE__ */ jsx(Link, { href, className, ...rest, children }) : /* @__PURE__ */ jsx("a", { href, className, ...rest, children });
3451
+ }
3452
+ function Breadcrumbs({ items, action, className }) {
3453
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex min-h-11 items-center justify-between gap-4 sm:min-h-0", className), children: [
3454
+ /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "min-w-0", children: /* @__PURE__ */ jsx("ol", { className: "flex min-w-0 items-center gap-1.5 text-[0.875rem] text-muted-foreground", children: items.map((c, i) => {
3455
+ const last = i === items.length - 1;
3456
+ return /* @__PURE__ */ jsxs("li", { className: cn("flex items-center gap-1.5", last ? "min-w-0" : "shrink-0"), children: [
3457
+ c.href && !last ? /* @__PURE__ */ jsx(DocLink, { href: c.href, className: "inline-flex min-h-11 items-center transition-colors hover:text-foreground sm:min-h-0", children: c.label }) : /* @__PURE__ */ jsx("span", { "aria-current": last ? "page" : void 0, className: cn("truncate", last && "text-foreground"), children: c.label }),
3458
+ !last ? /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }) : null
3459
+ ] }, i);
3460
+ }) }) }),
3461
+ action ? /* @__PURE__ */ jsx("div", { className: "shrink-0 text-[0.875rem]", children: action }) : null
3462
+ ] });
3463
+ }
3464
+ function DocsPager({ prev, next, className }) {
3465
+ if (!prev && !next) return null;
3466
+ const card = (l, dir) => /* @__PURE__ */ jsxs(
3467
+ DocLink,
3468
+ {
3469
+ href: l.href,
3470
+ className: cn(
3471
+ "group flex min-h-20 flex-col justify-center gap-1 rounded-2xl border border-border bg-card px-5 py-4 transition-colors hover:border-oca-hairline-strong",
3472
+ dir === "next" && "items-end text-right sm:col-start-2"
3473
+ ),
3474
+ children: [
3475
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
3476
+ dir === "prev" ? /* @__PURE__ */ jsx(ArrowLeft, { "aria-hidden": true, className: "size-3.5" }) : null,
3477
+ dir === "prev" ? "Previous" : "Next",
3478
+ l.section ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\xB7" }) : null,
3479
+ l.section ? /* @__PURE__ */ jsx("span", { className: "truncate", children: l.section }) : null,
3480
+ dir === "next" ? /* @__PURE__ */ jsx(ArrowRight, { "aria-hidden": true, className: "size-3.5" }) : null
3481
+ ] }),
3482
+ /* @__PURE__ */ jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: l.label })
3483
+ ]
3484
+ }
3485
+ );
3486
+ return /* @__PURE__ */ jsxs("nav", { "aria-label": "Previous and next page", className: cn("grid grid-cols-1 gap-3 border-t border-border pt-8 sm:grid-cols-2", className), children: [
3487
+ prev ? card(prev, "prev") : null,
3488
+ next ? card(next, "next") : null
3489
+ ] });
3490
+ }
3491
+ function useHeadings(selector = "#docs-content", key) {
3492
+ const [items, setItems] = useState([]);
3493
+ useEffect(() => {
3494
+ const read = () => {
3495
+ const root = document.querySelector(selector);
3496
+ if (!root) return setItems([]);
3497
+ setItems(
3498
+ Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
3499
+ id: h.id,
3500
+ // The anchor link's "#" is not part of the name.
3501
+ label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
3502
+ level: h.tagName === "H3" ? 3 : 2
3503
+ }))
3504
+ );
3505
+ };
3506
+ const raf = requestAnimationFrame(read);
3507
+ const t = setTimeout(read, 80);
3508
+ return () => {
3509
+ cancelAnimationFrame(raf);
3510
+ clearTimeout(t);
3511
+ };
3512
+ }, [selector, key]);
3513
+ const activeId = useActiveHeading(items.map((i) => i.id));
3514
+ return { items, activeId };
3515
+ }
3516
+ function OnThisPage({
3517
+ items,
3518
+ activeId,
3519
+ title = "On this page",
3520
+ onNavigate,
3521
+ className
3522
+ }) {
3523
+ const id = useId();
3524
+ if (items.length === 0) return null;
3525
+ return (
3526
+ // With no visible title (a folded list under its own summary) the name is still "On this page".
3527
+ /* @__PURE__ */ jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
3528
+ title ? /* @__PURE__ */ jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
3529
+ /* @__PURE__ */ jsx("ul", { children: items.map((t) => {
3530
+ const on = t.id === activeId;
3531
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
3532
+ "a",
3533
+ {
3534
+ href: `#${t.id}`,
3535
+ onClick: onNavigate,
3536
+ "aria-current": on ? "location" : void 0,
3537
+ className: cn(
3538
+ "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
3539
+ t.level === 3 ? "pl-7" : "pl-4",
3540
+ on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
3541
+ ),
3542
+ children: t.label
3543
+ }
3544
+ ) }, t.id);
3545
+ }) })
3546
+ ] })
3547
+ );
3548
+ }
3549
+ var CALLOUT_TONE = { note: "neutral", warning: "brand", danger: "danger" };
3550
+ function Callout({
3551
+ tone = "note",
3552
+ title,
3553
+ children,
3554
+ className
3555
+ }) {
3556
+ return /* @__PURE__ */ jsx(
3557
+ Notice,
3558
+ {
3559
+ tone: CALLOUT_TONE[tone],
3560
+ title,
3561
+ role: "note",
3562
+ className: cn("my-6 [&_p]:my-0 [&_p]:text-[0.9375rem] [&_p]:leading-relaxed [&_p+p]:mt-3", className),
3563
+ children
3564
+ }
3565
+ );
3566
+ }
3567
+ function Step({ title, id, children }) {
3568
+ return /* @__PURE__ */ jsxs("li", { className: "relative pb-8 pl-11 last:pb-0 [counter-increment:oca-step]", children: [
3569
+ /* @__PURE__ */ jsx(
3570
+ "span",
3571
+ {
3572
+ "aria-hidden": true,
3573
+ className: "absolute left-0 top-0 flex size-7 items-center justify-center rounded-full border border-oca-hairline-strong bg-card text-[0.8125rem] oca-tabular text-foreground before:content-[counter(oca-step)]"
3574
+ }
3575
+ ),
3576
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute bottom-1 left-[0.8125rem] top-9 w-px bg-border" }),
3577
+ /* @__PURE__ */ jsx("h3", { id, className: "scroll-mt-28 pt-0.5 text-[1.0625rem] font-medium leading-snug tracking-[-0.008em] text-foreground", children: title }),
3578
+ /* @__PURE__ */ jsx("div", { className: "mt-2 text-muted-foreground [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", children })
3579
+ ] });
3580
+ }
3581
+ function Steps({ children, className }) {
3582
+ return /* @__PURE__ */ jsx("ol", { className: cn("not-prose my-8 flex flex-col [counter-reset:oca-step] [&>li:last-child>span:nth-child(2)]:hidden", className), children });
3583
+ }
3584
+ function LinkCard({
3585
+ href,
3586
+ title,
3587
+ description,
3588
+ icon,
3589
+ meta,
3590
+ className
3591
+ }) {
3592
+ const Arrow = isInternal(href) ? ArrowRight : ArrowUpRight;
3593
+ return /* @__PURE__ */ jsxs(
3594
+ DocLink,
3595
+ {
3596
+ href,
3597
+ className: cn(
3598
+ "group flex h-full flex-col gap-3 rounded-[1.25rem] border border-border bg-card p-5 transition-colors hover:border-oca-hairline-strong",
3599
+ className
3600
+ ),
3601
+ children: [
3602
+ /* @__PURE__ */ jsxs("span", { className: "flex items-start justify-between gap-3", children: [
3603
+ icon ? /* @__PURE__ */ jsx("span", { className: "flex size-9 shrink-0 items-center justify-center rounded-xl bg-muted text-foreground [&_svg]:size-[1.125rem]", children: icon }) : /* @__PURE__ */ jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }),
3604
+ /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
3605
+ meta,
3606
+ /* @__PURE__ */ jsx(Arrow, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-hover:translate-x-0.5 group-hover:text-foreground" })
3607
+ ] })
3608
+ ] }),
3609
+ icon ? /* @__PURE__ */ jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }) : null,
3610
+ description ? /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem] leading-relaxed text-muted-foreground", children: description }) : null
3611
+ ]
3612
+ }
3613
+ );
3614
+ }
3615
+ function CardGrid({ columns = 2, children, className }) {
3616
+ return /* @__PURE__ */ jsx("div", { className: cn("not-prose my-6 grid grid-cols-1 gap-3 sm:grid-cols-2", columns === 3 && "lg:grid-cols-3", className), children });
3617
+ }
3618
+ function MdxTable({ className, ...props }) {
3619
+ return /* @__PURE__ */ jsx("div", { className: "not-prose my-6 overflow-hidden rounded-2xl border border-border bg-card", children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsx(
3620
+ "table",
3621
+ {
3622
+ className: cn(
3623
+ "w-full border-collapse text-left text-[0.875rem] leading-relaxed",
3624
+ "[&_th]:whitespace-nowrap [&_th]:border-b [&_th]:border-oca-hairline-strong [&_th]:bg-oca-table-head [&_th]:px-4 [&_th]:py-2.5 [&_th]:text-[0.8125rem] [&_th]:font-medium [&_th]:text-foreground",
3625
+ "[&_td]:border-t [&_td]:border-border [&_td]:px-4 [&_td]:py-2.5 [&_td]:align-top [&_td]:text-muted-foreground [&_tbody_tr:first-child_td]:border-t-0",
3626
+ "[&_td_code]:bg-transparent [&_td_code]:p-0 [&_td_code]:text-foreground [&_td:first-child]:text-foreground",
3627
+ "[&_[align=center]]:text-center [&_[align=right]]:text-right",
3628
+ // On a phone a cell keeps a readable width; the table scrolls instead of crushing it.
3629
+ "max-sm:[&_td]:min-w-[9rem]",
3630
+ className
3631
+ ),
3632
+ ...props
3633
+ }
3634
+ ) }) });
3635
+ }
3636
+ function ApiTable({
3637
+ rows,
3638
+ caption,
3639
+ nameHeader = "Name",
3640
+ className
3641
+ }) {
3642
+ const hasDefault = rows.some((r) => r.default !== void 0);
3643
+ const marks = (r) => /* @__PURE__ */ jsxs(Fragment, { children: [
3644
+ r.required ? /* @__PURE__ */ jsx("span", { className: "text-[0.75rem] text-oca-accent-ink", children: "Required" }) : null,
3645
+ r.deprecated ? /* @__PURE__ */ jsx(Badge, { tone: "muted", children: "Deprecated" }) : null,
3646
+ r.status ? /* @__PURE__ */ jsx(StatusBadge, { status: r.status }) : null
3647
+ ] });
3648
+ return /* @__PURE__ */ jsxs("div", { className: cn("not-prose my-6", className), children: [
3649
+ /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-2xl border border-border bg-card max-sm:hidden", children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-left text-[0.875rem]", children: [
3650
+ caption ? /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }) : null,
3651
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-oca-hairline-strong bg-oca-table-head text-[0.8125rem]", children: [
3652
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: nameHeader }),
3653
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Type" }),
3654
+ hasDefault ? /* @__PURE__ */ jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Default" }) : null,
3655
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Description" })
3656
+ ] }) }),
3657
+ /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-border", children: rows.map((r) => /* @__PURE__ */ jsxs("tr", { className: "align-top", children: [
3658
+ /* @__PURE__ */ jsx("th", { scope: "row", className: "px-4 py-3 text-left font-normal", children: /* @__PURE__ */ jsxs("span", { className: "flex flex-col items-start gap-1", children: [
3659
+ /* @__PURE__ */ jsx("code", { className: cn("font-mono text-[0.8125rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
3660
+ marks(r)
3661
+ ] }) }),
3662
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.type ?? "\u2014" }),
3663
+ hasDefault ? /* @__PURE__ */ jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.default ?? "\u2014" }) : null,
3664
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-3 leading-relaxed text-muted-foreground", children: r.description })
3665
+ ] }, r.name)) })
3666
+ ] }) }) }),
3667
+ /* @__PURE__ */ jsx("ul", { "aria-label": caption, className: "divide-y divide-border rounded-2xl border border-border bg-card sm:hidden", children: rows.map((r) => /* @__PURE__ */ jsxs("li", { className: "flex flex-col gap-1.5 px-4 py-3.5", children: [
3668
+ /* @__PURE__ */ jsxs("span", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
3669
+ /* @__PURE__ */ jsx("code", { className: cn("font-mono text-[0.875rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
3670
+ r.type ? /* @__PURE__ */ jsx("code", { className: "break-all font-mono text-[0.8125rem] text-muted-foreground", children: r.type }) : null
3671
+ ] }),
3672
+ /* @__PURE__ */ jsx("span", { className: "flex flex-wrap items-center gap-2 empty:hidden", children: marks(r) }),
3673
+ r.description ? /* @__PURE__ */ jsx("span", { className: "text-[0.875rem] leading-relaxed text-muted-foreground", children: r.description }) : null,
3674
+ r.default !== void 0 ? /* @__PURE__ */ jsxs("span", { className: "text-[0.8125rem] text-muted-foreground", children: [
3675
+ "Default ",
3676
+ /* @__PURE__ */ jsx("code", { className: "font-mono text-foreground", children: r.default })
3677
+ ] }) : null
3678
+ ] }, r.name)) })
3679
+ ] });
3680
+ }
3681
+ function useDarkMode() {
3682
+ const [dark, setDark] = useState(false);
3683
+ useEffect(() => {
3684
+ const root = document.documentElement;
3685
+ const read = () => setDark(root.classList.contains("dark"));
3686
+ read();
3687
+ const mo = new MutationObserver(read);
3688
+ mo.observe(root, { attributes: true, attributeFilter: ["class"] });
3689
+ return () => mo.disconnect();
3690
+ }, []);
3691
+ return dark;
3692
+ }
3693
+ function mermaidTheme(el) {
3694
+ const css = getComputedStyle(el);
3695
+ const v = (name) => css.getPropertyValue(name).trim();
3696
+ const card = v("--card");
3697
+ const muted = v("--muted");
3698
+ const text = v("--foreground");
3699
+ const subtle = v("--muted-foreground");
3700
+ const line = v("--input");
3701
+ const hair = v("--oca-hairline-strong");
3702
+ return {
3703
+ background: "transparent",
3704
+ fontFamily: css.fontFamily,
3705
+ fontSize: "14px",
3706
+ textColor: text,
3707
+ mainBkg: card,
3708
+ primaryColor: card,
3709
+ primaryTextColor: text,
3710
+ primaryBorderColor: hair,
3711
+ secondaryColor: muted,
3712
+ secondaryTextColor: text,
3713
+ secondaryBorderColor: hair,
3714
+ tertiaryColor: muted,
3715
+ tertiaryTextColor: text,
3716
+ tertiaryBorderColor: hair,
3717
+ nodeBorder: hair,
3718
+ lineColor: line,
3719
+ edgeLabelBackground: card,
3720
+ clusterBkg: muted,
3721
+ clusterBorder: hair,
3722
+ titleColor: text,
3723
+ noteBkgColor: muted,
3724
+ noteTextColor: text,
3725
+ noteBorderColor: hair,
3726
+ actorBkg: card,
3727
+ actorBorder: hair,
3728
+ actorTextColor: text,
3729
+ actorLineColor: line,
3730
+ signalColor: text,
3731
+ signalTextColor: text,
3732
+ labelBoxBkgColor: card,
3733
+ labelBoxBorderColor: hair,
3734
+ labelTextColor: text,
3735
+ loopTextColor: subtle,
3736
+ activationBkgColor: muted,
3737
+ activationBorderColor: hair,
3738
+ sequenceNumberColor: card
3739
+ };
3740
+ }
3741
+ function naturalSize(svg) {
3742
+ const w = svg.match(/viewBox="[\d.-]+ [\d.-]+ ([\d.]+) [\d.]+"/)?.[1];
3743
+ if (!w) return svg;
3744
+ return svg.replace(/<svg([^>]*?)\swidth="100%"/, `<svg$1 width="${Math.ceil(Number(w))}"`).replace(/max-width:\s*[\d.]+px;?/, "");
3745
+ }
3746
+ function Diagram({ chart, caption, load, className }) {
3747
+ const ref = useRef(null);
3748
+ const dark = useDarkMode();
3749
+ const raw = useId();
3750
+ const [svg, setSvg] = useState(null);
3751
+ const [failed, setFailed] = useState(false);
3752
+ useEffect(() => {
3753
+ let live = true;
3754
+ const el = ref.current;
3755
+ if (!el) return;
3756
+ (async () => {
3757
+ try {
3758
+ const mod = await load();
3759
+ const mermaid = "default" in mod ? mod.default : mod;
3760
+ mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme: "base", themeVariables: mermaidTheme(el) });
3761
+ const { svg: drawn } = await mermaid.render(`oca-diagram-${raw.replace(/[^a-zA-Z0-9]/g, "")}-${dark ? "d" : "l"}`, chart);
3762
+ if (live) {
3763
+ setSvg(naturalSize(drawn));
3764
+ setFailed(false);
3765
+ }
3766
+ } catch {
3767
+ if (live) setFailed(true);
3768
+ }
3769
+ })();
3770
+ return () => {
3771
+ live = false;
3772
+ };
3773
+ }, [chart, dark, load, raw]);
3774
+ if (failed) return /* @__PURE__ */ jsx(CodeBlock, { code: chart, caption: "Diagram (shown as its source)", className: cn("my-6", className) });
3775
+ return /* @__PURE__ */ jsxs("figure", { ref, className: cn("not-prose my-6 overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children: [
3776
+ svg ? /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsx(
3777
+ "div",
3778
+ {
3779
+ className: "flex w-max min-w-full justify-center p-6 [&_svg]:h-auto [&_svg]:max-w-none",
3780
+ role: "img",
3781
+ "aria-label": typeof caption === "string" ? caption : "Diagram",
3782
+ dangerouslySetInnerHTML: { __html: svg }
3783
+ }
3784
+ ) }) : /* @__PURE__ */ jsx("div", { role: "status", "aria-label": "Drawing the diagram", className: "p-6", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-40 w-full rounded-xl" }) }),
3785
+ caption ? /* @__PURE__ */ jsx("figcaption", { className: "border-t border-border px-5 py-3 text-[0.8125rem] text-muted-foreground", children: caption }) : null
3786
+ ] });
3787
+ }
3788
+ var HEADING = {
3789
+ h1: "oca-display-3 mb-4 text-foreground",
3790
+ h2: "mb-3 mt-12 text-[1.375rem] font-medium leading-tight tracking-[-0.015em] text-foreground md:text-[1.5rem]",
3791
+ h3: "mb-2 mt-9 text-[1.125rem] font-medium leading-snug tracking-[-0.01em] text-foreground",
3792
+ h4: "mb-2 mt-7 text-[1rem] font-medium leading-snug text-foreground"
3793
+ };
3794
+ function DocsHeading({
3795
+ as: Tag,
3796
+ id,
3797
+ children,
3798
+ className,
3799
+ ...props
3800
+ }) {
3801
+ return /* @__PURE__ */ jsxs(Tag, { id, className: cn("group scroll-mt-28", HEADING[Tag], className), ...props, children: [
3802
+ /* @__PURE__ */ jsx("span", { "data-heading-text": "", children }),
3803
+ id && Tag !== "h1" ? /* @__PURE__ */ jsxs(
3804
+ "a",
3805
+ {
3806
+ href: `#${id}`,
3807
+ className: "ml-2 inline-block rounded-md px-1 align-baseline text-[0.85em] font-normal text-oca-subtle no-underline opacity-0 transition-opacity hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100",
3808
+ children: [
3809
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "#" }),
3810
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Link to this section" })
3811
+ ]
3812
+ }
3813
+ ) : null
3814
+ ] });
3815
+ }
3816
+ function useMacKeys() {
3817
+ const [mac, setMac] = useState(true);
3818
+ useEffect(() => {
3819
+ setMac(/Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent));
3820
+ }, []);
3821
+ return mac;
3822
+ }
3823
+ var typing = (el) => el instanceof HTMLElement && (el.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName));
3824
+ var SearchButton = forwardRef(function SearchButton2({ label = "Search", onClick, className }, ref) {
3825
+ const mac = useMacKeys();
3826
+ return /* @__PURE__ */ jsxs(
3827
+ "button",
3828
+ {
3829
+ ref,
3830
+ type: "button",
3831
+ onClick,
3832
+ "aria-keyshortcuts": mac ? "Meta+K" : "Control+K",
3833
+ className: cn(
3834
+ "inline-flex size-10 items-center justify-center gap-2 rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
3835
+ "md:h-10 md:w-56 md:justify-start md:border md:border-border md:bg-card md:pl-3.5 md:pr-2 md:hover:border-oca-hairline-strong md:hover:bg-card",
3836
+ className
3837
+ ),
3838
+ children: [
3839
+ /* @__PURE__ */ jsx(Search, { "aria-hidden": true, className: "size-[1.125rem] shrink-0 md:size-4" }),
3840
+ /* @__PURE__ */ jsx("span", { className: "sr-only flex-1 text-left text-[0.9375rem] md:not-sr-only", children: label }),
3841
+ /* @__PURE__ */ jsx(Kbd, { "aria-hidden": true, className: "hidden md:inline-flex", children: mac ? "\u2318K" : "Ctrl K" })
3842
+ ]
3843
+ }
3844
+ );
3845
+ });
3846
+ function SearchDialog({
3847
+ onQuery,
3848
+ open: openProp,
3849
+ onOpenChange,
3850
+ onSelect,
3851
+ button = true,
3852
+ hotkey = true,
3853
+ label = "Search",
3854
+ placeholder = "Search the docs",
3855
+ idle,
3856
+ defaultQuery = "",
3857
+ debounceMs = 120,
3858
+ className
3859
+ }) {
3860
+ const [own, setOwn] = useState(false);
3861
+ const open = openProp ?? own;
3862
+ const setOpen = (v) => {
3863
+ if (openProp === void 0) setOwn(v);
3864
+ onOpenChange?.(v);
3865
+ };
3866
+ const [query, setQuery] = useState(defaultQuery);
3867
+ const [groups, setGroups] = useState([]);
3868
+ const [state, setState] = useState("idle");
3869
+ const [active, setActive] = useState(0);
3870
+ const listId = useId();
3871
+ const listRef = useRef(null);
3872
+ const buttonRef = useRef(null);
3873
+ const returnTo = useRef(null);
3874
+ const flat = useMemo(() => groups.flatMap((g) => g.results), [groups]);
3875
+ const latest = useRef({ open, setOpen, onQuery });
3876
+ latest.current = { open, setOpen, onQuery };
3877
+ useEffect(() => {
3878
+ if (!hotkey) return;
3879
+ const onKey = (e) => {
3880
+ const { open: isOpen, setOpen: set } = latest.current;
3881
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
3882
+ e.preventDefault();
3883
+ set(!isOpen);
3884
+ } else if (e.key === "/" && !isOpen && !typing(e.target)) {
3885
+ e.preventDefault();
3886
+ set(true);
3887
+ }
3888
+ };
3889
+ window.addEventListener("keydown", onKey);
3890
+ return () => window.removeEventListener("keydown", onKey);
3891
+ }, [hotkey]);
3892
+ useEffect(() => {
3893
+ const q = query.trim();
3894
+ if (!q) {
3895
+ setGroups([]);
3896
+ setState("idle");
3897
+ return;
3898
+ }
3899
+ const ctl = new AbortController();
3900
+ setState("loading");
3901
+ const t = setTimeout(async () => {
3902
+ try {
3903
+ const out = await latest.current.onQuery(q, ctl.signal);
3904
+ if (ctl.signal.aborted) return;
3905
+ setGroups(out.filter((g) => g.results.length > 0));
3906
+ setActive(0);
3907
+ setState("done");
3908
+ } catch {
3909
+ if (!ctl.signal.aborted) setState("error");
3910
+ }
3911
+ }, debounceMs);
3912
+ return () => {
3913
+ clearTimeout(t);
3914
+ ctl.abort();
3915
+ };
3916
+ }, [query, debounceMs]);
3917
+ useEffect(() => {
3918
+ listRef.current?.querySelector('[aria-selected="true"]')?.scrollIntoView({ block: "nearest" });
3919
+ }, [active]);
3920
+ const choose = (r) => {
3921
+ setOpen(false);
3922
+ if (onSelect) onSelect(r);
3923
+ else window.location.assign(r.href);
3924
+ };
3925
+ const optionId = (i) => `${listId}-o${i}`;
3926
+ const showList = state === "done" && flat.length > 0;
3927
+ let index = -1;
3928
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3929
+ button ? /* @__PURE__ */ jsx(SearchButton, { ref: buttonRef, label, onClick: () => setOpen(true), className }) : null,
3930
+ /* @__PURE__ */ jsx(DialogPrimitive.Root, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
3931
+ /* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: "oca-animate-fade fixed inset-0 z-50 bg-[rgb(10_10_10/0.38)] backdrop-blur-[2px]" }),
3932
+ /* @__PURE__ */ jsxs(
3933
+ DialogPrimitive.Content,
3934
+ {
3935
+ "aria-describedby": void 0,
3936
+ onOpenAutoFocus: () => {
3937
+ const el = document.activeElement;
3938
+ returnTo.current = el instanceof HTMLElement && el !== document.body ? el : null;
3939
+ },
3940
+ onCloseAutoFocus: (e) => {
3941
+ const back = returnTo.current?.isConnected ? returnTo.current : buttonRef.current;
3942
+ if (back) {
3943
+ e.preventDefault();
3944
+ back.focus();
3945
+ }
3946
+ },
3947
+ className: "oca-animate-rise fixed left-1/2 top-3 z-50 flex max-h-[calc(100dvh-1.5rem)] w-[calc(100vw-1.5rem)] -translate-x-1/2 flex-col overflow-hidden rounded-[1.5rem] border border-border bg-popover text-popover-foreground shadow-xl outline-none sm:top-[12vh] sm:max-h-[min(36rem,76vh)] sm:w-[min(92vw,40rem)]",
3948
+ children: [
3949
+ /* @__PURE__ */ jsx(DialogPrimitive.Title, { className: "sr-only", children: label }),
3950
+ /* @__PURE__ */ jsxs("div", { className: "flex h-14 shrink-0 items-center gap-3 border-b border-border pl-5 pr-3", children: [
3951
+ state === "loading" ? /* @__PURE__ */ jsx(Spinner, { className: "size-[1.125rem] text-muted-foreground" }) : /* @__PURE__ */ jsx(Search, { "aria-hidden": true, className: "size-[1.125rem] shrink-0 text-muted-foreground" }),
3952
+ /* @__PURE__ */ jsx(
3953
+ "input",
3954
+ {
3955
+ autoFocus: true,
3956
+ value: query,
3957
+ onChange: (e) => setQuery(e.target.value),
3958
+ onKeyDown: (e) => {
3959
+ if (!showList) return;
3960
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
3961
+ e.preventDefault();
3962
+ const d = e.key === "ArrowDown" ? 1 : -1;
3963
+ setActive((a) => (a + d + flat.length) % flat.length);
3964
+ } else if (e.key === "Enter" && flat[active]) {
3965
+ e.preventDefault();
3966
+ choose(flat[active]);
3967
+ }
3968
+ },
3969
+ placeholder,
3970
+ role: "combobox",
3971
+ "aria-label": label,
3972
+ "aria-expanded": showList,
3973
+ "aria-controls": listId,
3974
+ "aria-autocomplete": "list",
3975
+ "aria-activedescendant": showList ? optionId(active) : void 0,
3976
+ spellCheck: false,
3977
+ autoComplete: "off",
3978
+ className: "h-full min-w-0 flex-1 bg-transparent text-base text-foreground outline-none placeholder:text-oca-subtle"
3979
+ }
3980
+ ),
3981
+ /* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "inline-flex h-8 shrink-0 items-center rounded-md border border-border px-2 text-[0.75rem] text-muted-foreground transition-colors hover:text-foreground", children: [
3982
+ /* @__PURE__ */ jsx("span", { className: "sm:hidden", children: "Close" }),
3983
+ /* @__PURE__ */ jsx("span", { className: "max-sm:hidden", "aria-hidden": true, children: "Esc" }),
3984
+ /* @__PURE__ */ jsx("span", { className: "sr-only max-sm:hidden", children: "Close search" })
3985
+ ] })
3986
+ ] }),
3987
+ /* @__PURE__ */ jsxs("div", { ref: listRef, className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-2", children: [
3988
+ /* @__PURE__ */ jsx("div", { id: listId, role: "listbox", "aria-label": "Results", className: cn(!showList && "hidden"), children: groups.map((g, gi) => /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": typeof g.label === "string" ? g.label : void 0, className: "pb-1", children: [
3989
+ /* @__PURE__ */ jsx("p", { "aria-hidden": true, className: "px-3 pb-1.5 pt-3 text-[0.8125rem] text-muted-foreground", children: g.label }),
3990
+ g.results.map((r) => {
3991
+ index++;
3992
+ const i = index;
3993
+ const on = i === active;
3994
+ return /* @__PURE__ */ jsxs(
3995
+ "a",
3996
+ {
3997
+ id: optionId(i),
3998
+ href: r.href,
3999
+ role: "option",
4000
+ "aria-selected": on,
4001
+ tabIndex: -1,
4002
+ onMouseMove: () => setActive(i),
4003
+ onClick: (e) => {
4004
+ if (e.metaKey || e.ctrlKey || e.shiftKey) return;
4005
+ e.preventDefault();
4006
+ choose(r);
4007
+ },
4008
+ className: cn(
4009
+ "flex items-start gap-3 rounded-xl px-3 py-2.5 transition-colors",
4010
+ on ? "bg-accent" : "hover:bg-accent"
4011
+ ),
4012
+ children: [
4013
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
4014
+ /* @__PURE__ */ jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: r.title }),
4015
+ r.section ? /* @__PURE__ */ jsx("span", { className: "truncate text-[0.8125rem] text-muted-foreground", children: r.section }) : null,
4016
+ r.excerptHtml ? /* @__PURE__ */ jsx(
4017
+ "span",
4018
+ {
4019
+ className: "line-clamp-2 text-[0.875rem] leading-snug text-muted-foreground [&_mark]:rounded-sm [&_mark]:bg-[color-mix(in_oklab,var(--oca-orange)_22%,transparent)] [&_mark]:px-0.5 [&_mark]:text-foreground",
4020
+ dangerouslySetInnerHTML: { __html: r.excerptHtml }
4021
+ }
4022
+ ) : r.excerpt ? /* @__PURE__ */ jsx("span", { className: "line-clamp-2 text-[0.875rem] leading-snug text-muted-foreground", children: r.excerpt }) : null
4023
+ ] }),
4024
+ /* @__PURE__ */ jsx(CornerDownLeft, { "aria-hidden": true, className: cn("mt-1 size-4 shrink-0 text-muted-foreground", !on && "invisible") })
4025
+ ]
4026
+ },
4027
+ r.id
4028
+ );
4029
+ })
4030
+ ] }, gi)) }),
4031
+ state === "idle" ? /* @__PURE__ */ jsx("div", { className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: idle ?? "Type a word: a protocol, a function, an error." }) : null,
4032
+ state === "done" && flat.length === 0 ? /* @__PURE__ */ jsxs("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: [
4033
+ "No results for \u201C",
4034
+ query.trim(),
4035
+ "\u201D."
4036
+ ] }) : null,
4037
+ state === "error" ? /* @__PURE__ */ jsx("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: "Search is not available right now. Try again in a moment." }) : null
4038
+ ] }),
4039
+ /* @__PURE__ */ jsxs("div", { "aria-hidden": true, className: "hidden shrink-0 items-center gap-4 border-t border-border px-5 py-2.5 text-[0.75rem] text-muted-foreground sm:flex", children: [
4040
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
4041
+ /* @__PURE__ */ jsx(Kbd, { children: "\u2191" }),
4042
+ /* @__PURE__ */ jsx(Kbd, { children: "\u2193" }),
4043
+ " to move"
4044
+ ] }),
4045
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
4046
+ /* @__PURE__ */ jsx(Kbd, { children: "\u21B5" }),
4047
+ " to open"
4048
+ ] }),
4049
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
4050
+ /* @__PURE__ */ jsx(Kbd, { children: "esc" }),
4051
+ " to close"
4052
+ ] })
4053
+ ] }),
4054
+ /* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", children: state === "done" ? `${flat.length} result${flat.length === 1 ? "" : "s"}` : "" })
4055
+ ]
4056
+ }
4057
+ )
4058
+ ] }) })
4059
+ ] });
4060
+ }
4061
+ function pretty(content) {
4062
+ try {
4063
+ return JSON.stringify(JSON.parse(content), null, 2);
4064
+ } catch {
4065
+ return null;
4066
+ }
4067
+ }
4068
+ function download(content, filename, mime) {
4069
+ const url = URL.createObjectURL(new Blob([content], { type: mime }));
4070
+ const a = document.createElement("a");
4071
+ a.href = url;
4072
+ a.download = filename;
4073
+ document.body.appendChild(a);
4074
+ a.click();
4075
+ a.remove();
4076
+ setTimeout(() => URL.revokeObjectURL(url), 0);
4077
+ }
4078
+ var BAR_BUTTON = "inline-flex h-7 items-center gap-1.5 rounded-full px-2.5 text-[0.75rem] text-oca-ink-subtle transition-colors hover:bg-white/10 hover:text-white";
4079
+ function ArtifactView({
4080
+ content,
4081
+ title,
4082
+ filename,
4083
+ mime,
4084
+ defaultView = "formatted",
4085
+ maxLines = 28,
4086
+ className
4087
+ }) {
4088
+ const formatted = useMemo(() => pretty(content), [content]);
4089
+ const [view, setView] = useState(formatted ? defaultView : "raw");
4090
+ const shown = view === "formatted" && formatted ? formatted : content;
4091
+ const json = formatted !== null;
4092
+ return /* @__PURE__ */ jsx(
4093
+ CodeBlock,
4094
+ {
4095
+ code: shown,
4096
+ lang: json ? "json" : void 0,
4097
+ caption: title,
4098
+ maxLines,
4099
+ className,
4100
+ actions: /* @__PURE__ */ jsxs(Fragment, { children: [
4101
+ json ? /* @__PURE__ */ jsx("span", { role: "group", "aria-label": "View", className: "mr-1 flex items-center rounded-full bg-white/[0.06] p-0.5", children: ["formatted", "raw"].map((v) => /* @__PURE__ */ jsx(
4102
+ "button",
4103
+ {
4104
+ type: "button",
4105
+ "aria-pressed": view === v,
4106
+ onClick: () => setView(v),
4107
+ className: cn(
4108
+ "h-7 rounded-full px-2.5 text-[0.75rem] transition-colors",
4109
+ view === v ? "bg-white/[0.12] text-white" : "text-oca-ink-subtle hover:text-white"
4110
+ ),
4111
+ children: v === "formatted" ? "Formatted" : "Raw"
4112
+ },
4113
+ v
4114
+ )) }) : null,
4115
+ filename ? /* @__PURE__ */ jsxs(
4116
+ "button",
4117
+ {
4118
+ type: "button",
4119
+ onClick: () => download(content, filename, mime ?? (json ? "application/json" : "text/plain")),
4120
+ className: BAR_BUTTON,
4121
+ "aria-label": `Download ${filename}`,
4122
+ children: [
4123
+ /* @__PURE__ */ jsx(Download, { "aria-hidden": true, className: "size-3.5" }),
4124
+ /* @__PURE__ */ jsx("span", { className: "max-sm:hidden", children: "Download" })
4125
+ ]
4126
+ }
4127
+ ) : null
4128
+ ] })
4129
+ }
4130
+ );
4131
+ }
4132
+ function DropZone({
4133
+ onFile,
4134
+ onText,
4135
+ accept,
4136
+ title = "Drop a file here, or choose one",
4137
+ hint,
4138
+ privacy = "It stays in your browser. Only its hash leaves this page.",
4139
+ file,
4140
+ progress,
4141
+ progressLabel = "Hashing",
4142
+ onClear,
4143
+ error,
4144
+ disabled = false,
4145
+ className
4146
+ }) {
4147
+ const input = useRef(null);
4148
+ const [over, setOver] = useState(false);
4149
+ const depth = useRef(0);
4150
+ const [mode, setMode] = useState("file");
4151
+ const [text, setText] = useState("");
4152
+ const errorId = useId();
4153
+ const titleId = useId();
4154
+ const busy = progress !== null && progress !== void 0;
4155
+ const pct = busy ? Math.round(Math.max(0, Math.min(1, progress)) * 100) : 0;
4156
+ const take = (f) => {
4157
+ if (f && !disabled) onFile(f);
4158
+ };
4159
+ const privacyLine = privacy === null ? null : /* @__PURE__ */ jsxs("p", { className: "flex items-start gap-2 text-[0.8125rem] leading-snug text-muted-foreground", children: [
4160
+ /* @__PURE__ */ jsx(Lock, { "aria-hidden": true, className: "mt-0.5 size-3.5 shrink-0" }),
4161
+ /* @__PURE__ */ jsx("span", { children: privacy })
4162
+ ] });
4163
+ if (mode === "text" && onText) {
4164
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
4165
+ /* @__PURE__ */ jsx(
4166
+ Textarea,
4167
+ {
4168
+ value: text,
4169
+ onChange: (e) => setText(e.target.value),
4170
+ rows: 6,
4171
+ "aria-label": "Text",
4172
+ "aria-describedby": error ? errorId : void 0,
4173
+ "aria-invalid": error ? true : void 0,
4174
+ placeholder: "Paste the text here",
4175
+ className: "font-mono text-base md:text-[0.875rem]"
4176
+ }
4177
+ ),
4178
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
4179
+ /* @__PURE__ */ jsx(Button, { size: "sm", disabled: !text.trim() || disabled, onClick: () => onText(text), children: "Use this text" }),
4180
+ /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: () => setMode("file"), children: "Choose a file instead" })
4181
+ ] }),
4182
+ error ? /* @__PURE__ */ jsx("p", { id: errorId, role: "alert", className: "text-[0.8125rem] text-destructive", children: error }) : null,
4183
+ privacyLine
4184
+ ] });
4185
+ }
4186
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
4187
+ /* @__PURE__ */ jsxs(
4188
+ "div",
4189
+ {
4190
+ role: "group",
4191
+ "aria-labelledby": titleId,
4192
+ "aria-describedby": error ? errorId : void 0,
4193
+ "aria-busy": busy || void 0,
4194
+ onDragEnter: (e) => {
4195
+ e.preventDefault();
4196
+ depth.current++;
4197
+ if (!disabled) setOver(true);
4198
+ },
4199
+ onDragOver: (e) => e.preventDefault(),
4200
+ onDragLeave: () => {
4201
+ depth.current = Math.max(0, depth.current - 1);
4202
+ if (depth.current === 0) setOver(false);
4203
+ },
4204
+ onDrop: (e) => {
4205
+ e.preventDefault();
4206
+ depth.current = 0;
4207
+ setOver(false);
4208
+ take(e.dataTransfer.files?.[0]);
4209
+ },
4210
+ className: cn(
4211
+ "relative flex flex-col gap-3 rounded-[1.25rem] border border-dashed transition-colors",
4212
+ file ? "px-4 py-4 sm:px-5" : "items-center px-5 py-8 text-center md:py-10",
4213
+ over ? "border-foreground bg-accent" : "border-oca-hairline-strong bg-card",
4214
+ error && "border-destructive",
4215
+ disabled && "opacity-55"
4216
+ ),
4217
+ children: [
4218
+ /* @__PURE__ */ jsx(
4219
+ "input",
4220
+ {
4221
+ ref: input,
4222
+ type: "file",
4223
+ accept,
4224
+ disabled,
4225
+ tabIndex: -1,
4226
+ "aria-hidden": true,
4227
+ className: "sr-only",
4228
+ onChange: (e) => {
4229
+ take(e.target.files?.[0]);
4230
+ e.target.value = "";
4231
+ }
4232
+ }
4233
+ ),
4234
+ file ? /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-3", children: [
4235
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
4236
+ /* @__PURE__ */ jsx("span", { className: "flex size-10 shrink-0 items-center justify-center rounded-xl bg-muted text-foreground", children: busy ? /* @__PURE__ */ jsx(FileText, { "aria-hidden": true, className: "size-5" }) : /* @__PURE__ */ jsx(Check, { "aria-hidden": true, className: "size-5" }) }),
4237
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
4238
+ /* @__PURE__ */ jsx("span", { id: titleId, className: "truncate text-[0.9375rem] font-medium", title: file.name, children: file.name }),
4239
+ /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] text-muted-foreground", children: [formatBytes(file.size), file.type].filter(Boolean).join(" \xB7 ") })
4240
+ ] }),
4241
+ !busy && onClear ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "secondary", onClick: onClear, disabled, className: "shrink-0", children: "Choose another" }) : null
4242
+ ] }),
4243
+ busy ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
4244
+ /* @__PURE__ */ jsx(
4245
+ "div",
4246
+ {
4247
+ role: "progressbar",
4248
+ "aria-valuemin": 0,
4249
+ "aria-valuemax": 100,
4250
+ "aria-valuenow": pct,
4251
+ "aria-label": typeof progressLabel === "string" ? progressLabel : "Progress",
4252
+ className: "h-1.5 overflow-hidden rounded-full bg-muted",
4253
+ children: /* @__PURE__ */ jsx("div", { className: "h-full rounded-full bg-foreground transition-[width] duration-200", style: { width: `${pct}%` } })
4254
+ }
4255
+ ),
4256
+ /* @__PURE__ */ jsxs("span", { className: "text-[0.8125rem] text-muted-foreground oca-tabular", children: [
4257
+ progressLabel,
4258
+ " ",
4259
+ pct,
4260
+ "%"
4261
+ ] })
4262
+ ] }) : null
4263
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4264
+ /* @__PURE__ */ jsx("span", { className: "flex size-11 items-center justify-center rounded-full bg-muted text-foreground", children: /* @__PURE__ */ jsx(Upload, { "aria-hidden": true, className: "size-5" }) }),
4265
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
4266
+ /* @__PURE__ */ jsx("p", { id: titleId, className: "text-[1rem] font-medium", children: over ? "Drop it to add it" : title }),
4267
+ hint ? /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: hint }) : null
4268
+ ] }),
4269
+ /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-wrap items-center justify-center gap-2", children: [
4270
+ /* @__PURE__ */ jsx(Button, { size: "sm", variant: "secondary", disabled, onClick: () => input.current?.click(), children: "Choose a file" }),
4271
+ onText ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", disabled, onClick: () => setMode("text"), children: "Paste text instead" }) : null
4272
+ ] })
4273
+ ] })
4274
+ ]
4275
+ }
4276
+ ),
4277
+ error ? /* @__PURE__ */ jsx("p", { id: errorId, role: "alert", className: "text-[0.8125rem] text-destructive", children: error }) : null,
4278
+ privacyLine
4279
+ ] });
4280
+ }
4281
+ function FormSection({
4282
+ n,
4283
+ title,
4284
+ hint,
4285
+ status,
4286
+ action,
4287
+ as: Heading = "h2",
4288
+ id,
4289
+ children,
4290
+ className
4291
+ }) {
4292
+ const titleId = useId();
4293
+ const tight = useDensity() === "compact";
4294
+ return /* @__PURE__ */ jsxs(
4295
+ "section",
4296
+ {
4297
+ id,
4298
+ "aria-labelledby": titleId,
4299
+ "aria-current": status === "current" ? "step" : void 0,
4300
+ className: cn("scroll-mt-24 rounded-[1.25rem] border border-border bg-card", className),
4301
+ children: [
4302
+ /* @__PURE__ */ jsxs("header", { className: cn("flex items-start gap-3.5", tight ? "px-5 pt-5" : "px-6 pt-6"), children: [
4303
+ n !== void 0 ? /* @__PURE__ */ jsx(
4304
+ "span",
4305
+ {
4306
+ "aria-hidden": true,
4307
+ className: cn(
4308
+ "mt-px flex size-7 shrink-0 items-center justify-center rounded-full border text-[0.8125rem] oca-tabular",
4309
+ status === "done" && "border-primary bg-primary text-primary-foreground",
4310
+ status === "current" && "border-brand text-oca-accent-ink",
4311
+ status === "blocked" && "border-destructive text-destructive",
4312
+ (status === "upcoming" || status === void 0) && "border-oca-hairline-strong text-muted-foreground"
4313
+ ),
4314
+ children: status === "done" ? /* @__PURE__ */ jsx(Check, { className: "size-3.5", strokeWidth: 3 }) : n
4315
+ }
4316
+ ) : null,
4317
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
4318
+ /* @__PURE__ */ jsxs(Heading, { id: titleId, className: "text-[1.0625rem] font-medium leading-snug tracking-[-0.008em]", children: [
4319
+ n !== void 0 ? /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
4320
+ "Step ",
4321
+ n,
4322
+ ": "
4323
+ ] }) : null,
4324
+ title,
4325
+ status === "done" ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (done)" }) : null
4326
+ ] }),
4327
+ hint ? /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: hint }) : null
4328
+ ] }),
4329
+ action ? /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action }) : null
4330
+ ] }),
4331
+ /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", tight ? "gap-4 p-5" : "gap-5 p-6", n !== void 0 && (tight ? "sm:pl-[3.875rem]" : "sm:pl-[4.125rem]")), children })
4332
+ ]
4333
+ }
4334
+ );
4335
+ }
4336
+ var STATE_TONE = { good: "success", attention: "brand", bad: "danger", neutral: "neutral", quiet: "muted" };
4337
+ function StateBadge({
4338
+ tone = "neutral",
4339
+ children,
4340
+ title,
4341
+ className
4342
+ }) {
4343
+ return /* @__PURE__ */ jsx(Badge, { tone: STATE_TONE[tone], title, className, children });
4344
+ }
4345
+ function createStateBadge(states) {
4346
+ function ProtocolStateBadge({ state, className }) {
4347
+ const def = states[state];
4348
+ if (!def) {
4349
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
4350
+ console.warn(`StateBadge: no state "${state}"; known: ${Object.keys(states).join(", ")}`);
4351
+ }
4352
+ return /* @__PURE__ */ jsx(StateBadge, { className, children: String(state) });
4353
+ }
4354
+ return /* @__PURE__ */ jsx(StateBadge, { tone: def.tone, title: def.hint, className, children: def.label });
4355
+ }
4356
+ return ProtocolStateBadge;
4357
+ }
4358
+ function BlockHeight({
4359
+ height,
4360
+ label = false,
4361
+ link = true,
4362
+ network = "mainnet",
4363
+ className
4364
+ }) {
4365
+ const text = `${label ? "block " : ""}${formatBlockHeight(height)}`;
4366
+ if (!link) return /* @__PURE__ */ jsx("span", { className: cn("oca-tabular", className), children: text });
4367
+ return /* @__PURE__ */ jsxs(
4368
+ "a",
4369
+ {
4370
+ href: explorerUrl("block", Math.trunc(height), network),
4371
+ target: "_blank",
4372
+ rel: "noreferrer",
4373
+ title: `Block ${formatBlockHeight(height)} on mempool.space`,
4374
+ className: cn("oca-tabular underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground", className),
4375
+ children: [
4376
+ text,
4377
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (opens mempool.space in a new tab)" })
4378
+ ]
4379
+ }
4380
+ );
4381
+ }
4382
+ var ANCHOR = {
4383
+ anchored: { label: "Anchored", tone: "good" },
4384
+ pending: { label: "Anchor pending", tone: "attention" },
4385
+ unverified: { label: "Not checked", tone: "quiet" },
4386
+ none: { label: "Not anchored", tone: "quiet" },
4387
+ fail: { label: "Does not check out", tone: "bad" }
4388
+ };
4389
+ function hostOf(url) {
4390
+ try {
4391
+ return new URL(url).host;
4392
+ } catch {
4393
+ return url;
4394
+ }
4395
+ }
4396
+ function AnchorStatus({
4397
+ state,
4398
+ blockHeight,
4399
+ blockTime,
4400
+ submittedAt,
4401
+ calendar,
4402
+ message,
4403
+ network = "mainnet",
4404
+ variant = "detail",
4405
+ className
4406
+ }) {
4407
+ const def = ANCHOR[state];
4408
+ const block = blockHeight !== void 0 ? /* @__PURE__ */ jsx(BlockHeight, { height: blockHeight, label: true, network }) : null;
4409
+ const line = message ?? (state === "anchored" ? block ? /* @__PURE__ */ jsxs(Fragment, { children: [
4410
+ "In ",
4411
+ block,
4412
+ blockTime !== void 0 ? ` \xB7 ${formatUtc(blockTime)}` : null
4413
+ ] }) : "Its hash is in a Bitcoin block." : state === "pending" ? /* @__PURE__ */ jsxs(Fragment, { children: [
4414
+ "Submitted",
4415
+ submittedAt !== void 0 ? ` ${formatUtc(submittedAt)}` : "",
4416
+ " to",
4417
+ " ",
4418
+ calendar ? hostOf(calendar) : "an OpenTimestamps calendar",
4419
+ ". Waiting for a Bitcoin block."
4420
+ ] }) : state === "unverified" ? /* @__PURE__ */ jsxs(Fragment, { children: [
4421
+ "The proof names ",
4422
+ block ?? "a block",
4423
+ ", but its header could not be fetched to check it."
4424
+ ] }) : state === "fail" ? /* @__PURE__ */ jsxs(Fragment, { children: [
4425
+ "The proof does not lead to ",
4426
+ block ?? "the block it names",
4427
+ "."
4428
+ ] }) : "No timestamp yet. The signature still checks offline.");
4429
+ if (variant === "badge") {
4430
+ const plain = typeof line === "string" ? line : void 0;
4431
+ return /* @__PURE__ */ jsx(StateBadge, { tone: def.tone, title: plain, className, children: def.label });
4432
+ }
4433
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-start gap-1.5", className), children: [
4434
+ /* @__PURE__ */ jsx(StateBadge, { tone: def.tone, children: def.label }),
4435
+ /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: line })
4436
+ ] });
4437
+ }
4438
+ function BlockCountdown({
4439
+ target,
4440
+ tip,
4441
+ from,
4442
+ reached = "Reached",
4443
+ minutesPerBlock = 10,
4444
+ network = "mainnet",
4445
+ className
4446
+ }) {
4447
+ const known = typeof tip === "number";
4448
+ const left = known ? target - tip : null;
4449
+ const done = left !== null && left <= 0;
4450
+ const share = known && from !== void 0 && target > from ? Math.min(1, Math.max(0, (tip - from) / (target - from))) : null;
4451
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
4452
+ /* @__PURE__ */ jsx("p", { className: "text-[0.9375rem] leading-snug", children: !known ? /* @__PURE__ */ jsxs(Fragment, { children: [
4453
+ "At ",
4454
+ /* @__PURE__ */ jsx(BlockHeight, { height: target, label: true, network })
4455
+ ] }) : done ? /* @__PURE__ */ jsxs(Fragment, { children: [
4456
+ reached,
4457
+ " at ",
4458
+ /* @__PURE__ */ jsx(BlockHeight, { height: target, label: true, network })
4459
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4460
+ "In ",
4461
+ /* @__PURE__ */ jsx("span", { className: "oca-tabular font-medium", children: formatBlockHeight(left) }),
4462
+ " block",
4463
+ left === 1 ? "" : "s",
4464
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
4465
+ ", ",
4466
+ blocksToDuration(left, minutesPerBlock)
4467
+ ] })
4468
+ ] }) }),
4469
+ share !== null ? /* @__PURE__ */ jsx(
4470
+ "div",
4471
+ {
4472
+ role: "progressbar",
4473
+ "aria-valuemin": 0,
4474
+ "aria-valuemax": 100,
4475
+ "aria-valuenow": Math.round(share * 100),
4476
+ "aria-label": "Blocks passed",
4477
+ className: "h-1.5 overflow-hidden rounded-full bg-muted",
4478
+ children: /* @__PURE__ */ jsx("div", { className: "h-full rounded-full bg-foreground", style: { width: `${share * 100}%` } })
4479
+ }
4480
+ ) : null,
4481
+ known && !done ? /* @__PURE__ */ jsxs("p", { className: "text-[0.8125rem] text-muted-foreground", children: [
4482
+ "Target ",
4483
+ /* @__PURE__ */ jsx(BlockHeight, { height: target, network }),
4484
+ " \xB7 tip ",
4485
+ /* @__PURE__ */ jsx("span", { className: "oca-tabular", children: formatBlockHeight(tip) })
4486
+ ] }) : null
4487
+ ] });
4488
+ }
4489
+ function Meter({
4490
+ value,
4491
+ max,
4492
+ ghost,
4493
+ label,
4494
+ figure,
4495
+ tone = "ink",
4496
+ size = "md",
4497
+ className
4498
+ }) {
4499
+ const id = useId();
4500
+ const total = max > 0 ? max : 1;
4501
+ const v = Math.max(0, Math.min(1, value / total));
4502
+ const g = ghost ? Math.max(0, Math.min(1 - v, ghost / total)) : 0;
4503
+ const pct = `${Math.round(v * 100)}%`;
4504
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
4505
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-4 text-[0.875rem]", children: [
4506
+ /* @__PURE__ */ jsx("span", { id, className: "min-w-0 truncate", children: label }),
4507
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 oca-tabular text-muted-foreground", children: figure ?? pct })
4508
+ ] }),
4509
+ /* @__PURE__ */ jsxs(
4510
+ "div",
4511
+ {
4512
+ role: "meter",
4513
+ "aria-labelledby": id,
4514
+ "aria-valuemin": 0,
4515
+ "aria-valuemax": max,
4516
+ "aria-valuenow": value,
4517
+ "aria-valuetext": typeof figure === "string" ? figure : pct,
4518
+ className: cn("flex overflow-hidden rounded-full bg-muted", size === "sm" ? "h-1.5" : "h-2.5"),
4519
+ children: [
4520
+ /* @__PURE__ */ jsx(
4521
+ "div",
4522
+ {
4523
+ className: cn("h-full shrink-0 rounded-full", tone === "brand" ? "bg-oca-orange-deep" : "bg-foreground"),
4524
+ style: { width: `${v * 100}%` }
4525
+ }
4526
+ ),
4527
+ g > 0 ? /* @__PURE__ */ jsx(
4528
+ "div",
4529
+ {
4530
+ "aria-hidden": true,
4531
+ className: "-ml-1.5 h-full shrink-0 rounded-r-full pl-1.5 text-foreground/45",
4532
+ style: {
4533
+ width: `calc(${g * 100}% + 0.375rem)`,
4534
+ backgroundImage: "repeating-linear-gradient(-45deg, currentColor 0 2px, transparent 2px 6px)"
4535
+ }
4536
+ }
4537
+ ) : null
4538
+ ]
4539
+ }
4540
+ )
4541
+ ] });
4542
+ }
4543
+ function FilterChips({
4544
+ options,
4545
+ value,
4546
+ onChange,
4547
+ label,
4548
+ className
4549
+ }) {
4550
+ const tight = useDensity() === "compact";
4551
+ const multi = Array.isArray(value);
4552
+ const isOn = (v) => multi ? value.includes(v) : value === v;
4553
+ const press = (v) => {
4554
+ if (multi) {
4555
+ const cur = value;
4556
+ onChange(cur.includes(v) ? cur.filter((x) => x !== v) : [...cur, v]);
4557
+ } else onChange(v);
4558
+ };
4559
+ return /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--background)", className: cn("w-full", className), children: /* @__PURE__ */ jsx("div", { role: "group", "aria-label": label, className: "flex w-max items-center gap-2 py-0.5", children: options.map((o) => {
4560
+ const on = isOn(o.value);
4561
+ return /* @__PURE__ */ jsxs(
4562
+ "button",
4563
+ {
4564
+ type: "button",
4565
+ "aria-pressed": on,
4566
+ onClick: () => press(o.value),
4567
+ className: cn(
4568
+ "inline-flex shrink-0 items-center gap-1.5 rounded-full border px-3.5 text-[0.875rem] transition-colors",
4569
+ tight ? "h-8" : "h-9",
4570
+ on ? "border-foreground bg-foreground text-background" : "border-border bg-card text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
4571
+ ),
4572
+ children: [
4573
+ o.label,
4574
+ o.count !== void 0 ? /* @__PURE__ */ jsx("span", { className: "oca-tabular", children: o.count.toLocaleString("en-US") }) : null
4575
+ ]
4576
+ },
4577
+ o.value
4578
+ );
4579
+ }) }) });
4580
+ }
4581
+ function ToolGrid({
4582
+ tools,
4583
+ as: Heading = "h2",
4584
+ className
4585
+ }) {
4586
+ const tight = useDensity() === "compact";
4587
+ const n = tools.length;
4588
+ return /* @__PURE__ */ jsx(
4589
+ "ul",
4590
+ {
4591
+ className: cn(
4592
+ "grid grid-cols-1 gap-3 sm:grid-cols-2 md:gap-4",
4593
+ // Three or four sit in one row on a wide screen.
4594
+ n === 3 || n === 6 ? "lg:grid-cols-3" : n === 4 ? "xl:grid-cols-4" : null,
4595
+ className
4596
+ ),
4597
+ children: tools.map((t) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
4598
+ "div",
4599
+ {
4600
+ className: cn(
4601
+ "group relative flex h-full flex-col rounded-[1.25rem] border border-border bg-card transition-colors",
4602
+ tight ? "gap-3 p-5" : "gap-4 p-6",
4603
+ "hover:border-oca-hairline-strong has-[a:focus-visible]:ring-2 has-[a:focus-visible]:ring-ring has-[a:focus-visible]:ring-offset-2 has-[a:focus-visible]:ring-offset-background"
4604
+ ),
4605
+ children: [
4606
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
4607
+ t.icon ? /* @__PURE__ */ jsx("span", { className: "flex size-10 items-center justify-center rounded-xl bg-muted text-foreground [&_svg]:size-5", children: t.icon }) : /* @__PURE__ */ jsx("span", {}),
4608
+ /* @__PURE__ */ jsx(
4609
+ ArrowRight,
4610
+ {
4611
+ "aria-hidden": true,
4612
+ className: "size-4 text-muted-foreground transition-transform duration-200 group-hover:translate-x-0.5 group-hover:text-foreground"
4613
+ }
4614
+ )
4615
+ ] }),
4616
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
4617
+ /* @__PURE__ */ jsx(Heading, { className: "oca-title-sm", children: /* @__PURE__ */ jsx(
4618
+ Link,
4619
+ {
4620
+ href: t.href,
4621
+ className: "outline-none after:absolute after:inset-0 after:rounded-[1.25rem] after:content-['']",
4622
+ children: t.label
4623
+ }
4624
+ ) }),
4625
+ t.description ? /* @__PURE__ */ jsx("p", { className: "text-[0.9375rem] leading-relaxed text-muted-foreground", children: t.description }) : null
4626
+ ] })
4627
+ ]
4628
+ }
4629
+ ) }, t.href))
4630
+ }
4631
+ );
4632
+ }
2593
4633
 
2594
- export { Accent, ActivityList, AppCard, AppGrid, BrowserFrame, Closing, CodeBlock, ComparisonTable, Container, CopyButton, DataTable, Display, DocHeader, DocLayout, EmptyLine, EmptyState, EndpointList, ErrorBoundary, ErrorPage, Eyebrow, FactBlock, FactRows, Faq, FloatChip, Footnote, HashChip, KeyValueList, Lead, LegalDocument, LoadingBlock, Monogram, Notice, PackageCard, PageHeader, PageHero, PhoneFrame, ProgressSteps, ProofStrip, Prose, ProtocolGrid, ProtocolHero, ProtocolNav, Reveal, Sats, SatsFigure, ScrollStory, Section, SectionHeading, SectionIntro, SignMessage, SpecCard, SplitBar, StatCard, StatGrid, StepGrid, TextLink, Ticker, TruthTable, UsdApprox, VerifyBox, VerifyReport, monogramGround, monogramLetter, satsText, sectionVariants, useCopy, useInView };
4634
+ export { Accent, ActivityList, AnchorStatus, ApiTable, AppCard, AppGrid, ArtifactView, BlockCountdown, BlockHeight, Breadcrumbs, BrowserFrame, Callout, CardGrid, Closing, CodeBlock, CodeTabs, ComparisonTable, Container, CopyButton, DataTable, Diagram, Display, DocHeader, DocLayout, DocsHeading, DocsPager, DropZone, EmptyLine, EmptyState, EndpointList, ErrorBoundary, ErrorPage, Eyebrow, FactBlock, FactRows, Faq, FilterChips, FloatChip, Footnote, FormSection, HashChip, InstallTabs, KeyValueList, Lead, LegalDocument, LinkCard, LoadingBlock, MdxTable, Meter, Monogram, Notice, OnThisPage, PackageCard, PageHeader, PageHero, PhoneFrame, ProgressSteps, ProofStrip, Prose, ProtocolGrid, ProtocolHero, ProtocolNav, Reveal, Sats, SatsFigure, ScrollStory, SearchButton, SearchDialog, Section, SectionHeading, SectionIntro, SignMessage, SpecCard, SplitBar, StatCard, StatGrid, StateBadge, Step, StepGrid, Steps, TextLink, Ticker, ToolGrid, TruthTable, UsdApprox, VerifyBox, VerifyReport, createStateBadge, languageName, monogramGround, monogramLetter, satsText, sectionVariants, useActiveHeading, useCopy, useHeadings, useInView };
2595
4635
  //# sourceMappingURL=components.mjs.map
2596
4636
  //# sourceMappingURL=components.mjs.map