@orangecheck/app-design 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/chrome.d.mts +5 -4
  2. package/dist/chrome.d.ts +5 -4
  3. package/dist/chrome.js +171 -40
  4. package/dist/chrome.js.map +1 -1
  5. package/dist/chrome.mjs +172 -41
  6. package/dist/chrome.mjs.map +1 -1
  7. package/dist/components.d.mts +46 -9
  8. package/dist/components.d.ts +46 -9
  9. package/dist/components.js +334 -167
  10. package/dist/components.js.map +1 -1
  11. package/dist/components.mjs +333 -170
  12. package/dist/components.mjs.map +1 -1
  13. package/dist/{docs-BB9gK4KF.d.ts → docs-ByUx4t-D.d.ts} +2 -1
  14. package/dist/{docs-D-T-nHiu.d.mts → docs-CFE5mU_6.d.mts} +2 -1
  15. package/dist/index.d.mts +4 -4
  16. package/dist/index.d.ts +4 -4
  17. package/dist/index.js +572 -244
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.mjs +570 -246
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/mdx.d.mts +1 -1
  22. package/dist/mdx.d.ts +1 -1
  23. package/dist/mdx.js +7 -2
  24. package/dist/mdx.js.map +1 -1
  25. package/dist/mdx.mjs +7 -2
  26. package/dist/mdx.mjs.map +1 -1
  27. package/dist/primitives.d.mts +4 -3
  28. package/dist/primitives.d.ts +4 -3
  29. package/dist/primitives.js +37 -1
  30. package/dist/primitives.js.map +1 -1
  31. package/dist/primitives.mjs +37 -1
  32. package/dist/primitives.mjs.map +1 -1
  33. package/dist/session.d.mts +3 -3
  34. package/dist/session.d.ts +3 -3
  35. package/dist/session.js +1 -1
  36. package/dist/session.js.map +1 -1
  37. package/dist/session.mjs +1 -1
  38. package/dist/session.mjs.map +1 -1
  39. package/dist/{tool-shell-D8Q8XX11.d.mts → tool-shell-CQZNRUgH.d.mts} +8 -4
  40. package/dist/{tool-shell-gmlj47Ie.d.ts → tool-shell-CRmceGrV.d.ts} +8 -4
  41. package/dist/{tools-DFIxIj5p.d.mts → tools-Bg1gi2HO.d.mts} +1 -1
  42. package/dist/{tools-BggNN5DV.d.ts → tools-Bw7RhO92.d.ts} +1 -1
  43. package/package.json +3 -2
@@ -1,12 +1,13 @@
1
- import { forwardRef, createContext, useContext, useState, useEffect, createElement, useRef, Children, isValidElement, cloneElement, useCallback, useMemo, Component, useId, useSyncExternalStore, Fragment as Fragment$1 } from 'react';
1
+ import { forwardRef, createContext, useContext, useState, useEffect, createElement, useRef, Children, isValidElement, cloneElement, useCallback, useMemo, Component, useSyncExternalStore, useId, Fragment as Fragment$1 } from 'react';
2
2
  import { clsx } from 'clsx';
3
3
  import { extendTailwindMerge } from 'tailwind-merge';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import { cva } from 'class-variance-authority';
6
6
  import * as TabsPrimitive from '@radix-ui/react-tabs';
7
- import { ChevronDown, Check, Search, Copy, ArrowUpRight, ArrowRight, ChevronRight, CornerDownLeft, Download, FileText, Upload, ArrowLeft, Lock, CircleDashed, CircleMinus, CircleSlash, Clock, CircleX, CircleCheck } from 'lucide-react';
7
+ import { ChevronDown, Check, Search, Copy, Lock, ArrowUpRight, ArrowRight, ChevronRight, CornerDownLeft, Download, FileText, Upload, ArrowLeft, CircleDashed, CircleMinus, CircleSlash, Clock, CircleX, CircleCheck } from 'lucide-react';
8
8
  import { Slot } from '@radix-ui/react-slot';
9
9
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
10
+ import 'next-themes';
10
11
  import 'sonner';
11
12
  import Link from 'next/link';
12
13
  import { useRouter } from 'next/compat/router';
@@ -531,7 +532,7 @@ var JS_TAG = /<\/?(?=[A-Za-z])/y;
531
532
  var JS_TAG_NAME = /[A-Za-z][\w$.:-]*/y;
532
533
  var JS_PUNCT = /=>|\.\.\.|[{}()[\];,.<>=+\-*/%!?:&|^~#]/y;
533
534
  var JSX_BEFORE = /* @__PURE__ */ new Set(["(", ",", "=", "?", ":", "{", "[", ";", ">", "&&", "||", "=>", "return"]);
534
- function scanJs(src, emit, jsx35) {
535
+ function scanJs(src, emit, jsx36) {
535
536
  let i = 0;
536
537
  let prev = "";
537
538
  let tagDepth = 0;
@@ -557,7 +558,7 @@ function scanJs(src, emit, jsx35) {
557
558
  sig('"');
558
559
  continue;
559
560
  }
560
- if (jsx35 && tagDepth === 0 && (m = at(JS_TAG, src, i)) && (prev === "" || JSX_BEFORE.has(prev))) {
561
+ if (jsx36 && tagDepth === 0 && (m = at(JS_TAG, src, i)) && (prev === "" || JSX_BEFORE.has(prev))) {
561
562
  const name = at(JS_TAG_NAME, src, i + m.length);
562
563
  if (name) {
563
564
  emit(m);
@@ -569,7 +570,7 @@ function scanJs(src, emit, jsx35) {
569
570
  continue;
570
571
  }
571
572
  }
572
- if (jsx35 && tagDepth > 0 && braceInTag === 0) {
573
+ if (jsx36 && tagDepth > 0 && braceInTag === 0) {
573
574
  if (src.startsWith("/>", i) || src[i] === ">") {
574
575
  const close = src[i] === ">" ? ">" : "/>";
575
576
  emit(close);
@@ -589,7 +590,7 @@ function scanJs(src, emit, jsx35) {
589
590
  continue;
590
591
  }
591
592
  if (src[i] === "{") braceInTag = 1;
592
- } else if (jsx35 && tagDepth > 0 && braceInTag > 0) {
593
+ } else if (jsx36 && tagDepth > 0 && braceInTag > 0) {
593
594
  if (src[i] === "{") braceInTag++;
594
595
  else if (src[i] === "}") braceInTag--;
595
596
  }
@@ -1705,7 +1706,8 @@ function Well({
1705
1706
  lines,
1706
1707
  maxLines,
1707
1708
  diff,
1708
- lineNumbers
1709
+ lineNumbers,
1710
+ wrap
1709
1711
  }) {
1710
1712
  const foldable = maxLines !== void 0 && lines > maxLines + 2;
1711
1713
  const [open, setOpen] = useState(false);
@@ -1724,7 +1726,8 @@ function Well({
1724
1726
  "data-diff": diff ? "" : void 0,
1725
1727
  "data-line-numbers": lineNumbers ? "" : void 0,
1726
1728
  className: cn(
1727
- "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]",
1729
+ "oca-code py-4 font-mono text-[0.875rem] leading-[1.625] text-oca-ink-muted [font-variant-ligatures:none]",
1730
+ wrap ? "whitespace-pre-wrap break-all" : "w-max min-w-full",
1728
1731
  !lined && "px-5"
1729
1732
  ),
1730
1733
  children: lined ? /* @__PURE__ */ jsx("code", { className: "block", "data-lang": lang, dangerouslySetInnerHTML: { __html: html } }) : /* @__PURE__ */ jsx("code", { className: "block", "data-lang": lang, children })
@@ -1766,6 +1769,7 @@ function CodeBlock({
1766
1769
  highlight: marks,
1767
1770
  diff,
1768
1771
  lineNumbers,
1772
+ wrap,
1769
1773
  actions,
1770
1774
  className
1771
1775
  }) {
@@ -1797,6 +1801,7 @@ function CodeBlock({
1797
1801
  maxLines,
1798
1802
  diff: prepared ? prepared.diff : isDiff,
1799
1803
  lineNumbers,
1804
+ wrap,
1800
1805
  children
1801
1806
  }
1802
1807
  )
@@ -2299,6 +2304,133 @@ function MarkOutline({ className }) {
2299
2304
  points
2300
2305
  )) });
2301
2306
  }
2307
+
2308
+ // src/family/index.ts
2309
+ var OCHK_IO = "https://ochk.io";
2310
+ var DOCS_HREF = `${OCHK_IO}/docs`;
2311
+ function protocol(slug, verb, line, kinds) {
2312
+ return {
2313
+ slug,
2314
+ label: slug,
2315
+ href: `${OCHK_IO}/${slug}`,
2316
+ group: "protocol",
2317
+ line,
2318
+ status: "live",
2319
+ verb,
2320
+ pageHref: `${OCHK_IO}/${slug}`,
2321
+ toolHref: `https://${slug}.ochk.io`,
2322
+ specHref: `https://github.com/orangecheck/oc-${slug}-protocol`,
2323
+ kinds
2324
+ };
2325
+ }
2326
+ var PROTOCOLS = [
2327
+ protocol("attest", "identity", "Show that an address holds bitcoin, and for how long.", "30078"),
2328
+ protocol("lock", "confidentiality", "Encrypt to a Bitcoin address, so only its holder can open it.", "30078"),
2329
+ protocol("vote", "legitimacy", "Polls weighed in sats, that anyone can tally.", "30080\u201330082"),
2330
+ protocol("stamp", "provenance", "Prove who signed something, and when.", "30083"),
2331
+ protocol("agent", "authority", "Give software scoped, revocable permission to act for you.", "30083\u201330086"),
2332
+ protocol("pledge", "commitment", "Make a promise with bitcoin behind it, on a public record.", "30078")
2333
+ ];
2334
+ var PROTOCOL_ORDER = PROTOCOLS.map((p) => p.slug);
2335
+ var FAMILY = [
2336
+ {
2337
+ slug: "home",
2338
+ label: "ochk.io",
2339
+ href: OCHK_IO,
2340
+ group: "orangecheck",
2341
+ line: "The open protocols, and the company behind them.",
2342
+ status: "live"
2343
+ },
2344
+ {
2345
+ slug: "me",
2346
+ label: "ochk.app",
2347
+ href: "https://ochk.app",
2348
+ group: "orangecheck",
2349
+ line: "One account, with Bitcoin behind it.",
2350
+ status: "testing"
2351
+ },
2352
+ {
2353
+ slug: "docs",
2354
+ label: "docs",
2355
+ href: DOCS_HREF,
2356
+ group: "orangecheck",
2357
+ line: "Specs, SDKs and guides for every protocol.",
2358
+ status: "live"
2359
+ },
2360
+ ...PROTOCOLS,
2361
+ {
2362
+ slug: "vault",
2363
+ label: "vault",
2364
+ href: "https://vault.ochk.io",
2365
+ group: "app",
2366
+ line: "A password manager, encrypted in your browser.",
2367
+ status: "live",
2368
+ protocols: ["lock"]
2369
+ },
2370
+ {
2371
+ slug: "chat",
2372
+ label: "chat",
2373
+ href: "https://chat.ochk.io",
2374
+ group: "app",
2375
+ line: "Messages only the holder of a Bitcoin address can read.",
2376
+ status: "testing",
2377
+ protocols: ["lock"]
2378
+ },
2379
+ {
2380
+ slug: "cosign",
2381
+ label: "cosign",
2382
+ href: "https://cosign.ochk.io",
2383
+ group: "app",
2384
+ line: "Builders find co-founders and backers.",
2385
+ status: "testing",
2386
+ // Signs in with an orangecheck account and a wallet; uses none of the six directly.
2387
+ protocols: []
2388
+ },
2389
+ {
2390
+ slug: "me-demo",
2391
+ // "demo", not the made-up app's own name, so nobody takes it for ours.
2392
+ label: "demo",
2393
+ href: "https://me-demo.ochk.io",
2394
+ group: "app",
2395
+ line: "Lumen Notes, a made-up app that signs in with orangecheck.",
2396
+ status: "live"
2397
+ },
2398
+ {
2399
+ slug: "globe",
2400
+ label: "globe",
2401
+ href: "https://globe.ochk.io",
2402
+ group: "public-good",
2403
+ line: "The Bitcoin network, live, on a globe.",
2404
+ status: "live"
2405
+ },
2406
+ {
2407
+ slug: "btc",
2408
+ label: "btc",
2409
+ href: "https://btc.ochk.io",
2410
+ group: "public-good",
2411
+ line: "A free desk for reading the Bitcoin market.",
2412
+ status: "live"
2413
+ }
2414
+ ];
2415
+ var BY_SLUG = new Map(FAMILY.map((s) => [s.slug, s]));
2416
+ function protocolSite(slug) {
2417
+ return BY_SLUG.get(slug);
2418
+ }
2419
+ [
2420
+ {
2421
+ href: `${OCHK_IO}/protocols`,
2422
+ label: "Protocols",
2423
+ children: PROTOCOLS.map((p) => ({ href: p.pageHref, label: p.label, description: p.line }))
2424
+ },
2425
+ { href: `${OCHK_IO}/apps`, label: "Apps" },
2426
+ { href: DOCS_HREF, label: "Docs" },
2427
+ { href: `${OCHK_IO}/trust`, label: "Trust" },
2428
+ { href: `${OCHK_IO}/about`, label: "About" }
2429
+ ];
2430
+ var SiteHomeContext = sharedContext("site-home", void 0);
2431
+ function useSiteHome() {
2432
+ return useContext(SiteHomeContext);
2433
+ }
2302
2434
  var WORDS = {
2303
2435
  404: {
2304
2436
  name: "Not found",
@@ -2316,10 +2448,13 @@ function ErrorPage({
2316
2448
  title,
2317
2449
  detail,
2318
2450
  actions,
2319
- home = "/",
2451
+ home,
2452
+ protocol: protocol2,
2320
2453
  art,
2321
2454
  className
2322
2455
  }) {
2456
+ const shellHome = useSiteHome();
2457
+ const homeHref = home ?? (protocol2 ? protocolSite(protocol2).pageHref : shellHome ?? OCHK_IO);
2323
2458
  const words = WORDS[code] ?? (code >= 500 ? WORDS[500] : WORDS[404]);
2324
2459
  const server = code >= 500;
2325
2460
  return /* @__PURE__ */ jsx(Section, { space: "none", className: cn("flex min-h-[min(40rem,72dvh)] items-center py-16 md:py-24", className), children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 items-center gap-12 md:grid-cols-12", children: [
@@ -2333,12 +2468,137 @@ function ErrorPage({
2333
2468
  /* @__PURE__ */ jsx("p", { className: "oca-lead oca-enter [--enter-delay:150ms]", children: detail ?? words.detail }),
2334
2469
  /* @__PURE__ */ jsx("div", { className: "oca-enter flex flex-wrap gap-3 [--enter-delay:230ms]", children: actions ?? /* @__PURE__ */ jsxs(Fragment, { children: [
2335
2470
  server ? /* @__PURE__ */ jsx(Button, { onClick: () => window.location.reload(), children: "Try again" }) : null,
2336
- /* @__PURE__ */ jsx(Button, { asChild: true, variant: server ? "secondary" : "primary", children: /* @__PURE__ */ jsx(Link, { href: home, children: "Go home" }) })
2471
+ /* @__PURE__ */ jsx(Button, { asChild: true, variant: server ? "secondary" : "primary", children: /* @__PURE__ */ jsx(Link, { href: homeHref, children: "Go home" }) })
2337
2472
  ] }) })
2338
2473
  ] }),
2339
2474
  art !== null ? /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "oca-enter hidden justify-center md:col-span-5 md:flex [--enter-delay:120ms]", children: art ?? /* @__PURE__ */ jsx(MarkOutline, { className: "w-full max-w-[20rem] text-oca-hairline-strong" }) }) : null
2340
2475
  ] }) });
2341
2476
  }
2477
+ function onSecond(tick) {
2478
+ const id = setInterval(tick, 1e3);
2479
+ return () => clearInterval(id);
2480
+ }
2481
+ var nowSeconds = () => Math.floor(Date.now() / 1e3);
2482
+ function CountdownRing({
2483
+ period,
2484
+ remaining,
2485
+ warnAt = 5,
2486
+ size = 18,
2487
+ showSeconds = true,
2488
+ className
2489
+ }) {
2490
+ const now = useSyncExternalStore(onSecond, nowSeconds, () => null);
2491
+ const left = remaining ?? (now === null ? null : period - now % period);
2492
+ const share = left === null ? 1 : Math.max(0, Math.min(1, left / period));
2493
+ const warn = left !== null && left <= warnAt;
2494
+ const r = size / 2 - 1.5;
2495
+ const c = 2 * Math.PI * r;
2496
+ return /* @__PURE__ */ jsxs(
2497
+ "span",
2498
+ {
2499
+ role: "timer",
2500
+ "aria-label": left === null ? void 0 : `${left} second${left === 1 ? "" : "s"} left`,
2501
+ className: cn("inline-flex items-center gap-1.5", warn ? "text-destructive" : "text-muted-foreground", className),
2502
+ children: [
2503
+ /* @__PURE__ */ jsxs("svg", { "aria-hidden": true, width: size, height: size, viewBox: `0 0 ${size} ${size}`, className: "-rotate-90", children: [
2504
+ /* @__PURE__ */ jsx("circle", { cx: size / 2, cy: size / 2, r, fill: "none", stroke: "var(--border)", strokeWidth: 2 }),
2505
+ /* @__PURE__ */ jsx(
2506
+ "circle",
2507
+ {
2508
+ cx: size / 2,
2509
+ cy: size / 2,
2510
+ r,
2511
+ fill: "none",
2512
+ stroke: "currentColor",
2513
+ strokeWidth: 2,
2514
+ strokeLinecap: "round",
2515
+ strokeDasharray: c,
2516
+ strokeDashoffset: c * (1 - share),
2517
+ className: cn(left !== null && left < period && "transition-[stroke-dashoffset] duration-1000 ease-linear motion-reduce:transition-none")
2518
+ }
2519
+ )
2520
+ ] }),
2521
+ showSeconds && left !== null ? /* @__PURE__ */ jsxs("span", { className: "text-[0.8125rem] oca-tabular", children: [
2522
+ left,
2523
+ "s"
2524
+ ] }) : null
2525
+ ]
2526
+ }
2527
+ );
2528
+ }
2529
+ function PlanCard({
2530
+ name,
2531
+ subtitle,
2532
+ price,
2533
+ period,
2534
+ footnote,
2535
+ features = [],
2536
+ action,
2537
+ badge,
2538
+ badgeTone = "neutral",
2539
+ highlight: highlight2 = false,
2540
+ className
2541
+ }) {
2542
+ return /* @__PURE__ */ jsxs(
2543
+ "section",
2544
+ {
2545
+ className: cn(
2546
+ "flex h-full flex-col gap-5 rounded-[1.25rem] border bg-card p-6",
2547
+ highlight2 ? "border-foreground shadow-sm ring-1 ring-foreground" : "border-border",
2548
+ className
2549
+ ),
2550
+ children: [
2551
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
2552
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
2553
+ /* @__PURE__ */ jsx("h3", { className: "text-[1.0625rem] font-medium leading-snug", children: name }),
2554
+ badge ? /* @__PURE__ */ jsx(Badge, { tone: badgeTone, children: badge }) : null
2555
+ ] }),
2556
+ subtitle ? /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: subtitle }) : null
2557
+ ] }),
2558
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
2559
+ /* @__PURE__ */ jsxs("p", { className: "flex flex-wrap items-baseline gap-x-1.5", children: [
2560
+ /* @__PURE__ */ jsx("span", { className: "oca-display-3 oca-tabular", children: price }),
2561
+ period ? /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem] text-muted-foreground", children: period }) : null
2562
+ ] }),
2563
+ footnote ? /* @__PURE__ */ jsx("p", { className: "text-[0.8125rem] text-muted-foreground", children: footnote }) : null
2564
+ ] }),
2565
+ features.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2.5 text-[0.9375rem]", children: features.map((f, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2.5", children: [
2566
+ /* @__PURE__ */ jsx(Check, { "aria-hidden": true, className: "mt-1 size-4 shrink-0 text-muted-foreground" }),
2567
+ /* @__PURE__ */ jsx("span", { className: "min-w-0", children: f })
2568
+ ] }, i)) }) : null,
2569
+ action ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col pt-1 [&>*]:w-full", children: action }) : null
2570
+ ]
2571
+ }
2572
+ );
2573
+ }
2574
+ function LockedPreview({
2575
+ title,
2576
+ description,
2577
+ action,
2578
+ children,
2579
+ className
2580
+ }) {
2581
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
2582
+ children ? /* @__PURE__ */ jsx(
2583
+ "div",
2584
+ {
2585
+ inert: true,
2586
+ "aria-hidden": true,
2587
+ "data-oca-locked": "",
2588
+ className: "pointer-events-none max-h-[28rem] select-none overflow-hidden [mask-image:linear-gradient(to_bottom,#000_25%,transparent_85%)]",
2589
+ children
2590
+ }
2591
+ ) : null,
2592
+ /* @__PURE__ */ jsxs("div", { className: cn("relative mx-auto flex max-w-md flex-col items-center gap-4 rounded-[1.25rem] border border-border bg-card px-6 py-7 text-center shadow-sm", children && "-mt-40"), children: [
2593
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "flex size-10 items-center justify-center rounded-full bg-muted text-foreground", children: /* @__PURE__ */ jsx(Lock, { className: "size-[1.125rem]" }) }),
2594
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
2595
+ /* @__PURE__ */ jsx("p", { className: "text-[1.0625rem] font-medium leading-snug", children: title }),
2596
+ description ? /* @__PURE__ */ jsx("p", { className: "text-[0.9375rem] leading-snug text-muted-foreground", children: description }) : null
2597
+ ] }),
2598
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap justify-center gap-2", children: action })
2599
+ ] })
2600
+ ] });
2601
+ }
2342
2602
  function IsoCheck({ size = 360, settle = false, shadow = true, tilt = false, title, className }) {
2343
2603
  const ref = useRef(null);
2344
2604
  useEffect(() => {
@@ -2684,129 +2944,6 @@ function LegalDocument({ doc, className }) {
2684
2944
  }
2685
2945
  );
2686
2946
  }
2687
-
2688
- // src/family/index.ts
2689
- var OCHK_IO = "https://ochk.io";
2690
- var DOCS_HREF = `${OCHK_IO}/docs`;
2691
- function protocol(slug, verb, line, kinds) {
2692
- return {
2693
- slug,
2694
- label: slug,
2695
- href: `${OCHK_IO}/${slug}`,
2696
- group: "protocol",
2697
- line,
2698
- status: "live",
2699
- verb,
2700
- pageHref: `${OCHK_IO}/${slug}`,
2701
- toolHref: `https://${slug}.ochk.io`,
2702
- specHref: `https://github.com/orangecheck/oc-${slug}-protocol`,
2703
- kinds
2704
- };
2705
- }
2706
- var PROTOCOLS = [
2707
- protocol("attest", "identity", "Show that an address holds bitcoin, and for how long.", "30078"),
2708
- protocol("lock", "confidentiality", "Encrypt to a Bitcoin address, so only its holder can open it.", "30078"),
2709
- protocol("vote", "legitimacy", "Polls weighed in sats, that anyone can tally.", "30080\u201330082"),
2710
- protocol("stamp", "provenance", "Prove who signed something, and when.", "30083"),
2711
- protocol("agent", "authority", "Give software scoped, revocable permission to act for you.", "30083\u201330086"),
2712
- protocol("pledge", "commitment", "Make a promise with bitcoin behind it, on a public record.", "30078")
2713
- ];
2714
- var PROTOCOL_ORDER = PROTOCOLS.map((p) => p.slug);
2715
- var FAMILY = [
2716
- {
2717
- slug: "home",
2718
- label: "ochk.io",
2719
- href: OCHK_IO,
2720
- group: "orangecheck",
2721
- line: "The open protocols, and the company behind them.",
2722
- status: "live"
2723
- },
2724
- {
2725
- slug: "me",
2726
- label: "ochk.app",
2727
- href: "https://ochk.app",
2728
- group: "orangecheck",
2729
- line: "One account, with Bitcoin behind it.",
2730
- status: "testing"
2731
- },
2732
- {
2733
- slug: "docs",
2734
- label: "docs",
2735
- href: DOCS_HREF,
2736
- group: "orangecheck",
2737
- line: "Specs, SDKs and guides for every protocol.",
2738
- status: "live"
2739
- },
2740
- ...PROTOCOLS,
2741
- {
2742
- slug: "vault",
2743
- label: "vault",
2744
- href: "https://vault.ochk.io",
2745
- group: "app",
2746
- line: "A password manager, encrypted in your browser.",
2747
- status: "live",
2748
- protocols: ["lock"]
2749
- },
2750
- {
2751
- slug: "chat",
2752
- label: "chat",
2753
- href: "https://chat.ochk.io",
2754
- group: "app",
2755
- line: "Messages only the holder of a Bitcoin address can read.",
2756
- status: "testing",
2757
- protocols: ["lock"]
2758
- },
2759
- {
2760
- slug: "cosign",
2761
- label: "cosign",
2762
- href: "https://cosign.ochk.io",
2763
- group: "app",
2764
- line: "Builders find co-founders and backers.",
2765
- status: "testing",
2766
- // Signs in with an orangecheck account and a wallet; uses none of the six directly.
2767
- protocols: []
2768
- },
2769
- {
2770
- slug: "me-demo",
2771
- // "demo", not the made-up app's own name, so nobody takes it for ours.
2772
- label: "demo",
2773
- href: "https://me-demo.ochk.io",
2774
- group: "app",
2775
- line: "Lumen Notes, a made-up app that signs in with orangecheck.",
2776
- status: "live"
2777
- },
2778
- {
2779
- slug: "globe",
2780
- label: "globe",
2781
- href: "https://globe.ochk.io",
2782
- group: "public-good",
2783
- line: "The Bitcoin network, live, on a globe.",
2784
- status: "live"
2785
- },
2786
- {
2787
- slug: "btc",
2788
- label: "btc",
2789
- href: "https://btc.ochk.io",
2790
- group: "public-good",
2791
- line: "A free desk for reading the Bitcoin market.",
2792
- status: "live"
2793
- }
2794
- ];
2795
- var BY_SLUG = new Map(FAMILY.map((s) => [s.slug, s]));
2796
- function protocolSite(slug) {
2797
- return BY_SLUG.get(slug);
2798
- }
2799
- [
2800
- {
2801
- href: `${OCHK_IO}/protocols`,
2802
- label: "Protocols",
2803
- children: PROTOCOLS.map((p) => ({ href: p.pageHref, label: p.label, description: p.line }))
2804
- },
2805
- { href: `${OCHK_IO}/apps`, label: "Apps" },
2806
- { href: DOCS_HREF, label: "Docs" },
2807
- { href: `${OCHK_IO}/trust`, label: "Trust" },
2808
- { href: `${OCHK_IO}/about`, label: "About" }
2809
- ];
2810
2947
  var InDocsContext = sharedContext("in-docs", false);
2811
2948
  function useInDocs() {
2812
2949
  return useContext(InDocsContext);
@@ -3821,6 +3958,7 @@ function SignMessage({
3821
3958
  error,
3822
3959
  submitLabel = "Confirm",
3823
3960
  secondary,
3961
+ scheme = "bip322",
3824
3962
  onSignature,
3825
3963
  className
3826
3964
  }) {
@@ -3835,7 +3973,7 @@ function SignMessage({
3835
3973
  /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" })
3836
3974
  ] })
3837
3975
  ] }) : null,
3838
- /* @__PURE__ */ jsx(CodeBlock, { code: message, caption: "Message to sign" }),
3976
+ /* @__PURE__ */ jsx(CodeBlock, { code: message, caption: "Message to sign", wrap: true }),
3839
3977
  /* @__PURE__ */ jsxs(
3840
3978
  "form",
3841
3979
  {
@@ -3851,7 +3989,9 @@ function SignMessage({
3851
3989
  label: "Signature",
3852
3990
  error,
3853
3991
  hint: /* @__PURE__ */ jsxs(Fragment, { children: [
3854
- "From your wallet\u2019s \u201Csign message\u201D (BIP-322), signed by",
3992
+ "From your wallet\u2019s \u201Csign message\u201D (",
3993
+ scheme === "legacy" ? "legacy, BIP-137" : "BIP-322",
3994
+ "), signed by",
3855
3995
  " ",
3856
3996
  /* @__PURE__ */ jsx("span", { className: "break-all font-mono", children: address }),
3857
3997
  "."
@@ -3919,6 +4059,7 @@ function SearchDialog({
3919
4059
  idle,
3920
4060
  defaultQuery = "",
3921
4061
  debounceMs = 120,
4062
+ browse = false,
3922
4063
  className
3923
4064
  }) {
3924
4065
  const [own, setOwn] = useState(false);
@@ -3955,7 +4096,7 @@ function SearchDialog({
3955
4096
  }, [hotkey]);
3956
4097
  useEffect(() => {
3957
4098
  const q = query.trim();
3958
- if (!q) {
4099
+ if (!q && !(browse && open)) {
3959
4100
  setGroups([]);
3960
4101
  setState("idle");
3961
4102
  return;
@@ -3977,14 +4118,15 @@ function SearchDialog({
3977
4118
  clearTimeout(t);
3978
4119
  ctl.abort();
3979
4120
  };
3980
- }, [query, debounceMs]);
4121
+ }, [query, debounceMs, browse, open]);
3981
4122
  useEffect(() => {
3982
4123
  listRef.current?.querySelector('[aria-selected="true"]')?.scrollIntoView({ block: "nearest" });
3983
4124
  }, [active]);
3984
4125
  const choose = (r) => {
3985
4126
  setOpen(false);
3986
- if (onSelect) onSelect(r);
3987
- else window.location.assign(r.href);
4127
+ if (r.run) r.run();
4128
+ else if (onSelect) onSelect(r);
4129
+ else if (r.href) window.location.assign(r.href);
3988
4130
  };
3989
4131
  const optionId = (i) => `${listId}-o${i}`;
3990
4132
  const showList = state === "done" && flat.length > 0;
@@ -4055,25 +4197,28 @@ function SearchDialog({
4055
4197
  index++;
4056
4198
  const i = index;
4057
4199
  const on = i === active;
4200
+ const Option = r.href ? "a" : "div";
4058
4201
  return /* @__PURE__ */ jsxs(
4059
- "a",
4202
+ Option,
4060
4203
  {
4061
4204
  id: optionId(i),
4062
- href: r.href,
4205
+ ...r.href ? { href: r.href } : {},
4063
4206
  role: "option",
4064
4207
  "aria-selected": on,
4065
4208
  tabIndex: -1,
4066
4209
  onMouseMove: () => setActive(i),
4067
4210
  onClick: (e) => {
4068
- if (e.metaKey || e.ctrlKey || e.shiftKey) return;
4211
+ if (r.href && (e.metaKey || e.ctrlKey || e.shiftKey)) return;
4069
4212
  e.preventDefault();
4070
4213
  choose(r);
4071
4214
  },
4072
4215
  className: cn(
4073
4216
  "flex items-start gap-3 rounded-xl px-3 py-2.5 transition-colors",
4074
- on ? "bg-accent" : "hover:bg-accent"
4217
+ on ? "bg-accent" : "hover:bg-accent",
4218
+ !r.href && "cursor-pointer"
4075
4219
  ),
4076
4220
  children: [
4221
+ r.icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "mt-0.5 flex size-5 shrink-0 items-center justify-center text-muted-foreground [&_svg]:size-[1.0625rem]", children: r.icon }) : null,
4077
4222
  /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
4078
4223
  /* @__PURE__ */ jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: r.title }),
4079
4224
  r.section ? /* @__PURE__ */ jsx("span", { className: "truncate text-[0.8125rem] text-muted-foreground", children: r.section }) : null,
@@ -4085,6 +4230,7 @@ function SearchDialog({
4085
4230
  }
4086
4231
  ) : r.excerpt ? /* @__PURE__ */ jsx("span", { className: "line-clamp-2 text-[0.875rem] leading-snug text-muted-foreground", children: r.excerpt }) : null
4087
4232
  ] }),
4233
+ r.meta ? /* @__PURE__ */ jsx("span", { className: "mt-0.5 shrink-0 text-[0.8125rem] text-muted-foreground", children: r.meta }) : null,
4088
4234
  /* @__PURE__ */ jsx(CornerDownLeft, { "aria-hidden": true, className: cn("mt-1 size-4 shrink-0 text-muted-foreground", !on && "invisible") })
4089
4235
  ]
4090
4236
  },
@@ -4093,11 +4239,11 @@ function SearchDialog({
4093
4239
  })
4094
4240
  ] }, gi)) }),
4095
4241
  state === "idle" ? /* @__PURE__ */ jsx("div", { className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: idle ?? "Type a word: a protocol, a function, an error." }) : null,
4096
- state === "done" && flat.length === 0 ? /* @__PURE__ */ jsxs("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: [
4242
+ state === "done" && flat.length === 0 ? /* @__PURE__ */ jsx("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: query.trim() ? /* @__PURE__ */ jsxs(Fragment, { children: [
4097
4243
  "No results for \u201C",
4098
4244
  query.trim(),
4099
4245
  "\u201D."
4100
- ] }) : null,
4246
+ ] }) : "Nothing here yet." }) : null,
4101
4247
  state === "error" ? /* @__PURE__ */ jsx("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: "Search is not available right now. Try again in a moment." }) : null
4102
4248
  ] }),
4103
4249
  /* @__PURE__ */ jsxs("div", { "aria-hidden": true, className: "hidden shrink-0 items-center gap-4 border-t border-border px-5 py-2.5 text-[0.75rem] text-muted-foreground sm:flex", children: [
@@ -4122,6 +4268,13 @@ function SearchDialog({
4122
4268
  ] }) })
4123
4269
  ] });
4124
4270
  }
4271
+ function CommandDialog({
4272
+ label = "Commands",
4273
+ placeholder = "Search, or run a command",
4274
+ ...props
4275
+ }) {
4276
+ return /* @__PURE__ */ jsx(SearchDialog, { ...props, label, placeholder, button: false, browse: true });
4277
+ }
4125
4278
  function pretty(content) {
4126
4279
  try {
4127
4280
  return JSON.stringify(JSON.parse(content), null, 2);
@@ -4363,7 +4516,7 @@ function FormSection({
4363
4516
  "aria-current": status === "current" ? "step" : void 0,
4364
4517
  className: cn("scroll-mt-24 rounded-[1.25rem] border border-border bg-card", className),
4365
4518
  children: [
4366
- /* @__PURE__ */ jsxs("header", { className: cn("flex items-start gap-3.5", tight ? "px-5 pt-5" : "px-6 pt-6"), children: [
4519
+ /* @__PURE__ */ jsxs("header", { className: cn("flex flex-wrap items-start gap-x-3.5 gap-y-3", tight ? "px-5 pt-5" : "px-6 pt-6"), children: [
4367
4520
  n !== void 0 ? /* @__PURE__ */ jsx(
4368
4521
  "span",
4369
4522
  {
@@ -4390,7 +4543,7 @@ function FormSection({
4390
4543
  ] }),
4391
4544
  hint ? /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: hint }) : null
4392
4545
  ] }),
4393
- action ? /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action }) : null
4546
+ action ? /* @__PURE__ */ jsx("div", { className: cn("shrink-0 max-sm:basis-full", n !== void 0 && "max-sm:pl-[2.625rem]"), children: action }) : null
4394
4547
  ] }),
4395
4548
  /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", tight ? "gap-4 p-5" : "gap-5 p-6", n !== void 0 && (tight ? "sm:pl-[3.875rem]" : "sm:pl-[4.125rem]")), children })
4396
4549
  ]
@@ -4550,6 +4703,13 @@ function BlockCountdown({
4550
4703
  ] }) : null
4551
4704
  ] });
4552
4705
  }
4706
+ var METER_FILL = {
4707
+ ink: "bg-foreground",
4708
+ brand: "bg-oca-orange-deep",
4709
+ good: "bg-success",
4710
+ caution: "bg-warning",
4711
+ bad: "bg-destructive"
4712
+ };
4553
4713
  function Meter({
4554
4714
  value,
4555
4715
  max,
@@ -4584,7 +4744,7 @@ function Meter({
4584
4744
  /* @__PURE__ */ jsx(
4585
4745
  "div",
4586
4746
  {
4587
- className: cn("h-full shrink-0 rounded-full", tone === "brand" ? "bg-oca-orange-deep" : "bg-foreground"),
4747
+ className: cn("h-full shrink-0 rounded-full", METER_FILL[tone]),
4588
4748
  style: { width: `${v * 100}%` }
4589
4749
  }
4590
4750
  ),
@@ -4620,27 +4780,30 @@ function FilterChips({
4620
4780
  onChange(cur.includes(v) ? cur.filter((x) => x !== v) : [...cur, v]);
4621
4781
  } else onChange(v);
4622
4782
  };
4623
- return /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--background)", className: cn("w-full", className), children: /* @__PURE__ */ jsx("div", { role: "group", "aria-label": label, className: "flex w-max items-center gap-2 py-0.5", children: options.map((o) => {
4624
- const on = isOn(o.value);
4625
- return /* @__PURE__ */ jsxs(
4626
- "button",
4627
- {
4628
- type: "button",
4629
- "aria-pressed": on,
4630
- onClick: () => press(o.value),
4631
- className: cn(
4632
- "inline-flex shrink-0 items-center gap-1.5 rounded-full border px-3.5 text-[0.875rem] transition-colors",
4633
- tight ? "h-8" : "h-9",
4634
- on ? "border-foreground bg-foreground text-background" : "border-border bg-card text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
4635
- ),
4636
- children: [
4637
- o.label,
4638
- o.count !== void 0 ? /* @__PURE__ */ jsx("span", { className: "oca-tabular", children: o.count.toLocaleString("en-US") }) : null
4639
- ]
4640
- },
4641
- o.value
4642
- );
4643
- }) }) });
4783
+ return (
4784
+ // Wraps rather than scrolls: every filter stays in view on a phone.
4785
+ /* @__PURE__ */ jsx("div", { role: "group", "aria-label": label, className: cn("flex flex-wrap items-center gap-2 py-0.5", className), children: options.map((o) => {
4786
+ const on = isOn(o.value);
4787
+ return /* @__PURE__ */ jsxs(
4788
+ "button",
4789
+ {
4790
+ type: "button",
4791
+ "aria-pressed": on,
4792
+ onClick: () => press(o.value),
4793
+ className: cn(
4794
+ "inline-flex shrink-0 items-center gap-1.5 rounded-full border px-3.5 text-[0.875rem] transition-colors",
4795
+ tight ? "h-8" : "h-9",
4796
+ on ? "border-foreground bg-foreground text-background" : "border-border bg-card text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
4797
+ ),
4798
+ children: [
4799
+ o.label,
4800
+ o.count !== void 0 ? /* @__PURE__ */ jsx("span", { className: "oca-tabular", children: o.count.toLocaleString("en-US") }) : null
4801
+ ]
4802
+ },
4803
+ o.value
4804
+ );
4805
+ }) })
4806
+ );
4644
4807
  }
4645
4808
  function ToolGrid({
4646
4809
  tools,
@@ -4695,6 +4858,6 @@ function ToolGrid({
4695
4858
  );
4696
4859
  }
4697
4860
 
4698
- export { Accent, ActivityList, AnchorStatus, ApiTable, AppCard, AppGrid, ArtifactView, BlockCountdown, BlockHeight, Breadcrumbs, BrowserFrame, Callout, CardGrid, Closing, CodeBlock, CodeTabs, ComparisonTable, Container, CopyButton, DataTable, Diagram, Display, DocHeader, DocLayout, DocsHeading, DocsPager, DropZone, EmptyLine, EmptyState, EndpointList, ErrorBoundary, ErrorPage, Eyebrow, FactBlock, FactRows, Faq, FilterChips, FloatChip, Footnote, FormSection, HashChip, InstallTabs, KeyValueList, Lead, LegalDocument, LinkCard, LoadingBlock, MdxTable, Meter, Monogram, Notice, OnThisPage, PackageCard, PageHeader, PageHero, PhoneFrame, ProgressSteps, ProofStrip, Prose, ProtocolGrid, ProtocolHero, ProtocolNav, Reveal, Sats, SatsFigure, ScrollStory, SearchButton, SearchDialog, Section, SectionHeading, SectionIntro, SignMessage, SpecCard, SplitBar, StatCard, StatGrid, StateBadge, Step, StepGrid, Steps, TextLink, Ticker, ToolGrid, TruthTable, UsdApprox, VerifyBox, VerifyReport, createStateBadge, languageName, monogramGround, monogramLetter, satsText, sectionVariants, useActiveHeading, useCopy, useHeadings, useInView };
4861
+ export { Accent, ActivityList, AnchorStatus, ApiTable, AppCard, AppGrid, ArtifactView, BlockCountdown, BlockHeight, Breadcrumbs, BrowserFrame, Callout, CardGrid, Closing, CodeBlock, CodeTabs, CommandDialog, ComparisonTable, Container, CopyButton, CountdownRing, DataTable, Diagram, Display, DocHeader, DocLayout, DocsHeading, DocsPager, DropZone, EmptyLine, EmptyState, EndpointList, ErrorBoundary, ErrorPage, Eyebrow, FactBlock, FactRows, Faq, FilterChips, FloatChip, Footnote, FormSection, HashChip, InstallTabs, KeyValueList, Lead, LegalDocument, LinkCard, LoadingBlock, LockedPreview, MdxTable, Meter, Monogram, Notice, OnThisPage, PackageCard, PageHeader, PageHero, PhoneFrame, PlanCard, ProgressSteps, ProofStrip, Prose, ProtocolGrid, ProtocolHero, ProtocolNav, Reveal, Sats, SatsFigure, ScrollStory, SearchButton, SearchDialog, Section, SectionHeading, SectionIntro, SignMessage, SpecCard, SplitBar, StatCard, StatGrid, StateBadge, Step, StepGrid, Steps, TextLink, Ticker, ToolGrid, TruthTable, UsdApprox, VerifyBox, VerifyReport, createStateBadge, languageName, monogramGround, monogramLetter, satsText, sectionVariants, useActiveHeading, useCopy, useHeadings, useInView };
4699
4862
  //# sourceMappingURL=components.mjs.map
4700
4863
  //# sourceMappingURL=components.mjs.map