@orangecheck/app-design 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +21 -5
  2. package/dist/chrome.d.mts +31 -42
  3. package/dist/chrome.d.ts +31 -42
  4. package/dist/chrome.js +500 -23
  5. package/dist/chrome.js.map +1 -1
  6. package/dist/chrome.mjs +495 -25
  7. package/dist/chrome.mjs.map +1 -1
  8. package/dist/code.d.mts +52 -0
  9. package/dist/code.d.ts +52 -0
  10. package/dist/code.js +534 -0
  11. package/dist/code.js.map +1 -0
  12. package/dist/code.mjs +522 -0
  13. package/dist/code.mjs.map +1 -0
  14. package/dist/components.d.mts +61 -117
  15. package/dist/components.d.ts +61 -117
  16. package/dist/components.js +2170 -105
  17. package/dist/components.js.map +1 -1
  18. package/dist/components.mjs +2142 -109
  19. package/dist/components.mjs.map +1 -1
  20. package/dist/docs-DhnstueM.d.ts +219 -0
  21. package/dist/docs-DiR6s43s.d.mts +219 -0
  22. package/dist/format.d.mts +12 -0
  23. package/dist/format.d.ts +12 -0
  24. package/dist/format.js +65 -0
  25. package/dist/format.js.map +1 -0
  26. package/dist/format.mjs +58 -0
  27. package/dist/format.mjs.map +1 -0
  28. package/dist/hero-Dn37il-9.d.mts +31 -0
  29. package/dist/hero-Dn37il-9.d.ts +31 -0
  30. package/dist/index.d.mts +10 -3
  31. package/dist/index.d.ts +10 -3
  32. package/dist/index.js +2668 -131
  33. package/dist/index.js.map +1 -1
  34. package/dist/index.mjs +2614 -134
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/mdx.d.mts +58 -0
  37. package/dist/mdx.d.ts +58 -0
  38. package/dist/mdx.js +1712 -0
  39. package/dist/mdx.js.map +1 -0
  40. package/dist/mdx.mjs +1685 -0
  41. package/dist/mdx.mjs.map +1 -0
  42. package/dist/primitives.d.mts +22 -5
  43. package/dist/primitives.d.ts +22 -5
  44. package/dist/primitives.js +51 -5
  45. package/dist/primitives.js.map +1 -1
  46. package/dist/primitives.mjs +51 -7
  47. package/dist/primitives.mjs.map +1 -1
  48. package/dist/session.d.mts +18 -0
  49. package/dist/session.d.ts +18 -0
  50. package/dist/session.js +432 -0
  51. package/dist/session.js.map +1 -0
  52. package/dist/session.mjs +401 -0
  53. package/dist/session.mjs.map +1 -0
  54. package/dist/styles/code.css +97 -0
  55. package/dist/styles/theme.css +2 -0
  56. package/dist/styles/tokens.css +40 -0
  57. package/dist/styles.css +1 -0
  58. package/dist/tool-shell-B1C7ahKE.d.ts +81 -0
  59. package/dist/tool-shell-BDx_N5ai.d.mts +81 -0
  60. package/dist/tools-BggNN5DV.d.ts +131 -0
  61. package/dist/tools-DFIxIj5p.d.mts +131 -0
  62. package/package.json +31 -2
@@ -0,0 +1,219 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, HTMLAttributes, TableHTMLAttributes } from 'react';
3
+ import { j as ProtocolSlug, S as SiteStatus, b as FamilyGroup, d as FamilySlug } from './index-C6hDqOOS.js';
4
+ import { a as Status } from './status-badge-BEOxeY9j.js';
5
+ import { T as TocItem } from './hero-Dn37il-9.js';
6
+
7
+ declare function languageName(lang?: string): string | undefined;
8
+ interface CodeBlockProps {
9
+ code?: string;
10
+ html?: string;
11
+ children?: ReactNode;
12
+ lang?: string;
13
+ caption?: ReactNode;
14
+ copy?: boolean;
15
+ clearAfter?: number;
16
+ maxLines?: number;
17
+ highlight?: string | readonly number[];
18
+ diff?: boolean;
19
+ lineNumbers?: boolean;
20
+ actions?: ReactNode;
21
+ className?: string;
22
+ }
23
+ declare function CodeBlock({ code, html, children, lang, caption, copy, clearAfter, maxLines, highlight: marks, diff, lineNumbers, actions, className, }: CodeBlockProps): react.JSX.Element;
24
+ interface CodeTab {
25
+ label: string;
26
+ code: string;
27
+ lang?: string;
28
+ }
29
+ declare function CodeTabs({ items, syncKey, defaultValue, maxLines, className, }: {
30
+ items: CodeTab[];
31
+ syncKey?: string;
32
+ defaultValue?: string;
33
+ maxLines?: number;
34
+ className?: string;
35
+ }): react.JSX.Element;
36
+ declare function InstallTabs({ pkg, dev, className }: {
37
+ pkg: string;
38
+ dev?: boolean;
39
+ className?: string;
40
+ }): react.JSX.Element;
41
+
42
+ declare function ProtocolGrid({ protocols, link, className, }: {
43
+ protocols?: readonly ProtocolSlug[];
44
+ link?: 'page' | 'tool' | 'docs';
45
+ className?: string;
46
+ }): react.JSX.Element;
47
+ interface AppCardProps {
48
+ name: ReactNode;
49
+ line: ReactNode;
50
+ href: string;
51
+ protocols?: readonly ProtocolSlug[];
52
+ status?: SiteStatus;
53
+ className?: string;
54
+ }
55
+ declare function AppCard({ name, line, href, protocols, status, className }: AppCardProps): react.JSX.Element;
56
+ declare function AppGrid({ group, sites, className, }: {
57
+ group?: Extract<FamilyGroup, 'app' | 'public-good'>;
58
+ sites?: readonly FamilySlug[];
59
+ className?: string;
60
+ }): react.JSX.Element;
61
+
62
+ declare function ProtocolHero({ protocol, title, lead, actions, art, children, className, }: {
63
+ protocol: ProtocolSlug;
64
+ title: ReactNode;
65
+ lead?: ReactNode;
66
+ actions?: ReactNode;
67
+ art?: ReactNode;
68
+ children?: ReactNode;
69
+ className?: string;
70
+ }): react.JSX.Element;
71
+ declare function ProtocolNav({ current, link, className, }: {
72
+ current?: ProtocolSlug;
73
+ link?: 'page' | 'tool';
74
+ className?: string;
75
+ }): react.JSX.Element;
76
+ declare function SpecCard({ protocol, version, license, vectors, size, className, }: {
77
+ protocol: ProtocolSlug;
78
+ version: string;
79
+ license?: string;
80
+ vectors?: number;
81
+ size?: 'md' | 'sm';
82
+ className?: string;
83
+ }): react.JSX.Element;
84
+ declare function VerifyBox({ action, param, title, description, label, placeholder, hint, submitLabel, multiline, onVerify, className, }: {
85
+ action: string;
86
+ param?: string;
87
+ title?: ReactNode;
88
+ description?: ReactNode;
89
+ label?: ReactNode;
90
+ placeholder?: string;
91
+ hint?: ReactNode;
92
+ submitLabel?: string;
93
+ multiline?: boolean;
94
+ onVerify?: (value: string) => void;
95
+ className?: string;
96
+ }): react.JSX.Element;
97
+ interface ComparisonColumn {
98
+ key: string;
99
+ label: ReactNode;
100
+ highlight?: boolean;
101
+ }
102
+ interface ComparisonRow {
103
+ label: ReactNode;
104
+ note?: ReactNode;
105
+ values: Record<string, ReactNode>;
106
+ }
107
+ declare function ComparisonTable({ columns, rows, label, propertyHeading, className, }: {
108
+ columns: ComparisonColumn[];
109
+ rows: ComparisonRow[];
110
+ label: string;
111
+ propertyHeading?: ReactNode;
112
+ className?: string;
113
+ }): react.JSX.Element;
114
+
115
+ interface Crumb {
116
+ label: ReactNode;
117
+ href?: string;
118
+ }
119
+ declare function Breadcrumbs({ items, action, className }: {
120
+ items: Crumb[];
121
+ action?: ReactNode;
122
+ className?: string;
123
+ }): react.JSX.Element;
124
+ interface PagerLink {
125
+ href: string;
126
+ label: ReactNode;
127
+ section?: ReactNode;
128
+ }
129
+ declare function DocsPager({ prev, next, className }: {
130
+ prev?: PagerLink;
131
+ next?: PagerLink;
132
+ className?: string;
133
+ }): react.JSX.Element | null;
134
+ declare function useHeadings(selector?: string, key?: string): {
135
+ items: TocItem[];
136
+ activeId?: string;
137
+ };
138
+ declare function OnThisPage({ items, activeId, title, onNavigate, className, }: {
139
+ items: TocItem[];
140
+ activeId?: string;
141
+ title?: ReactNode;
142
+ onNavigate?: () => void;
143
+ className?: string;
144
+ }): react.JSX.Element | null;
145
+ declare const CALLOUT_TONE: {
146
+ readonly note: "neutral";
147
+ readonly warning: "brand";
148
+ readonly danger: "danger";
149
+ };
150
+ declare function Callout({ tone, title, children, className, }: {
151
+ tone?: keyof typeof CALLOUT_TONE;
152
+ title?: ReactNode;
153
+ children?: ReactNode;
154
+ className?: string;
155
+ }): react.JSX.Element;
156
+ declare function Step({ title, id, children }: {
157
+ title: ReactNode;
158
+ id?: string;
159
+ children?: ReactNode;
160
+ }): react.JSX.Element;
161
+ declare function Steps({ children, className }: {
162
+ children: ReactNode;
163
+ className?: string;
164
+ }): react.JSX.Element;
165
+ declare function LinkCard({ href, title, description, icon, meta, className, }: {
166
+ href: string;
167
+ title: ReactNode;
168
+ description?: ReactNode;
169
+ icon?: ReactNode;
170
+ meta?: ReactNode;
171
+ className?: string;
172
+ }): react.JSX.Element;
173
+ declare function CardGrid({ columns, children, className }: {
174
+ columns?: 2 | 3;
175
+ children: ReactNode;
176
+ className?: string;
177
+ }): react.JSX.Element;
178
+ declare function MdxTable({ className, ...props }: TableHTMLAttributes<HTMLTableElement>): react.JSX.Element;
179
+ interface ApiRow {
180
+ name: string;
181
+ type?: ReactNode;
182
+ required?: boolean;
183
+ default?: ReactNode;
184
+ description?: ReactNode;
185
+ deprecated?: boolean;
186
+ status?: Exclude<Status, 'live' | 'good' | 'caution' | 'refused'>;
187
+ }
188
+ declare function ApiTable({ rows, caption, nameHeader, className, }: {
189
+ rows: ApiRow[];
190
+ caption?: string;
191
+ nameHeader?: string;
192
+ className?: string;
193
+ }): react.JSX.Element;
194
+ interface MermaidLike {
195
+ initialize(config: Record<string, unknown>): void;
196
+ render(id: string, text: string): Promise<{
197
+ svg: string;
198
+ }>;
199
+ }
200
+ type MermaidLoader = () => Promise<MermaidLike | {
201
+ default: MermaidLike;
202
+ }>;
203
+ declare function Diagram({ chart, caption, load, className }: {
204
+ chart: string;
205
+ caption?: ReactNode;
206
+ load: MermaidLoader;
207
+ className?: string;
208
+ }): react.JSX.Element;
209
+ declare const HEADING: {
210
+ readonly h1: "oca-display-3 mb-4 text-foreground";
211
+ readonly h2: "mb-3 mt-12 text-[1.375rem] font-medium leading-tight tracking-[-0.015em] text-foreground md:text-[1.5rem]";
212
+ readonly h3: "mb-2 mt-9 text-[1.125rem] font-medium leading-snug tracking-[-0.01em] text-foreground";
213
+ readonly h4: "mb-2 mt-7 text-[1rem] font-medium leading-snug text-foreground";
214
+ };
215
+ declare function DocsHeading({ as: Tag, id, children, className, ...props }: HTMLAttributes<HTMLHeadingElement> & {
216
+ as: keyof typeof HEADING;
217
+ }): react.JSX.Element;
218
+
219
+ export { type ApiRow as A, Breadcrumbs as B, Callout as C, Diagram as D, InstallTabs as I, LinkCard as L, MdxTable as M, OnThisPage as O, type PagerLink as P, SpecCard as S, VerifyBox as V, ApiTable as a, AppCard as b, type AppCardProps as c, AppGrid as d, CardGrid as e, CodeBlock as f, type CodeBlockProps as g, type CodeTab as h, CodeTabs as i, type ComparisonColumn as j, type ComparisonRow as k, ComparisonTable as l, type Crumb as m, DocsHeading as n, DocsPager as o, type MermaidLike as p, type MermaidLoader as q, ProtocolGrid as r, ProtocolHero as s, ProtocolNav as t, Step as u, Steps as v, languageName as w, useHeadings as x };
@@ -0,0 +1,219 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, HTMLAttributes, TableHTMLAttributes } from 'react';
3
+ import { j as ProtocolSlug, S as SiteStatus, b as FamilyGroup, d as FamilySlug } from './index-C6hDqOOS.mjs';
4
+ import { a as Status } from './status-badge-DRwGhB0h.mjs';
5
+ import { T as TocItem } from './hero-Dn37il-9.mjs';
6
+
7
+ declare function languageName(lang?: string): string | undefined;
8
+ interface CodeBlockProps {
9
+ code?: string;
10
+ html?: string;
11
+ children?: ReactNode;
12
+ lang?: string;
13
+ caption?: ReactNode;
14
+ copy?: boolean;
15
+ clearAfter?: number;
16
+ maxLines?: number;
17
+ highlight?: string | readonly number[];
18
+ diff?: boolean;
19
+ lineNumbers?: boolean;
20
+ actions?: ReactNode;
21
+ className?: string;
22
+ }
23
+ declare function CodeBlock({ code, html, children, lang, caption, copy, clearAfter, maxLines, highlight: marks, diff, lineNumbers, actions, className, }: CodeBlockProps): react.JSX.Element;
24
+ interface CodeTab {
25
+ label: string;
26
+ code: string;
27
+ lang?: string;
28
+ }
29
+ declare function CodeTabs({ items, syncKey, defaultValue, maxLines, className, }: {
30
+ items: CodeTab[];
31
+ syncKey?: string;
32
+ defaultValue?: string;
33
+ maxLines?: number;
34
+ className?: string;
35
+ }): react.JSX.Element;
36
+ declare function InstallTabs({ pkg, dev, className }: {
37
+ pkg: string;
38
+ dev?: boolean;
39
+ className?: string;
40
+ }): react.JSX.Element;
41
+
42
+ declare function ProtocolGrid({ protocols, link, className, }: {
43
+ protocols?: readonly ProtocolSlug[];
44
+ link?: 'page' | 'tool' | 'docs';
45
+ className?: string;
46
+ }): react.JSX.Element;
47
+ interface AppCardProps {
48
+ name: ReactNode;
49
+ line: ReactNode;
50
+ href: string;
51
+ protocols?: readonly ProtocolSlug[];
52
+ status?: SiteStatus;
53
+ className?: string;
54
+ }
55
+ declare function AppCard({ name, line, href, protocols, status, className }: AppCardProps): react.JSX.Element;
56
+ declare function AppGrid({ group, sites, className, }: {
57
+ group?: Extract<FamilyGroup, 'app' | 'public-good'>;
58
+ sites?: readonly FamilySlug[];
59
+ className?: string;
60
+ }): react.JSX.Element;
61
+
62
+ declare function ProtocolHero({ protocol, title, lead, actions, art, children, className, }: {
63
+ protocol: ProtocolSlug;
64
+ title: ReactNode;
65
+ lead?: ReactNode;
66
+ actions?: ReactNode;
67
+ art?: ReactNode;
68
+ children?: ReactNode;
69
+ className?: string;
70
+ }): react.JSX.Element;
71
+ declare function ProtocolNav({ current, link, className, }: {
72
+ current?: ProtocolSlug;
73
+ link?: 'page' | 'tool';
74
+ className?: string;
75
+ }): react.JSX.Element;
76
+ declare function SpecCard({ protocol, version, license, vectors, size, className, }: {
77
+ protocol: ProtocolSlug;
78
+ version: string;
79
+ license?: string;
80
+ vectors?: number;
81
+ size?: 'md' | 'sm';
82
+ className?: string;
83
+ }): react.JSX.Element;
84
+ declare function VerifyBox({ action, param, title, description, label, placeholder, hint, submitLabel, multiline, onVerify, className, }: {
85
+ action: string;
86
+ param?: string;
87
+ title?: ReactNode;
88
+ description?: ReactNode;
89
+ label?: ReactNode;
90
+ placeholder?: string;
91
+ hint?: ReactNode;
92
+ submitLabel?: string;
93
+ multiline?: boolean;
94
+ onVerify?: (value: string) => void;
95
+ className?: string;
96
+ }): react.JSX.Element;
97
+ interface ComparisonColumn {
98
+ key: string;
99
+ label: ReactNode;
100
+ highlight?: boolean;
101
+ }
102
+ interface ComparisonRow {
103
+ label: ReactNode;
104
+ note?: ReactNode;
105
+ values: Record<string, ReactNode>;
106
+ }
107
+ declare function ComparisonTable({ columns, rows, label, propertyHeading, className, }: {
108
+ columns: ComparisonColumn[];
109
+ rows: ComparisonRow[];
110
+ label: string;
111
+ propertyHeading?: ReactNode;
112
+ className?: string;
113
+ }): react.JSX.Element;
114
+
115
+ interface Crumb {
116
+ label: ReactNode;
117
+ href?: string;
118
+ }
119
+ declare function Breadcrumbs({ items, action, className }: {
120
+ items: Crumb[];
121
+ action?: ReactNode;
122
+ className?: string;
123
+ }): react.JSX.Element;
124
+ interface PagerLink {
125
+ href: string;
126
+ label: ReactNode;
127
+ section?: ReactNode;
128
+ }
129
+ declare function DocsPager({ prev, next, className }: {
130
+ prev?: PagerLink;
131
+ next?: PagerLink;
132
+ className?: string;
133
+ }): react.JSX.Element | null;
134
+ declare function useHeadings(selector?: string, key?: string): {
135
+ items: TocItem[];
136
+ activeId?: string;
137
+ };
138
+ declare function OnThisPage({ items, activeId, title, onNavigate, className, }: {
139
+ items: TocItem[];
140
+ activeId?: string;
141
+ title?: ReactNode;
142
+ onNavigate?: () => void;
143
+ className?: string;
144
+ }): react.JSX.Element | null;
145
+ declare const CALLOUT_TONE: {
146
+ readonly note: "neutral";
147
+ readonly warning: "brand";
148
+ readonly danger: "danger";
149
+ };
150
+ declare function Callout({ tone, title, children, className, }: {
151
+ tone?: keyof typeof CALLOUT_TONE;
152
+ title?: ReactNode;
153
+ children?: ReactNode;
154
+ className?: string;
155
+ }): react.JSX.Element;
156
+ declare function Step({ title, id, children }: {
157
+ title: ReactNode;
158
+ id?: string;
159
+ children?: ReactNode;
160
+ }): react.JSX.Element;
161
+ declare function Steps({ children, className }: {
162
+ children: ReactNode;
163
+ className?: string;
164
+ }): react.JSX.Element;
165
+ declare function LinkCard({ href, title, description, icon, meta, className, }: {
166
+ href: string;
167
+ title: ReactNode;
168
+ description?: ReactNode;
169
+ icon?: ReactNode;
170
+ meta?: ReactNode;
171
+ className?: string;
172
+ }): react.JSX.Element;
173
+ declare function CardGrid({ columns, children, className }: {
174
+ columns?: 2 | 3;
175
+ children: ReactNode;
176
+ className?: string;
177
+ }): react.JSX.Element;
178
+ declare function MdxTable({ className, ...props }: TableHTMLAttributes<HTMLTableElement>): react.JSX.Element;
179
+ interface ApiRow {
180
+ name: string;
181
+ type?: ReactNode;
182
+ required?: boolean;
183
+ default?: ReactNode;
184
+ description?: ReactNode;
185
+ deprecated?: boolean;
186
+ status?: Exclude<Status, 'live' | 'good' | 'caution' | 'refused'>;
187
+ }
188
+ declare function ApiTable({ rows, caption, nameHeader, className, }: {
189
+ rows: ApiRow[];
190
+ caption?: string;
191
+ nameHeader?: string;
192
+ className?: string;
193
+ }): react.JSX.Element;
194
+ interface MermaidLike {
195
+ initialize(config: Record<string, unknown>): void;
196
+ render(id: string, text: string): Promise<{
197
+ svg: string;
198
+ }>;
199
+ }
200
+ type MermaidLoader = () => Promise<MermaidLike | {
201
+ default: MermaidLike;
202
+ }>;
203
+ declare function Diagram({ chart, caption, load, className }: {
204
+ chart: string;
205
+ caption?: ReactNode;
206
+ load: MermaidLoader;
207
+ className?: string;
208
+ }): react.JSX.Element;
209
+ declare const HEADING: {
210
+ readonly h1: "oca-display-3 mb-4 text-foreground";
211
+ readonly h2: "mb-3 mt-12 text-[1.375rem] font-medium leading-tight tracking-[-0.015em] text-foreground md:text-[1.5rem]";
212
+ readonly h3: "mb-2 mt-9 text-[1.125rem] font-medium leading-snug tracking-[-0.01em] text-foreground";
213
+ readonly h4: "mb-2 mt-7 text-[1rem] font-medium leading-snug text-foreground";
214
+ };
215
+ declare function DocsHeading({ as: Tag, id, children, className, ...props }: HTMLAttributes<HTMLHeadingElement> & {
216
+ as: keyof typeof HEADING;
217
+ }): react.JSX.Element;
218
+
219
+ export { type ApiRow as A, Breadcrumbs as B, Callout as C, Diagram as D, InstallTabs as I, LinkCard as L, MdxTable as M, OnThisPage as O, type PagerLink as P, SpecCard as S, VerifyBox as V, ApiTable as a, AppCard as b, type AppCardProps as c, AppGrid as d, CardGrid as e, CodeBlock as f, type CodeBlockProps as g, type CodeTab as h, CodeTabs as i, type ComparisonColumn as j, type ComparisonRow as k, ComparisonTable as l, type Crumb as m, DocsHeading as n, DocsPager as o, type MermaidLike as p, type MermaidLoader as q, ProtocolGrid as r, ProtocolHero as s, ProtocolNav as t, Step as u, Steps as v, languageName as w, useHeadings as x };
@@ -0,0 +1,12 @@
1
+ type Network = 'mainnet' | 'testnet' | 'testnet4' | 'signet';
2
+ type ExplorerKind = 'address' | 'tx' | 'block';
3
+ declare function explorerUrl(kind: ExplorerKind, value: string | number, network?: Network): string;
4
+ declare function shortenMiddle(value: string, head?: number, tail?: number): string;
5
+ declare function formatBlockHeight(height: number): string;
6
+ declare function blocksToDuration(blocks: number, minutesPerBlock?: number): string;
7
+ declare function formatUtc(at: Date | string | number, opts?: {
8
+ date?: boolean;
9
+ }): string;
10
+ declare function formatBytes(bytes: number): string;
11
+
12
+ export { type ExplorerKind, type Network, blocksToDuration, explorerUrl, formatBlockHeight, formatBytes, formatUtc, shortenMiddle };
@@ -0,0 +1,12 @@
1
+ type Network = 'mainnet' | 'testnet' | 'testnet4' | 'signet';
2
+ type ExplorerKind = 'address' | 'tx' | 'block';
3
+ declare function explorerUrl(kind: ExplorerKind, value: string | number, network?: Network): string;
4
+ declare function shortenMiddle(value: string, head?: number, tail?: number): string;
5
+ declare function formatBlockHeight(height: number): string;
6
+ declare function blocksToDuration(blocks: number, minutesPerBlock?: number): string;
7
+ declare function formatUtc(at: Date | string | number, opts?: {
8
+ date?: boolean;
9
+ }): string;
10
+ declare function formatBytes(bytes: number): string;
11
+
12
+ export { type ExplorerKind, type Network, blocksToDuration, explorerUrl, formatBlockHeight, formatBytes, formatUtc, shortenMiddle };
package/dist/format.js ADDED
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ // src/format/index.ts
4
+ var EXPLORER = "https://mempool.space";
5
+ function explorerUrl(kind, value, network = "mainnet") {
6
+ const net = network === "mainnet" ? "" : `/${network}`;
7
+ return `${EXPLORER}${net}/${kind}/${encodeURIComponent(String(value))}`;
8
+ }
9
+ function shortenMiddle(value, head = 8, tail = 6) {
10
+ return value.length <= head + tail + 1 ? value : `${value.slice(0, head)}\u2026${value.slice(-tail)}`;
11
+ }
12
+ function formatBlockHeight(height) {
13
+ return Math.trunc(height).toLocaleString("en-US");
14
+ }
15
+ function blocksToDuration(blocks, minutesPerBlock = 10) {
16
+ const minutes = Math.max(0, Math.round(blocks * minutesPerBlock));
17
+ if (minutes < 60) return `about ${minutes} minute${minutes === 1 ? "" : "s"}`;
18
+ const units = [
19
+ [60 * 24 * 7, "week"],
20
+ [60 * 24, "day"],
21
+ [60, "hour"],
22
+ [1, "minute"]
23
+ ];
24
+ const parts = [];
25
+ let rest = minutes;
26
+ for (const [size, word] of units) {
27
+ const n = Math.floor(rest / size);
28
+ if (n > 0 && parts.length < 2) {
29
+ parts.push(`${n} ${word}${n === 1 ? "" : "s"}`);
30
+ rest -= n * size;
31
+ } else if (parts.length > 0) break;
32
+ }
33
+ return `about ${parts.join(" ")}`;
34
+ }
35
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
36
+ function formatUtc(at, opts = {}) {
37
+ const d = typeof at === "number" ? new Date(at * 1e3) : new Date(at);
38
+ if (Number.isNaN(d.getTime())) return "\u2014";
39
+ const day = `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]} ${d.getUTCFullYear()}`;
40
+ if (opts.date) return day;
41
+ const hh = String(d.getUTCHours()).padStart(2, "0");
42
+ const mm = String(d.getUTCMinutes()).padStart(2, "0");
43
+ return `${day}, ${hh}:${mm} UTC`;
44
+ }
45
+ function formatBytes(bytes) {
46
+ if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
47
+ if (bytes < 1024) return `${bytes} B`;
48
+ const units = ["KB", "MB", "GB", "TB"];
49
+ let v = bytes / 1024;
50
+ let u = 0;
51
+ while (v >= 1024 && u < units.length - 1) {
52
+ v /= 1024;
53
+ u++;
54
+ }
55
+ return `${v < 10 ? v.toFixed(1).replace(/\.0$/, "") : Math.round(v)} ${units[u]}`;
56
+ }
57
+
58
+ exports.blocksToDuration = blocksToDuration;
59
+ exports.explorerUrl = explorerUrl;
60
+ exports.formatBlockHeight = formatBlockHeight;
61
+ exports.formatBytes = formatBytes;
62
+ exports.formatUtc = formatUtc;
63
+ exports.shortenMiddle = shortenMiddle;
64
+ //# sourceMappingURL=format.js.map
65
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/format/index.ts"],"names":[],"mappings":"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","file":"format.js","sourcesContent":["/*\n * Formatting for the things the family shows over and over: Bitcoin\n * explorer links, shortened ids, block heights, the time to a block. No\n * React, so server code and OG renderers import it too.\n */\n\nexport type Network = 'mainnet' | 'testnet' | 'testnet4' | 'signet';\nexport type ExplorerKind = 'address' | 'tx' | 'block';\n\nconst EXPLORER = 'https://mempool.space';\n\n/** A mempool.space link for an address, a transaction, or a block (by height or hash). */\nexport function explorerUrl(kind: ExplorerKind, value: string | number, network: Network = 'mainnet'): string {\n const net = network === 'mainnet' ? '' : `/${network}`;\n return `${EXPLORER}${net}/${kind}/${encodeURIComponent(String(value))}`;\n}\n\n/** head…tail, leaving short values whole. */\nexport function shortenMiddle(value: string, head = 8, tail = 6): string {\n return value.length <= head + tail + 1 ? value : `${value.slice(0, head)}…${value.slice(-tail)}`;\n}\n\n/** 971632 → \"971,632\". */\nexport function formatBlockHeight(height: number): string {\n return Math.trunc(height).toLocaleString('en-US');\n}\n\n/**\n * How long a number of blocks takes at ten minutes each, in the largest two\n * units: \"about 40 minutes\", \"about 2 days 13 hours\". Blocks come when they\n * come, so it is always \"about\".\n */\nexport function blocksToDuration(blocks: number, minutesPerBlock = 10): string {\n const minutes = Math.max(0, Math.round(blocks * minutesPerBlock));\n if (minutes < 60) return `about ${minutes} minute${minutes === 1 ? '' : 's'}`;\n const units: [number, string][] = [\n [60 * 24 * 7, 'week'],\n [60 * 24, 'day'],\n [60, 'hour'],\n [1, 'minute'],\n ];\n const parts: string[] = [];\n let rest = minutes;\n for (const [size, word] of units) {\n const n = Math.floor(rest / size);\n if (n > 0 && parts.length < 2) {\n parts.push(`${n} ${word}${n === 1 ? '' : 's'}`);\n rest -= n * size;\n } else if (parts.length > 0) break;\n }\n return `about ${parts.join(' ')}`;\n}\n\nconst MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n\n/**\n * A moment in UTC, the same for every reader: \"20 Oct 2026, 09:14 UTC\".\n * Takes a Date, an ISO string, or unix seconds. `date: true` drops the time.\n */\nexport function formatUtc(at: Date | string | number, opts: { date?: boolean } = {}): string {\n const d = typeof at === 'number' ? new Date(at * 1000) : new Date(at);\n if (Number.isNaN(d.getTime())) return '—';\n const day = `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]} ${d.getUTCFullYear()}`;\n if (opts.date) return day;\n const hh = String(d.getUTCHours()).padStart(2, '0');\n const mm = String(d.getUTCMinutes()).padStart(2, '0');\n return `${day}, ${hh}:${mm} UTC`;\n}\n\n/** 482113 → \"471 KB\"; 1288490 → \"1.2 MB\". Binary steps, the way a file dialog counts. */\nexport function formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return '—';\n if (bytes < 1024) return `${bytes} B`;\n const units = ['KB', 'MB', 'GB', 'TB'];\n let v = bytes / 1024;\n let u = 0;\n while (v >= 1024 && u < units.length - 1) {\n v /= 1024;\n u++;\n }\n return `${v < 10 ? v.toFixed(1).replace(/\\.0$/, '') : Math.round(v)} ${units[u]}`;\n}\n"]}
@@ -0,0 +1,58 @@
1
+ // src/format/index.ts
2
+ var EXPLORER = "https://mempool.space";
3
+ function explorerUrl(kind, value, network = "mainnet") {
4
+ const net = network === "mainnet" ? "" : `/${network}`;
5
+ return `${EXPLORER}${net}/${kind}/${encodeURIComponent(String(value))}`;
6
+ }
7
+ function shortenMiddle(value, head = 8, tail = 6) {
8
+ return value.length <= head + tail + 1 ? value : `${value.slice(0, head)}\u2026${value.slice(-tail)}`;
9
+ }
10
+ function formatBlockHeight(height) {
11
+ return Math.trunc(height).toLocaleString("en-US");
12
+ }
13
+ function blocksToDuration(blocks, minutesPerBlock = 10) {
14
+ const minutes = Math.max(0, Math.round(blocks * minutesPerBlock));
15
+ if (minutes < 60) return `about ${minutes} minute${minutes === 1 ? "" : "s"}`;
16
+ const units = [
17
+ [60 * 24 * 7, "week"],
18
+ [60 * 24, "day"],
19
+ [60, "hour"],
20
+ [1, "minute"]
21
+ ];
22
+ const parts = [];
23
+ let rest = minutes;
24
+ for (const [size, word] of units) {
25
+ const n = Math.floor(rest / size);
26
+ if (n > 0 && parts.length < 2) {
27
+ parts.push(`${n} ${word}${n === 1 ? "" : "s"}`);
28
+ rest -= n * size;
29
+ } else if (parts.length > 0) break;
30
+ }
31
+ return `about ${parts.join(" ")}`;
32
+ }
33
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
34
+ function formatUtc(at, opts = {}) {
35
+ const d = typeof at === "number" ? new Date(at * 1e3) : new Date(at);
36
+ if (Number.isNaN(d.getTime())) return "\u2014";
37
+ const day = `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]} ${d.getUTCFullYear()}`;
38
+ if (opts.date) return day;
39
+ const hh = String(d.getUTCHours()).padStart(2, "0");
40
+ const mm = String(d.getUTCMinutes()).padStart(2, "0");
41
+ return `${day}, ${hh}:${mm} UTC`;
42
+ }
43
+ function formatBytes(bytes) {
44
+ if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
45
+ if (bytes < 1024) return `${bytes} B`;
46
+ const units = ["KB", "MB", "GB", "TB"];
47
+ let v = bytes / 1024;
48
+ let u = 0;
49
+ while (v >= 1024 && u < units.length - 1) {
50
+ v /= 1024;
51
+ u++;
52
+ }
53
+ return `${v < 10 ? v.toFixed(1).replace(/\.0$/, "") : Math.round(v)} ${units[u]}`;
54
+ }
55
+
56
+ export { blocksToDuration, explorerUrl, formatBlockHeight, formatBytes, formatUtc, shortenMiddle };
57
+ //# sourceMappingURL=format.mjs.map
58
+ //# sourceMappingURL=format.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/format/index.ts"],"names":[],"mappings":"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","file":"format.mjs","sourcesContent":["/*\n * Formatting for the things the family shows over and over: Bitcoin\n * explorer links, shortened ids, block heights, the time to a block. No\n * React, so server code and OG renderers import it too.\n */\n\nexport type Network = 'mainnet' | 'testnet' | 'testnet4' | 'signet';\nexport type ExplorerKind = 'address' | 'tx' | 'block';\n\nconst EXPLORER = 'https://mempool.space';\n\n/** A mempool.space link for an address, a transaction, or a block (by height or hash). */\nexport function explorerUrl(kind: ExplorerKind, value: string | number, network: Network = 'mainnet'): string {\n const net = network === 'mainnet' ? '' : `/${network}`;\n return `${EXPLORER}${net}/${kind}/${encodeURIComponent(String(value))}`;\n}\n\n/** head…tail, leaving short values whole. */\nexport function shortenMiddle(value: string, head = 8, tail = 6): string {\n return value.length <= head + tail + 1 ? value : `${value.slice(0, head)}…${value.slice(-tail)}`;\n}\n\n/** 971632 → \"971,632\". */\nexport function formatBlockHeight(height: number): string {\n return Math.trunc(height).toLocaleString('en-US');\n}\n\n/**\n * How long a number of blocks takes at ten minutes each, in the largest two\n * units: \"about 40 minutes\", \"about 2 days 13 hours\". Blocks come when they\n * come, so it is always \"about\".\n */\nexport function blocksToDuration(blocks: number, minutesPerBlock = 10): string {\n const minutes = Math.max(0, Math.round(blocks * minutesPerBlock));\n if (minutes < 60) return `about ${minutes} minute${minutes === 1 ? '' : 's'}`;\n const units: [number, string][] = [\n [60 * 24 * 7, 'week'],\n [60 * 24, 'day'],\n [60, 'hour'],\n [1, 'minute'],\n ];\n const parts: string[] = [];\n let rest = minutes;\n for (const [size, word] of units) {\n const n = Math.floor(rest / size);\n if (n > 0 && parts.length < 2) {\n parts.push(`${n} ${word}${n === 1 ? '' : 's'}`);\n rest -= n * size;\n } else if (parts.length > 0) break;\n }\n return `about ${parts.join(' ')}`;\n}\n\nconst MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n\n/**\n * A moment in UTC, the same for every reader: \"20 Oct 2026, 09:14 UTC\".\n * Takes a Date, an ISO string, or unix seconds. `date: true` drops the time.\n */\nexport function formatUtc(at: Date | string | number, opts: { date?: boolean } = {}): string {\n const d = typeof at === 'number' ? new Date(at * 1000) : new Date(at);\n if (Number.isNaN(d.getTime())) return '—';\n const day = `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]} ${d.getUTCFullYear()}`;\n if (opts.date) return day;\n const hh = String(d.getUTCHours()).padStart(2, '0');\n const mm = String(d.getUTCMinutes()).padStart(2, '0');\n return `${day}, ${hh}:${mm} UTC`;\n}\n\n/** 482113 → \"471 KB\"; 1288490 → \"1.2 MB\". Binary steps, the way a file dialog counts. */\nexport function formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return '—';\n if (bytes < 1024) return `${bytes} B`;\n const units = ['KB', 'MB', 'GB', 'TB'];\n let v = bytes / 1024;\n let u = 0;\n while (v >= 1024 && u < units.length - 1) {\n v /= 1024;\n u++;\n }\n return `${v < 10 ? v.toFixed(1).replace(/\\.0$/, '') : Math.round(v)} ${units[u]}`;\n}\n"]}
@@ -0,0 +1,31 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ interface PageHeroProps {
5
+ eyebrow?: ReactNode;
6
+ title: ReactNode;
7
+ lead?: ReactNode;
8
+ actions?: ReactNode;
9
+ art?: ReactNode;
10
+ meta?: ReactNode;
11
+ children?: ReactNode;
12
+ variant?: 'page' | 'document';
13
+ size?: 'lg' | 'xl';
14
+ className?: string;
15
+ }
16
+ declare function PageHero({ eyebrow, title, lead, actions, art, meta, children, variant, size, className, }: PageHeroProps): react.JSX.Element;
17
+ declare function DocHeader({ eyebrow, title, lead, meta, actions, children, className, }: Pick<PageHeroProps, 'eyebrow' | 'title' | 'lead' | 'meta' | 'actions' | 'children' | 'className'>): react.JSX.Element;
18
+ interface TocItem {
19
+ id: string;
20
+ label: ReactNode;
21
+ level?: 2 | 3;
22
+ }
23
+ declare function useActiveHeading(ids: string[]): string | undefined;
24
+ declare function DocLayout({ toc, header, children, className, }: {
25
+ toc?: TocItem[];
26
+ header?: ReactNode;
27
+ children: ReactNode;
28
+ className?: string;
29
+ }): react.JSX.Element;
30
+
31
+ export { DocHeader as D, PageHero as P, type TocItem as T, DocLayout as a, type PageHeroProps as b, useActiveHeading as u };