@orangecheck/app-design 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,7 @@ import * as TabsPrimitive from '@radix-ui/react-tabs';
7
7
  import { ChevronDown, Check, Search, Copy, ArrowUpRight, ArrowRight, ChevronRight, CornerDownLeft, Download, FileText, Upload, ArrowLeft, Lock, 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';
@@ -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,7 +2468,7 @@ 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
@@ -2684,129 +2819,6 @@ function LegalDocument({ doc, className }) {
2684
2819
  }
2685
2820
  );
2686
2821
  }
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
2822
  var InDocsContext = sharedContext("in-docs", false);
2811
2823
  function useInDocs() {
2812
2824
  return useContext(InDocsContext);
@@ -3821,6 +3833,7 @@ function SignMessage({
3821
3833
  error,
3822
3834
  submitLabel = "Confirm",
3823
3835
  secondary,
3836
+ scheme = "bip322",
3824
3837
  onSignature,
3825
3838
  className
3826
3839
  }) {
@@ -3835,7 +3848,7 @@ function SignMessage({
3835
3848
  /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" })
3836
3849
  ] })
3837
3850
  ] }) : null,
3838
- /* @__PURE__ */ jsx(CodeBlock, { code: message, caption: "Message to sign" }),
3851
+ /* @__PURE__ */ jsx(CodeBlock, { code: message, caption: "Message to sign", wrap: true }),
3839
3852
  /* @__PURE__ */ jsxs(
3840
3853
  "form",
3841
3854
  {
@@ -3851,7 +3864,9 @@ function SignMessage({
3851
3864
  label: "Signature",
3852
3865
  error,
3853
3866
  hint: /* @__PURE__ */ jsxs(Fragment, { children: [
3854
- "From your wallet\u2019s \u201Csign message\u201D (BIP-322), signed by",
3867
+ "From your wallet\u2019s \u201Csign message\u201D (",
3868
+ scheme === "legacy" ? "legacy, BIP-137" : "BIP-322",
3869
+ "), signed by",
3855
3870
  " ",
3856
3871
  /* @__PURE__ */ jsx("span", { className: "break-all font-mono", children: address }),
3857
3872
  "."
@@ -4363,7 +4378,7 @@ function FormSection({
4363
4378
  "aria-current": status === "current" ? "step" : void 0,
4364
4379
  className: cn("scroll-mt-24 rounded-[1.25rem] border border-border bg-card", className),
4365
4380
  children: [
4366
- /* @__PURE__ */ jsxs("header", { className: cn("flex items-start gap-3.5", tight ? "px-5 pt-5" : "px-6 pt-6"), children: [
4381
+ /* @__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
4382
  n !== void 0 ? /* @__PURE__ */ jsx(
4368
4383
  "span",
4369
4384
  {
@@ -4390,7 +4405,7 @@ function FormSection({
4390
4405
  ] }),
4391
4406
  hint ? /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: hint }) : null
4392
4407
  ] }),
4393
- action ? /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action }) : null
4408
+ action ? /* @__PURE__ */ jsx("div", { className: cn("shrink-0 max-sm:basis-full", n !== void 0 && "max-sm:pl-[2.625rem]"), children: action }) : null
4394
4409
  ] }),
4395
4410
  /* @__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
4411
  ]
@@ -4620,27 +4635,30 @@ function FilterChips({
4620
4635
  onChange(cur.includes(v) ? cur.filter((x) => x !== v) : [...cur, v]);
4621
4636
  } else onChange(v);
4622
4637
  };
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
- }) }) });
4638
+ return (
4639
+ // Wraps rather than scrolls: every filter stays in view on a phone.
4640
+ /* @__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) => {
4641
+ const on = isOn(o.value);
4642
+ return /* @__PURE__ */ jsxs(
4643
+ "button",
4644
+ {
4645
+ type: "button",
4646
+ "aria-pressed": on,
4647
+ onClick: () => press(o.value),
4648
+ className: cn(
4649
+ "inline-flex shrink-0 items-center gap-1.5 rounded-full border px-3.5 text-[0.875rem] transition-colors",
4650
+ tight ? "h-8" : "h-9",
4651
+ on ? "border-foreground bg-foreground text-background" : "border-border bg-card text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
4652
+ ),
4653
+ children: [
4654
+ o.label,
4655
+ o.count !== void 0 ? /* @__PURE__ */ jsx("span", { className: "oca-tabular", children: o.count.toLocaleString("en-US") }) : null
4656
+ ]
4657
+ },
4658
+ o.value
4659
+ );
4660
+ }) })
4661
+ );
4644
4662
  }
4645
4663
  function ToolGrid({
4646
4664
  tools,