@orangecheck/app-design 0.6.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -6
- package/dist/brand.js.map +1 -1
- package/dist/brand.mjs.map +1 -1
- package/dist/chrome.d.mts +78 -55
- package/dist/chrome.d.ts +78 -55
- package/dist/chrome.js +1100 -59
- package/dist/chrome.js.map +1 -1
- package/dist/chrome.mjs +1091 -61
- package/dist/chrome.mjs.map +1 -1
- package/dist/code.d.mts +52 -0
- package/dist/code.d.ts +52 -0
- package/dist/code.js +534 -0
- package/dist/code.js.map +1 -0
- package/dist/code.mjs +522 -0
- package/dist/code.mjs.map +1 -0
- package/dist/components.d.mts +216 -42
- package/dist/components.d.ts +216 -42
- package/dist/components.js +3350 -100
- package/dist/components.js.map +1 -1
- package/dist/components.mjs +3293 -103
- package/dist/components.mjs.map +1 -1
- package/dist/docs-DhnstueM.d.ts +219 -0
- package/dist/docs-DiR6s43s.d.mts +219 -0
- package/dist/family.d.mts +2 -0
- package/dist/family.d.ts +2 -0
- package/dist/family.js +167 -0
- package/dist/family.js.map +1 -0
- package/dist/family.mjs +154 -0
- package/dist/family.mjs.map +1 -0
- package/dist/format.d.mts +12 -0
- package/dist/format.d.ts +12 -0
- package/dist/format.js +65 -0
- package/dist/format.js.map +1 -0
- package/dist/format.mjs +58 -0
- package/dist/format.mjs.map +1 -0
- package/dist/hero-Dn37il-9.d.mts +31 -0
- package/dist/hero-Dn37il-9.d.ts +31 -0
- package/dist/index-C6hDqOOS.d.mts +58 -0
- package/dist/index-C6hDqOOS.d.ts +58 -0
- package/dist/index.d.mts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js +4319 -295
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4219 -298
- package/dist/index.mjs.map +1 -1
- package/dist/mdx.d.mts +58 -0
- package/dist/mdx.d.ts +58 -0
- package/dist/mdx.js +1712 -0
- package/dist/mdx.js.map +1 -0
- package/dist/mdx.mjs +1685 -0
- package/dist/mdx.mjs.map +1 -0
- package/dist/primitives.d.mts +73 -5
- package/dist/primitives.d.ts +73 -5
- package/dist/primitives.js +331 -8
- package/dist/primitives.js.map +1 -1
- package/dist/primitives.mjs +320 -11
- package/dist/primitives.mjs.map +1 -1
- package/dist/session.d.mts +18 -0
- package/dist/session.d.ts +18 -0
- package/dist/session.js +432 -0
- package/dist/session.js.map +1 -0
- package/dist/session.mjs +401 -0
- package/dist/session.mjs.map +1 -0
- package/dist/status-badge-BEOxeY9j.d.ts +13 -0
- package/dist/status-badge-DRwGhB0h.d.mts +13 -0
- package/dist/styles/code.css +97 -0
- package/dist/styles/fonts.css +1 -1
- package/dist/styles/theme.css +2 -0
- package/dist/styles/tokens.css +44 -2
- package/dist/styles.css +1 -0
- package/dist/tokens.d.mts +3 -1
- package/dist/tokens.d.ts +3 -1
- package/dist/tokens.js +5 -3
- package/dist/tokens.js.map +1 -1
- package/dist/tokens.mjs +5 -3
- package/dist/tokens.mjs.map +1 -1
- package/dist/tool-shell-B1C7ahKE.d.ts +81 -0
- package/dist/tool-shell-BDx_N5ai.d.mts +81 -0
- package/dist/tools-BggNN5DV.d.ts +131 -0
- package/dist/tools-DFIxIj5p.d.mts +131 -0
- package/package.json +38 -2
package/dist/components.js
CHANGED
|
@@ -5,10 +5,20 @@ var clsx = require('clsx');
|
|
|
5
5
|
var tailwindMerge = require('tailwind-merge');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
var classVarianceAuthority = require('class-variance-authority');
|
|
8
|
+
var TabsPrimitive = require('@radix-ui/react-tabs');
|
|
8
9
|
var lucideReact = require('lucide-react');
|
|
9
10
|
var reactSlot = require('@radix-ui/react-slot');
|
|
10
11
|
var SeparatorPrimitive = require('@radix-ui/react-separator');
|
|
11
12
|
require('sonner');
|
|
13
|
+
var Link = require('next/link');
|
|
14
|
+
var CheckboxPrimitive = require('@radix-ui/react-checkbox');
|
|
15
|
+
var LabelPrimitive = require('@radix-ui/react-label');
|
|
16
|
+
var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
|
|
17
|
+
var SelectPrimitive = require('@radix-ui/react-select');
|
|
18
|
+
var SwitchPrimitive = require('@radix-ui/react-switch');
|
|
19
|
+
var DialogPrimitive = require('@radix-ui/react-dialog');
|
|
20
|
+
|
|
21
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
22
|
|
|
13
23
|
function _interopNamespace(e) {
|
|
14
24
|
if (e && e.__esModule) return e;
|
|
@@ -28,7 +38,15 @@ function _interopNamespace(e) {
|
|
|
28
38
|
return Object.freeze(n);
|
|
29
39
|
}
|
|
30
40
|
|
|
41
|
+
var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
|
|
31
42
|
var SeparatorPrimitive__namespace = /*#__PURE__*/_interopNamespace(SeparatorPrimitive);
|
|
43
|
+
var Link__default = /*#__PURE__*/_interopDefault(Link);
|
|
44
|
+
var CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespace(CheckboxPrimitive);
|
|
45
|
+
var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
|
|
46
|
+
var RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(RadioGroupPrimitive);
|
|
47
|
+
var SelectPrimitive__namespace = /*#__PURE__*/_interopNamespace(SelectPrimitive);
|
|
48
|
+
var SwitchPrimitive__namespace = /*#__PURE__*/_interopNamespace(SwitchPrimitive);
|
|
49
|
+
var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
|
|
32
50
|
|
|
33
51
|
var merge = tailwindMerge.extendTailwindMerge({
|
|
34
52
|
extend: {
|
|
@@ -292,6 +310,7 @@ function useActiveHeading(ids) {
|
|
|
292
310
|
const [active, setActive] = react.useState(ids[0]);
|
|
293
311
|
const key = ids.join("|");
|
|
294
312
|
react.useEffect(() => {
|
|
313
|
+
setActive(key.split("|")[0] || void 0);
|
|
295
314
|
const els = key.split("|").map((id) => document.getElementById(id)).filter((el) => el !== null);
|
|
296
315
|
if (els.length === 0 || typeof IntersectionObserver === "undefined") return;
|
|
297
316
|
const io = new IntersectionObserver(
|
|
@@ -365,13 +384,13 @@ var badgeVariants = classVarianceAuthority.cva(
|
|
|
365
384
|
tone: {
|
|
366
385
|
neutral: "border-border bg-card text-foreground",
|
|
367
386
|
muted: "border-transparent bg-muted text-muted-foreground",
|
|
368
|
-
brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)
|
|
387
|
+
brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
|
|
369
388
|
danger: "border-transparent bg-[color-mix(in_oklab,var(--destructive)_12%,var(--card))] text-destructive",
|
|
370
389
|
// A good state is a neutral pill with a green dot, not a green pill.
|
|
371
390
|
success: GOOD_DOT,
|
|
372
391
|
// Aliases kept so older call sites keep compiling: attention is
|
|
373
392
|
// the brand accent, information is neutral.
|
|
374
|
-
warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)
|
|
393
|
+
warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
|
|
375
394
|
info: "border-border bg-card text-foreground",
|
|
376
395
|
// Inverted in dark mode, where ink would sit on a card of nearly its own colour.
|
|
377
396
|
ink: "border-transparent bg-oca-ink text-oca-ink-foreground dark:bg-foreground dark:text-background",
|
|
@@ -441,6 +460,487 @@ function StepGrid({ items, look = "cards", className }) {
|
|
|
441
460
|
] }) }, i)
|
|
442
461
|
) });
|
|
443
462
|
}
|
|
463
|
+
var KIND = {
|
|
464
|
+
package: "text-oca-code-package",
|
|
465
|
+
tag: "text-oca-code-tag",
|
|
466
|
+
link: "text-oca-code-link"
|
|
467
|
+
};
|
|
468
|
+
function PackageCard({ items, className }) {
|
|
469
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
470
|
+
"div",
|
|
471
|
+
{
|
|
472
|
+
className: cn(
|
|
473
|
+
"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",
|
|
474
|
+
className
|
|
475
|
+
),
|
|
476
|
+
children: items.map((it, i) => {
|
|
477
|
+
const code = /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[0.9375rem]", KIND[it.kind ?? "package"]), children: it.code });
|
|
478
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
479
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[1.125rem] font-semibold tracking-[-0.01em] text-oca-ink-title", children: it.title }),
|
|
480
|
+
it.href ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: it.href, className: "w-fit underline decoration-transparent underline-offset-4 hover:decoration-current", children: code }) : code,
|
|
481
|
+
it.note ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[0.9375rem] leading-relaxed text-oca-ink-subtle", children: [
|
|
482
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "// " }),
|
|
483
|
+
it.note
|
|
484
|
+
] }) : null
|
|
485
|
+
] }, i);
|
|
486
|
+
})
|
|
487
|
+
}
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// src/code/highlight.ts
|
|
492
|
+
var TOKEN_CLASS = {
|
|
493
|
+
keyword: "oca-k",
|
|
494
|
+
string: "oca-s",
|
|
495
|
+
number: "oca-n",
|
|
496
|
+
function: "oca-f",
|
|
497
|
+
type: "oca-y",
|
|
498
|
+
property: "oca-p",
|
|
499
|
+
comment: "oca-c",
|
|
500
|
+
tag: "oca-g",
|
|
501
|
+
url: "oca-u"
|
|
502
|
+
};
|
|
503
|
+
var ALIASES = {
|
|
504
|
+
ts: "js",
|
|
505
|
+
typescript: "js",
|
|
506
|
+
tsx: "js",
|
|
507
|
+
js: "js",
|
|
508
|
+
javascript: "js",
|
|
509
|
+
jsx: "js",
|
|
510
|
+
mjs: "js",
|
|
511
|
+
cjs: "js",
|
|
512
|
+
json: "json",
|
|
513
|
+
jsonc: "json",
|
|
514
|
+
json5: "json",
|
|
515
|
+
bash: "shell",
|
|
516
|
+
sh: "shell",
|
|
517
|
+
shell: "shell",
|
|
518
|
+
zsh: "shell",
|
|
519
|
+
console: "shell",
|
|
520
|
+
terminal: "shell",
|
|
521
|
+
py: "python",
|
|
522
|
+
python: "python",
|
|
523
|
+
yaml: "yaml",
|
|
524
|
+
yml: "yaml",
|
|
525
|
+
diff: "diff"
|
|
526
|
+
};
|
|
527
|
+
function grammarOf(lang) {
|
|
528
|
+
return lang && ALIASES[lang.toLowerCase()] || "plain";
|
|
529
|
+
}
|
|
530
|
+
function collector() {
|
|
531
|
+
const tokens = [];
|
|
532
|
+
const emit = (text, kind) => {
|
|
533
|
+
if (!text) return;
|
|
534
|
+
const last = tokens[tokens.length - 1];
|
|
535
|
+
if (last && last.kind === kind) last.text += text;
|
|
536
|
+
else tokens.push(kind ? { text, kind } : { text });
|
|
537
|
+
};
|
|
538
|
+
return { emit, tokens };
|
|
539
|
+
}
|
|
540
|
+
function at(re, src, i) {
|
|
541
|
+
re.lastIndex = i;
|
|
542
|
+
const m = re.exec(src);
|
|
543
|
+
return m ? m[0] : null;
|
|
544
|
+
}
|
|
545
|
+
var WS = /[ \t]+/y;
|
|
546
|
+
var NEWLINE = /\r?\n/y;
|
|
547
|
+
var JS_KEYWORDS = new Set(
|
|
548
|
+
"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(" ")
|
|
549
|
+
);
|
|
550
|
+
var JS_CONSTANTS = /* @__PURE__ */ new Set(["true", "false", "null", "undefined", "NaN", "Infinity"]);
|
|
551
|
+
var TS_PRIMITIVES = /* @__PURE__ */ new Set(["string", "number", "boolean", "bigint", "symbol", "object", "unknown", "any", "never"]);
|
|
552
|
+
var isConstant = (m) => /^[A-Z][A-Z\d_]+$/.test(m) && (m.includes("_") || m.length > 4);
|
|
553
|
+
var JS_LINE_COMMENT = /\/\/[^\n]*/y;
|
|
554
|
+
var JS_BLOCK_COMMENT = /\/\*[\s\S]*?(?:\*\/|$)/y;
|
|
555
|
+
var JS_TEMPLATE = /`(?:\\[\s\S]|[^\\`])*`?/y;
|
|
556
|
+
var JS_STRING = /'(?:\\.|[^\\'\n])*'?|"(?:\\.|[^\\"\n])*"?/y;
|
|
557
|
+
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;
|
|
558
|
+
var JS_IDENT = /[A-Za-z_$][\w$]*/y;
|
|
559
|
+
var JS_DECORATOR = /@[A-Za-z_$][\w$.]*/y;
|
|
560
|
+
var JS_CALL_AFTER = /\s*(?:<[\w$\s,.[\]|&'"]*>)?\s*\(/y;
|
|
561
|
+
var JS_TAG = /<\/?(?=[A-Za-z])/y;
|
|
562
|
+
var JS_TAG_NAME = /[A-Za-z][\w$.:-]*/y;
|
|
563
|
+
var JS_PUNCT = /=>|\.\.\.|[{}()[\];,.<>=+\-*/%!?:&|^~#]/y;
|
|
564
|
+
var JSX_BEFORE = /* @__PURE__ */ new Set(["(", ",", "=", "?", ":", "{", "[", ";", ">", "&&", "||", "=>", "return"]);
|
|
565
|
+
function scanJs(src, emit, jsx35) {
|
|
566
|
+
let i = 0;
|
|
567
|
+
let prev = "";
|
|
568
|
+
let tagDepth = 0;
|
|
569
|
+
let braceInTag = 0;
|
|
570
|
+
const sig = (t) => {
|
|
571
|
+
prev = t;
|
|
572
|
+
};
|
|
573
|
+
while (i < src.length) {
|
|
574
|
+
let m;
|
|
575
|
+
if ((m = at(WS, src, i)) || (m = at(NEWLINE, src, i))) {
|
|
576
|
+
emit(m);
|
|
577
|
+
i += m.length;
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
if ((m = at(JS_LINE_COMMENT, src, i)) || (m = at(JS_BLOCK_COMMENT, src, i))) {
|
|
581
|
+
emit(m, "comment");
|
|
582
|
+
i += m.length;
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
if ((m = at(JS_TEMPLATE, src, i)) || (m = at(JS_STRING, src, i))) {
|
|
586
|
+
emit(m, "string");
|
|
587
|
+
i += m.length;
|
|
588
|
+
sig('"');
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
if (jsx35 && tagDepth === 0 && (m = at(JS_TAG, src, i)) && (prev === "" || JSX_BEFORE.has(prev))) {
|
|
592
|
+
const name = at(JS_TAG_NAME, src, i + m.length);
|
|
593
|
+
if (name) {
|
|
594
|
+
emit(m);
|
|
595
|
+
emit(name, "tag");
|
|
596
|
+
i += m.length + name.length;
|
|
597
|
+
tagDepth = 1;
|
|
598
|
+
braceInTag = 0;
|
|
599
|
+
sig("tag");
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (jsx35 && tagDepth > 0 && braceInTag === 0) {
|
|
604
|
+
if (src.startsWith("/>", i) || src[i] === ">") {
|
|
605
|
+
const close = src[i] === ">" ? ">" : "/>";
|
|
606
|
+
emit(close);
|
|
607
|
+
i += close.length;
|
|
608
|
+
tagDepth = 0;
|
|
609
|
+
sig(">");
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
if ((m = at(JS_IDENT, src, i)) && /^\s*=/.test(src.slice(i + m.length, i + m.length + 4))) {
|
|
613
|
+
emit(m, "property");
|
|
614
|
+
i += m.length;
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
if (m = at(JS_IDENT, src, i)) {
|
|
618
|
+
emit(m, "property");
|
|
619
|
+
i += m.length;
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
if (src[i] === "{") braceInTag = 1;
|
|
623
|
+
} else if (jsx35 && tagDepth > 0 && braceInTag > 0) {
|
|
624
|
+
if (src[i] === "{") braceInTag++;
|
|
625
|
+
else if (src[i] === "}") braceInTag--;
|
|
626
|
+
}
|
|
627
|
+
if (m = at(JS_DECORATOR, src, i)) {
|
|
628
|
+
emit(m, "function");
|
|
629
|
+
i += m.length;
|
|
630
|
+
sig("@");
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
if (m = at(JS_IDENT, src, i)) {
|
|
634
|
+
const end = i + m.length;
|
|
635
|
+
let kind;
|
|
636
|
+
if (prev !== "." && JS_CONSTANTS.has(m)) kind = "number";
|
|
637
|
+
else if (prev !== "." && JS_KEYWORDS.has(m)) kind = "keyword";
|
|
638
|
+
else if (at(JS_CALL_AFTER, src, end) !== null) kind = "function";
|
|
639
|
+
else if (prev !== "." && TS_PRIMITIVES.has(m)) kind = "type";
|
|
640
|
+
else if (isConstant(m)) kind = "number";
|
|
641
|
+
else if (/^[A-Z]/.test(m)) kind = "type";
|
|
642
|
+
emit(m, kind);
|
|
643
|
+
i = end;
|
|
644
|
+
sig(kind === "keyword" ? m : "id");
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
if (m = at(JS_NUMBER, src, i)) {
|
|
648
|
+
emit(m, "number");
|
|
649
|
+
i += m.length;
|
|
650
|
+
sig("0");
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
if (m = at(JS_PUNCT, src, i)) {
|
|
654
|
+
emit(m);
|
|
655
|
+
i += m.length;
|
|
656
|
+
sig(m === "." ? "." : m);
|
|
657
|
+
continue;
|
|
658
|
+
}
|
|
659
|
+
emit(src[i]);
|
|
660
|
+
i++;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
var JSON_STRING = /"(?:\\.|[^\\"\n])*"?/y;
|
|
664
|
+
var JSON_KEY_AFTER = /\s*:/y;
|
|
665
|
+
var JSON_NUMBER = /-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/y;
|
|
666
|
+
var JSON_WORD = /true|false|null/y;
|
|
667
|
+
function scanJson(src, emit) {
|
|
668
|
+
let i = 0;
|
|
669
|
+
while (i < src.length) {
|
|
670
|
+
let m;
|
|
671
|
+
if ((m = at(JS_LINE_COMMENT, src, i)) || (m = at(JS_BLOCK_COMMENT, src, i))) {
|
|
672
|
+
emit(m, "comment");
|
|
673
|
+
} else if (m = at(JSON_STRING, src, i)) {
|
|
674
|
+
emit(m, at(JSON_KEY_AFTER, src, i + m.length) !== null ? "property" : "string");
|
|
675
|
+
} else if ((m = at(JSON_NUMBER, src, i)) || (m = at(JSON_WORD, src, i))) {
|
|
676
|
+
emit(m, "number");
|
|
677
|
+
} else {
|
|
678
|
+
m = src[i];
|
|
679
|
+
emit(m);
|
|
680
|
+
}
|
|
681
|
+
i += m.length;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
var SH_KEYWORDS = new Set(
|
|
685
|
+
"if then else elif fi for in do done case esac while until function return export local select time".split(" ")
|
|
686
|
+
);
|
|
687
|
+
var SH_PROMPT = /\$ (?=\S)/y;
|
|
688
|
+
var SH_COMMENT = /#[^\n]*/y;
|
|
689
|
+
var SH_SINGLE = /'[^']*'?/y;
|
|
690
|
+
var SH_DOUBLE = /"(?:\\.|[^\\"])*"?/y;
|
|
691
|
+
var SH_VAR = /\$(?:\{[^}\n]*\}?|[A-Za-z_][\w]*|[@*#?$!\d])/y;
|
|
692
|
+
var SH_URL = /https?:\/\/[^\s'"`)]+/y;
|
|
693
|
+
var SH_FLAG = /--?[A-Za-z][\w-]*/y;
|
|
694
|
+
var SH_ASSIGN = /[A-Za-z_][\w]*(?==)/y;
|
|
695
|
+
var SH_VALUE = /=[^\s|&;()<>'"`$]*/y;
|
|
696
|
+
var SH_WORD = /[^\s|&;()<>'"`$#]+/y;
|
|
697
|
+
var SH_OPERATOR = /\|\||&&|[|;&]|\$\(|[()<>]/y;
|
|
698
|
+
function scanShell(src, emit) {
|
|
699
|
+
let i = 0;
|
|
700
|
+
let command = true;
|
|
701
|
+
let lineStart = true;
|
|
702
|
+
while (i < src.length) {
|
|
703
|
+
let m;
|
|
704
|
+
if (m = at(NEWLINE, src, i)) {
|
|
705
|
+
emit(m);
|
|
706
|
+
i += m.length;
|
|
707
|
+
command = !/\\\s*$/.test(src.slice(0, i - m.length));
|
|
708
|
+
lineStart = true;
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
if (m = at(WS, src, i)) {
|
|
712
|
+
emit(m);
|
|
713
|
+
i += m.length;
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
716
|
+
if (lineStart && (m = at(SH_PROMPT, src, i))) {
|
|
717
|
+
emit(m, "comment");
|
|
718
|
+
i += m.length;
|
|
719
|
+
lineStart = false;
|
|
720
|
+
continue;
|
|
721
|
+
}
|
|
722
|
+
lineStart = false;
|
|
723
|
+
if ((m = at(SH_COMMENT, src, i)) && (i === 0 || /\s/.test(src[i - 1]))) {
|
|
724
|
+
emit(m, "comment");
|
|
725
|
+
i += m.length;
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
if ((m = at(SH_SINGLE, src, i)) || (m = at(SH_DOUBLE, src, i))) {
|
|
729
|
+
emit(m, "string");
|
|
730
|
+
i += m.length;
|
|
731
|
+
command = false;
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
if (m = at(SH_OPERATOR, src, i)) {
|
|
735
|
+
emit(m);
|
|
736
|
+
i += m.length;
|
|
737
|
+
command = m !== ")" && m !== ">" && m !== "<";
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
if (m = at(SH_VAR, src, i)) {
|
|
741
|
+
emit(m, "type");
|
|
742
|
+
i += m.length;
|
|
743
|
+
command = false;
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
if (m = at(SH_URL, src, i)) {
|
|
747
|
+
emit(m, "url");
|
|
748
|
+
i += m.length;
|
|
749
|
+
command = false;
|
|
750
|
+
continue;
|
|
751
|
+
}
|
|
752
|
+
if (command && (m = at(SH_ASSIGN, src, i))) {
|
|
753
|
+
emit(m, "property");
|
|
754
|
+
i += m.length;
|
|
755
|
+
const v = at(SH_VALUE, src, i);
|
|
756
|
+
emit(v);
|
|
757
|
+
i += v.length;
|
|
758
|
+
continue;
|
|
759
|
+
}
|
|
760
|
+
if ((m = at(SH_FLAG, src, i)) && !command) {
|
|
761
|
+
emit(m, "keyword");
|
|
762
|
+
i += m.length;
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
if (m = at(SH_WORD, src, i)) {
|
|
766
|
+
if (command && SH_KEYWORDS.has(m)) emit(m, "keyword");
|
|
767
|
+
else if (command) {
|
|
768
|
+
emit(m, "function");
|
|
769
|
+
command = m === "sudo" || m === "npx" || m === "env" || m === "time";
|
|
770
|
+
i += m.length;
|
|
771
|
+
continue;
|
|
772
|
+
} else emit(m);
|
|
773
|
+
i += m.length;
|
|
774
|
+
continue;
|
|
775
|
+
}
|
|
776
|
+
emit(src[i]);
|
|
777
|
+
i++;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
var PY_KEYWORDS = new Set(
|
|
781
|
+
"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(" ")
|
|
782
|
+
);
|
|
783
|
+
var PY_CONSTANTS = /* @__PURE__ */ new Set(["True", "False", "None"]);
|
|
784
|
+
var PY_TYPES = /* @__PURE__ */ new Set(["int", "str", "bool", "float", "bytes", "list", "dict", "tuple", "set", "object"]);
|
|
785
|
+
var PY_COMMENT = /#[^\n]*/y;
|
|
786
|
+
var PY_TRIPLE = /[rRbBuUfF]{0,2}(?:"""[\s\S]*?(?:"""|$)|'''[\s\S]*?(?:'''|$))/y;
|
|
787
|
+
var PY_STRING = /[rRbBuUfF]{0,2}(?:'(?:\\.|[^\\'\n])*'?|"(?:\\.|[^\\"\n])*"?)/y;
|
|
788
|
+
var PY_NUMBER = /(?:0[xX][\da-fA-F_]+|\d[\d_]*(?:\.[\d_]*)?(?:[eE][+-]?\d+)?j?)/y;
|
|
789
|
+
var PY_IDENT = /[A-Za-z_]\w*/y;
|
|
790
|
+
var PY_DECORATOR = /@[A-Za-z_][\w.]*/y;
|
|
791
|
+
var PY_CALL_AFTER = /\s*\(/y;
|
|
792
|
+
function scanPython(src, emit) {
|
|
793
|
+
let i = 0;
|
|
794
|
+
let prev = "";
|
|
795
|
+
while (i < src.length) {
|
|
796
|
+
let m;
|
|
797
|
+
if ((m = at(WS, src, i)) || (m = at(NEWLINE, src, i))) {
|
|
798
|
+
emit(m);
|
|
799
|
+
i += m.length;
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
if (m = at(PY_COMMENT, src, i)) {
|
|
803
|
+
emit(m, "comment");
|
|
804
|
+
} else if ((m = at(PY_TRIPLE, src, i)) || (m = at(PY_STRING, src, i))) {
|
|
805
|
+
if (/^[A-Za-z]+$/.test(m)) {
|
|
806
|
+
emit(m);
|
|
807
|
+
} else emit(m, "string");
|
|
808
|
+
prev = '"';
|
|
809
|
+
} else if (m = at(PY_DECORATOR, src, i)) {
|
|
810
|
+
emit(m, "function");
|
|
811
|
+
prev = "@";
|
|
812
|
+
} else if (m = at(PY_IDENT, src, i)) {
|
|
813
|
+
let kind;
|
|
814
|
+
if (PY_CONSTANTS.has(m)) kind = "number";
|
|
815
|
+
else if (prev !== "." && PY_KEYWORDS.has(m)) kind = "keyword";
|
|
816
|
+
else if (prev === "def" || at(PY_CALL_AFTER, src, i + m.length) !== null) kind = "function";
|
|
817
|
+
else if (prev === "class" || /^[A-Z][a-z]/.test(m) || PY_TYPES.has(m)) kind = "type";
|
|
818
|
+
else if (isConstant(m)) kind = "number";
|
|
819
|
+
emit(m, kind);
|
|
820
|
+
prev = kind === "keyword" ? m : "id";
|
|
821
|
+
} else if (m = at(PY_NUMBER, src, i)) {
|
|
822
|
+
emit(m, "number");
|
|
823
|
+
prev = "0";
|
|
824
|
+
} else {
|
|
825
|
+
m = src[i];
|
|
826
|
+
emit(m);
|
|
827
|
+
prev = m;
|
|
828
|
+
}
|
|
829
|
+
i += m.length;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
var YAML_KEY = /[ \t]*(?:- )?[\w.$/-]+(?=[ \t]*:(?:\s|$))/y;
|
|
833
|
+
var YAML_VALUE_WORD = /(?:true|false|null|yes|no|~|-?\d+(?:\.\d+)?)(?=\s*(?:#|$))/y;
|
|
834
|
+
function scanYaml(src, emit) {
|
|
835
|
+
let i = 0;
|
|
836
|
+
let lineStart = true;
|
|
837
|
+
while (i < src.length) {
|
|
838
|
+
let m;
|
|
839
|
+
if (m = at(NEWLINE, src, i)) {
|
|
840
|
+
emit(m);
|
|
841
|
+
i += m.length;
|
|
842
|
+
lineStart = true;
|
|
843
|
+
continue;
|
|
844
|
+
}
|
|
845
|
+
if (lineStart && (m = at(YAML_KEY, src, i))) {
|
|
846
|
+
const dash = m.match(/^([ \t]*(?:- )?)/)[1];
|
|
847
|
+
emit(dash);
|
|
848
|
+
emit(m.slice(dash.length), "property");
|
|
849
|
+
i += m.length;
|
|
850
|
+
lineStart = false;
|
|
851
|
+
continue;
|
|
852
|
+
}
|
|
853
|
+
lineStart = false;
|
|
854
|
+
if ((m = at(SH_COMMENT, src, i)) && (i === 0 || /\s/.test(src[i - 1]))) emit(m, "comment");
|
|
855
|
+
else if ((m = at(SH_SINGLE, src, i)) || (m = at(JSON_STRING, src, i))) emit(m, "string");
|
|
856
|
+
else if (m = at(YAML_VALUE_WORD, src, i)) emit(m, "number");
|
|
857
|
+
else if (m = at(SH_URL, src, i)) emit(m, "url");
|
|
858
|
+
else {
|
|
859
|
+
m = src[i];
|
|
860
|
+
emit(m);
|
|
861
|
+
}
|
|
862
|
+
i += m.length;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
function toLines(tokens) {
|
|
866
|
+
const lines = [[]];
|
|
867
|
+
for (const t of tokens) {
|
|
868
|
+
const parts = t.text.split(/\r?\n/);
|
|
869
|
+
parts.forEach((part, j) => {
|
|
870
|
+
if (j > 0) lines.push([]);
|
|
871
|
+
if (part) lines[lines.length - 1].push(t.kind ? { text: part, kind: t.kind } : { text: part });
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
return lines;
|
|
875
|
+
}
|
|
876
|
+
function highlight(code, lang) {
|
|
877
|
+
const src = code.replace(/\r?\n$/, "");
|
|
878
|
+
const grammar = grammarOf(lang);
|
|
879
|
+
const { emit, tokens } = collector();
|
|
880
|
+
const name = (lang ?? "").toLowerCase();
|
|
881
|
+
switch (grammar) {
|
|
882
|
+
case "js":
|
|
883
|
+
scanJs(src, emit, name === "tsx" || name === "jsx");
|
|
884
|
+
break;
|
|
885
|
+
case "json":
|
|
886
|
+
scanJson(src, emit);
|
|
887
|
+
break;
|
|
888
|
+
case "shell":
|
|
889
|
+
scanShell(src, emit);
|
|
890
|
+
break;
|
|
891
|
+
case "python":
|
|
892
|
+
scanPython(src, emit);
|
|
893
|
+
break;
|
|
894
|
+
case "yaml":
|
|
895
|
+
scanYaml(src, emit);
|
|
896
|
+
break;
|
|
897
|
+
default:
|
|
898
|
+
emit(src);
|
|
899
|
+
}
|
|
900
|
+
return toLines(tokens);
|
|
901
|
+
}
|
|
902
|
+
function readDiff(code) {
|
|
903
|
+
const diff = /* @__PURE__ */ new Map();
|
|
904
|
+
const lines = code.replace(/\r?\n$/, "").split(/\r?\n/);
|
|
905
|
+
const out = lines.map((line, i) => {
|
|
906
|
+
const c = line[0];
|
|
907
|
+
if (c === "+" || c === "-") {
|
|
908
|
+
diff.set(i + 1, c === "+" ? "add" : "remove");
|
|
909
|
+
return line.slice(1);
|
|
910
|
+
}
|
|
911
|
+
return c === " " ? line.slice(1) : line;
|
|
912
|
+
});
|
|
913
|
+
return { code: out.join("\n"), diff };
|
|
914
|
+
}
|
|
915
|
+
function parseLineRanges(spec) {
|
|
916
|
+
if (!spec) return /* @__PURE__ */ new Set();
|
|
917
|
+
if (typeof spec !== "string") return new Set(spec);
|
|
918
|
+
const out = /* @__PURE__ */ new Set();
|
|
919
|
+
for (const part of spec.split(",")) {
|
|
920
|
+
const m = part.trim().match(/^(\d+)(?:\s*-\s*(\d+))?$/);
|
|
921
|
+
if (!m) continue;
|
|
922
|
+
const a = Number(m[1]);
|
|
923
|
+
const b = m[2] ? Number(m[2]) : a;
|
|
924
|
+
for (let n = Math.min(a, b); n <= Math.max(a, b) && n - a < 1e4; n++) out.add(n);
|
|
925
|
+
}
|
|
926
|
+
return out;
|
|
927
|
+
}
|
|
928
|
+
var ESCAPE = { "&": "&", "<": "<", ">": ">", '"': """ };
|
|
929
|
+
function escapeHtml(s) {
|
|
930
|
+
return s.replace(/[&<>"]/g, (c) => ESCAPE[c]);
|
|
931
|
+
}
|
|
932
|
+
function linesToHtml(lines, marks = {}) {
|
|
933
|
+
return lines.map((line, i) => {
|
|
934
|
+
const n = i + 1;
|
|
935
|
+
const attrs = [
|
|
936
|
+
'data-line=""',
|
|
937
|
+
marks.highlight?.has(n) ? 'data-mark=""' : "",
|
|
938
|
+
marks.diff?.has(n) ? `data-diff="${marks.diff.get(n)}"` : ""
|
|
939
|
+
].filter(Boolean).join(" ");
|
|
940
|
+
const body = line.map((t) => t.kind ? `<span class="${TOKEN_CLASS[t.kind]}">${escapeHtml(t.text)}</span>` : escapeHtml(t.text)).join("");
|
|
941
|
+
return `<span ${attrs}>${body}</span>`;
|
|
942
|
+
}).join("\n");
|
|
943
|
+
}
|
|
444
944
|
function ScrollFade({ fade = "var(--card)", className, innerClassName, children, ...props }) {
|
|
445
945
|
const ref = react.useRef(null);
|
|
446
946
|
const [edges, setEdges] = react.useState({ left: false, right: false });
|
|
@@ -499,7 +999,73 @@ function ScrollFade({ fade = "var(--card)", className, innerClassName, children,
|
|
|
499
999
|
)
|
|
500
1000
|
] });
|
|
501
1001
|
}
|
|
502
|
-
|
|
1002
|
+
|
|
1003
|
+
// src/format/index.ts
|
|
1004
|
+
var EXPLORER = "https://mempool.space";
|
|
1005
|
+
function explorerUrl(kind, value, network = "mainnet") {
|
|
1006
|
+
const net = network === "mainnet" ? "" : `/${network}`;
|
|
1007
|
+
return `${EXPLORER}${net}/${kind}/${encodeURIComponent(String(value))}`;
|
|
1008
|
+
}
|
|
1009
|
+
function shortenMiddle(value, head = 8, tail = 6) {
|
|
1010
|
+
return value.length <= head + tail + 1 ? value : `${value.slice(0, head)}\u2026${value.slice(-tail)}`;
|
|
1011
|
+
}
|
|
1012
|
+
function formatBlockHeight(height) {
|
|
1013
|
+
return Math.trunc(height).toLocaleString("en-US");
|
|
1014
|
+
}
|
|
1015
|
+
function blocksToDuration(blocks, minutesPerBlock = 10) {
|
|
1016
|
+
const minutes = Math.max(0, Math.round(blocks * minutesPerBlock));
|
|
1017
|
+
if (minutes < 60) return `about ${minutes} minute${minutes === 1 ? "" : "s"}`;
|
|
1018
|
+
const units = [
|
|
1019
|
+
[60 * 24 * 7, "week"],
|
|
1020
|
+
[60 * 24, "day"],
|
|
1021
|
+
[60, "hour"],
|
|
1022
|
+
[1, "minute"]
|
|
1023
|
+
];
|
|
1024
|
+
const parts = [];
|
|
1025
|
+
let rest = minutes;
|
|
1026
|
+
for (const [size, word] of units) {
|
|
1027
|
+
const n = Math.floor(rest / size);
|
|
1028
|
+
if (n > 0 && parts.length < 2) {
|
|
1029
|
+
parts.push(`${n} ${word}${n === 1 ? "" : "s"}`);
|
|
1030
|
+
rest -= n * size;
|
|
1031
|
+
} else if (parts.length > 0) break;
|
|
1032
|
+
}
|
|
1033
|
+
return `about ${parts.join(" ")}`;
|
|
1034
|
+
}
|
|
1035
|
+
var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
1036
|
+
function formatUtc(at2, opts = {}) {
|
|
1037
|
+
const d = typeof at2 === "number" ? new Date(at2 * 1e3) : new Date(at2);
|
|
1038
|
+
if (Number.isNaN(d.getTime())) return "\u2014";
|
|
1039
|
+
const day = `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]} ${d.getUTCFullYear()}`;
|
|
1040
|
+
if (opts.date) return day;
|
|
1041
|
+
const hh = String(d.getUTCHours()).padStart(2, "0");
|
|
1042
|
+
const mm = String(d.getUTCMinutes()).padStart(2, "0");
|
|
1043
|
+
return `${day}, ${hh}:${mm} UTC`;
|
|
1044
|
+
}
|
|
1045
|
+
function formatBytes(bytes) {
|
|
1046
|
+
if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
|
|
1047
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
1048
|
+
const units = ["KB", "MB", "GB", "TB"];
|
|
1049
|
+
let v = bytes / 1024;
|
|
1050
|
+
let u = 0;
|
|
1051
|
+
while (v >= 1024 && u < units.length - 1) {
|
|
1052
|
+
v /= 1024;
|
|
1053
|
+
u++;
|
|
1054
|
+
}
|
|
1055
|
+
return `${v < 10 ? v.toFixed(1).replace(/\.0$/, "") : Math.round(v)} ${units[u]}`;
|
|
1056
|
+
}
|
|
1057
|
+
function sharedContext(name, initial) {
|
|
1058
|
+
const key = /* @__PURE__ */ Symbol.for(`@orangecheck/app-design/${name}`);
|
|
1059
|
+
const store = globalThis;
|
|
1060
|
+
return store[key] ?? (store[key] = react.createContext(initial));
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
// src/lib/density.ts
|
|
1064
|
+
var DensityContext = sharedContext("density", "comfortable");
|
|
1065
|
+
function useDensity() {
|
|
1066
|
+
return react.useContext(DensityContext);
|
|
1067
|
+
}
|
|
1068
|
+
var ShellContext = sharedContext("shell-place", {});
|
|
503
1069
|
function useShellPlace() {
|
|
504
1070
|
return react.useContext(ShellContext);
|
|
505
1071
|
}
|
|
@@ -554,6 +1120,18 @@ react.forwardRef(function Separator2({ className, orientation = "horizontal", de
|
|
|
554
1120
|
}
|
|
555
1121
|
);
|
|
556
1122
|
});
|
|
1123
|
+
function Kbd({ className, ...props }) {
|
|
1124
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1125
|
+
"kbd",
|
|
1126
|
+
{
|
|
1127
|
+
className: cn(
|
|
1128
|
+
"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",
|
|
1129
|
+
className
|
|
1130
|
+
),
|
|
1131
|
+
...props
|
|
1132
|
+
}
|
|
1133
|
+
);
|
|
1134
|
+
}
|
|
557
1135
|
var buttonVariants = classVarianceAuthority.cva(
|
|
558
1136
|
[
|
|
559
1137
|
"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-full font-medium",
|
|
@@ -627,26 +1205,30 @@ function PageHeader({
|
|
|
627
1205
|
] });
|
|
628
1206
|
}
|
|
629
1207
|
var InStatGrid = react.createContext(false);
|
|
630
|
-
function StatCard({ label, value, hint, className }) {
|
|
1208
|
+
function StatCard({ label, value, hint, size, className }) {
|
|
631
1209
|
const inGrid = react.useContext(InStatGrid);
|
|
1210
|
+
const density = useDensity();
|
|
1211
|
+
const sm = (size ?? (density === "compact" ? "sm" : "md")) === "sm";
|
|
632
1212
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
633
1213
|
"div",
|
|
634
1214
|
{
|
|
635
1215
|
"data-ui": "stat",
|
|
636
1216
|
className: cn(
|
|
637
|
-
"
|
|
1217
|
+
"border border-border bg-card",
|
|
1218
|
+
sm ? "rounded-2xl p-4" : "rounded-[1.25rem] p-5 md:p-6",
|
|
638
1219
|
// In a grid, label, value and hint each share a row with their
|
|
639
1220
|
// neighbours, so values line up whatever wraps above them.
|
|
640
1221
|
inGrid ? "row-span-3 grid grid-rows-subgrid gap-1.5" : "flex flex-col gap-2",
|
|
641
1222
|
className
|
|
642
1223
|
),
|
|
643
1224
|
children: [
|
|
644
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.
|
|
1225
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("leading-snug text-muted-foreground", sm ? "text-[0.8125rem]" : "text-[0.875rem]"), children: label }),
|
|
645
1226
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
646
1227
|
"span",
|
|
647
1228
|
{
|
|
648
1229
|
className: cn(
|
|
649
|
-
"break-words oca-tabular
|
|
1230
|
+
"break-words oca-tabular leading-tight tracking-[-0.02em]",
|
|
1231
|
+
sm ? "text-[1.25rem]" : "text-[1.5rem] md:text-[1.75rem]",
|
|
650
1232
|
inGrid && "self-end"
|
|
651
1233
|
),
|
|
652
1234
|
children: value
|
|
@@ -708,6 +1290,7 @@ function StatGrid({ columns, empty, isEmpty, className, children, ...props }) {
|
|
|
708
1290
|
const items = react.Children.toArray(children).filter(react.isValidElement);
|
|
709
1291
|
const n = items.length;
|
|
710
1292
|
const allZero = n > 0 && items.every((el) => "raw" in el.props && (el.props.raw === 0 || el.props.raw === null));
|
|
1293
|
+
const compact = useDensity() === "compact";
|
|
711
1294
|
if (isEmpty ?? allZero) return /* @__PURE__ */ jsxRuntime.jsx(EmptyLine, { className, children: empty ?? "Nothing here yet." });
|
|
712
1295
|
const lg = columns ?? statColumns(n);
|
|
713
1296
|
const md = lg > 4 ? 3 : lg;
|
|
@@ -717,7 +1300,8 @@ function StatGrid({ columns, empty, isEmpty, className, children, ...props }) {
|
|
|
717
1300
|
"div",
|
|
718
1301
|
{
|
|
719
1302
|
className: cn(
|
|
720
|
-
"grid
|
|
1303
|
+
"grid",
|
|
1304
|
+
compact ? "gap-2.5 md:gap-3" : "gap-3 md:gap-4",
|
|
721
1305
|
n === 1 ? "grid-cols-1" : "grid-cols-2",
|
|
722
1306
|
MD_COLS[md],
|
|
723
1307
|
LG_COLS[lg],
|
|
@@ -736,11 +1320,40 @@ function StatGrid({ columns, empty, isEmpty, className, children, ...props }) {
|
|
|
736
1320
|
}
|
|
737
1321
|
) });
|
|
738
1322
|
}
|
|
739
|
-
function KeyValueList({
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
1323
|
+
function KeyValueList({
|
|
1324
|
+
items,
|
|
1325
|
+
dense,
|
|
1326
|
+
className
|
|
1327
|
+
}) {
|
|
1328
|
+
const density = useDensity();
|
|
1329
|
+
const tight = dense ?? density === "compact";
|
|
1330
|
+
return (
|
|
1331
|
+
// The rows go side by side when the list itself is wide enough, wherever it sits: a narrow card stacks them.
|
|
1332
|
+
/* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs(
|
|
1333
|
+
"div",
|
|
1334
|
+
{
|
|
1335
|
+
className: cn(
|
|
1336
|
+
"flex flex-col gap-1 @md:flex-row @md:items-baseline",
|
|
1337
|
+
tight ? "px-4 py-2.5 @md:gap-5" : "px-5 py-3.5 @md:gap-6"
|
|
1338
|
+
),
|
|
1339
|
+
children: [
|
|
1340
|
+
/* @__PURE__ */ jsxRuntime.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 }),
|
|
1341
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1342
|
+
"dd",
|
|
1343
|
+
{
|
|
1344
|
+
className: cn(
|
|
1345
|
+
"min-w-0 break-words",
|
|
1346
|
+
tight ? "text-[0.875rem]" : "text-[0.9375rem]",
|
|
1347
|
+
it.mono && (tight ? "font-mono text-[0.8125rem]" : "font-mono text-[0.875rem]")
|
|
1348
|
+
),
|
|
1349
|
+
children: it.value
|
|
1350
|
+
}
|
|
1351
|
+
)
|
|
1352
|
+
]
|
|
1353
|
+
},
|
|
1354
|
+
i
|
|
1355
|
+
)) })
|
|
1356
|
+
);
|
|
744
1357
|
}
|
|
745
1358
|
function DataTable({
|
|
746
1359
|
columns,
|
|
@@ -749,8 +1362,11 @@ function DataTable({
|
|
|
749
1362
|
empty,
|
|
750
1363
|
caption,
|
|
751
1364
|
phone = "cards",
|
|
1365
|
+
dense,
|
|
752
1366
|
className
|
|
753
1367
|
}) {
|
|
1368
|
+
const density = useDensity();
|
|
1369
|
+
const tight = dense ?? density === "compact";
|
|
754
1370
|
if (rows.length === 0 && empty) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: empty });
|
|
755
1371
|
const primary = columns.find((c) => c.primary) ?? columns[0];
|
|
756
1372
|
const right = (c) => c.numeric || c.align === "end";
|
|
@@ -758,11 +1374,12 @@ function DataTable({
|
|
|
758
1374
|
"div",
|
|
759
1375
|
{
|
|
760
1376
|
className: cn(
|
|
761
|
-
"overflow-hidden
|
|
1377
|
+
"overflow-hidden border border-border bg-card",
|
|
1378
|
+
tight ? "rounded-2xl" : "rounded-[1.25rem]",
|
|
762
1379
|
phone === "cards" && "max-sm:hidden",
|
|
763
1380
|
className
|
|
764
1381
|
),
|
|
765
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse text-left text-[0.9375rem]", children: [
|
|
1382
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: cn("w-full border-collapse text-left", tight ? "text-[0.875rem]" : "text-[0.9375rem]"), children: [
|
|
766
1383
|
caption ? /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: caption }) : null,
|
|
767
1384
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "border-b border-border", children: columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
768
1385
|
"th",
|
|
@@ -770,7 +1387,8 @@ function DataTable({
|
|
|
770
1387
|
scope: "col",
|
|
771
1388
|
style: { width: c.width, minWidth: c.minWidth },
|
|
772
1389
|
className: cn(
|
|
773
|
-
"whitespace-nowrap
|
|
1390
|
+
"whitespace-nowrap text-[0.8125rem] font-medium text-muted-foreground",
|
|
1391
|
+
tight ? "px-4 py-2.5" : "px-5 py-3",
|
|
774
1392
|
right(c) && "text-right",
|
|
775
1393
|
c.wide && "hidden md:table-cell"
|
|
776
1394
|
),
|
|
@@ -783,7 +1401,8 @@ function DataTable({
|
|
|
783
1401
|
{
|
|
784
1402
|
style: { minWidth: c.minWidth },
|
|
785
1403
|
className: cn(
|
|
786
|
-
"
|
|
1404
|
+
"align-middle",
|
|
1405
|
+
tight ? "px-4 py-2" : "px-5 py-3.5",
|
|
787
1406
|
right(c) && "text-right",
|
|
788
1407
|
c.numeric && "whitespace-nowrap oca-tabular",
|
|
789
1408
|
c.wide && "hidden md:table-cell"
|
|
@@ -803,8 +1422,12 @@ function DataTable({
|
|
|
803
1422
|
"ul",
|
|
804
1423
|
{
|
|
805
1424
|
"aria-label": caption,
|
|
806
|
-
className: cn(
|
|
807
|
-
|
|
1425
|
+
className: cn(
|
|
1426
|
+
"divide-y divide-border border border-border bg-card sm:hidden",
|
|
1427
|
+
tight ? "rounded-2xl" : "rounded-[1.25rem]",
|
|
1428
|
+
className
|
|
1429
|
+
),
|
|
1430
|
+
children: rows.map((r, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: cn("flex flex-col gap-2.5 px-4", tight ? "py-3" : "py-4"), children: [
|
|
808
1431
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 break-words text-[0.9375rem] font-medium", children: primary?.cell(r) }),
|
|
809
1432
|
rest.length > 0 ? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("div", { className: "contents", children: [
|
|
810
1433
|
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-muted-foreground", children: c.header }),
|
|
@@ -851,13 +1474,14 @@ function Notice({
|
|
|
851
1474
|
title,
|
|
852
1475
|
children,
|
|
853
1476
|
action,
|
|
1477
|
+
role,
|
|
854
1478
|
className
|
|
855
1479
|
}) {
|
|
856
1480
|
const kind = NOTICE_KIND[tone];
|
|
857
1481
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
858
1482
|
"div",
|
|
859
1483
|
{
|
|
860
|
-
role: tone === "danger" || tone === "warning" ? "alert" : "note",
|
|
1484
|
+
role: role ?? (tone === "danger" || tone === "warning" ? "alert" : "note"),
|
|
861
1485
|
"data-tone": kind,
|
|
862
1486
|
className: cn(
|
|
863
1487
|
"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",
|
|
@@ -907,45 +1531,66 @@ function LoadingBlock({
|
|
|
907
1531
|
}
|
|
908
1532
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-label": label, className: cn("flex flex-col gap-3", className), children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-16 rounded-2xl" }, i)) });
|
|
909
1533
|
}
|
|
910
|
-
function
|
|
911
|
-
|
|
1534
|
+
async function wipeIfUnchanged(expected) {
|
|
1535
|
+
try {
|
|
1536
|
+
if (await navigator.clipboard.readText() !== expected) return;
|
|
1537
|
+
} catch {
|
|
1538
|
+
}
|
|
1539
|
+
try {
|
|
1540
|
+
await navigator.clipboard.writeText("");
|
|
1541
|
+
} catch {
|
|
1542
|
+
}
|
|
912
1543
|
}
|
|
913
1544
|
function useCopy(timeoutMs = 1600) {
|
|
914
1545
|
const [copied, setCopied] = react.useState(false);
|
|
915
1546
|
const t = react.useRef(null);
|
|
916
|
-
react.
|
|
917
|
-
|
|
918
|
-
|
|
1547
|
+
const wipe = react.useRef(null);
|
|
1548
|
+
react.useEffect(
|
|
1549
|
+
() => () => {
|
|
1550
|
+
if (t.current) clearTimeout(t.current);
|
|
1551
|
+
},
|
|
1552
|
+
[]
|
|
1553
|
+
);
|
|
919
1554
|
const copy = react.useCallback(
|
|
920
|
-
async (text) => {
|
|
1555
|
+
async (text, opts = {}) => {
|
|
921
1556
|
try {
|
|
922
1557
|
await navigator.clipboard.writeText(text);
|
|
923
1558
|
setCopied(true);
|
|
924
1559
|
if (t.current) clearTimeout(t.current);
|
|
925
1560
|
t.current = setTimeout(() => setCopied(false), timeoutMs);
|
|
1561
|
+
if (opts.clearAfter && opts.clearAfter > 0) {
|
|
1562
|
+
if (wipe.current) clearTimeout(wipe.current);
|
|
1563
|
+
wipe.current = setTimeout(() => void wipeIfUnchanged(text), opts.clearAfter);
|
|
1564
|
+
}
|
|
1565
|
+
return true;
|
|
926
1566
|
} catch {
|
|
927
1567
|
setCopied(false);
|
|
1568
|
+
return false;
|
|
928
1569
|
}
|
|
929
1570
|
},
|
|
930
1571
|
[timeoutMs]
|
|
931
1572
|
);
|
|
932
1573
|
return { copied, copy };
|
|
933
1574
|
}
|
|
934
|
-
function CopyButton({ value, label = "Copy", className }) {
|
|
1575
|
+
function CopyButton({ value, label = "Copy", clearAfter, onCopied, className }) {
|
|
935
1576
|
const { copied, copy } = useCopy();
|
|
1577
|
+
const done = copied ? clearAfter ? `Copied. Cleared in ${Math.round(clearAfter / 1e3)} seconds` : "Copied" : "";
|
|
936
1578
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
937
1579
|
"button",
|
|
938
1580
|
{
|
|
939
1581
|
type: "button",
|
|
940
|
-
onClick: () =>
|
|
1582
|
+
onClick: async () => {
|
|
1583
|
+
if (await copy(typeof value === "function" ? value() : value, { clearAfter })) onCopied?.();
|
|
1584
|
+
},
|
|
941
1585
|
"aria-label": copied ? "Copied" : label,
|
|
1586
|
+
title: label,
|
|
942
1587
|
className: cn(
|
|
943
1588
|
"inline-flex size-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
|
|
944
1589
|
className
|
|
945
1590
|
),
|
|
946
1591
|
children: [
|
|
947
1592
|
copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-4 text-success" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "size-4" }),
|
|
948
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-live": "polite", className: "sr-only", children:
|
|
1593
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-live": "polite", className: "sr-only", children: done })
|
|
949
1594
|
]
|
|
950
1595
|
}
|
|
951
1596
|
);
|
|
@@ -956,12 +1601,27 @@ function HashChip({
|
|
|
956
1601
|
tail = 6,
|
|
957
1602
|
copy = true,
|
|
958
1603
|
href,
|
|
1604
|
+
explorer,
|
|
1605
|
+
network = "mainnet",
|
|
959
1606
|
className
|
|
960
1607
|
}) {
|
|
961
|
-
const shown =
|
|
1608
|
+
const shown = shortenMiddle(value, head, tail);
|
|
1609
|
+
const link = href ?? (explorer ? explorerUrl(explorer, value, network) : void 0);
|
|
1610
|
+
const offsite = !!link && /^https?:\/\//.test(link);
|
|
962
1611
|
const text = /* @__PURE__ */ jsxRuntime.jsx("span", { title: value, className: "font-mono text-[0.875rem]", children: shown });
|
|
963
1612
|
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("inline-flex max-w-full items-center gap-1", className), children: [
|
|
964
|
-
|
|
1613
|
+
link ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1614
|
+
"a",
|
|
1615
|
+
{
|
|
1616
|
+
href: link,
|
|
1617
|
+
...offsite ? { target: "_blank", rel: "noreferrer" } : {},
|
|
1618
|
+
className: "underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground",
|
|
1619
|
+
children: [
|
|
1620
|
+
text,
|
|
1621
|
+
offsite ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " (opens in a new tab)" }) : null
|
|
1622
|
+
]
|
|
1623
|
+
}
|
|
1624
|
+
) : text,
|
|
965
1625
|
copy ? /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value, label: "Copy full value" }) : null
|
|
966
1626
|
] });
|
|
967
1627
|
}
|
|
@@ -1015,96 +1675,269 @@ function ActivityList({ items, empty, className }) {
|
|
|
1015
1675
|
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: it.href ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: it.href, className: "block transition-colors hover:bg-accent/60", children: body }) : body }, it.id);
|
|
1016
1676
|
}) });
|
|
1017
1677
|
}
|
|
1018
|
-
var
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1678
|
+
var LANG_NAME = {
|
|
1679
|
+
ts: "TypeScript",
|
|
1680
|
+
typescript: "TypeScript",
|
|
1681
|
+
tsx: "TSX",
|
|
1682
|
+
js: "JavaScript",
|
|
1683
|
+
javascript: "JavaScript",
|
|
1684
|
+
jsx: "JSX",
|
|
1685
|
+
mjs: "JavaScript",
|
|
1686
|
+
json: "JSON",
|
|
1687
|
+
jsonc: "JSON",
|
|
1688
|
+
bash: "Shell",
|
|
1689
|
+
sh: "Shell",
|
|
1690
|
+
shell: "Shell",
|
|
1691
|
+
zsh: "Shell",
|
|
1692
|
+
console: "Terminal",
|
|
1693
|
+
terminal: "Terminal",
|
|
1694
|
+
python: "Python",
|
|
1695
|
+
py: "Python",
|
|
1696
|
+
yaml: "YAML",
|
|
1697
|
+
yml: "YAML",
|
|
1698
|
+
diff: "Diff",
|
|
1699
|
+
text: "Text"
|
|
1022
1700
|
};
|
|
1023
|
-
function
|
|
1024
|
-
return
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1701
|
+
function languageName(lang) {
|
|
1702
|
+
return lang ? LANG_NAME[lang.toLowerCase()] ?? lang : void 0;
|
|
1703
|
+
}
|
|
1704
|
+
function forClipboard(text, lang) {
|
|
1705
|
+
if (grammarOf(lang) !== "shell") return text;
|
|
1706
|
+
const lines = text.split("\n");
|
|
1707
|
+
if (!lines.some((l) => l.startsWith("$ "))) return text;
|
|
1708
|
+
return lines.filter((l) => l.startsWith("$ ")).map((l) => l.slice(2)).join("\n");
|
|
1709
|
+
}
|
|
1710
|
+
function linesFromDom(pre) {
|
|
1711
|
+
if (!pre) return null;
|
|
1712
|
+
const lines = pre.querySelectorAll("[data-line]");
|
|
1713
|
+
if (lines.length === 0) return pre.textContent ?? "";
|
|
1714
|
+
return Array.from(lines).filter((l) => l.getAttribute("data-diff") !== "remove").map((l) => l.textContent ?? "").join("\n");
|
|
1715
|
+
}
|
|
1716
|
+
function prepare(code, lang, marks, diff) {
|
|
1717
|
+
const d = diff ? readDiff(code) : null;
|
|
1718
|
+
const src = d ? d.code : code.replace(/\r?\n$/, "");
|
|
1719
|
+
const lines = highlight(src, lang === "diff" ? void 0 : lang);
|
|
1720
|
+
const kept = d ? src.split("\n").filter((_, i) => d.diff.get(i + 1) !== "remove") : null;
|
|
1721
|
+
return {
|
|
1722
|
+
html: linesToHtml(lines, { highlight: parseLineRanges(marks), diff: d?.diff }),
|
|
1723
|
+
copy: kept ? kept.join("\n") : src,
|
|
1724
|
+
lines: lines.length,
|
|
1725
|
+
diff: !!d
|
|
1726
|
+
};
|
|
1727
|
+
}
|
|
1728
|
+
function Well({
|
|
1729
|
+
preRef,
|
|
1730
|
+
html,
|
|
1731
|
+
children,
|
|
1732
|
+
lang,
|
|
1733
|
+
lines,
|
|
1734
|
+
maxLines,
|
|
1735
|
+
diff,
|
|
1736
|
+
lineNumbers
|
|
1737
|
+
}) {
|
|
1738
|
+
const foldable = maxLines !== void 0 && lines > maxLines + 2;
|
|
1739
|
+
const [open, setOpen] = react.useState(false);
|
|
1740
|
+
const folded = foldable && !open;
|
|
1741
|
+
const lined = html !== void 0;
|
|
1742
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
1743
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1744
|
+
"div",
|
|
1745
|
+
{
|
|
1746
|
+
className: cn(folded && "overflow-hidden"),
|
|
1747
|
+
style: folded ? { maxHeight: `calc(${maxLines} * 1.625em + 2rem)` } : void 0,
|
|
1748
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--oca-code-surface)", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1749
|
+
"pre",
|
|
1750
|
+
{
|
|
1751
|
+
ref: preRef,
|
|
1752
|
+
"data-diff": diff ? "" : void 0,
|
|
1753
|
+
"data-line-numbers": lineNumbers ? "" : void 0,
|
|
1754
|
+
className: cn(
|
|
1755
|
+
"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]",
|
|
1756
|
+
!lined && "px-5"
|
|
1757
|
+
),
|
|
1758
|
+
children: lined ? /* @__PURE__ */ jsxRuntime.jsx("code", { className: "block", "data-lang": lang, dangerouslySetInnerHTML: { __html: html } }) : /* @__PURE__ */ jsxRuntime.jsx("code", { className: "block", "data-lang": lang, children })
|
|
1759
|
+
}
|
|
1760
|
+
) })
|
|
1761
|
+
}
|
|
1762
|
+
),
|
|
1763
|
+
foldable ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1764
|
+
"div",
|
|
1765
|
+
{
|
|
1766
|
+
className: cn("flex justify-center px-5 pb-4", folded && "absolute inset-x-0 bottom-0 pt-16"),
|
|
1767
|
+
style: folded ? { background: "linear-gradient(to top, var(--oca-code-surface) 40%, transparent)" } : void 0,
|
|
1768
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1769
|
+
"button",
|
|
1770
|
+
{
|
|
1771
|
+
type: "button",
|
|
1772
|
+
onClick: () => setOpen((v) => !v),
|
|
1773
|
+
"aria-expanded": open,
|
|
1774
|
+
className: "rounded-full border border-white/20 px-4 py-1.5 text-[0.8125rem] text-white transition-colors hover:bg-white/10",
|
|
1775
|
+
children: open ? "Show less" : `Show all ${lines} lines`
|
|
1776
|
+
}
|
|
1777
|
+
)
|
|
1778
|
+
}
|
|
1779
|
+
) : null
|
|
1780
|
+
] });
|
|
1044
1781
|
}
|
|
1782
|
+
var FRAME = "overflow-hidden rounded-[1.25rem] border border-[var(--oca-code-line)] bg-[var(--oca-code-surface)]";
|
|
1783
|
+
var COPY_ON_INK = "text-oca-ink-subtle hover:bg-white/10 hover:text-white";
|
|
1045
1784
|
function CodeBlock({
|
|
1046
1785
|
code,
|
|
1786
|
+
html,
|
|
1787
|
+
children,
|
|
1788
|
+
lang,
|
|
1047
1789
|
caption,
|
|
1048
1790
|
copy = true,
|
|
1791
|
+
clearAfter,
|
|
1049
1792
|
maxLines,
|
|
1793
|
+
highlight: marks,
|
|
1794
|
+
diff,
|
|
1795
|
+
lineNumbers,
|
|
1796
|
+
actions,
|
|
1050
1797
|
className
|
|
1051
1798
|
}) {
|
|
1052
|
-
const
|
|
1053
|
-
const
|
|
1054
|
-
const
|
|
1055
|
-
const
|
|
1799
|
+
const preRef = react.useRef(null);
|
|
1800
|
+
const isDiff = diff || lang === "diff";
|
|
1801
|
+
const markKey = typeof marks === "string" ? marks : marks?.join(",");
|
|
1802
|
+
const prepared = react.useMemo(
|
|
1803
|
+
() => html === void 0 && children === void 0 && code !== void 0 ? prepare(code, lang, markKey, !!isDiff) : null,
|
|
1804
|
+
[code, html, children, lang, markKey, isDiff]
|
|
1805
|
+
);
|
|
1806
|
+
const markup = prepared?.html ?? html;
|
|
1807
|
+
const lines = prepared?.lines ?? (html !== void 0 ? html.split("\n").length : code?.split("\n").length ?? 0);
|
|
1808
|
+
const read = () => forClipboard(prepared?.copy ?? linesFromDom(preRef.current) ?? code ?? "", lang);
|
|
1809
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: cn(FRAME, className), children: [
|
|
1810
|
+
/* @__PURE__ */ jsxRuntime.jsxs("figcaption", { className: "flex h-11 items-center justify-between gap-3 border-b border-[var(--oca-code-line)] pl-5 pr-2", children: [
|
|
1811
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.8125rem] text-oca-ink-subtle", children: caption ?? languageName(lang) ?? "Code" }),
|
|
1812
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
|
|
1813
|
+
actions,
|
|
1814
|
+
copy ? /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: read, label: "Copy code", clearAfter, className: COPY_ON_INK }) : null
|
|
1815
|
+
] })
|
|
1816
|
+
] }),
|
|
1817
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1818
|
+
Well,
|
|
1819
|
+
{
|
|
1820
|
+
preRef,
|
|
1821
|
+
html: markup,
|
|
1822
|
+
lang,
|
|
1823
|
+
lines,
|
|
1824
|
+
maxLines,
|
|
1825
|
+
diff: prepared ? prepared.diff : isDiff,
|
|
1826
|
+
lineNumbers,
|
|
1827
|
+
children
|
|
1828
|
+
}
|
|
1829
|
+
)
|
|
1830
|
+
] });
|
|
1831
|
+
}
|
|
1832
|
+
var tabListeners = /* @__PURE__ */ new Map();
|
|
1833
|
+
var tabMemory = /* @__PURE__ */ new Map();
|
|
1834
|
+
var storeKey = (k) => `oca-code-tab:${k}`;
|
|
1835
|
+
function readTab(key) {
|
|
1836
|
+
if (tabMemory.has(key)) return tabMemory.get(key);
|
|
1837
|
+
try {
|
|
1838
|
+
return window.localStorage.getItem(storeKey(key));
|
|
1839
|
+
} catch {
|
|
1840
|
+
return null;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
function writeTab(key, value) {
|
|
1844
|
+
tabMemory.set(key, value);
|
|
1845
|
+
try {
|
|
1846
|
+
window.localStorage.setItem(storeKey(key), value);
|
|
1847
|
+
} catch {
|
|
1848
|
+
}
|
|
1849
|
+
tabListeners.get(key)?.forEach((l) => l());
|
|
1850
|
+
}
|
|
1851
|
+
function useSyncedTab(key) {
|
|
1852
|
+
const subscribe = react.useCallback(
|
|
1853
|
+
(cb) => {
|
|
1854
|
+
if (!key) return () => {
|
|
1855
|
+
};
|
|
1856
|
+
const set = tabListeners.get(key) ?? /* @__PURE__ */ new Set();
|
|
1857
|
+
set.add(cb);
|
|
1858
|
+
tabListeners.set(key, set);
|
|
1859
|
+
return () => {
|
|
1860
|
+
set.delete(cb);
|
|
1861
|
+
};
|
|
1862
|
+
},
|
|
1863
|
+
[key]
|
|
1864
|
+
);
|
|
1865
|
+
const value = react.useSyncExternalStore(
|
|
1866
|
+
subscribe,
|
|
1867
|
+
() => key ? readTab(key) : null,
|
|
1868
|
+
() => null
|
|
1869
|
+
);
|
|
1870
|
+
return [value, (v) => key && writeTab(key, v)];
|
|
1871
|
+
}
|
|
1872
|
+
function CodeTabs({
|
|
1873
|
+
items,
|
|
1874
|
+
syncKey,
|
|
1875
|
+
defaultValue,
|
|
1876
|
+
maxLines,
|
|
1877
|
+
className
|
|
1878
|
+
}) {
|
|
1879
|
+
const [synced, setSynced] = useSyncedTab(syncKey);
|
|
1880
|
+
const [local, setLocal] = react.useState(null);
|
|
1881
|
+
const labels = items.map((it) => it.label);
|
|
1882
|
+
const pick = [local, synced, defaultValue].find((v) => !!v && labels.includes(v)) ?? labels[0] ?? "";
|
|
1883
|
+
const active = items.find((it) => it.label === pick);
|
|
1884
|
+
const prepared = react.useMemo(() => items.map((it) => prepare(it.code, it.lang, void 0, it.lang === "diff")), [items]);
|
|
1056
1885
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1057
|
-
|
|
1886
|
+
TabsPrimitive__namespace.Root,
|
|
1058
1887
|
{
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1888
|
+
value: pick,
|
|
1889
|
+
onValueChange: (v) => {
|
|
1890
|
+
setLocal(v);
|
|
1891
|
+
setSynced(v);
|
|
1892
|
+
},
|
|
1893
|
+
className: cn(FRAME, className),
|
|
1063
1894
|
children: [
|
|
1064
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
1065
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
1066
|
-
|
|
1067
|
-
CopyButton,
|
|
1068
|
-
{
|
|
1069
|
-
value: code,
|
|
1070
|
-
label: "Copy code",
|
|
1071
|
-
className: "text-oca-ink-subtle hover:bg-white/10 hover:text-white"
|
|
1072
|
-
}
|
|
1073
|
-
) : null
|
|
1074
|
-
] }),
|
|
1075
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
1076
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1077
|
-
"div",
|
|
1078
|
-
{
|
|
1079
|
-
className: cn(folded && "overflow-hidden"),
|
|
1080
|
-
style: folded ? { maxHeight: `calc(${maxLines} * 1.625em + 2.5rem)` } : void 0,
|
|
1081
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--oca-code-surface)", children: /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("code", { children: code }) }) })
|
|
1082
|
-
}
|
|
1083
|
-
),
|
|
1084
|
-
foldable ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1085
|
-
"div",
|
|
1895
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-11 items-center justify-between gap-3 border-b border-[var(--oca-code-line)] pl-2 pr-2", children: [
|
|
1896
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--oca-code-surface)", className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(TabsPrimitive__namespace.List, { "aria-label": "Versions", className: "flex w-max items-center gap-0.5", children: items.map((it) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1897
|
+
TabsPrimitive__namespace.Trigger,
|
|
1086
1898
|
{
|
|
1899
|
+
value: it.label,
|
|
1087
1900
|
className: cn(
|
|
1088
|
-
"flex
|
|
1089
|
-
|
|
1901
|
+
"relative inline-flex h-11 items-center whitespace-nowrap px-3 text-[0.8125rem] text-oca-ink-subtle outline-none transition-colors",
|
|
1902
|
+
"hover:text-white focus-visible:text-white focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
1903
|
+
"data-[state=active]:text-white",
|
|
1904
|
+
"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"
|
|
1090
1905
|
),
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1906
|
+
children: it.label
|
|
1907
|
+
},
|
|
1908
|
+
it.label
|
|
1909
|
+
)) }) }),
|
|
1910
|
+
active ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1911
|
+
CopyButton,
|
|
1912
|
+
{
|
|
1913
|
+
value: () => forClipboard(prepared[items.indexOf(active)]?.copy ?? active.code, active.lang),
|
|
1914
|
+
label: `Copy ${active.label}`,
|
|
1915
|
+
className: COPY_ON_INK
|
|
1101
1916
|
}
|
|
1102
1917
|
) : null
|
|
1103
|
-
] })
|
|
1918
|
+
] }),
|
|
1919
|
+
items.map((it, i) => /* @__PURE__ */ jsxRuntime.jsx(TabsPrimitive__namespace.Content, { value: it.label, className: "outline-none", tabIndex: -1, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1920
|
+
Well,
|
|
1921
|
+
{
|
|
1922
|
+
html: prepared[i].html,
|
|
1923
|
+
lang: it.lang,
|
|
1924
|
+
lines: prepared[i].lines,
|
|
1925
|
+
maxLines,
|
|
1926
|
+
diff: prepared[i].diff
|
|
1927
|
+
}
|
|
1928
|
+
) }, it.label))
|
|
1104
1929
|
]
|
|
1105
1930
|
}
|
|
1106
1931
|
);
|
|
1107
1932
|
}
|
|
1933
|
+
function InstallTabs({ pkg, dev = false, className }) {
|
|
1934
|
+
const items = [
|
|
1935
|
+
{ label: "npm", code: `npm install ${dev ? "--save-dev " : ""}${pkg}`, lang: "bash" },
|
|
1936
|
+
{ label: "yarn", code: `yarn add ${dev ? "--dev " : ""}${pkg}`, lang: "bash" },
|
|
1937
|
+
{ label: "pnpm", code: `pnpm add ${dev ? "--save-dev " : ""}${pkg}`, lang: "bash" }
|
|
1938
|
+
];
|
|
1939
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CodeTabs, { items, syncKey: "package-manager", className });
|
|
1940
|
+
}
|
|
1108
1941
|
function SplitBar({
|
|
1109
1942
|
segments,
|
|
1110
1943
|
caption,
|
|
@@ -1455,53 +2288,2470 @@ var ErrorBoundary = class extends react.Component {
|
|
|
1455
2288
|
) });
|
|
1456
2289
|
}
|
|
1457
2290
|
};
|
|
2291
|
+
var TOP = "0,3 2,2 6,4 14,0 16,1 6,6";
|
|
2292
|
+
var LEFT = "0,3 6,6 6,8 0,5";
|
|
2293
|
+
var RIGHT = "6,6 16,1 16,3 6,8";
|
|
2294
|
+
var MARK_FACES = { top: "#FED8AB", left: "#FB933C", right: "#EA580B" };
|
|
2295
|
+
function Mark({ title, size, className, ...rest }) {
|
|
2296
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2297
|
+
"svg",
|
|
2298
|
+
{
|
|
2299
|
+
viewBox: "0 0 16 8",
|
|
2300
|
+
width: size,
|
|
2301
|
+
height: size ? size / 2 : void 0,
|
|
2302
|
+
role: title ? "img" : void 0,
|
|
2303
|
+
"aria-hidden": title ? void 0 : true,
|
|
2304
|
+
className: cn("shrink-0", className),
|
|
2305
|
+
...rest,
|
|
2306
|
+
children: [
|
|
2307
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx("title", { children: title }) : null,
|
|
2308
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: LEFT, fill: MARK_FACES.left }),
|
|
2309
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: RIGHT, fill: MARK_FACES.right }),
|
|
2310
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: TOP, fill: MARK_FACES.top })
|
|
2311
|
+
]
|
|
2312
|
+
}
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
function MarkOutline({ className }) {
|
|
2316
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "-0.2 -0.2 16.4 8.4", "aria-hidden": true, className: cn("shrink-0 overflow-visible", className), children: [TOP, LEFT, RIGHT].map((points) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2317
|
+
"polygon",
|
|
2318
|
+
{
|
|
2319
|
+
points,
|
|
2320
|
+
fill: "none",
|
|
2321
|
+
stroke: "currentColor",
|
|
2322
|
+
strokeWidth: "1",
|
|
2323
|
+
strokeLinejoin: "round",
|
|
2324
|
+
vectorEffect: "non-scaling-stroke"
|
|
2325
|
+
},
|
|
2326
|
+
points
|
|
2327
|
+
)) });
|
|
2328
|
+
}
|
|
2329
|
+
var WORDS = {
|
|
2330
|
+
404: {
|
|
2331
|
+
name: "Not found",
|
|
2332
|
+
title: "This page isn\u2019t here.",
|
|
2333
|
+
detail: "The link may be old, or the address mistyped."
|
|
2334
|
+
},
|
|
2335
|
+
500: {
|
|
2336
|
+
name: "Server error",
|
|
2337
|
+
title: "Something broke on our side.",
|
|
2338
|
+
detail: "Try again in a moment."
|
|
2339
|
+
}
|
|
2340
|
+
};
|
|
2341
|
+
function ErrorPage({
|
|
2342
|
+
code = 404,
|
|
2343
|
+
title,
|
|
2344
|
+
detail,
|
|
2345
|
+
actions,
|
|
2346
|
+
home = "/",
|
|
2347
|
+
art,
|
|
2348
|
+
className
|
|
2349
|
+
}) {
|
|
2350
|
+
const words = WORDS[code] ?? (code >= 500 ? WORDS[500] : WORDS[404]);
|
|
2351
|
+
const server = code >= 500;
|
|
2352
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Section, { space: "none", className: cn("flex min-h-[min(40rem,72dvh)] items-center py-16 md:py-24", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 items-center gap-12 md:grid-cols-12", children: [
|
|
2353
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-w-[40rem] flex-col items-start gap-6 md:col-span-7", children: [
|
|
2354
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "oca-eyebrow oca-enter", children: [
|
|
2355
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-tabular", children: code }),
|
|
2356
|
+
" \xB7 ",
|
|
2357
|
+
WORDS[code]?.name ?? (server ? "Error" : "Not available")
|
|
2358
|
+
] }),
|
|
2359
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "oca-display-2 oca-enter [--enter-delay:70ms]", children: title ?? words.title }),
|
|
2360
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead oca-enter [--enter-delay:150ms]", children: detail ?? words.detail }),
|
|
2361
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-enter flex flex-wrap gap-3 [--enter-delay:230ms]", children: actions ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2362
|
+
server ? /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => window.location.reload(), children: "Try again" }) : null,
|
|
2363
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, variant: server ? "secondary" : "primary", children: /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: home, children: "Go home" }) })
|
|
2364
|
+
] }) })
|
|
2365
|
+
] }),
|
|
2366
|
+
art !== null ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "oca-enter hidden justify-center md:col-span-5 md:flex [--enter-delay:120ms]", children: art ?? /* @__PURE__ */ jsxRuntime.jsx(MarkOutline, { className: "w-full max-w-[20rem] text-oca-hairline-strong" }) }) : null
|
|
2367
|
+
] }) });
|
|
2368
|
+
}
|
|
2369
|
+
function IsoCheck({ size = 360, settle = false, shadow = true, tilt = false, title, className }) {
|
|
2370
|
+
const ref = react.useRef(null);
|
|
2371
|
+
react.useEffect(() => {
|
|
2372
|
+
const el = ref.current;
|
|
2373
|
+
if (!el || !tilt || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
2374
|
+
let raf = 0;
|
|
2375
|
+
let tx = 0;
|
|
2376
|
+
let ty = 0;
|
|
2377
|
+
let x = 0;
|
|
2378
|
+
let y = 0;
|
|
2379
|
+
const step = () => {
|
|
2380
|
+
x += (tx - x) * 0.08;
|
|
2381
|
+
y += (ty - y) * 0.08;
|
|
2382
|
+
el.style.setProperty("--rx", `${(-y * 10).toFixed(2)}deg`);
|
|
2383
|
+
el.style.setProperty("--ry", `${(x * 14).toFixed(2)}deg`);
|
|
2384
|
+
raf = Math.abs(tx - x) + Math.abs(ty - y) > 1e-3 ? requestAnimationFrame(step) : 0;
|
|
2385
|
+
};
|
|
2386
|
+
const move = (e) => {
|
|
2387
|
+
const b = el.getBoundingClientRect();
|
|
2388
|
+
tx = Math.max(-1, Math.min(1, (e.clientX - (b.left + b.width / 2)) / (window.innerWidth / 2)));
|
|
2389
|
+
ty = Math.max(-1, Math.min(1, (e.clientY - (b.top + b.height / 2)) / (window.innerHeight / 2)));
|
|
2390
|
+
if (!raf) raf = requestAnimationFrame(step);
|
|
2391
|
+
};
|
|
2392
|
+
window.addEventListener("pointermove", move, { passive: true });
|
|
2393
|
+
return () => {
|
|
2394
|
+
cancelAnimationFrame(raf);
|
|
2395
|
+
window.removeEventListener("pointermove", move);
|
|
2396
|
+
};
|
|
2397
|
+
}, [tilt]);
|
|
2398
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2399
|
+
"div",
|
|
2400
|
+
{
|
|
2401
|
+
ref,
|
|
2402
|
+
className: cn("relative inline-block", settle && "oca-animate-settle", className),
|
|
2403
|
+
style: { width: size, perspective: tilt ? 900 : void 0 },
|
|
2404
|
+
children: [
|
|
2405
|
+
tilt ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2406
|
+
"div",
|
|
2407
|
+
{
|
|
2408
|
+
"aria-hidden": true,
|
|
2409
|
+
className: "absolute left-1/2 top-1/2 -z-0 aspect-square w-[120%] -translate-x-1/2 -translate-y-1/2 rounded-full opacity-70 blur-3xl",
|
|
2410
|
+
style: { background: "radial-gradient(closest-side, rgb(255 140 70 / 0.35), transparent)" }
|
|
2411
|
+
}
|
|
2412
|
+
) : null,
|
|
2413
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2414
|
+
"div",
|
|
2415
|
+
{
|
|
2416
|
+
className: "relative z-10 transition-transform duration-300 ease-out",
|
|
2417
|
+
style: tilt ? { transform: "rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))", transformStyle: "preserve-3d" } : void 0,
|
|
2418
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Mark, { size, title, className: "block" })
|
|
2419
|
+
}
|
|
2420
|
+
),
|
|
2421
|
+
shadow ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2422
|
+
"div",
|
|
2423
|
+
{
|
|
2424
|
+
"aria-hidden": true,
|
|
2425
|
+
className: "absolute left-[8%] right-[8%] rounded-[50%] opacity-60 blur-xl",
|
|
2426
|
+
style: { height: size * 0.08, bottom: -size * 0.04, background: "rgb(234 88 11 / 0.18)" }
|
|
2427
|
+
}
|
|
2428
|
+
) : null
|
|
2429
|
+
]
|
|
2430
|
+
}
|
|
2431
|
+
);
|
|
2432
|
+
}
|
|
2433
|
+
var GroupName = react.createContext(void 0);
|
|
2434
|
+
function Accordion({
|
|
2435
|
+
single = false,
|
|
2436
|
+
children,
|
|
2437
|
+
className
|
|
2438
|
+
}) {
|
|
2439
|
+
const name = react.useId();
|
|
2440
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GroupName.Provider, { value: single ? name : void 0, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("divide-y divide-border overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children }) });
|
|
2441
|
+
}
|
|
2442
|
+
function AccordionItem({
|
|
2443
|
+
title,
|
|
2444
|
+
children,
|
|
2445
|
+
defaultOpen = false,
|
|
2446
|
+
id,
|
|
2447
|
+
className
|
|
2448
|
+
}) {
|
|
2449
|
+
const name = react.useContext(GroupName);
|
|
2450
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("details", { id, name, open: defaultOpen || void 0, className: cn("group scroll-mt-24", className), children: [
|
|
2451
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2452
|
+
"summary",
|
|
2453
|
+
{
|
|
2454
|
+
className: cn(
|
|
2455
|
+
"flex min-h-14 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[1rem] font-medium leading-snug md:px-6",
|
|
2456
|
+
// Inside the card's clip, so the ring is drawn within the row.
|
|
2457
|
+
"transition-colors hover:bg-accent/60 focus-visible:outline-offset-[-2px] [&::-webkit-details-marker]:hidden"
|
|
2458
|
+
),
|
|
2459
|
+
children: [
|
|
2460
|
+
title,
|
|
2461
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2462
|
+
lucideReact.ChevronDown,
|
|
2463
|
+
{
|
|
2464
|
+
"aria-hidden": true,
|
|
2465
|
+
className: "size-4 shrink-0 text-muted-foreground transition-transform duration-200 group-open:rotate-180"
|
|
2466
|
+
}
|
|
2467
|
+
)
|
|
2468
|
+
]
|
|
2469
|
+
}
|
|
2470
|
+
),
|
|
2471
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-body px-5 pb-5 text-[0.9375rem] md:px-6 md:pb-6", children })
|
|
2472
|
+
] });
|
|
2473
|
+
}
|
|
2474
|
+
function SectionHeading({
|
|
2475
|
+
eyebrow,
|
|
2476
|
+
title,
|
|
2477
|
+
lead,
|
|
2478
|
+
id,
|
|
2479
|
+
onInk = false,
|
|
2480
|
+
level = 2,
|
|
2481
|
+
as = "h2",
|
|
2482
|
+
align = "start",
|
|
2483
|
+
reveal = true,
|
|
2484
|
+
className
|
|
2485
|
+
}) {
|
|
2486
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(SectionIntro, { align, reveal, className: cn("max-w-3xl gap-4 md:gap-4", className), children: [
|
|
2487
|
+
eyebrow ? /* @__PURE__ */ jsxRuntime.jsx(Eyebrow, { onInk, children: eyebrow }) : null,
|
|
2488
|
+
/* @__PURE__ */ jsxRuntime.jsx(Display, { level, as, id, className: "scroll-mt-24", children: title }),
|
|
2489
|
+
lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("oca-lead", onInk && "text-oca-ink-muted"), children: lead }) : null
|
|
2490
|
+
] });
|
|
2491
|
+
}
|
|
2492
|
+
function FactBlock({
|
|
2493
|
+
id,
|
|
2494
|
+
title,
|
|
2495
|
+
description,
|
|
2496
|
+
aside,
|
|
2497
|
+
children,
|
|
2498
|
+
className
|
|
2499
|
+
}) {
|
|
2500
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { id, className: cn("flex scroll-mt-24 flex-col gap-6", className), children: [
|
|
2501
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-end md:justify-between md:gap-8", children: [
|
|
2502
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-w-[44rem] flex-col gap-3", children: [
|
|
2503
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "oca-display-3", children: title }),
|
|
2504
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-body text-[1.0625rem]", children: description }) : null
|
|
2505
|
+
] }),
|
|
2506
|
+
aside ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 flex-wrap gap-x-5 gap-y-2 text-[0.9375rem]", children: aside }) : null
|
|
2507
|
+
] }),
|
|
2508
|
+
children
|
|
2509
|
+
] });
|
|
2510
|
+
}
|
|
2511
|
+
function FactRows({
|
|
2512
|
+
rows,
|
|
2513
|
+
columns = 1,
|
|
2514
|
+
label,
|
|
2515
|
+
className
|
|
2516
|
+
}) {
|
|
2517
|
+
return /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": label, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex flex-col gap-5 px-5 py-6 md:px-8 md:py-7", children: [
|
|
2518
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between gap-x-6", children: [
|
|
2519
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title min-w-0 text-pretty", children: r.title }),
|
|
2520
|
+
r.figure ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-tabular shrink-0 whitespace-nowrap text-[1.75rem] leading-none tracking-[-0.02em]", children: r.figure }) : null
|
|
2521
|
+
] }),
|
|
2522
|
+
/* @__PURE__ */ jsxRuntime.jsx("dl", { className: columns === 2 ? "grid grid-cols-1 gap-x-10 gap-y-4 md:grid-cols-2" : "flex flex-col gap-4", children: r.fields.map((f, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
2523
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-[0.875rem] font-medium text-muted-foreground", children: f.label }),
|
|
2524
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "break-words text-[1rem] leading-relaxed", children: f.value })
|
|
2525
|
+
] }, i)) })
|
|
2526
|
+
] }, r.key)) });
|
|
2527
|
+
}
|
|
2528
|
+
function EndpointList({ items, label, className }) {
|
|
2529
|
+
return /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": label, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: items.map((a) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2530
|
+
"a",
|
|
2531
|
+
{
|
|
2532
|
+
href: a.href,
|
|
2533
|
+
target: "_blank",
|
|
2534
|
+
rel: "noreferrer",
|
|
2535
|
+
className: "flex flex-col gap-1 px-5 py-3.5 transition-colors hover:bg-accent/60 sm:flex-row sm:items-baseline sm:justify-between sm:gap-6",
|
|
2536
|
+
children: [
|
|
2537
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "break-all text-[0.875rem] text-foreground", children: a.label ?? a.href }),
|
|
2538
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[0.875rem] text-muted-foreground sm:text-right", children: [
|
|
2539
|
+
a.description,
|
|
2540
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " (opens in a new tab)" })
|
|
2541
|
+
] })
|
|
2542
|
+
]
|
|
2543
|
+
}
|
|
2544
|
+
) }, a.href)) });
|
|
2545
|
+
}
|
|
2546
|
+
function ProofStrip({ items, className }) {
|
|
2547
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border-y border-border", className), children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "oca-container grid grid-cols-2 gap-x-6 gap-y-4 py-6 md:grid-cols-4", children: items.map((it, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2548
|
+
"li",
|
|
2549
|
+
{
|
|
2550
|
+
className: "flex items-center gap-3 text-[0.9375rem] [&_svg]:size-[1.1rem] [&_svg]:shrink-0 [&_svg]:text-oca-accent-ink",
|
|
2551
|
+
children: [
|
|
2552
|
+
it.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "flex", children: it.icon }) : null,
|
|
2553
|
+
it.label
|
|
2554
|
+
]
|
|
2555
|
+
},
|
|
2556
|
+
i
|
|
2557
|
+
)) }) });
|
|
2558
|
+
}
|
|
2559
|
+
function Closing({
|
|
2560
|
+
title,
|
|
2561
|
+
lead,
|
|
2562
|
+
actions,
|
|
2563
|
+
art,
|
|
2564
|
+
className
|
|
2565
|
+
}) {
|
|
2566
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Section, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 items-center gap-12 md:grid-cols-12", children: [
|
|
2567
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Reveal, { className: "flex flex-col items-start gap-8 md:col-span-7", children: [
|
|
2568
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
|
|
2569
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "oca-display-1 text-[clamp(2.5rem,1.5rem+4vw,5rem)] leading-[1]", children: title }),
|
|
2570
|
+
lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead max-w-[34rem]", children: lead }) : null
|
|
2571
|
+
] }),
|
|
2572
|
+
actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-3", children: actions }) : null
|
|
2573
|
+
] }),
|
|
2574
|
+
art !== null ? (
|
|
2575
|
+
// Room under the check on a phone, so its glow fades before the band ends.
|
|
2576
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "flex justify-center max-md:pb-16 md:col-span-5", children: art ?? /* @__PURE__ */ jsxRuntime.jsx(IsoCheck, { size: 340, settle: true, tilt: true, className: "max-w-full" }) })
|
|
2577
|
+
) : null
|
|
2578
|
+
] }) });
|
|
2579
|
+
}
|
|
2580
|
+
function Faq({
|
|
2581
|
+
items,
|
|
2582
|
+
className
|
|
2583
|
+
}) {
|
|
2584
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Accordion, { single: true, className, children: items.map((it, i) => /* @__PURE__ */ jsxRuntime.jsx(AccordionItem, { id: it.id, title: it.q, children: it.a }, it.id ?? i)) });
|
|
2585
|
+
}
|
|
2586
|
+
var LINK = "text-foreground underline decoration-foreground/35 underline-offset-4 transition-colors hover:decoration-foreground";
|
|
2587
|
+
function TextLink({
|
|
2588
|
+
href,
|
|
2589
|
+
children,
|
|
2590
|
+
external,
|
|
2591
|
+
className
|
|
2592
|
+
}) {
|
|
2593
|
+
const internal = href.startsWith("/") && !href.startsWith("/api/") && !href.startsWith("/.well-known/");
|
|
2594
|
+
const offsite = external ?? /^https?:\/\//.test(href);
|
|
2595
|
+
if (internal && !offsite) {
|
|
2596
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href, className: cn(LINK, className), children });
|
|
2597
|
+
}
|
|
2598
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("a", { href, className: cn(LINK, className), ...offsite ? { target: "_blank", rel: "noreferrer" } : {}, children: [
|
|
2599
|
+
children,
|
|
2600
|
+
offsite ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " (opens in a new tab)" }) : null
|
|
2601
|
+
] });
|
|
2602
|
+
}
|
|
2603
|
+
var PROPER = {
|
|
2604
|
+
kyc: "KYC",
|
|
2605
|
+
pii: "PII",
|
|
2606
|
+
ccpa: "CCPA",
|
|
2607
|
+
cpra: "CPRA",
|
|
2608
|
+
gdpr: "GDPR",
|
|
2609
|
+
uk: "UK",
|
|
2610
|
+
eu: "EU",
|
|
2611
|
+
california: "California",
|
|
2612
|
+
europe: "Europe",
|
|
2613
|
+
united: "United",
|
|
2614
|
+
kingdom: "Kingdom"
|
|
2615
|
+
};
|
|
2616
|
+
function headingCase(text) {
|
|
2617
|
+
const words = text.replace(/\b[a-z]+\b/g, (w) => PROPER[w] ?? w);
|
|
2618
|
+
if (/^orangecheck\b/.test(words)) return `OrangeCheck${words.slice("orangecheck".length)}`;
|
|
2619
|
+
return words.length === 0 ? words : words[0].toUpperCase() + words.slice(1);
|
|
2620
|
+
}
|
|
2621
|
+
function sentencesCase(text) {
|
|
2622
|
+
return text.split(/(?<=[.!?])\s+/).map((s) => headingCase(s)).join(" ");
|
|
2623
|
+
}
|
|
2624
|
+
function openSentence(text) {
|
|
2625
|
+
const first = /^\S+/.exec(text)?.[0] ?? "";
|
|
2626
|
+
if (!/^[a-z][a-z'’-]*,?$/.test(first)) return text;
|
|
2627
|
+
return text[0].toUpperCase() + text.slice(1);
|
|
2628
|
+
}
|
|
2629
|
+
var INLINE = /(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\([^)]+\))/g;
|
|
2630
|
+
var LINK2 = /^\[([^\]]+)\]\(([^)]+)\)$/;
|
|
2631
|
+
function Inline({ text }) {
|
|
2632
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: text.split(INLINE).map((part, i) => {
|
|
2633
|
+
if (!part) return null;
|
|
2634
|
+
if (part.startsWith("**") && part.endsWith("**") && part.length > 4) {
|
|
2635
|
+
return /* @__PURE__ */ jsxRuntime.jsx("strong", { children: /* @__PURE__ */ jsxRuntime.jsx(Inline, { text: part.slice(2, -2) }) }, i);
|
|
2636
|
+
}
|
|
2637
|
+
if (part.startsWith("`") && part.endsWith("`") && part.length > 2) return /* @__PURE__ */ jsxRuntime.jsx("code", { children: part.slice(1, -1) }, i);
|
|
2638
|
+
const link = LINK2.exec(part);
|
|
2639
|
+
if (link) {
|
|
2640
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextLink, { href: link[2] ?? "", children: link[1] }, i);
|
|
2641
|
+
}
|
|
2642
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: part }, i);
|
|
2643
|
+
}) });
|
|
2644
|
+
}
|
|
2645
|
+
function BlockView({ block }) {
|
|
2646
|
+
switch (block.kind) {
|
|
2647
|
+
case "para":
|
|
2648
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: block.text.split(/\n{2,}/).map((para, i) => /* @__PURE__ */ jsxRuntime.jsx("p", { children: /* @__PURE__ */ jsxRuntime.jsx(Inline, { text: para }) }, i)) });
|
|
2649
|
+
case "subhead":
|
|
2650
|
+
return /* @__PURE__ */ jsxRuntime.jsx("h3", { children: /* @__PURE__ */ jsxRuntime.jsx(Inline, { text: headingCase(block.text) }) });
|
|
2651
|
+
case "bullets":
|
|
2652
|
+
return /* @__PURE__ */ jsxRuntime.jsx("ul", { children: block.items.map(
|
|
2653
|
+
(item, i) => typeof item === "string" ? /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(Inline, { text: item }) }, i) : /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
2654
|
+
/* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
|
|
2655
|
+
headingCase(item.k),
|
|
2656
|
+
"."
|
|
2657
|
+
] }),
|
|
2658
|
+
" ",
|
|
2659
|
+
/* @__PURE__ */ jsxRuntime.jsx(Inline, { text: openSentence(item.v) })
|
|
2660
|
+
] }, i)
|
|
2661
|
+
) });
|
|
2662
|
+
case "callout":
|
|
2663
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "not-prose my-6", children: /* @__PURE__ */ jsxRuntime.jsx(Notice, { tone: block.emphatic ? "brand" : "neutral", children: /* @__PURE__ */ jsxRuntime.jsx(Inline, { text: block.text }) }) });
|
|
2664
|
+
case "stub":
|
|
2665
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "not-prose my-6", children: /* @__PURE__ */ jsxRuntime.jsx(Notice, { tone: "brand", title: "Pending counsel review", children: /* @__PURE__ */ jsxRuntime.jsx(Inline, { text: block.text }) }) });
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
function LegalDocument({ doc, className }) {
|
|
2669
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2670
|
+
DocLayout,
|
|
2671
|
+
{
|
|
2672
|
+
className,
|
|
2673
|
+
header: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2674
|
+
DocHeader,
|
|
2675
|
+
{
|
|
2676
|
+
eyebrow: headingCase(doc.eyebrow),
|
|
2677
|
+
title: doc.title,
|
|
2678
|
+
lead: doc.description,
|
|
2679
|
+
meta: `Effective ${doc.effective} \xB7 last updated ${doc.updated}`
|
|
2680
|
+
}
|
|
2681
|
+
),
|
|
2682
|
+
toc: doc.sections.map((s) => ({ id: s.id, label: headingCase(s.heading) })),
|
|
2683
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("article", { className: "min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs(Prose, { children: [
|
|
2684
|
+
doc.preamble?.map((b, i) => /* @__PURE__ */ jsxRuntime.jsx(BlockView, { block: b }, i)),
|
|
2685
|
+
doc.sections.map((s) => /* @__PURE__ */ jsxRuntime.jsxs("section", { children: [
|
|
2686
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h2", { id: s.id, className: "scroll-mt-24", children: [
|
|
2687
|
+
s.num ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "oca-tabular text-muted-foreground", children: [
|
|
2688
|
+
s.num,
|
|
2689
|
+
" "
|
|
2690
|
+
] }) : null,
|
|
2691
|
+
headingCase(s.heading)
|
|
2692
|
+
] }),
|
|
2693
|
+
s.hint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.9375rem]", children: headingCase(s.hint) }) : null,
|
|
2694
|
+
s.blocks.map((b, i) => /* @__PURE__ */ jsxRuntime.jsx(BlockView, { block: b }, i))
|
|
2695
|
+
] }, s.id)),
|
|
2696
|
+
doc.summary ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-14 border-t border-border pt-6 text-[0.9375rem]", children: [
|
|
2697
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "In short." }),
|
|
2698
|
+
" ",
|
|
2699
|
+
sentencesCase(doc.summary.replace(/^summary:\s*/i, ""))
|
|
2700
|
+
] }) : null
|
|
2701
|
+
] }) })
|
|
2702
|
+
}
|
|
2703
|
+
);
|
|
2704
|
+
}
|
|
2705
|
+
|
|
2706
|
+
// src/family/index.ts
|
|
2707
|
+
var OCHK_IO = "https://ochk.io";
|
|
2708
|
+
var DOCS_HREF = `${OCHK_IO}/docs`;
|
|
2709
|
+
function protocol(slug, verb, line, kinds) {
|
|
2710
|
+
return {
|
|
2711
|
+
slug,
|
|
2712
|
+
label: slug,
|
|
2713
|
+
href: `${OCHK_IO}/${slug}`,
|
|
2714
|
+
group: "protocol",
|
|
2715
|
+
line,
|
|
2716
|
+
status: "live",
|
|
2717
|
+
verb,
|
|
2718
|
+
pageHref: `${OCHK_IO}/${slug}`,
|
|
2719
|
+
toolHref: `https://${slug}.ochk.io`,
|
|
2720
|
+
specHref: `https://github.com/orangecheck/oc-${slug}-protocol`,
|
|
2721
|
+
kinds
|
|
2722
|
+
};
|
|
2723
|
+
}
|
|
2724
|
+
var PROTOCOLS = [
|
|
2725
|
+
protocol("attest", "identity", "Show that an address holds bitcoin, and for how long.", "30078"),
|
|
2726
|
+
protocol("lock", "confidentiality", "Encrypt to a Bitcoin address, so only its holder can open it.", "30078"),
|
|
2727
|
+
protocol("vote", "legitimacy", "Polls weighed in sats, that anyone can tally.", "30080\u201330082"),
|
|
2728
|
+
protocol("stamp", "provenance", "Prove who signed something, and when.", "30083"),
|
|
2729
|
+
protocol("agent", "authority", "Give software scoped, revocable permission to act for you.", "30083\u201330086"),
|
|
2730
|
+
protocol("pledge", "commitment", "Make a promise with bitcoin behind it, on a public record.", "30078")
|
|
2731
|
+
];
|
|
2732
|
+
var PROTOCOL_ORDER = PROTOCOLS.map((p) => p.slug);
|
|
2733
|
+
var FAMILY = [
|
|
2734
|
+
{
|
|
2735
|
+
slug: "home",
|
|
2736
|
+
label: "ochk.io",
|
|
2737
|
+
href: OCHK_IO,
|
|
2738
|
+
group: "orangecheck",
|
|
2739
|
+
line: "The open protocols, and the company behind them.",
|
|
2740
|
+
status: "live"
|
|
2741
|
+
},
|
|
2742
|
+
{
|
|
2743
|
+
slug: "me",
|
|
2744
|
+
label: "ochk.app",
|
|
2745
|
+
href: "https://ochk.app",
|
|
2746
|
+
group: "orangecheck",
|
|
2747
|
+
line: "One account, with Bitcoin behind it.",
|
|
2748
|
+
status: "testing"
|
|
2749
|
+
},
|
|
2750
|
+
{
|
|
2751
|
+
slug: "docs",
|
|
2752
|
+
label: "docs",
|
|
2753
|
+
href: DOCS_HREF,
|
|
2754
|
+
group: "orangecheck",
|
|
2755
|
+
line: "Specs, SDKs and guides for every protocol.",
|
|
2756
|
+
status: "live"
|
|
2757
|
+
},
|
|
2758
|
+
...PROTOCOLS,
|
|
2759
|
+
{
|
|
2760
|
+
slug: "vault",
|
|
2761
|
+
label: "vault",
|
|
2762
|
+
href: "https://vault.ochk.io",
|
|
2763
|
+
group: "app",
|
|
2764
|
+
line: "A password manager, encrypted in your browser.",
|
|
2765
|
+
status: "live",
|
|
2766
|
+
protocols: ["lock"]
|
|
2767
|
+
},
|
|
2768
|
+
{
|
|
2769
|
+
slug: "chat",
|
|
2770
|
+
label: "chat",
|
|
2771
|
+
href: "https://chat.ochk.io",
|
|
2772
|
+
group: "app",
|
|
2773
|
+
line: "Messages only the holder of a Bitcoin address can read.",
|
|
2774
|
+
status: "testing",
|
|
2775
|
+
protocols: ["lock"]
|
|
2776
|
+
},
|
|
2777
|
+
{
|
|
2778
|
+
slug: "cosign",
|
|
2779
|
+
label: "cosign",
|
|
2780
|
+
href: "https://cosign.ochk.io",
|
|
2781
|
+
group: "app",
|
|
2782
|
+
line: "Builders find co-founders and backers.",
|
|
2783
|
+
status: "testing",
|
|
2784
|
+
protocols: ["attest"]
|
|
2785
|
+
},
|
|
2786
|
+
{
|
|
2787
|
+
slug: "me-demo",
|
|
2788
|
+
// "demo", not the made-up app's own name, so nobody takes it for ours.
|
|
2789
|
+
label: "demo",
|
|
2790
|
+
href: "https://me-demo.ochk.io",
|
|
2791
|
+
group: "app",
|
|
2792
|
+
line: "Lumen Notes, a made-up app that signs in with orangecheck.",
|
|
2793
|
+
status: "live"
|
|
2794
|
+
},
|
|
2795
|
+
{
|
|
2796
|
+
slug: "globe",
|
|
2797
|
+
label: "globe",
|
|
2798
|
+
href: "https://globe.ochk.io",
|
|
2799
|
+
group: "public-good",
|
|
2800
|
+
line: "The Bitcoin network, live, on a globe.",
|
|
2801
|
+
status: "live"
|
|
2802
|
+
},
|
|
2803
|
+
{
|
|
2804
|
+
slug: "btc",
|
|
2805
|
+
label: "btc",
|
|
2806
|
+
href: "https://btc.ochk.io",
|
|
2807
|
+
group: "public-good",
|
|
2808
|
+
line: "A free desk for reading the Bitcoin market.",
|
|
2809
|
+
status: "live"
|
|
2810
|
+
}
|
|
2811
|
+
];
|
|
2812
|
+
var BY_SLUG = new Map(FAMILY.map((s) => [s.slug, s]));
|
|
2813
|
+
function protocolSite(slug) {
|
|
2814
|
+
return BY_SLUG.get(slug);
|
|
2815
|
+
}
|
|
2816
|
+
[
|
|
2817
|
+
{
|
|
2818
|
+
href: `${OCHK_IO}/protocols`,
|
|
2819
|
+
label: "Protocols",
|
|
2820
|
+
children: PROTOCOLS.map((p) => ({ href: p.pageHref, label: p.label, description: p.line }))
|
|
2821
|
+
},
|
|
2822
|
+
{ href: `${OCHK_IO}/apps`, label: "Apps" },
|
|
2823
|
+
{ href: DOCS_HREF, label: "Docs" },
|
|
2824
|
+
{ href: `${OCHK_IO}/trust`, label: "Trust" },
|
|
2825
|
+
{ href: `${OCHK_IO}/about`, label: "About" }
|
|
2826
|
+
];
|
|
2827
|
+
var WORD = {
|
|
2828
|
+
live: "Live",
|
|
2829
|
+
testing: "In testing",
|
|
2830
|
+
"not-yet": "Not yet",
|
|
2831
|
+
paused: "Paused",
|
|
2832
|
+
good: "Good",
|
|
2833
|
+
caution: "Caution",
|
|
2834
|
+
refused: "Refused"
|
|
2835
|
+
};
|
|
2836
|
+
var TONE2 = {
|
|
2837
|
+
live: "success",
|
|
2838
|
+
testing: "brand",
|
|
2839
|
+
"not-yet": "muted",
|
|
2840
|
+
paused: "muted",
|
|
2841
|
+
good: "success",
|
|
2842
|
+
caution: "brand",
|
|
2843
|
+
refused: "danger"
|
|
2844
|
+
};
|
|
2845
|
+
function StatusBadge({ status, className, ...props }) {
|
|
2846
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: TONE2[status], "data-status": status, className: cn(className), ...props, children: WORD[status] });
|
|
2847
|
+
}
|
|
2848
|
+
var CARD = "group relative flex h-full flex-col rounded-[1.25rem] border border-border bg-card p-6 transition-colors hover:border-oca-hairline-strong md:p-7 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";
|
|
2849
|
+
var STRETCH = 'outline-none after:absolute after:inset-0 after:rounded-[1.25rem] after:content-[""]';
|
|
2850
|
+
var pad2 = (n) => String(n + 1).padStart(2, "0");
|
|
2851
|
+
function ProtocolGrid({
|
|
2852
|
+
protocols = PROTOCOL_ORDER,
|
|
2853
|
+
link = "page",
|
|
2854
|
+
className
|
|
2855
|
+
}) {
|
|
2856
|
+
return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: cn("grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 md:gap-5", className), children: protocols.map((slug) => {
|
|
2857
|
+
const p = protocolSite(slug);
|
|
2858
|
+
const i = PROTOCOL_ORDER.indexOf(slug);
|
|
2859
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(CARD, "gap-4"), children: [
|
|
2860
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
2861
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "oca-numeral", children: [
|
|
2862
|
+
pad2(i),
|
|
2863
|
+
" ",
|
|
2864
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1.5 capitalize", children: p.verb })
|
|
2865
|
+
] }),
|
|
2866
|
+
p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null
|
|
2867
|
+
] }),
|
|
2868
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-display-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2869
|
+
"a",
|
|
2870
|
+
{
|
|
2871
|
+
href: link === "tool" ? p.toolHref : link === "docs" ? `${DOCS_HREF}/${p.slug}` : p.pageHref,
|
|
2872
|
+
className: STRETCH,
|
|
2873
|
+
children: p.label
|
|
2874
|
+
}
|
|
2875
|
+
) }),
|
|
2876
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body", children: p.line }),
|
|
2877
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-auto flex items-center justify-between gap-3 pt-2 text-[0.875rem] text-muted-foreground", children: [
|
|
2878
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "oca-tabular", children: [
|
|
2879
|
+
"Nostr kind ",
|
|
2880
|
+
p.kinds
|
|
2881
|
+
] }),
|
|
2882
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2883
|
+
lucideReact.ArrowUpRight,
|
|
2884
|
+
{
|
|
2885
|
+
"aria-hidden": true,
|
|
2886
|
+
className: "size-4 transition-transform duration-200 group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:text-foreground"
|
|
2887
|
+
}
|
|
2888
|
+
)
|
|
2889
|
+
] })
|
|
2890
|
+
] }) }, slug);
|
|
2891
|
+
}) });
|
|
2892
|
+
}
|
|
2893
|
+
function AppCard({ name, line, href, protocols = [], status = "live", className }) {
|
|
2894
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(CARD, "gap-3", className), children: [
|
|
2895
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
2896
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href, className: STRETCH, children: name }) }),
|
|
2897
|
+
status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status }) : null
|
|
2898
|
+
] }),
|
|
2899
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body text-[0.9375rem]", children: line }),
|
|
2900
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-auto flex items-end justify-between gap-3 pt-3", children: [
|
|
2901
|
+
protocols.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex flex-wrap items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
|
|
2902
|
+
"Shows",
|
|
2903
|
+
protocols.map((p) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: p }, p))
|
|
2904
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
|
|
2905
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-1 text-[0.875rem] text-muted-foreground transition-colors group-hover:text-foreground", children: [
|
|
2906
|
+
href.replace(/^https?:\/\//, ""),
|
|
2907
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true, className: "size-4" })
|
|
2908
|
+
] })
|
|
2909
|
+
] })
|
|
2910
|
+
] });
|
|
2911
|
+
}
|
|
2912
|
+
function AppGrid({
|
|
2913
|
+
group = "app",
|
|
2914
|
+
sites,
|
|
2915
|
+
className
|
|
2916
|
+
}) {
|
|
2917
|
+
const list = sites ? sites.map((slug) => FAMILY.find((s) => s.slug === slug)).filter((s) => s !== void 0) : FAMILY.filter((s) => s.group === group);
|
|
2918
|
+
return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: cn("grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-5", className), children: list.map((s) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(AppCard, { name: s.label, line: s.line, href: s.href, protocols: s.protocols, status: s.status }) }, s.slug)) });
|
|
2919
|
+
}
|
|
2920
|
+
var fieldBase = [
|
|
2921
|
+
"w-full rounded-xl border border-input bg-card text-foreground placeholder:text-oca-subtle",
|
|
2922
|
+
"text-base md:text-[0.9375rem] outline-none transition-[border-color,box-shadow]",
|
|
2923
|
+
"focus:border-foreground/35 focus:ring-4 focus:ring-[color-mix(in_oklab,var(--oca-orange)_16%,transparent)]",
|
|
2924
|
+
"disabled:cursor-not-allowed disabled:opacity-55",
|
|
2925
|
+
"aria-[invalid=true]:border-destructive aria-[invalid=true]:focus:ring-[color-mix(in_oklab,var(--destructive)_14%,transparent)]"
|
|
2926
|
+
];
|
|
2927
|
+
var FIELD_SIZE = {
|
|
2928
|
+
md: "h-11 px-3.5",
|
|
2929
|
+
sm: "h-9 rounded-[0.625rem] px-3 md:text-[0.875rem]"
|
|
2930
|
+
};
|
|
2931
|
+
var Input = react.forwardRef(function Input2({ className, type = "text", size, ...props }, ref) {
|
|
2932
|
+
const density = useDensity();
|
|
2933
|
+
const s = size ?? (density === "compact" ? "sm" : "md");
|
|
2934
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2935
|
+
"input",
|
|
2936
|
+
{
|
|
2937
|
+
ref,
|
|
2938
|
+
type,
|
|
2939
|
+
"data-ui": "input",
|
|
2940
|
+
"data-size": s,
|
|
2941
|
+
className: cn(fieldBase, FIELD_SIZE[s], className),
|
|
2942
|
+
...props
|
|
2943
|
+
}
|
|
2944
|
+
);
|
|
2945
|
+
});
|
|
2946
|
+
var Textarea = react.forwardRef(
|
|
2947
|
+
function Textarea2({ className, ...props }, ref) {
|
|
2948
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2949
|
+
"textarea",
|
|
2950
|
+
{
|
|
2951
|
+
ref,
|
|
2952
|
+
"data-ui": "textarea",
|
|
2953
|
+
className: cn(fieldBase, "min-h-28 px-3.5 py-3 leading-relaxed", className),
|
|
2954
|
+
...props
|
|
2955
|
+
}
|
|
2956
|
+
);
|
|
2957
|
+
}
|
|
2958
|
+
);
|
|
2959
|
+
var Label = react.forwardRef(function Label2({ className, ...props }, ref) {
|
|
2960
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2961
|
+
LabelPrimitive__namespace.Root,
|
|
2962
|
+
{
|
|
2963
|
+
ref,
|
|
2964
|
+
className: cn("text-sm font-medium leading-none text-foreground", className),
|
|
2965
|
+
...props
|
|
2966
|
+
}
|
|
2967
|
+
);
|
|
2968
|
+
});
|
|
2969
|
+
function Field({ label, hint, optional, error, children, className, hideLabel, action }) {
|
|
2970
|
+
const id = react.useId();
|
|
2971
|
+
const hintId = hint ? `${id}-hint` : void 0;
|
|
2972
|
+
const errorId = error ? `${id}-error` : void 0;
|
|
2973
|
+
const describedBy = [hintId, errorId].filter(Boolean).join(" ") || void 0;
|
|
2974
|
+
const control = react.isValidElement(children) ? react.cloneElement(children, {
|
|
2975
|
+
id,
|
|
2976
|
+
"aria-describedby": describedBy,
|
|
2977
|
+
"aria-invalid": error ? true : void 0
|
|
2978
|
+
}) : children;
|
|
2979
|
+
const hintNode = hint ? /* @__PURE__ */ jsxRuntime.jsx("p", { id: hintId, className: "text-[0.8125rem] leading-snug text-muted-foreground", children: hint }) : null;
|
|
2980
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
|
|
2981
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: id, className: hideLabel ? "sr-only" : "flex items-baseline gap-2", children: [
|
|
2982
|
+
label,
|
|
2983
|
+
optional ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.8125rem] font-normal text-muted-foreground", children: "Optional" }) : null
|
|
2984
|
+
] }),
|
|
2985
|
+
action ? (
|
|
2986
|
+
// The hint belongs to the input, so it sits under the input, not under the button.
|
|
2987
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start", children: [
|
|
2988
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2 [&>input]:w-full", children: [
|
|
2989
|
+
control,
|
|
2990
|
+
hintNode
|
|
2991
|
+
] }),
|
|
2992
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: action })
|
|
2993
|
+
] })
|
|
2994
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2995
|
+
control,
|
|
2996
|
+
hintNode
|
|
2997
|
+
] }),
|
|
2998
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx("p", { id: errorId, role: "alert", className: "text-[0.8125rem] leading-snug text-destructive", children: error }) : null
|
|
2999
|
+
] });
|
|
3000
|
+
}
|
|
3001
|
+
var SelectFieldContext = sharedContext("select-field", null);
|
|
3002
|
+
react.forwardRef(function SelectTrigger2({ className, children, size, ...props }, ref) {
|
|
3003
|
+
const density = useDensity();
|
|
3004
|
+
const field = react.useContext(SelectFieldContext);
|
|
3005
|
+
const s = size ?? (density === "compact" ? "sm" : "md");
|
|
3006
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3007
|
+
SelectPrimitive__namespace.Trigger,
|
|
3008
|
+
{
|
|
3009
|
+
ref,
|
|
3010
|
+
id: field?.id,
|
|
3011
|
+
"aria-describedby": field?.["aria-describedby"],
|
|
3012
|
+
"aria-invalid": field?.["aria-invalid"],
|
|
3013
|
+
className: cn(fieldBase, FIELD_SIZE[s], "flex items-center justify-between gap-2 text-left", className),
|
|
3014
|
+
...props,
|
|
3015
|
+
children: [
|
|
3016
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children }),
|
|
3017
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Icon, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-4 shrink-0 text-muted-foreground" }) })
|
|
3018
|
+
]
|
|
3019
|
+
}
|
|
3020
|
+
);
|
|
3021
|
+
});
|
|
3022
|
+
react.forwardRef(function SelectContent2({ className, children, position = "popper", ...props }, ref) {
|
|
3023
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3024
|
+
SelectPrimitive__namespace.Content,
|
|
3025
|
+
{
|
|
3026
|
+
ref,
|
|
3027
|
+
position,
|
|
3028
|
+
sideOffset: 6,
|
|
3029
|
+
className: cn(
|
|
3030
|
+
"oca-animate-fade z-50 max-h-[min(24rem,var(--radix-select-content-available-height))] min-w-[var(--radix-select-trigger-width)] overflow-hidden rounded-xl border border-border bg-popover p-1 text-popover-foreground shadow-lg",
|
|
3031
|
+
className
|
|
3032
|
+
),
|
|
3033
|
+
...props,
|
|
3034
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Viewport, { children })
|
|
3035
|
+
}
|
|
3036
|
+
) });
|
|
3037
|
+
});
|
|
3038
|
+
react.forwardRef(function SelectItem2({ className, children, ...props }, ref) {
|
|
3039
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3040
|
+
SelectPrimitive__namespace.Item,
|
|
3041
|
+
{
|
|
3042
|
+
ref,
|
|
3043
|
+
className: cn(
|
|
3044
|
+
"relative flex h-10 cursor-default select-none items-center rounded-lg pl-3 pr-9 text-[0.9375rem] outline-none",
|
|
3045
|
+
"data-[highlighted]:bg-accent data-[disabled]:opacity-50",
|
|
3046
|
+
className
|
|
3047
|
+
),
|
|
3048
|
+
...props,
|
|
3049
|
+
children: [
|
|
3050
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ItemText, { children }),
|
|
3051
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ItemIndicator, { className: "absolute right-3", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-4" }) })
|
|
3052
|
+
]
|
|
3053
|
+
}
|
|
3054
|
+
);
|
|
3055
|
+
});
|
|
3056
|
+
react.forwardRef(function Checkbox2({ className, ...props }, ref) {
|
|
3057
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3058
|
+
CheckboxPrimitive__namespace.Root,
|
|
3059
|
+
{
|
|
3060
|
+
ref,
|
|
3061
|
+
className: cn(
|
|
3062
|
+
"peer inline-flex size-5 shrink-0 items-center justify-center rounded-[6px] border border-input bg-card",
|
|
3063
|
+
"outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
3064
|
+
"data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
|
3065
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
3066
|
+
className
|
|
3067
|
+
),
|
|
3068
|
+
...props,
|
|
3069
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(CheckboxPrimitive__namespace.Indicator, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3.5", strokeWidth: 3 }) })
|
|
3070
|
+
}
|
|
3071
|
+
);
|
|
3072
|
+
});
|
|
3073
|
+
react.forwardRef(function Switch2({ className, ...props }, ref) {
|
|
3074
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3075
|
+
SwitchPrimitive__namespace.Root,
|
|
3076
|
+
{
|
|
3077
|
+
ref,
|
|
3078
|
+
className: cn(
|
|
3079
|
+
"peer inline-flex h-6 w-11 shrink-0 items-center rounded-full border border-transparent bg-input p-0.5",
|
|
3080
|
+
"outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
3081
|
+
// The deep orange: the track is the state, so it must clear 3:1 on a card.
|
|
3082
|
+
"data-[state=checked]:bg-oca-orange-deep disabled:cursor-not-allowed disabled:opacity-50",
|
|
3083
|
+
className
|
|
3084
|
+
),
|
|
3085
|
+
...props,
|
|
3086
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SwitchPrimitive__namespace.Thumb, { className: "pointer-events-none block size-5 rounded-full bg-white shadow-sm transition-transform data-[state=checked]:translate-x-5" })
|
|
3087
|
+
}
|
|
3088
|
+
);
|
|
3089
|
+
});
|
|
3090
|
+
react.forwardRef(function RadioGroup2({ className, ...props }, ref) {
|
|
3091
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Root, { ref, className: cn("grid gap-3", className), ...props });
|
|
3092
|
+
});
|
|
3093
|
+
react.forwardRef(function RadioGroupItem2({ className, ...props }, ref) {
|
|
3094
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3095
|
+
RadioGroupPrimitive__namespace.Item,
|
|
3096
|
+
{
|
|
3097
|
+
ref,
|
|
3098
|
+
className: cn(
|
|
3099
|
+
"inline-flex size-5 shrink-0 items-center justify-center rounded-full border border-input bg-card",
|
|
3100
|
+
"outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
3101
|
+
"data-[state=checked]:border-primary disabled:cursor-not-allowed disabled:opacity-50",
|
|
3102
|
+
className
|
|
3103
|
+
),
|
|
3104
|
+
...props,
|
|
3105
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Indicator, { className: "block size-2.5 rounded-full bg-primary" })
|
|
3106
|
+
}
|
|
3107
|
+
);
|
|
3108
|
+
});
|
|
3109
|
+
function ProtocolHero({
|
|
3110
|
+
protocol: protocol2,
|
|
3111
|
+
title,
|
|
3112
|
+
lead,
|
|
3113
|
+
actions,
|
|
3114
|
+
art,
|
|
3115
|
+
children,
|
|
3116
|
+
className
|
|
3117
|
+
}) {
|
|
3118
|
+
const p = protocolSite(protocol2);
|
|
3119
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3120
|
+
PageHero,
|
|
3121
|
+
{
|
|
3122
|
+
className,
|
|
3123
|
+
eyebrow: `Protocol \xB7 ${p.verb}`,
|
|
3124
|
+
title,
|
|
3125
|
+
lead,
|
|
3126
|
+
actions,
|
|
3127
|
+
art,
|
|
3128
|
+
children: p.status !== "live" || children ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-4", children: [
|
|
3129
|
+
p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null,
|
|
3130
|
+
children
|
|
3131
|
+
] }) : null
|
|
3132
|
+
}
|
|
3133
|
+
);
|
|
3134
|
+
}
|
|
3135
|
+
function ProtocolNav({
|
|
3136
|
+
current,
|
|
3137
|
+
link = "page",
|
|
3138
|
+
className
|
|
3139
|
+
}) {
|
|
3140
|
+
return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Protocols", className, children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--background)", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex w-max min-w-full items-center gap-6 border-b border-border", children: PROTOCOLS.map((p) => {
|
|
3141
|
+
const on = p.slug === current;
|
|
3142
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3143
|
+
"a",
|
|
3144
|
+
{
|
|
3145
|
+
href: link === "tool" ? p.toolHref : p.pageHref,
|
|
3146
|
+
"aria-current": on ? "page" : void 0,
|
|
3147
|
+
className: cn(
|
|
3148
|
+
"-mb-px inline-flex h-11 items-center border-b-2 text-[0.9375rem] transition-colors",
|
|
3149
|
+
on ? "border-foreground text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
|
|
3150
|
+
),
|
|
3151
|
+
children: p.label
|
|
3152
|
+
}
|
|
3153
|
+
) }, p.slug);
|
|
3154
|
+
}) }) }) });
|
|
3155
|
+
}
|
|
3156
|
+
function SpecCard({
|
|
3157
|
+
protocol: protocol2,
|
|
3158
|
+
version,
|
|
3159
|
+
license,
|
|
3160
|
+
vectors,
|
|
3161
|
+
size = "md",
|
|
3162
|
+
className
|
|
3163
|
+
}) {
|
|
3164
|
+
const p = protocolSite(protocol2);
|
|
3165
|
+
const repo = `oc-${p.slug}-protocol`;
|
|
3166
|
+
const facts = [
|
|
3167
|
+
["Version", version],
|
|
3168
|
+
...license ? [["Licence", license]] : [],
|
|
3169
|
+
["Nostr kind", p.kinds],
|
|
3170
|
+
...vectors !== void 0 ? [["Test vectors", String(vectors)]] : []
|
|
3171
|
+
];
|
|
3172
|
+
if (size === "sm") {
|
|
3173
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3174
|
+
"a",
|
|
3175
|
+
{
|
|
3176
|
+
href: p.specHref,
|
|
3177
|
+
className: cn(
|
|
3178
|
+
"group flex flex-wrap items-center gap-x-4 gap-y-1 rounded-2xl border border-border bg-card px-4 py-3 text-[0.875rem] transition-colors hover:border-oca-hairline-strong",
|
|
3179
|
+
className
|
|
3180
|
+
),
|
|
3181
|
+
children: [
|
|
3182
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[0.8125rem] text-foreground", children: repo }),
|
|
3183
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: facts.map(([k, v]) => k === "Version" ? `v${v}` : k === "Nostr kind" ? `kind ${v}` : v).join(" \xB7 ") }),
|
|
3184
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto flex items-center gap-1 text-muted-foreground group-hover:text-foreground", children: [
|
|
3185
|
+
"Read the spec ",
|
|
3186
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true, className: "size-4" })
|
|
3187
|
+
] })
|
|
3188
|
+
]
|
|
3189
|
+
}
|
|
3190
|
+
);
|
|
3191
|
+
}
|
|
3192
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-6 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className), children: [
|
|
3193
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
|
|
3194
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
3195
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: "The spec" }),
|
|
3196
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title break-all font-mono text-[1.0625rem] tracking-normal", children: repo })
|
|
3197
|
+
] }),
|
|
3198
|
+
p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null
|
|
3199
|
+
] }),
|
|
3200
|
+
/* @__PURE__ */ jsxRuntime.jsx("dl", { className: "grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-4", children: facts.map(([k, v]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3201
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-[0.8125rem] text-muted-foreground", children: k }),
|
|
3202
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "oca-tabular text-[1.0625rem]", children: v })
|
|
3203
|
+
] }, k)) }),
|
|
3204
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: p.specHref, children: [
|
|
3205
|
+
"Read the spec ",
|
|
3206
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true })
|
|
3207
|
+
] }) }) })
|
|
3208
|
+
] });
|
|
3209
|
+
}
|
|
3210
|
+
function VerifyBox({
|
|
3211
|
+
action,
|
|
3212
|
+
param = "q",
|
|
3213
|
+
title,
|
|
3214
|
+
description,
|
|
3215
|
+
label = "Id, envelope or link",
|
|
3216
|
+
placeholder,
|
|
3217
|
+
hint,
|
|
3218
|
+
submitLabel = "Verify",
|
|
3219
|
+
multiline = false,
|
|
3220
|
+
onVerify,
|
|
3221
|
+
className
|
|
3222
|
+
}) {
|
|
3223
|
+
const [value, setValue] = react.useState("");
|
|
3224
|
+
const submit = (e) => {
|
|
3225
|
+
if (!onVerify) return;
|
|
3226
|
+
e.preventDefault();
|
|
3227
|
+
if (value.trim()) onVerify(value.trim());
|
|
3228
|
+
};
|
|
3229
|
+
const button = /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", className: multiline ? void 0 : "w-full sm:w-auto", children: submitLabel });
|
|
3230
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3231
|
+
"form",
|
|
3232
|
+
{
|
|
3233
|
+
action,
|
|
3234
|
+
method: "get",
|
|
3235
|
+
onSubmit: submit,
|
|
3236
|
+
className: cn("flex flex-col gap-5 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className),
|
|
3237
|
+
children: [
|
|
3238
|
+
title || description ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3239
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title", children: title }) : null,
|
|
3240
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body text-[0.9375rem]", children: description }) : null
|
|
3241
|
+
] }) : null,
|
|
3242
|
+
multiline ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3243
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3244
|
+
Textarea,
|
|
3245
|
+
{
|
|
3246
|
+
name: param,
|
|
3247
|
+
required: true,
|
|
3248
|
+
value,
|
|
3249
|
+
onChange: (e) => setValue(e.target.value),
|
|
3250
|
+
placeholder,
|
|
3251
|
+
spellCheck: false,
|
|
3252
|
+
className: "min-h-32 font-mono text-base md:text-[0.8125rem]"
|
|
3253
|
+
}
|
|
3254
|
+
) }),
|
|
3255
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: button })
|
|
3256
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, action: button, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3257
|
+
Input,
|
|
3258
|
+
{
|
|
3259
|
+
name: param,
|
|
3260
|
+
required: true,
|
|
3261
|
+
value,
|
|
3262
|
+
onChange: (e) => setValue(e.target.value),
|
|
3263
|
+
placeholder,
|
|
3264
|
+
spellCheck: false,
|
|
3265
|
+
autoComplete: "off",
|
|
3266
|
+
className: "font-mono text-base md:text-[0.875rem]"
|
|
3267
|
+
}
|
|
3268
|
+
) })
|
|
3269
|
+
]
|
|
3270
|
+
}
|
|
3271
|
+
);
|
|
3272
|
+
}
|
|
3273
|
+
var TINT = "bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))]";
|
|
3274
|
+
function ComparisonTable({
|
|
3275
|
+
columns,
|
|
3276
|
+
rows,
|
|
3277
|
+
label,
|
|
3278
|
+
propertyHeading = "Property",
|
|
3279
|
+
className
|
|
3280
|
+
}) {
|
|
3281
|
+
const wide = columns.length > 3;
|
|
3282
|
+
const grid = wide ? "lg:grid lg:grid-cols-[var(--oca-compare)]" : "md:grid md:grid-cols-[var(--oca-compare)]";
|
|
3283
|
+
const desk = wide ? "lg" : "md";
|
|
3284
|
+
const style = {
|
|
3285
|
+
// The argued-for column gets a little more room: its answers carry the page.
|
|
3286
|
+
"--oca-compare": ["minmax(0, 1.4fr)", ...columns.map((c) => c.highlight ? "minmax(0, 1.3fr)" : "minmax(0, 1fr)")].join(" ")
|
|
3287
|
+
};
|
|
3288
|
+
const ordered = [...columns].sort((a, b) => Number(Boolean(b.highlight)) - Number(Boolean(a.highlight)));
|
|
3289
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("ul", { "aria-label": label, style, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: [
|
|
3290
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3291
|
+
"li",
|
|
3292
|
+
{
|
|
3293
|
+
"aria-hidden": true,
|
|
3294
|
+
className: cn(
|
|
3295
|
+
"hidden gap-5 px-5 py-4 text-[0.875rem] font-medium text-muted-foreground",
|
|
3296
|
+
wide ? "lg:grid lg:px-8" : "md:grid md:px-8",
|
|
3297
|
+
grid
|
|
3298
|
+
),
|
|
3299
|
+
children: [
|
|
3300
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: propertyHeading }),
|
|
3301
|
+
columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(c.highlight && cn(TINT, "-my-4 px-4 py-4 text-oca-accent-ink")), children: c.label }, c.key))
|
|
3302
|
+
]
|
|
3303
|
+
}
|
|
3304
|
+
),
|
|
3305
|
+
rows.map((r, ri) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: cn("grid grid-cols-1 gap-3 px-5 py-5", wide ? "lg:items-start lg:gap-5 lg:px-8" : "md:items-start md:gap-5 md:px-8", grid), children: [
|
|
3306
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
3307
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-title-sm", children: r.label }),
|
|
3308
|
+
r.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: r.note }) : null
|
|
3309
|
+
] }),
|
|
3310
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid grid-cols-2 gap-1", desk === "lg" ? "lg:contents" : "md:contents"), children: columns.map((c) => {
|
|
3311
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3312
|
+
"div",
|
|
3313
|
+
{
|
|
3314
|
+
style: { "--oca-order": ordered.indexOf(c) },
|
|
3315
|
+
className: cn(
|
|
3316
|
+
// Two rows of the pair's grid (name, answer), so answers line up
|
|
3317
|
+
// across a pair even when one name wraps.
|
|
3318
|
+
"order-[var(--oca-order)] row-span-2 grid min-w-0 grid-rows-subgrid gap-1 rounded-xl px-3 py-2.5",
|
|
3319
|
+
desk === "lg" ? "lg:order-none lg:row-span-1 lg:flex lg:flex-col" : "md:order-none md:row-span-1 md:flex md:flex-col",
|
|
3320
|
+
c.highlight ? cn(
|
|
3321
|
+
TINT,
|
|
3322
|
+
"col-span-2",
|
|
3323
|
+
desk === "lg" ? "lg:col-span-1 lg:-my-5 lg:self-stretch lg:rounded-none lg:px-4 lg:py-5" : "md:col-span-1 md:-my-5 md:self-stretch md:rounded-none md:px-4 md:py-5"
|
|
3324
|
+
) : desk === "lg" ? "lg:p-0" : "md:p-0"
|
|
3325
|
+
),
|
|
3326
|
+
children: [
|
|
3327
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3328
|
+
"span",
|
|
3329
|
+
{
|
|
3330
|
+
className: cn(
|
|
3331
|
+
"text-[0.8125rem]",
|
|
3332
|
+
c.highlight ? "text-oca-accent-ink" : "text-muted-foreground",
|
|
3333
|
+
desk === "lg" ? "lg:sr-only" : "md:sr-only"
|
|
3334
|
+
),
|
|
3335
|
+
children: c.label
|
|
3336
|
+
}
|
|
3337
|
+
),
|
|
3338
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[0.9375rem]", c.highlight && "font-medium"), children: r.values[c.key] ?? "\u2014" })
|
|
3339
|
+
]
|
|
3340
|
+
},
|
|
3341
|
+
c.key
|
|
3342
|
+
);
|
|
3343
|
+
}) })
|
|
3344
|
+
] }, ri))
|
|
3345
|
+
] });
|
|
3346
|
+
}
|
|
3347
|
+
var CHECK = {
|
|
3348
|
+
ok: { word: "Passed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, {}), tone: "text-success" },
|
|
3349
|
+
fail: { word: "Failed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleX, {}), tone: "text-destructive" },
|
|
3350
|
+
pending: { word: "Pending", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, {}), tone: "text-oca-accent-ink" },
|
|
3351
|
+
skipped: { word: "Skipped", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleMinus, {}), tone: "text-muted-foreground" },
|
|
3352
|
+
unchecked: { word: "Not checked", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleDashed, {}), tone: "text-oca-subtle" }
|
|
3353
|
+
};
|
|
3354
|
+
function VerifyReport({
|
|
3355
|
+
verdict,
|
|
3356
|
+
title,
|
|
3357
|
+
summary,
|
|
3358
|
+
checks,
|
|
3359
|
+
facts,
|
|
3360
|
+
notChecked,
|
|
3361
|
+
actions,
|
|
3362
|
+
as: Heading = "h2",
|
|
3363
|
+
className
|
|
3364
|
+
}) {
|
|
3365
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3366
|
+
"section",
|
|
3367
|
+
{
|
|
3368
|
+
"aria-label": "Verification result",
|
|
3369
|
+
className: cn("overflow-hidden rounded-[1.25rem] border border-border bg-card", className),
|
|
3370
|
+
children: [
|
|
3371
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col items-start gap-3 p-6 md:p-8", children: [
|
|
3372
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: verdict }),
|
|
3373
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { className: "oca-display-3", children: title }),
|
|
3374
|
+
summary ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body max-w-[40rem]", children: summary }) : null
|
|
3375
|
+
] }),
|
|
3376
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": "Checks", className: "divide-y divide-border border-t border-border", children: checks.map((c, i) => {
|
|
3377
|
+
const k = CHECK[c.state];
|
|
3378
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-3 px-6 py-3.5 md:px-8", children: [
|
|
3379
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: cn("mt-0.5 shrink-0 [&_svg]:size-[1.125rem]", k.tone), children: k.icon }),
|
|
3380
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5 sm:flex-row sm:items-baseline sm:justify-between sm:gap-6", children: [
|
|
3381
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
3382
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem]", children: c.label }),
|
|
3383
|
+
c.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-words text-[0.8125rem] leading-snug text-muted-foreground", children: c.note }) : null
|
|
3384
|
+
] }),
|
|
3385
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3386
|
+
"span",
|
|
3387
|
+
{
|
|
3388
|
+
className: cn(
|
|
3389
|
+
"shrink-0 text-[0.8125rem]",
|
|
3390
|
+
c.state === "fail" ? "text-destructive" : "text-muted-foreground"
|
|
3391
|
+
),
|
|
3392
|
+
children: k.word
|
|
3393
|
+
}
|
|
3394
|
+
)
|
|
3395
|
+
] })
|
|
3396
|
+
] }, i);
|
|
3397
|
+
}) }),
|
|
3398
|
+
facts && facts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { items: facts, className: "rounded-none border-x-0 border-b-0 bg-transparent [&>div]:px-6 md:[&>div]:px-8" }) : null,
|
|
3399
|
+
notChecked && notChecked.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 border-t border-border bg-muted/50 px-6 py-5 md:px-8", children: [
|
|
3400
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] font-medium", children: "What this did not check" }),
|
|
3401
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex list-disc flex-col gap-1 pl-5 text-[0.875rem] leading-relaxed text-muted-foreground", children: notChecked.map((n, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: n }, i)) })
|
|
3402
|
+
] }) : null,
|
|
3403
|
+
actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-3 border-t border-border px-6 py-5 md:px-8", children: actions }) : null
|
|
3404
|
+
]
|
|
3405
|
+
}
|
|
3406
|
+
);
|
|
3407
|
+
}
|
|
3408
|
+
function SignMessage({
|
|
3409
|
+
lead,
|
|
3410
|
+
address,
|
|
3411
|
+
message,
|
|
3412
|
+
wallets,
|
|
3413
|
+
busy = false,
|
|
3414
|
+
error,
|
|
3415
|
+
submitLabel = "Confirm",
|
|
3416
|
+
secondary,
|
|
3417
|
+
onSignature,
|
|
3418
|
+
className
|
|
3419
|
+
}) {
|
|
3420
|
+
const [pasted, setPasted] = react.useState("");
|
|
3421
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
|
|
3422
|
+
lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.9375rem] leading-relaxed", children: lead }) : null,
|
|
3423
|
+
wallets ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3424
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: wallets }),
|
|
3425
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-[0.8125rem] text-muted-foreground", children: [
|
|
3426
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" }),
|
|
3427
|
+
"or sign it in any wallet",
|
|
3428
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" })
|
|
3429
|
+
] })
|
|
3430
|
+
] }) : null,
|
|
3431
|
+
/* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: message, caption: "Message to sign" }),
|
|
3432
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3433
|
+
"form",
|
|
3434
|
+
{
|
|
3435
|
+
className: "flex flex-col gap-4",
|
|
3436
|
+
onSubmit: (e) => {
|
|
3437
|
+
e.preventDefault();
|
|
3438
|
+
if (pasted.trim()) onSignature(pasted.trim());
|
|
3439
|
+
},
|
|
3440
|
+
children: [
|
|
3441
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3442
|
+
Field,
|
|
3443
|
+
{
|
|
3444
|
+
label: "Signature",
|
|
3445
|
+
error,
|
|
3446
|
+
hint: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3447
|
+
"From your wallet\u2019s \u201Csign message\u201D (BIP-322), signed by",
|
|
3448
|
+
" ",
|
|
3449
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-all font-mono", children: address }),
|
|
3450
|
+
"."
|
|
3451
|
+
] }),
|
|
3452
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3453
|
+
Textarea,
|
|
3454
|
+
{
|
|
3455
|
+
value: pasted,
|
|
3456
|
+
onChange: (e) => setPasted(e.target.value),
|
|
3457
|
+
rows: 3,
|
|
3458
|
+
spellCheck: false,
|
|
3459
|
+
className: "min-h-24 font-mono text-base md:text-[0.8125rem]"
|
|
3460
|
+
}
|
|
3461
|
+
)
|
|
3462
|
+
}
|
|
3463
|
+
),
|
|
3464
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
3465
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", loading: busy, disabled: !pasted.trim(), children: submitLabel }),
|
|
3466
|
+
secondary
|
|
3467
|
+
] })
|
|
3468
|
+
]
|
|
3469
|
+
}
|
|
3470
|
+
)
|
|
3471
|
+
] });
|
|
3472
|
+
}
|
|
3473
|
+
var isInternal = (href) => href.startsWith("/") || href.startsWith("#");
|
|
3474
|
+
function DocLink({ href, className, children, ...rest }) {
|
|
3475
|
+
return isInternal(href) ? /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href, className, ...rest, children }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href, className, ...rest, children });
|
|
3476
|
+
}
|
|
3477
|
+
function Breadcrumbs({ items, action, className }) {
|
|
3478
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-h-11 items-center justify-between gap-4 sm:min-h-0", className), children: [
|
|
3479
|
+
/* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Breadcrumb", className: "min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex min-w-0 items-center gap-1.5 text-[0.875rem] text-muted-foreground", children: items.map((c, i) => {
|
|
3480
|
+
const last = i === items.length - 1;
|
|
3481
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: cn("flex items-center gap-1.5", last ? "min-w-0" : "shrink-0"), children: [
|
|
3482
|
+
c.href && !last ? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("span", { "aria-current": last ? "page" : void 0, className: cn("truncate", last && "text-foreground"), children: c.label }),
|
|
3483
|
+
!last ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }) : null
|
|
3484
|
+
] }, i);
|
|
3485
|
+
}) }) }),
|
|
3486
|
+
action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 text-[0.875rem]", children: action }) : null
|
|
3487
|
+
] });
|
|
3488
|
+
}
|
|
3489
|
+
function DocsPager({ prev, next, className }) {
|
|
3490
|
+
if (!prev && !next) return null;
|
|
3491
|
+
const card = (l, dir) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3492
|
+
DocLink,
|
|
3493
|
+
{
|
|
3494
|
+
href: l.href,
|
|
3495
|
+
className: cn(
|
|
3496
|
+
"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",
|
|
3497
|
+
dir === "next" && "items-end text-right sm:col-start-2"
|
|
3498
|
+
),
|
|
3499
|
+
children: [
|
|
3500
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
|
|
3501
|
+
dir === "prev" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { "aria-hidden": true, className: "size-3.5" }) : null,
|
|
3502
|
+
dir === "prev" ? "Previous" : "Next",
|
|
3503
|
+
l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "\xB7" }) : null,
|
|
3504
|
+
l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: l.section }) : null,
|
|
3505
|
+
dir === "next" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { "aria-hidden": true, className: "size-3.5" }) : null
|
|
3506
|
+
] }),
|
|
3507
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: l.label })
|
|
3508
|
+
]
|
|
3509
|
+
}
|
|
3510
|
+
);
|
|
3511
|
+
return /* @__PURE__ */ jsxRuntime.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: [
|
|
3512
|
+
prev ? card(prev, "prev") : null,
|
|
3513
|
+
next ? card(next, "next") : null
|
|
3514
|
+
] });
|
|
3515
|
+
}
|
|
3516
|
+
function useHeadings(selector = "#docs-content", key) {
|
|
3517
|
+
const [items, setItems] = react.useState([]);
|
|
3518
|
+
react.useEffect(() => {
|
|
3519
|
+
const read = () => {
|
|
3520
|
+
const root = document.querySelector(selector);
|
|
3521
|
+
if (!root) return setItems([]);
|
|
3522
|
+
setItems(
|
|
3523
|
+
Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
|
|
3524
|
+
id: h.id,
|
|
3525
|
+
// The anchor link's "#" is not part of the name.
|
|
3526
|
+
label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
|
|
3527
|
+
level: h.tagName === "H3" ? 3 : 2
|
|
3528
|
+
}))
|
|
3529
|
+
);
|
|
3530
|
+
};
|
|
3531
|
+
const raf = requestAnimationFrame(read);
|
|
3532
|
+
const t = setTimeout(read, 80);
|
|
3533
|
+
return () => {
|
|
3534
|
+
cancelAnimationFrame(raf);
|
|
3535
|
+
clearTimeout(t);
|
|
3536
|
+
};
|
|
3537
|
+
}, [selector, key]);
|
|
3538
|
+
const activeId = useActiveHeading(items.map((i) => i.id));
|
|
3539
|
+
return { items, activeId };
|
|
3540
|
+
}
|
|
3541
|
+
function OnThisPage({
|
|
3542
|
+
items,
|
|
3543
|
+
activeId,
|
|
3544
|
+
title = "On this page",
|
|
3545
|
+
onNavigate,
|
|
3546
|
+
className
|
|
3547
|
+
}) {
|
|
3548
|
+
const id = react.useId();
|
|
3549
|
+
if (items.length === 0) return null;
|
|
3550
|
+
return (
|
|
3551
|
+
// With no visible title (a folded list under its own summary) the name is still "On this page".
|
|
3552
|
+
/* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
|
|
3553
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
|
|
3554
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { children: items.map((t) => {
|
|
3555
|
+
const on = t.id === activeId;
|
|
3556
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3557
|
+
"a",
|
|
3558
|
+
{
|
|
3559
|
+
href: `#${t.id}`,
|
|
3560
|
+
onClick: onNavigate,
|
|
3561
|
+
"aria-current": on ? "location" : void 0,
|
|
3562
|
+
className: cn(
|
|
3563
|
+
"block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
|
|
3564
|
+
t.level === 3 ? "pl-7" : "pl-4",
|
|
3565
|
+
on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
|
|
3566
|
+
),
|
|
3567
|
+
children: t.label
|
|
3568
|
+
}
|
|
3569
|
+
) }, t.id);
|
|
3570
|
+
}) })
|
|
3571
|
+
] })
|
|
3572
|
+
);
|
|
3573
|
+
}
|
|
3574
|
+
var CALLOUT_TONE = { note: "neutral", warning: "brand", danger: "danger" };
|
|
3575
|
+
function Callout({
|
|
3576
|
+
tone = "note",
|
|
3577
|
+
title,
|
|
3578
|
+
children,
|
|
3579
|
+
className
|
|
3580
|
+
}) {
|
|
3581
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3582
|
+
Notice,
|
|
3583
|
+
{
|
|
3584
|
+
tone: CALLOUT_TONE[tone],
|
|
3585
|
+
title,
|
|
3586
|
+
role: "note",
|
|
3587
|
+
className: cn("my-6 [&_p]:my-0 [&_p]:text-[0.9375rem] [&_p]:leading-relaxed [&_p+p]:mt-3", className),
|
|
3588
|
+
children
|
|
3589
|
+
}
|
|
3590
|
+
);
|
|
3591
|
+
}
|
|
3592
|
+
function Step({ title, id, children }) {
|
|
3593
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "relative pb-8 pl-11 last:pb-0 [counter-increment:oca-step]", children: [
|
|
3594
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3595
|
+
"span",
|
|
3596
|
+
{
|
|
3597
|
+
"aria-hidden": true,
|
|
3598
|
+
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)]"
|
|
3599
|
+
}
|
|
3600
|
+
),
|
|
3601
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute bottom-1 left-[0.8125rem] top-9 w-px bg-border" }),
|
|
3602
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { id, className: "scroll-mt-28 pt-0.5 text-[1.0625rem] font-medium leading-snug tracking-[-0.008em] text-foreground", children: title }),
|
|
3603
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-muted-foreground [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", children })
|
|
3604
|
+
] });
|
|
3605
|
+
}
|
|
3606
|
+
function Steps({ children, className }) {
|
|
3607
|
+
return /* @__PURE__ */ jsxRuntime.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 });
|
|
3608
|
+
}
|
|
3609
|
+
function LinkCard({
|
|
3610
|
+
href,
|
|
3611
|
+
title,
|
|
3612
|
+
description,
|
|
3613
|
+
icon,
|
|
3614
|
+
meta,
|
|
3615
|
+
className
|
|
3616
|
+
}) {
|
|
3617
|
+
const Arrow = isInternal(href) ? lucideReact.ArrowRight : lucideReact.ArrowUpRight;
|
|
3618
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3619
|
+
DocLink,
|
|
3620
|
+
{
|
|
3621
|
+
href,
|
|
3622
|
+
className: cn(
|
|
3623
|
+
"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",
|
|
3624
|
+
className
|
|
3625
|
+
),
|
|
3626
|
+
children: [
|
|
3627
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-start justify-between gap-3", children: [
|
|
3628
|
+
icon ? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }),
|
|
3629
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
|
|
3630
|
+
meta,
|
|
3631
|
+
/* @__PURE__ */ jsxRuntime.jsx(Arrow, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-hover:translate-x-0.5 group-hover:text-foreground" })
|
|
3632
|
+
] })
|
|
3633
|
+
] }),
|
|
3634
|
+
icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }) : null,
|
|
3635
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] leading-relaxed text-muted-foreground", children: description }) : null
|
|
3636
|
+
]
|
|
3637
|
+
}
|
|
3638
|
+
);
|
|
3639
|
+
}
|
|
3640
|
+
function CardGrid({ columns = 2, children, className }) {
|
|
3641
|
+
return /* @__PURE__ */ jsxRuntime.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 });
|
|
3642
|
+
}
|
|
3643
|
+
function MdxTable({ className, ...props }) {
|
|
3644
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "not-prose my-6 overflow-hidden rounded-2xl border border-border bg-card", children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3645
|
+
"table",
|
|
3646
|
+
{
|
|
3647
|
+
className: cn(
|
|
3648
|
+
"w-full border-collapse text-left text-[0.875rem] leading-relaxed",
|
|
3649
|
+
"[&_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",
|
|
3650
|
+
"[&_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",
|
|
3651
|
+
"[&_td_code]:bg-transparent [&_td_code]:p-0 [&_td_code]:text-foreground [&_td:first-child]:text-foreground",
|
|
3652
|
+
"[&_[align=center]]:text-center [&_[align=right]]:text-right",
|
|
3653
|
+
// On a phone a cell keeps a readable width; the table scrolls instead of crushing it.
|
|
3654
|
+
"max-sm:[&_td]:min-w-[9rem]",
|
|
3655
|
+
className
|
|
3656
|
+
),
|
|
3657
|
+
...props
|
|
3658
|
+
}
|
|
3659
|
+
) }) });
|
|
3660
|
+
}
|
|
3661
|
+
function ApiTable({
|
|
3662
|
+
rows,
|
|
3663
|
+
caption,
|
|
3664
|
+
nameHeader = "Name",
|
|
3665
|
+
className
|
|
3666
|
+
}) {
|
|
3667
|
+
const hasDefault = rows.some((r) => r.default !== void 0);
|
|
3668
|
+
const marks = (r) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3669
|
+
r.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.75rem] text-oca-accent-ink", children: "Required" }) : null,
|
|
3670
|
+
r.deprecated ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: "Deprecated" }) : null,
|
|
3671
|
+
r.status ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: r.status }) : null
|
|
3672
|
+
] });
|
|
3673
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("not-prose my-6", className), children: [
|
|
3674
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-2xl border border-border bg-card max-sm:hidden", children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse text-left text-[0.875rem]", children: [
|
|
3675
|
+
caption ? /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: caption }) : null,
|
|
3676
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-oca-hairline-strong bg-oca-table-head text-[0.8125rem]", children: [
|
|
3677
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: nameHeader }),
|
|
3678
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Type" }),
|
|
3679
|
+
hasDefault ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Default" }) : null,
|
|
3680
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Description" })
|
|
3681
|
+
] }) }),
|
|
3682
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-border", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "align-top", children: [
|
|
3683
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "row", className: "px-4 py-3 text-left font-normal", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col items-start gap-1", children: [
|
|
3684
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { className: cn("font-mono text-[0.8125rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
|
|
3685
|
+
marks(r)
|
|
3686
|
+
] }) }),
|
|
3687
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.type ?? "\u2014" }),
|
|
3688
|
+
hasDefault ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.default ?? "\u2014" }) : null,
|
|
3689
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 leading-relaxed text-muted-foreground", children: r.description })
|
|
3690
|
+
] }, r.name)) })
|
|
3691
|
+
] }) }) }),
|
|
3692
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": caption, className: "divide-y divide-border rounded-2xl border border-border bg-card sm:hidden", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex flex-col gap-1.5 px-4 py-3.5", children: [
|
|
3693
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
|
|
3694
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { className: cn("font-mono text-[0.875rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
|
|
3695
|
+
r.type ? /* @__PURE__ */ jsxRuntime.jsx("code", { className: "break-all font-mono text-[0.8125rem] text-muted-foreground", children: r.type }) : null
|
|
3696
|
+
] }),
|
|
3697
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-wrap items-center gap-2 empty:hidden", children: marks(r) }),
|
|
3698
|
+
r.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] leading-relaxed text-muted-foreground", children: r.description }) : null,
|
|
3699
|
+
r.default !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[0.8125rem] text-muted-foreground", children: [
|
|
3700
|
+
"Default ",
|
|
3701
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-foreground", children: r.default })
|
|
3702
|
+
] }) : null
|
|
3703
|
+
] }, r.name)) })
|
|
3704
|
+
] });
|
|
3705
|
+
}
|
|
3706
|
+
function useDarkMode() {
|
|
3707
|
+
const [dark, setDark] = react.useState(false);
|
|
3708
|
+
react.useEffect(() => {
|
|
3709
|
+
const root = document.documentElement;
|
|
3710
|
+
const read = () => setDark(root.classList.contains("dark"));
|
|
3711
|
+
read();
|
|
3712
|
+
const mo = new MutationObserver(read);
|
|
3713
|
+
mo.observe(root, { attributes: true, attributeFilter: ["class"] });
|
|
3714
|
+
return () => mo.disconnect();
|
|
3715
|
+
}, []);
|
|
3716
|
+
return dark;
|
|
3717
|
+
}
|
|
3718
|
+
function mermaidTheme(el) {
|
|
3719
|
+
const css = getComputedStyle(el);
|
|
3720
|
+
const v = (name) => css.getPropertyValue(name).trim();
|
|
3721
|
+
const card = v("--card");
|
|
3722
|
+
const muted = v("--muted");
|
|
3723
|
+
const text = v("--foreground");
|
|
3724
|
+
const subtle = v("--muted-foreground");
|
|
3725
|
+
const line = v("--input");
|
|
3726
|
+
const hair = v("--oca-hairline-strong");
|
|
3727
|
+
return {
|
|
3728
|
+
background: "transparent",
|
|
3729
|
+
fontFamily: css.fontFamily,
|
|
3730
|
+
fontSize: "14px",
|
|
3731
|
+
textColor: text,
|
|
3732
|
+
mainBkg: card,
|
|
3733
|
+
primaryColor: card,
|
|
3734
|
+
primaryTextColor: text,
|
|
3735
|
+
primaryBorderColor: hair,
|
|
3736
|
+
secondaryColor: muted,
|
|
3737
|
+
secondaryTextColor: text,
|
|
3738
|
+
secondaryBorderColor: hair,
|
|
3739
|
+
tertiaryColor: muted,
|
|
3740
|
+
tertiaryTextColor: text,
|
|
3741
|
+
tertiaryBorderColor: hair,
|
|
3742
|
+
nodeBorder: hair,
|
|
3743
|
+
lineColor: line,
|
|
3744
|
+
edgeLabelBackground: card,
|
|
3745
|
+
clusterBkg: muted,
|
|
3746
|
+
clusterBorder: hair,
|
|
3747
|
+
titleColor: text,
|
|
3748
|
+
noteBkgColor: muted,
|
|
3749
|
+
noteTextColor: text,
|
|
3750
|
+
noteBorderColor: hair,
|
|
3751
|
+
actorBkg: card,
|
|
3752
|
+
actorBorder: hair,
|
|
3753
|
+
actorTextColor: text,
|
|
3754
|
+
actorLineColor: line,
|
|
3755
|
+
signalColor: text,
|
|
3756
|
+
signalTextColor: text,
|
|
3757
|
+
labelBoxBkgColor: card,
|
|
3758
|
+
labelBoxBorderColor: hair,
|
|
3759
|
+
labelTextColor: text,
|
|
3760
|
+
loopTextColor: subtle,
|
|
3761
|
+
activationBkgColor: muted,
|
|
3762
|
+
activationBorderColor: hair,
|
|
3763
|
+
sequenceNumberColor: card
|
|
3764
|
+
};
|
|
3765
|
+
}
|
|
3766
|
+
function naturalSize(svg) {
|
|
3767
|
+
const w = svg.match(/viewBox="[\d.-]+ [\d.-]+ ([\d.]+) [\d.]+"/)?.[1];
|
|
3768
|
+
if (!w) return svg;
|
|
3769
|
+
return svg.replace(/<svg([^>]*?)\swidth="100%"/, `<svg$1 width="${Math.ceil(Number(w))}"`).replace(/max-width:\s*[\d.]+px;?/, "");
|
|
3770
|
+
}
|
|
3771
|
+
function Diagram({ chart, caption, load, className }) {
|
|
3772
|
+
const ref = react.useRef(null);
|
|
3773
|
+
const dark = useDarkMode();
|
|
3774
|
+
const raw = react.useId();
|
|
3775
|
+
const [svg, setSvg] = react.useState(null);
|
|
3776
|
+
const [failed, setFailed] = react.useState(false);
|
|
3777
|
+
react.useEffect(() => {
|
|
3778
|
+
let live = true;
|
|
3779
|
+
const el = ref.current;
|
|
3780
|
+
if (!el) return;
|
|
3781
|
+
(async () => {
|
|
3782
|
+
try {
|
|
3783
|
+
const mod = await load();
|
|
3784
|
+
const mermaid = "default" in mod ? mod.default : mod;
|
|
3785
|
+
mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme: "base", themeVariables: mermaidTheme(el) });
|
|
3786
|
+
const { svg: drawn } = await mermaid.render(`oca-diagram-${raw.replace(/[^a-zA-Z0-9]/g, "")}-${dark ? "d" : "l"}`, chart);
|
|
3787
|
+
if (live) {
|
|
3788
|
+
setSvg(naturalSize(drawn));
|
|
3789
|
+
setFailed(false);
|
|
3790
|
+
}
|
|
3791
|
+
} catch {
|
|
3792
|
+
if (live) setFailed(true);
|
|
3793
|
+
}
|
|
3794
|
+
})();
|
|
3795
|
+
return () => {
|
|
3796
|
+
live = false;
|
|
3797
|
+
};
|
|
3798
|
+
}, [chart, dark, load, raw]);
|
|
3799
|
+
if (failed) return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: chart, caption: "Diagram (shown as its source)", className: cn("my-6", className) });
|
|
3800
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("figure", { ref, className: cn("not-prose my-6 overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children: [
|
|
3801
|
+
svg ? /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3802
|
+
"div",
|
|
3803
|
+
{
|
|
3804
|
+
className: "flex w-max min-w-full justify-center p-6 [&_svg]:h-auto [&_svg]:max-w-none",
|
|
3805
|
+
role: "img",
|
|
3806
|
+
"aria-label": typeof caption === "string" ? caption : "Diagram",
|
|
3807
|
+
dangerouslySetInnerHTML: { __html: svg }
|
|
3808
|
+
}
|
|
3809
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-label": "Drawing the diagram", className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-40 w-full rounded-xl" }) }),
|
|
3810
|
+
caption ? /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "border-t border-border px-5 py-3 text-[0.8125rem] text-muted-foreground", children: caption }) : null
|
|
3811
|
+
] });
|
|
3812
|
+
}
|
|
3813
|
+
var HEADING = {
|
|
3814
|
+
h1: "oca-display-3 mb-4 text-foreground",
|
|
3815
|
+
h2: "mb-3 mt-12 text-[1.375rem] font-medium leading-tight tracking-[-0.015em] text-foreground md:text-[1.5rem]",
|
|
3816
|
+
h3: "mb-2 mt-9 text-[1.125rem] font-medium leading-snug tracking-[-0.01em] text-foreground",
|
|
3817
|
+
h4: "mb-2 mt-7 text-[1rem] font-medium leading-snug text-foreground"
|
|
3818
|
+
};
|
|
3819
|
+
function DocsHeading({
|
|
3820
|
+
as: Tag,
|
|
3821
|
+
id,
|
|
3822
|
+
children,
|
|
3823
|
+
className,
|
|
3824
|
+
...props
|
|
3825
|
+
}) {
|
|
3826
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Tag, { id, className: cn("group scroll-mt-28", HEADING[Tag], className), ...props, children: [
|
|
3827
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-heading-text": "", children }),
|
|
3828
|
+
id && Tag !== "h1" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3829
|
+
"a",
|
|
3830
|
+
{
|
|
3831
|
+
href: `#${id}`,
|
|
3832
|
+
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",
|
|
3833
|
+
children: [
|
|
3834
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "#" }),
|
|
3835
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Link to this section" })
|
|
3836
|
+
]
|
|
3837
|
+
}
|
|
3838
|
+
) : null
|
|
3839
|
+
] });
|
|
3840
|
+
}
|
|
3841
|
+
function useMacKeys() {
|
|
3842
|
+
const [mac, setMac] = react.useState(true);
|
|
3843
|
+
react.useEffect(() => {
|
|
3844
|
+
setMac(/Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent));
|
|
3845
|
+
}, []);
|
|
3846
|
+
return mac;
|
|
3847
|
+
}
|
|
3848
|
+
var typing = (el) => el instanceof HTMLElement && (el.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName));
|
|
3849
|
+
var SearchButton = react.forwardRef(function SearchButton2({ label = "Search", onClick, className }, ref) {
|
|
3850
|
+
const mac = useMacKeys();
|
|
3851
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3852
|
+
"button",
|
|
3853
|
+
{
|
|
3854
|
+
ref,
|
|
3855
|
+
type: "button",
|
|
3856
|
+
onClick,
|
|
3857
|
+
"aria-keyshortcuts": mac ? "Meta+K" : "Control+K",
|
|
3858
|
+
className: cn(
|
|
3859
|
+
"inline-flex size-10 items-center justify-center gap-2 rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
|
|
3860
|
+
"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",
|
|
3861
|
+
className
|
|
3862
|
+
),
|
|
3863
|
+
children: [
|
|
3864
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { "aria-hidden": true, className: "size-[1.125rem] shrink-0 md:size-4" }),
|
|
3865
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only flex-1 text-left text-[0.9375rem] md:not-sr-only", children: label }),
|
|
3866
|
+
/* @__PURE__ */ jsxRuntime.jsx(Kbd, { "aria-hidden": true, className: "hidden md:inline-flex", children: mac ? "\u2318K" : "Ctrl K" })
|
|
3867
|
+
]
|
|
3868
|
+
}
|
|
3869
|
+
);
|
|
3870
|
+
});
|
|
3871
|
+
function SearchDialog({
|
|
3872
|
+
onQuery,
|
|
3873
|
+
open: openProp,
|
|
3874
|
+
onOpenChange,
|
|
3875
|
+
onSelect,
|
|
3876
|
+
button = true,
|
|
3877
|
+
hotkey = true,
|
|
3878
|
+
label = "Search",
|
|
3879
|
+
placeholder = "Search the docs",
|
|
3880
|
+
idle,
|
|
3881
|
+
defaultQuery = "",
|
|
3882
|
+
debounceMs = 120,
|
|
3883
|
+
className
|
|
3884
|
+
}) {
|
|
3885
|
+
const [own, setOwn] = react.useState(false);
|
|
3886
|
+
const open = openProp ?? own;
|
|
3887
|
+
const setOpen = (v) => {
|
|
3888
|
+
if (openProp === void 0) setOwn(v);
|
|
3889
|
+
onOpenChange?.(v);
|
|
3890
|
+
};
|
|
3891
|
+
const [query, setQuery] = react.useState(defaultQuery);
|
|
3892
|
+
const [groups, setGroups] = react.useState([]);
|
|
3893
|
+
const [state, setState] = react.useState("idle");
|
|
3894
|
+
const [active, setActive] = react.useState(0);
|
|
3895
|
+
const listId = react.useId();
|
|
3896
|
+
const listRef = react.useRef(null);
|
|
3897
|
+
const buttonRef = react.useRef(null);
|
|
3898
|
+
const returnTo = react.useRef(null);
|
|
3899
|
+
const flat = react.useMemo(() => groups.flatMap((g) => g.results), [groups]);
|
|
3900
|
+
const latest = react.useRef({ open, setOpen, onQuery });
|
|
3901
|
+
latest.current = { open, setOpen, onQuery };
|
|
3902
|
+
react.useEffect(() => {
|
|
3903
|
+
if (!hotkey) return;
|
|
3904
|
+
const onKey = (e) => {
|
|
3905
|
+
const { open: isOpen, setOpen: set } = latest.current;
|
|
3906
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
|
|
3907
|
+
e.preventDefault();
|
|
3908
|
+
set(!isOpen);
|
|
3909
|
+
} else if (e.key === "/" && !isOpen && !typing(e.target)) {
|
|
3910
|
+
e.preventDefault();
|
|
3911
|
+
set(true);
|
|
3912
|
+
}
|
|
3913
|
+
};
|
|
3914
|
+
window.addEventListener("keydown", onKey);
|
|
3915
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
3916
|
+
}, [hotkey]);
|
|
3917
|
+
react.useEffect(() => {
|
|
3918
|
+
const q = query.trim();
|
|
3919
|
+
if (!q) {
|
|
3920
|
+
setGroups([]);
|
|
3921
|
+
setState("idle");
|
|
3922
|
+
return;
|
|
3923
|
+
}
|
|
3924
|
+
const ctl = new AbortController();
|
|
3925
|
+
setState("loading");
|
|
3926
|
+
const t = setTimeout(async () => {
|
|
3927
|
+
try {
|
|
3928
|
+
const out = await latest.current.onQuery(q, ctl.signal);
|
|
3929
|
+
if (ctl.signal.aborted) return;
|
|
3930
|
+
setGroups(out.filter((g) => g.results.length > 0));
|
|
3931
|
+
setActive(0);
|
|
3932
|
+
setState("done");
|
|
3933
|
+
} catch {
|
|
3934
|
+
if (!ctl.signal.aborted) setState("error");
|
|
3935
|
+
}
|
|
3936
|
+
}, debounceMs);
|
|
3937
|
+
return () => {
|
|
3938
|
+
clearTimeout(t);
|
|
3939
|
+
ctl.abort();
|
|
3940
|
+
};
|
|
3941
|
+
}, [query, debounceMs]);
|
|
3942
|
+
react.useEffect(() => {
|
|
3943
|
+
listRef.current?.querySelector('[aria-selected="true"]')?.scrollIntoView({ block: "nearest" });
|
|
3944
|
+
}, [active]);
|
|
3945
|
+
const choose = (r) => {
|
|
3946
|
+
setOpen(false);
|
|
3947
|
+
if (onSelect) onSelect(r);
|
|
3948
|
+
else window.location.assign(r.href);
|
|
3949
|
+
};
|
|
3950
|
+
const optionId = (i) => `${listId}-o${i}`;
|
|
3951
|
+
const showList = state === "done" && flat.length > 0;
|
|
3952
|
+
let index = -1;
|
|
3953
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3954
|
+
button ? /* @__PURE__ */ jsxRuntime.jsx(SearchButton, { ref: buttonRef, label, onClick: () => setOpen(true), className }) : null,
|
|
3955
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Root, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Portal, { children: [
|
|
3956
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Overlay, { className: "oca-animate-fade fixed inset-0 z-50 bg-[rgb(10_10_10/0.38)] backdrop-blur-[2px]" }),
|
|
3957
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3958
|
+
DialogPrimitive__namespace.Content,
|
|
3959
|
+
{
|
|
3960
|
+
"aria-describedby": void 0,
|
|
3961
|
+
onOpenAutoFocus: () => {
|
|
3962
|
+
const el = document.activeElement;
|
|
3963
|
+
returnTo.current = el instanceof HTMLElement && el !== document.body ? el : null;
|
|
3964
|
+
},
|
|
3965
|
+
onCloseAutoFocus: (e) => {
|
|
3966
|
+
const back = returnTo.current?.isConnected ? returnTo.current : buttonRef.current;
|
|
3967
|
+
if (back) {
|
|
3968
|
+
e.preventDefault();
|
|
3969
|
+
back.focus();
|
|
3970
|
+
}
|
|
3971
|
+
},
|
|
3972
|
+
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)]",
|
|
3973
|
+
children: [
|
|
3974
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Title, { className: "sr-only", children: label }),
|
|
3975
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-14 shrink-0 items-center gap-3 border-b border-border pl-5 pr-3", children: [
|
|
3976
|
+
state === "loading" ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, { className: "size-[1.125rem] text-muted-foreground" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { "aria-hidden": true, className: "size-[1.125rem] shrink-0 text-muted-foreground" }),
|
|
3977
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3978
|
+
"input",
|
|
3979
|
+
{
|
|
3980
|
+
autoFocus: true,
|
|
3981
|
+
value: query,
|
|
3982
|
+
onChange: (e) => setQuery(e.target.value),
|
|
3983
|
+
onKeyDown: (e) => {
|
|
3984
|
+
if (!showList) return;
|
|
3985
|
+
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
3986
|
+
e.preventDefault();
|
|
3987
|
+
const d = e.key === "ArrowDown" ? 1 : -1;
|
|
3988
|
+
setActive((a) => (a + d + flat.length) % flat.length);
|
|
3989
|
+
} else if (e.key === "Enter" && flat[active]) {
|
|
3990
|
+
e.preventDefault();
|
|
3991
|
+
choose(flat[active]);
|
|
3992
|
+
}
|
|
3993
|
+
},
|
|
3994
|
+
placeholder,
|
|
3995
|
+
role: "combobox",
|
|
3996
|
+
"aria-label": label,
|
|
3997
|
+
"aria-expanded": showList,
|
|
3998
|
+
"aria-controls": listId,
|
|
3999
|
+
"aria-autocomplete": "list",
|
|
4000
|
+
"aria-activedescendant": showList ? optionId(active) : void 0,
|
|
4001
|
+
spellCheck: false,
|
|
4002
|
+
autoComplete: "off",
|
|
4003
|
+
className: "h-full min-w-0 flex-1 bg-transparent text-base text-foreground outline-none placeholder:text-oca-subtle"
|
|
4004
|
+
}
|
|
4005
|
+
),
|
|
4006
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.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: [
|
|
4007
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sm:hidden", children: "Close" }),
|
|
4008
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-sm:hidden", "aria-hidden": true, children: "Esc" }),
|
|
4009
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only max-sm:hidden", children: "Close search" })
|
|
4010
|
+
] })
|
|
4011
|
+
] }),
|
|
4012
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { ref: listRef, className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-2", children: [
|
|
4013
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { id: listId, role: "listbox", "aria-label": "Results", className: cn(!showList && "hidden"), children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "group", "aria-label": typeof g.label === "string" ? g.label : void 0, className: "pb-1", children: [
|
|
4014
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { "aria-hidden": true, className: "px-3 pb-1.5 pt-3 text-[0.8125rem] text-muted-foreground", children: g.label }),
|
|
4015
|
+
g.results.map((r) => {
|
|
4016
|
+
index++;
|
|
4017
|
+
const i = index;
|
|
4018
|
+
const on = i === active;
|
|
4019
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4020
|
+
"a",
|
|
4021
|
+
{
|
|
4022
|
+
id: optionId(i),
|
|
4023
|
+
href: r.href,
|
|
4024
|
+
role: "option",
|
|
4025
|
+
"aria-selected": on,
|
|
4026
|
+
tabIndex: -1,
|
|
4027
|
+
onMouseMove: () => setActive(i),
|
|
4028
|
+
onClick: (e) => {
|
|
4029
|
+
if (e.metaKey || e.ctrlKey || e.shiftKey) return;
|
|
4030
|
+
e.preventDefault();
|
|
4031
|
+
choose(r);
|
|
4032
|
+
},
|
|
4033
|
+
className: cn(
|
|
4034
|
+
"flex items-start gap-3 rounded-xl px-3 py-2.5 transition-colors",
|
|
4035
|
+
on ? "bg-accent" : "hover:bg-accent"
|
|
4036
|
+
),
|
|
4037
|
+
children: [
|
|
4038
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
4039
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: r.title }),
|
|
4040
|
+
r.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.8125rem] text-muted-foreground", children: r.section }) : null,
|
|
4041
|
+
r.excerptHtml ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4042
|
+
"span",
|
|
4043
|
+
{
|
|
4044
|
+
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",
|
|
4045
|
+
dangerouslySetInnerHTML: { __html: r.excerptHtml }
|
|
4046
|
+
}
|
|
4047
|
+
) : r.excerpt ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "line-clamp-2 text-[0.875rem] leading-snug text-muted-foreground", children: r.excerpt }) : null
|
|
4048
|
+
] }),
|
|
4049
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CornerDownLeft, { "aria-hidden": true, className: cn("mt-1 size-4 shrink-0 text-muted-foreground", !on && "invisible") })
|
|
4050
|
+
]
|
|
4051
|
+
},
|
|
4052
|
+
r.id
|
|
4053
|
+
);
|
|
4054
|
+
})
|
|
4055
|
+
] }, gi)) }),
|
|
4056
|
+
state === "idle" ? /* @__PURE__ */ jsxRuntime.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,
|
|
4057
|
+
state === "done" && flat.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: [
|
|
4058
|
+
"No results for \u201C",
|
|
4059
|
+
query.trim(),
|
|
4060
|
+
"\u201D."
|
|
4061
|
+
] }) : null,
|
|
4062
|
+
state === "error" ? /* @__PURE__ */ jsxRuntime.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
|
|
4063
|
+
] }),
|
|
4064
|
+
/* @__PURE__ */ jsxRuntime.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: [
|
|
4065
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
4066
|
+
/* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "\u2191" }),
|
|
4067
|
+
/* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "\u2193" }),
|
|
4068
|
+
" to move"
|
|
4069
|
+
] }),
|
|
4070
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
4071
|
+
/* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "\u21B5" }),
|
|
4072
|
+
" to open"
|
|
4073
|
+
] }),
|
|
4074
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
4075
|
+
/* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "esc" }),
|
|
4076
|
+
" to close"
|
|
4077
|
+
] })
|
|
4078
|
+
] }),
|
|
4079
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-live": "polite", className: "sr-only", children: state === "done" ? `${flat.length} result${flat.length === 1 ? "" : "s"}` : "" })
|
|
4080
|
+
]
|
|
4081
|
+
}
|
|
4082
|
+
)
|
|
4083
|
+
] }) })
|
|
4084
|
+
] });
|
|
4085
|
+
}
|
|
4086
|
+
function pretty(content) {
|
|
4087
|
+
try {
|
|
4088
|
+
return JSON.stringify(JSON.parse(content), null, 2);
|
|
4089
|
+
} catch {
|
|
4090
|
+
return null;
|
|
4091
|
+
}
|
|
4092
|
+
}
|
|
4093
|
+
function download(content, filename, mime) {
|
|
4094
|
+
const url = URL.createObjectURL(new Blob([content], { type: mime }));
|
|
4095
|
+
const a = document.createElement("a");
|
|
4096
|
+
a.href = url;
|
|
4097
|
+
a.download = filename;
|
|
4098
|
+
document.body.appendChild(a);
|
|
4099
|
+
a.click();
|
|
4100
|
+
a.remove();
|
|
4101
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
4102
|
+
}
|
|
4103
|
+
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";
|
|
4104
|
+
function ArtifactView({
|
|
4105
|
+
content,
|
|
4106
|
+
title,
|
|
4107
|
+
filename,
|
|
4108
|
+
mime,
|
|
4109
|
+
defaultView = "formatted",
|
|
4110
|
+
maxLines = 28,
|
|
4111
|
+
className
|
|
4112
|
+
}) {
|
|
4113
|
+
const formatted = react.useMemo(() => pretty(content), [content]);
|
|
4114
|
+
const [view, setView] = react.useState(formatted ? defaultView : "raw");
|
|
4115
|
+
const shown = view === "formatted" && formatted ? formatted : content;
|
|
4116
|
+
const json = formatted !== null;
|
|
4117
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4118
|
+
CodeBlock,
|
|
4119
|
+
{
|
|
4120
|
+
code: shown,
|
|
4121
|
+
lang: json ? "json" : void 0,
|
|
4122
|
+
caption: title,
|
|
4123
|
+
maxLines,
|
|
4124
|
+
className,
|
|
4125
|
+
actions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4126
|
+
json ? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(
|
|
4127
|
+
"button",
|
|
4128
|
+
{
|
|
4129
|
+
type: "button",
|
|
4130
|
+
"aria-pressed": view === v,
|
|
4131
|
+
onClick: () => setView(v),
|
|
4132
|
+
className: cn(
|
|
4133
|
+
"h-7 rounded-full px-2.5 text-[0.75rem] transition-colors",
|
|
4134
|
+
view === v ? "bg-white/[0.12] text-white" : "text-oca-ink-subtle hover:text-white"
|
|
4135
|
+
),
|
|
4136
|
+
children: v === "formatted" ? "Formatted" : "Raw"
|
|
4137
|
+
},
|
|
4138
|
+
v
|
|
4139
|
+
)) }) : null,
|
|
4140
|
+
filename ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4141
|
+
"button",
|
|
4142
|
+
{
|
|
4143
|
+
type: "button",
|
|
4144
|
+
onClick: () => download(content, filename, mime ?? (json ? "application/json" : "text/plain")),
|
|
4145
|
+
className: BAR_BUTTON,
|
|
4146
|
+
"aria-label": `Download ${filename}`,
|
|
4147
|
+
children: [
|
|
4148
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { "aria-hidden": true, className: "size-3.5" }),
|
|
4149
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-sm:hidden", children: "Download" })
|
|
4150
|
+
]
|
|
4151
|
+
}
|
|
4152
|
+
) : null
|
|
4153
|
+
] })
|
|
4154
|
+
}
|
|
4155
|
+
);
|
|
4156
|
+
}
|
|
4157
|
+
function DropZone({
|
|
4158
|
+
onFile,
|
|
4159
|
+
onText,
|
|
4160
|
+
accept,
|
|
4161
|
+
title = "Drop a file here, or choose one",
|
|
4162
|
+
hint,
|
|
4163
|
+
privacy = "It stays in your browser. Only its hash leaves this page.",
|
|
4164
|
+
file,
|
|
4165
|
+
progress,
|
|
4166
|
+
progressLabel = "Hashing",
|
|
4167
|
+
onClear,
|
|
4168
|
+
error,
|
|
4169
|
+
disabled = false,
|
|
4170
|
+
className
|
|
4171
|
+
}) {
|
|
4172
|
+
const input = react.useRef(null);
|
|
4173
|
+
const [over, setOver] = react.useState(false);
|
|
4174
|
+
const depth = react.useRef(0);
|
|
4175
|
+
const [mode, setMode] = react.useState("file");
|
|
4176
|
+
const [text, setText] = react.useState("");
|
|
4177
|
+
const errorId = react.useId();
|
|
4178
|
+
const titleId = react.useId();
|
|
4179
|
+
const busy = progress !== null && progress !== void 0;
|
|
4180
|
+
const pct = busy ? Math.round(Math.max(0, Math.min(1, progress)) * 100) : 0;
|
|
4181
|
+
const take = (f) => {
|
|
4182
|
+
if (f && !disabled) onFile(f);
|
|
4183
|
+
};
|
|
4184
|
+
const privacyLine = privacy === null ? null : /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-start gap-2 text-[0.8125rem] leading-snug text-muted-foreground", children: [
|
|
4185
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Lock, { "aria-hidden": true, className: "mt-0.5 size-3.5 shrink-0" }),
|
|
4186
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: privacy })
|
|
4187
|
+
] });
|
|
4188
|
+
if (mode === "text" && onText) {
|
|
4189
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
|
|
4190
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4191
|
+
Textarea,
|
|
4192
|
+
{
|
|
4193
|
+
value: text,
|
|
4194
|
+
onChange: (e) => setText(e.target.value),
|
|
4195
|
+
rows: 6,
|
|
4196
|
+
"aria-label": "Text",
|
|
4197
|
+
"aria-describedby": error ? errorId : void 0,
|
|
4198
|
+
"aria-invalid": error ? true : void 0,
|
|
4199
|
+
placeholder: "Paste the text here",
|
|
4200
|
+
className: "font-mono text-base md:text-[0.875rem]"
|
|
4201
|
+
}
|
|
4202
|
+
),
|
|
4203
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
4204
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", disabled: !text.trim() || disabled, onClick: () => onText(text), children: "Use this text" }),
|
|
4205
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", variant: "ghost", onClick: () => setMode("file"), children: "Choose a file instead" })
|
|
4206
|
+
] }),
|
|
4207
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx("p", { id: errorId, role: "alert", className: "text-[0.8125rem] text-destructive", children: error }) : null,
|
|
4208
|
+
privacyLine
|
|
4209
|
+
] });
|
|
4210
|
+
}
|
|
4211
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
|
|
4212
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4213
|
+
"div",
|
|
4214
|
+
{
|
|
4215
|
+
role: "group",
|
|
4216
|
+
"aria-labelledby": titleId,
|
|
4217
|
+
"aria-describedby": error ? errorId : void 0,
|
|
4218
|
+
"aria-busy": busy || void 0,
|
|
4219
|
+
onDragEnter: (e) => {
|
|
4220
|
+
e.preventDefault();
|
|
4221
|
+
depth.current++;
|
|
4222
|
+
if (!disabled) setOver(true);
|
|
4223
|
+
},
|
|
4224
|
+
onDragOver: (e) => e.preventDefault(),
|
|
4225
|
+
onDragLeave: () => {
|
|
4226
|
+
depth.current = Math.max(0, depth.current - 1);
|
|
4227
|
+
if (depth.current === 0) setOver(false);
|
|
4228
|
+
},
|
|
4229
|
+
onDrop: (e) => {
|
|
4230
|
+
e.preventDefault();
|
|
4231
|
+
depth.current = 0;
|
|
4232
|
+
setOver(false);
|
|
4233
|
+
take(e.dataTransfer.files?.[0]);
|
|
4234
|
+
},
|
|
4235
|
+
className: cn(
|
|
4236
|
+
"relative flex flex-col gap-3 rounded-[1.25rem] border border-dashed transition-colors",
|
|
4237
|
+
file ? "px-4 py-4 sm:px-5" : "items-center px-5 py-8 text-center md:py-10",
|
|
4238
|
+
over ? "border-foreground bg-accent" : "border-oca-hairline-strong bg-card",
|
|
4239
|
+
error && "border-destructive",
|
|
4240
|
+
disabled && "opacity-55"
|
|
4241
|
+
),
|
|
4242
|
+
children: [
|
|
4243
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4244
|
+
"input",
|
|
4245
|
+
{
|
|
4246
|
+
ref: input,
|
|
4247
|
+
type: "file",
|
|
4248
|
+
accept,
|
|
4249
|
+
disabled,
|
|
4250
|
+
tabIndex: -1,
|
|
4251
|
+
"aria-hidden": true,
|
|
4252
|
+
className: "sr-only",
|
|
4253
|
+
onChange: (e) => {
|
|
4254
|
+
take(e.target.files?.[0]);
|
|
4255
|
+
e.target.value = "";
|
|
4256
|
+
}
|
|
4257
|
+
}
|
|
4258
|
+
),
|
|
4259
|
+
file ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-3", children: [
|
|
4260
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
4261
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-10 shrink-0 items-center justify-center rounded-xl bg-muted text-foreground", children: busy ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { "aria-hidden": true, className: "size-5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { "aria-hidden": true, className: "size-5" }) }),
|
|
4262
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
4263
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { id: titleId, className: "truncate text-[0.9375rem] font-medium", title: file.name, children: file.name }),
|
|
4264
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.8125rem] text-muted-foreground", children: [formatBytes(file.size), file.type].filter(Boolean).join(" \xB7 ") })
|
|
4265
|
+
] }),
|
|
4266
|
+
!busy && onClear ? /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", variant: "secondary", onClick: onClear, disabled, className: "shrink-0", children: "Choose another" }) : null
|
|
4267
|
+
] }),
|
|
4268
|
+
busy ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
4269
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4270
|
+
"div",
|
|
4271
|
+
{
|
|
4272
|
+
role: "progressbar",
|
|
4273
|
+
"aria-valuemin": 0,
|
|
4274
|
+
"aria-valuemax": 100,
|
|
4275
|
+
"aria-valuenow": pct,
|
|
4276
|
+
"aria-label": typeof progressLabel === "string" ? progressLabel : "Progress",
|
|
4277
|
+
className: "h-1.5 overflow-hidden rounded-full bg-muted",
|
|
4278
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full rounded-full bg-foreground transition-[width] duration-200", style: { width: `${pct}%` } })
|
|
4279
|
+
}
|
|
4280
|
+
),
|
|
4281
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[0.8125rem] text-muted-foreground oca-tabular", children: [
|
|
4282
|
+
progressLabel,
|
|
4283
|
+
" ",
|
|
4284
|
+
pct,
|
|
4285
|
+
"%"
|
|
4286
|
+
] })
|
|
4287
|
+
] }) : null
|
|
4288
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4289
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-11 items-center justify-center rounded-full bg-muted text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Upload, { "aria-hidden": true, className: "size-5" }) }),
|
|
4290
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4291
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { id: titleId, className: "text-[1rem] font-medium", children: over ? "Drop it to add it" : title }),
|
|
4292
|
+
hint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: hint }) : null
|
|
4293
|
+
] }),
|
|
4294
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex flex-wrap items-center justify-center gap-2", children: [
|
|
4295
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", variant: "secondary", disabled, onClick: () => input.current?.click(), children: "Choose a file" }),
|
|
4296
|
+
onText ? /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", variant: "ghost", disabled, onClick: () => setMode("text"), children: "Paste text instead" }) : null
|
|
4297
|
+
] })
|
|
4298
|
+
] })
|
|
4299
|
+
]
|
|
4300
|
+
}
|
|
4301
|
+
),
|
|
4302
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx("p", { id: errorId, role: "alert", className: "text-[0.8125rem] text-destructive", children: error }) : null,
|
|
4303
|
+
privacyLine
|
|
4304
|
+
] });
|
|
4305
|
+
}
|
|
4306
|
+
function FormSection({
|
|
4307
|
+
n,
|
|
4308
|
+
title,
|
|
4309
|
+
hint,
|
|
4310
|
+
status,
|
|
4311
|
+
action,
|
|
4312
|
+
as: Heading = "h2",
|
|
4313
|
+
id,
|
|
4314
|
+
children,
|
|
4315
|
+
className
|
|
4316
|
+
}) {
|
|
4317
|
+
const titleId = react.useId();
|
|
4318
|
+
const tight = useDensity() === "compact";
|
|
4319
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4320
|
+
"section",
|
|
4321
|
+
{
|
|
4322
|
+
id,
|
|
4323
|
+
"aria-labelledby": titleId,
|
|
4324
|
+
"aria-current": status === "current" ? "step" : void 0,
|
|
4325
|
+
className: cn("scroll-mt-24 rounded-[1.25rem] border border-border bg-card", className),
|
|
4326
|
+
children: [
|
|
4327
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: cn("flex items-start gap-3.5", tight ? "px-5 pt-5" : "px-6 pt-6"), children: [
|
|
4328
|
+
n !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4329
|
+
"span",
|
|
4330
|
+
{
|
|
4331
|
+
"aria-hidden": true,
|
|
4332
|
+
className: cn(
|
|
4333
|
+
"mt-px flex size-7 shrink-0 items-center justify-center rounded-full border text-[0.8125rem] oca-tabular",
|
|
4334
|
+
status === "done" && "border-primary bg-primary text-primary-foreground",
|
|
4335
|
+
status === "current" && "border-brand text-oca-accent-ink",
|
|
4336
|
+
status === "blocked" && "border-destructive text-destructive",
|
|
4337
|
+
(status === "upcoming" || status === void 0) && "border-oca-hairline-strong text-muted-foreground"
|
|
4338
|
+
),
|
|
4339
|
+
children: status === "done" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3.5", strokeWidth: 3 }) : n
|
|
4340
|
+
}
|
|
4341
|
+
) : null,
|
|
4342
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
|
|
4343
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Heading, { id: titleId, className: "text-[1.0625rem] font-medium leading-snug tracking-[-0.008em]", children: [
|
|
4344
|
+
n !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sr-only", children: [
|
|
4345
|
+
"Step ",
|
|
4346
|
+
n,
|
|
4347
|
+
": "
|
|
4348
|
+
] }) : null,
|
|
4349
|
+
title,
|
|
4350
|
+
status === "done" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " (done)" }) : null
|
|
4351
|
+
] }),
|
|
4352
|
+
hint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: hint }) : null
|
|
4353
|
+
] }),
|
|
4354
|
+
action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: action }) : null
|
|
4355
|
+
] }),
|
|
4356
|
+
/* @__PURE__ */ jsxRuntime.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 })
|
|
4357
|
+
]
|
|
4358
|
+
}
|
|
4359
|
+
);
|
|
4360
|
+
}
|
|
4361
|
+
var STATE_TONE = { good: "success", attention: "brand", bad: "danger", neutral: "neutral", quiet: "muted" };
|
|
4362
|
+
function StateBadge({
|
|
4363
|
+
tone = "neutral",
|
|
4364
|
+
children,
|
|
4365
|
+
title,
|
|
4366
|
+
className
|
|
4367
|
+
}) {
|
|
4368
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: STATE_TONE[tone], title, className, children });
|
|
4369
|
+
}
|
|
4370
|
+
function createStateBadge(states) {
|
|
4371
|
+
function ProtocolStateBadge({ state, className }) {
|
|
4372
|
+
const def = states[state];
|
|
4373
|
+
if (!def) {
|
|
4374
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
4375
|
+
console.warn(`StateBadge: no state "${state}"; known: ${Object.keys(states).join(", ")}`);
|
|
4376
|
+
}
|
|
4377
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StateBadge, { className, children: String(state) });
|
|
4378
|
+
}
|
|
4379
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StateBadge, { tone: def.tone, title: def.hint, className, children: def.label });
|
|
4380
|
+
}
|
|
4381
|
+
return ProtocolStateBadge;
|
|
4382
|
+
}
|
|
4383
|
+
function BlockHeight({
|
|
4384
|
+
height,
|
|
4385
|
+
label = false,
|
|
4386
|
+
link = true,
|
|
4387
|
+
network = "mainnet",
|
|
4388
|
+
className
|
|
4389
|
+
}) {
|
|
4390
|
+
const text = `${label ? "block " : ""}${formatBlockHeight(height)}`;
|
|
4391
|
+
if (!link) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("oca-tabular", className), children: text });
|
|
4392
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4393
|
+
"a",
|
|
4394
|
+
{
|
|
4395
|
+
href: explorerUrl("block", Math.trunc(height), network),
|
|
4396
|
+
target: "_blank",
|
|
4397
|
+
rel: "noreferrer",
|
|
4398
|
+
title: `Block ${formatBlockHeight(height)} on mempool.space`,
|
|
4399
|
+
className: cn("oca-tabular underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground", className),
|
|
4400
|
+
children: [
|
|
4401
|
+
text,
|
|
4402
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " (opens mempool.space in a new tab)" })
|
|
4403
|
+
]
|
|
4404
|
+
}
|
|
4405
|
+
);
|
|
4406
|
+
}
|
|
4407
|
+
var ANCHOR = {
|
|
4408
|
+
anchored: { label: "Anchored", tone: "good" },
|
|
4409
|
+
pending: { label: "Anchor pending", tone: "attention" },
|
|
4410
|
+
unverified: { label: "Not checked", tone: "quiet" },
|
|
4411
|
+
none: { label: "Not anchored", tone: "quiet" },
|
|
4412
|
+
fail: { label: "Does not check out", tone: "bad" }
|
|
4413
|
+
};
|
|
4414
|
+
function hostOf(url) {
|
|
4415
|
+
try {
|
|
4416
|
+
return new URL(url).host;
|
|
4417
|
+
} catch {
|
|
4418
|
+
return url;
|
|
4419
|
+
}
|
|
4420
|
+
}
|
|
4421
|
+
function AnchorStatus({
|
|
4422
|
+
state,
|
|
4423
|
+
blockHeight,
|
|
4424
|
+
blockTime,
|
|
4425
|
+
submittedAt,
|
|
4426
|
+
calendar,
|
|
4427
|
+
message,
|
|
4428
|
+
network = "mainnet",
|
|
4429
|
+
variant = "detail",
|
|
4430
|
+
className
|
|
4431
|
+
}) {
|
|
4432
|
+
const def = ANCHOR[state];
|
|
4433
|
+
const block = blockHeight !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(BlockHeight, { height: blockHeight, label: true, network }) : null;
|
|
4434
|
+
const line = message ?? (state === "anchored" ? block ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4435
|
+
"In ",
|
|
4436
|
+
block,
|
|
4437
|
+
blockTime !== void 0 ? ` \xB7 ${formatUtc(blockTime)}` : null
|
|
4438
|
+
] }) : "Its hash is in a Bitcoin block." : state === "pending" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4439
|
+
"Submitted",
|
|
4440
|
+
submittedAt !== void 0 ? ` ${formatUtc(submittedAt)}` : "",
|
|
4441
|
+
" to",
|
|
4442
|
+
" ",
|
|
4443
|
+
calendar ? hostOf(calendar) : "an OpenTimestamps calendar",
|
|
4444
|
+
". Waiting for a Bitcoin block."
|
|
4445
|
+
] }) : state === "unverified" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4446
|
+
"The proof names ",
|
|
4447
|
+
block ?? "a block",
|
|
4448
|
+
", but its header could not be fetched to check it."
|
|
4449
|
+
] }) : state === "fail" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4450
|
+
"The proof does not lead to ",
|
|
4451
|
+
block ?? "the block it names",
|
|
4452
|
+
"."
|
|
4453
|
+
] }) : "No timestamp yet. The signature still checks offline.");
|
|
4454
|
+
if (variant === "badge") {
|
|
4455
|
+
const plain = typeof line === "string" ? line : void 0;
|
|
4456
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StateBadge, { tone: def.tone, title: plain, className, children: def.label });
|
|
4457
|
+
}
|
|
4458
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col items-start gap-1.5", className), children: [
|
|
4459
|
+
/* @__PURE__ */ jsxRuntime.jsx(StateBadge, { tone: def.tone, children: def.label }),
|
|
4460
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: line })
|
|
4461
|
+
] });
|
|
4462
|
+
}
|
|
4463
|
+
function BlockCountdown({
|
|
4464
|
+
target,
|
|
4465
|
+
tip,
|
|
4466
|
+
from,
|
|
4467
|
+
reached = "Reached",
|
|
4468
|
+
minutesPerBlock = 10,
|
|
4469
|
+
network = "mainnet",
|
|
4470
|
+
className
|
|
4471
|
+
}) {
|
|
4472
|
+
const known = typeof tip === "number";
|
|
4473
|
+
const left = known ? target - tip : null;
|
|
4474
|
+
const done = left !== null && left <= 0;
|
|
4475
|
+
const share = known && from !== void 0 && target > from ? Math.min(1, Math.max(0, (tip - from) / (target - from))) : null;
|
|
4476
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
|
|
4477
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.9375rem] leading-snug", children: !known ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4478
|
+
"At ",
|
|
4479
|
+
/* @__PURE__ */ jsxRuntime.jsx(BlockHeight, { height: target, label: true, network })
|
|
4480
|
+
] }) : done ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4481
|
+
reached,
|
|
4482
|
+
" at ",
|
|
4483
|
+
/* @__PURE__ */ jsxRuntime.jsx(BlockHeight, { height: target, label: true, network })
|
|
4484
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4485
|
+
"In ",
|
|
4486
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-tabular font-medium", children: formatBlockHeight(left) }),
|
|
4487
|
+
" block",
|
|
4488
|
+
left === 1 ? "" : "s",
|
|
4489
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
|
|
4490
|
+
", ",
|
|
4491
|
+
blocksToDuration(left, minutesPerBlock)
|
|
4492
|
+
] })
|
|
4493
|
+
] }) }),
|
|
4494
|
+
share !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4495
|
+
"div",
|
|
4496
|
+
{
|
|
4497
|
+
role: "progressbar",
|
|
4498
|
+
"aria-valuemin": 0,
|
|
4499
|
+
"aria-valuemax": 100,
|
|
4500
|
+
"aria-valuenow": Math.round(share * 100),
|
|
4501
|
+
"aria-label": "Blocks passed",
|
|
4502
|
+
className: "h-1.5 overflow-hidden rounded-full bg-muted",
|
|
4503
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full rounded-full bg-foreground", style: { width: `${share * 100}%` } })
|
|
4504
|
+
}
|
|
4505
|
+
) : null,
|
|
4506
|
+
known && !done ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[0.8125rem] text-muted-foreground", children: [
|
|
4507
|
+
"Target ",
|
|
4508
|
+
/* @__PURE__ */ jsxRuntime.jsx(BlockHeight, { height: target, network }),
|
|
4509
|
+
" \xB7 tip ",
|
|
4510
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-tabular", children: formatBlockHeight(tip) })
|
|
4511
|
+
] }) : null
|
|
4512
|
+
] });
|
|
4513
|
+
}
|
|
4514
|
+
function Meter({
|
|
4515
|
+
value,
|
|
4516
|
+
max,
|
|
4517
|
+
ghost,
|
|
4518
|
+
label,
|
|
4519
|
+
figure,
|
|
4520
|
+
tone = "ink",
|
|
4521
|
+
size = "md",
|
|
4522
|
+
className
|
|
4523
|
+
}) {
|
|
4524
|
+
const id = react.useId();
|
|
4525
|
+
const total = max > 0 ? max : 1;
|
|
4526
|
+
const v = Math.max(0, Math.min(1, value / total));
|
|
4527
|
+
const g = ghost ? Math.max(0, Math.min(1 - v, ghost / total)) : 0;
|
|
4528
|
+
const pct = `${Math.round(v * 100)}%`;
|
|
4529
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
|
|
4530
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between gap-4 text-[0.875rem]", children: [
|
|
4531
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { id, className: "min-w-0 truncate", children: label }),
|
|
4532
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 oca-tabular text-muted-foreground", children: figure ?? pct })
|
|
4533
|
+
] }),
|
|
4534
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4535
|
+
"div",
|
|
4536
|
+
{
|
|
4537
|
+
role: "meter",
|
|
4538
|
+
"aria-labelledby": id,
|
|
4539
|
+
"aria-valuemin": 0,
|
|
4540
|
+
"aria-valuemax": max,
|
|
4541
|
+
"aria-valuenow": value,
|
|
4542
|
+
"aria-valuetext": typeof figure === "string" ? figure : pct,
|
|
4543
|
+
className: cn("flex overflow-hidden rounded-full bg-muted", size === "sm" ? "h-1.5" : "h-2.5"),
|
|
4544
|
+
children: [
|
|
4545
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4546
|
+
"div",
|
|
4547
|
+
{
|
|
4548
|
+
className: cn("h-full shrink-0 rounded-full", tone === "brand" ? "bg-oca-orange-deep" : "bg-foreground"),
|
|
4549
|
+
style: { width: `${v * 100}%` }
|
|
4550
|
+
}
|
|
4551
|
+
),
|
|
4552
|
+
g > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4553
|
+
"div",
|
|
4554
|
+
{
|
|
4555
|
+
"aria-hidden": true,
|
|
4556
|
+
className: "-ml-1.5 h-full shrink-0 rounded-r-full pl-1.5 text-foreground/45",
|
|
4557
|
+
style: {
|
|
4558
|
+
width: `calc(${g * 100}% + 0.375rem)`,
|
|
4559
|
+
backgroundImage: "repeating-linear-gradient(-45deg, currentColor 0 2px, transparent 2px 6px)"
|
|
4560
|
+
}
|
|
4561
|
+
}
|
|
4562
|
+
) : null
|
|
4563
|
+
]
|
|
4564
|
+
}
|
|
4565
|
+
)
|
|
4566
|
+
] });
|
|
4567
|
+
}
|
|
4568
|
+
function FilterChips({
|
|
4569
|
+
options,
|
|
4570
|
+
value,
|
|
4571
|
+
onChange,
|
|
4572
|
+
label,
|
|
4573
|
+
className
|
|
4574
|
+
}) {
|
|
4575
|
+
const tight = useDensity() === "compact";
|
|
4576
|
+
const multi = Array.isArray(value);
|
|
4577
|
+
const isOn = (v) => multi ? value.includes(v) : value === v;
|
|
4578
|
+
const press = (v) => {
|
|
4579
|
+
if (multi) {
|
|
4580
|
+
const cur = value;
|
|
4581
|
+
onChange(cur.includes(v) ? cur.filter((x) => x !== v) : [...cur, v]);
|
|
4582
|
+
} else onChange(v);
|
|
4583
|
+
};
|
|
4584
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--background)", className: cn("w-full", className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { role: "group", "aria-label": label, className: "flex w-max items-center gap-2 py-0.5", children: options.map((o) => {
|
|
4585
|
+
const on = isOn(o.value);
|
|
4586
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4587
|
+
"button",
|
|
4588
|
+
{
|
|
4589
|
+
type: "button",
|
|
4590
|
+
"aria-pressed": on,
|
|
4591
|
+
onClick: () => press(o.value),
|
|
4592
|
+
className: cn(
|
|
4593
|
+
"inline-flex shrink-0 items-center gap-1.5 rounded-full border px-3.5 text-[0.875rem] transition-colors",
|
|
4594
|
+
tight ? "h-8" : "h-9",
|
|
4595
|
+
on ? "border-foreground bg-foreground text-background" : "border-border bg-card text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
|
|
4596
|
+
),
|
|
4597
|
+
children: [
|
|
4598
|
+
o.label,
|
|
4599
|
+
o.count !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-tabular", children: o.count.toLocaleString("en-US") }) : null
|
|
4600
|
+
]
|
|
4601
|
+
},
|
|
4602
|
+
o.value
|
|
4603
|
+
);
|
|
4604
|
+
}) }) });
|
|
4605
|
+
}
|
|
4606
|
+
function ToolGrid({
|
|
4607
|
+
tools,
|
|
4608
|
+
as: Heading = "h2",
|
|
4609
|
+
className
|
|
4610
|
+
}) {
|
|
4611
|
+
const tight = useDensity() === "compact";
|
|
4612
|
+
const n = tools.length;
|
|
4613
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4614
|
+
"ul",
|
|
4615
|
+
{
|
|
4616
|
+
className: cn(
|
|
4617
|
+
"grid grid-cols-1 gap-3 sm:grid-cols-2 md:gap-4",
|
|
4618
|
+
// Three or four sit in one row on a wide screen.
|
|
4619
|
+
n === 3 || n === 6 ? "lg:grid-cols-3" : n === 4 ? "xl:grid-cols-4" : null,
|
|
4620
|
+
className
|
|
4621
|
+
),
|
|
4622
|
+
children: tools.map((t) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4623
|
+
"div",
|
|
4624
|
+
{
|
|
4625
|
+
className: cn(
|
|
4626
|
+
"group relative flex h-full flex-col rounded-[1.25rem] border border-border bg-card transition-colors",
|
|
4627
|
+
tight ? "gap-3 p-5" : "gap-4 p-6",
|
|
4628
|
+
"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"
|
|
4629
|
+
),
|
|
4630
|
+
children: [
|
|
4631
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
4632
|
+
t.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-10 items-center justify-center rounded-xl bg-muted text-foreground [&_svg]:size-5", children: t.icon }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
|
|
4633
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4634
|
+
lucideReact.ArrowRight,
|
|
4635
|
+
{
|
|
4636
|
+
"aria-hidden": true,
|
|
4637
|
+
className: "size-4 text-muted-foreground transition-transform duration-200 group-hover:translate-x-0.5 group-hover:text-foreground"
|
|
4638
|
+
}
|
|
4639
|
+
)
|
|
4640
|
+
] }),
|
|
4641
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
4642
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { className: "oca-title-sm", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4643
|
+
Link__default.default,
|
|
4644
|
+
{
|
|
4645
|
+
href: t.href,
|
|
4646
|
+
className: "outline-none after:absolute after:inset-0 after:rounded-[1.25rem] after:content-['']",
|
|
4647
|
+
children: t.label
|
|
4648
|
+
}
|
|
4649
|
+
) }),
|
|
4650
|
+
t.description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.9375rem] leading-relaxed text-muted-foreground", children: t.description }) : null
|
|
4651
|
+
] })
|
|
4652
|
+
]
|
|
4653
|
+
}
|
|
4654
|
+
) }, t.href))
|
|
4655
|
+
}
|
|
4656
|
+
);
|
|
4657
|
+
}
|
|
1458
4658
|
|
|
1459
4659
|
exports.Accent = Accent;
|
|
1460
4660
|
exports.ActivityList = ActivityList;
|
|
4661
|
+
exports.AnchorStatus = AnchorStatus;
|
|
4662
|
+
exports.ApiTable = ApiTable;
|
|
4663
|
+
exports.AppCard = AppCard;
|
|
4664
|
+
exports.AppGrid = AppGrid;
|
|
4665
|
+
exports.ArtifactView = ArtifactView;
|
|
4666
|
+
exports.BlockCountdown = BlockCountdown;
|
|
4667
|
+
exports.BlockHeight = BlockHeight;
|
|
4668
|
+
exports.Breadcrumbs = Breadcrumbs;
|
|
1461
4669
|
exports.BrowserFrame = BrowserFrame;
|
|
4670
|
+
exports.Callout = Callout;
|
|
4671
|
+
exports.CardGrid = CardGrid;
|
|
4672
|
+
exports.Closing = Closing;
|
|
1462
4673
|
exports.CodeBlock = CodeBlock;
|
|
4674
|
+
exports.CodeTabs = CodeTabs;
|
|
4675
|
+
exports.ComparisonTable = ComparisonTable;
|
|
1463
4676
|
exports.Container = Container;
|
|
1464
4677
|
exports.CopyButton = CopyButton;
|
|
1465
4678
|
exports.DataTable = DataTable;
|
|
4679
|
+
exports.Diagram = Diagram;
|
|
1466
4680
|
exports.Display = Display;
|
|
1467
4681
|
exports.DocHeader = DocHeader;
|
|
1468
4682
|
exports.DocLayout = DocLayout;
|
|
4683
|
+
exports.DocsHeading = DocsHeading;
|
|
4684
|
+
exports.DocsPager = DocsPager;
|
|
4685
|
+
exports.DropZone = DropZone;
|
|
1469
4686
|
exports.EmptyLine = EmptyLine;
|
|
1470
4687
|
exports.EmptyState = EmptyState;
|
|
4688
|
+
exports.EndpointList = EndpointList;
|
|
1471
4689
|
exports.ErrorBoundary = ErrorBoundary;
|
|
4690
|
+
exports.ErrorPage = ErrorPage;
|
|
1472
4691
|
exports.Eyebrow = Eyebrow;
|
|
4692
|
+
exports.FactBlock = FactBlock;
|
|
4693
|
+
exports.FactRows = FactRows;
|
|
4694
|
+
exports.Faq = Faq;
|
|
4695
|
+
exports.FilterChips = FilterChips;
|
|
1473
4696
|
exports.FloatChip = FloatChip;
|
|
1474
4697
|
exports.Footnote = Footnote;
|
|
4698
|
+
exports.FormSection = FormSection;
|
|
1475
4699
|
exports.HashChip = HashChip;
|
|
4700
|
+
exports.InstallTabs = InstallTabs;
|
|
1476
4701
|
exports.KeyValueList = KeyValueList;
|
|
1477
4702
|
exports.Lead = Lead;
|
|
4703
|
+
exports.LegalDocument = LegalDocument;
|
|
4704
|
+
exports.LinkCard = LinkCard;
|
|
1478
4705
|
exports.LoadingBlock = LoadingBlock;
|
|
4706
|
+
exports.MdxTable = MdxTable;
|
|
4707
|
+
exports.Meter = Meter;
|
|
1479
4708
|
exports.Monogram = Monogram;
|
|
1480
4709
|
exports.Notice = Notice;
|
|
4710
|
+
exports.OnThisPage = OnThisPage;
|
|
1481
4711
|
exports.PackageCard = PackageCard;
|
|
1482
4712
|
exports.PageHeader = PageHeader;
|
|
1483
4713
|
exports.PageHero = PageHero;
|
|
1484
4714
|
exports.PhoneFrame = PhoneFrame;
|
|
1485
4715
|
exports.ProgressSteps = ProgressSteps;
|
|
4716
|
+
exports.ProofStrip = ProofStrip;
|
|
1486
4717
|
exports.Prose = Prose;
|
|
4718
|
+
exports.ProtocolGrid = ProtocolGrid;
|
|
4719
|
+
exports.ProtocolHero = ProtocolHero;
|
|
4720
|
+
exports.ProtocolNav = ProtocolNav;
|
|
1487
4721
|
exports.Reveal = Reveal;
|
|
1488
4722
|
exports.Sats = Sats;
|
|
1489
4723
|
exports.SatsFigure = SatsFigure;
|
|
1490
4724
|
exports.ScrollStory = ScrollStory;
|
|
4725
|
+
exports.SearchButton = SearchButton;
|
|
4726
|
+
exports.SearchDialog = SearchDialog;
|
|
1491
4727
|
exports.Section = Section;
|
|
4728
|
+
exports.SectionHeading = SectionHeading;
|
|
1492
4729
|
exports.SectionIntro = SectionIntro;
|
|
4730
|
+
exports.SignMessage = SignMessage;
|
|
4731
|
+
exports.SpecCard = SpecCard;
|
|
1493
4732
|
exports.SplitBar = SplitBar;
|
|
1494
4733
|
exports.StatCard = StatCard;
|
|
1495
4734
|
exports.StatGrid = StatGrid;
|
|
4735
|
+
exports.StateBadge = StateBadge;
|
|
4736
|
+
exports.Step = Step;
|
|
1496
4737
|
exports.StepGrid = StepGrid;
|
|
4738
|
+
exports.Steps = Steps;
|
|
4739
|
+
exports.TextLink = TextLink;
|
|
1497
4740
|
exports.Ticker = Ticker;
|
|
4741
|
+
exports.ToolGrid = ToolGrid;
|
|
1498
4742
|
exports.TruthTable = TruthTable;
|
|
1499
4743
|
exports.UsdApprox = UsdApprox;
|
|
4744
|
+
exports.VerifyBox = VerifyBox;
|
|
4745
|
+
exports.VerifyReport = VerifyReport;
|
|
4746
|
+
exports.createStateBadge = createStateBadge;
|
|
4747
|
+
exports.languageName = languageName;
|
|
1500
4748
|
exports.monogramGround = monogramGround;
|
|
1501
4749
|
exports.monogramLetter = monogramLetter;
|
|
1502
4750
|
exports.satsText = satsText;
|
|
1503
4751
|
exports.sectionVariants = sectionVariants;
|
|
4752
|
+
exports.useActiveHeading = useActiveHeading;
|
|
1504
4753
|
exports.useCopy = useCopy;
|
|
4754
|
+
exports.useHeadings = useHeadings;
|
|
1505
4755
|
exports.useInView = useInView;
|
|
1506
4756
|
//# sourceMappingURL=components.js.map
|
|
1507
4757
|
//# sourceMappingURL=components.js.map
|