agent-docs-kit 2.1.0__py3-none-any.whl

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 (40) hide show
  1. agent_docs_kit-2.1.0.dist-info/METADATA +299 -0
  2. agent_docs_kit-2.1.0.dist-info/RECORD +40 -0
  3. agent_docs_kit-2.1.0.dist-info/WHEEL +4 -0
  4. agent_docs_kit-2.1.0.dist-info/entry_points.txt +3 -0
  5. agent_docs_kit-2.1.0.dist-info/licenses/LICENSE +21 -0
  6. living_docs_cli/__init__.py +686 -0
  7. living_docs_cli/__main__.py +3 -0
  8. living_docs_cli/assets/fumadocs-starter/app/docs/[[...slug]]/page.tsx +44 -0
  9. living_docs_cli/assets/fumadocs-starter/app/docs/layout.tsx +12 -0
  10. living_docs_cli/assets/fumadocs-starter/app/global.css +450 -0
  11. living_docs_cli/assets/fumadocs-starter/app/layout.tsx +15 -0
  12. living_docs_cli/assets/fumadocs-starter/app/page.tsx +5 -0
  13. living_docs_cli/assets/fumadocs-starter/components/living-docs/index.tsx +185 -0
  14. living_docs_cli/assets/fumadocs-starter/components/mdx.tsx +27 -0
  15. living_docs_cli/assets/fumadocs-starter/content/docs/architecture.mdx +55 -0
  16. living_docs_cli/assets/fumadocs-starter/content/docs/components.mdx +132 -0
  17. living_docs_cli/assets/fumadocs-starter/content/docs/glossary.mdx +16 -0
  18. living_docs_cli/assets/fumadocs-starter/content/docs/index.mdx +72 -0
  19. living_docs_cli/assets/fumadocs-starter/content/docs/meta.json +4 -0
  20. living_docs_cli/assets/fumadocs-starter/lib/layout.shared.ts +7 -0
  21. living_docs_cli/assets/fumadocs-starter/lib/source.ts +7 -0
  22. living_docs_cli/assets/fumadocs-starter/next-env.d.ts +4 -0
  23. living_docs_cli/assets/fumadocs-starter/next.config.mjs +10 -0
  24. living_docs_cli/assets/fumadocs-starter/package.json +27 -0
  25. living_docs_cli/assets/fumadocs-starter/source.config.ts +34 -0
  26. living_docs_cli/assets/fumadocs-starter/tsconfig.json +23 -0
  27. living_docs_cli/assets/project/.living-docs/scripts/check.mjs +72 -0
  28. living_docs_cli/assets/project/.living-docs/scripts/create-doc.mjs +88 -0
  29. living_docs_cli/assets/project/.living-docs/scripts/glossary.mjs +107 -0
  30. living_docs_cli/assets/project/.living-docs/templates/architecture.mdx +51 -0
  31. living_docs_cli/assets/project/.living-docs/templates/change.mdx +40 -0
  32. living_docs_cli/assets/project/.living-docs/templates/glossary.mdx +15 -0
  33. living_docs_cli/assets/project/.living-docs/templates/plan.mdx +54 -0
  34. living_docs_cli/assets/styles/atlas.css +450 -0
  35. living_docs_cli/assets/workflow-skills/living-docs-architecture/SKILL.md +55 -0
  36. living_docs_cli/assets/workflow-skills/living-docs-change/SKILL.md +62 -0
  37. living_docs_cli/assets/workflow-skills/living-docs-check/SKILL.md +32 -0
  38. living_docs_cli/assets/workflow-skills/living-docs-glossary/SKILL.md +30 -0
  39. living_docs_cli/assets/workflow-skills/living-docs-plan/SKILL.md +55 -0
  40. living_docs_cli/assets/workflow-skills/living-docs-write/SKILL.md +46 -0
@@ -0,0 +1,44 @@
1
+ import { notFound } from 'next/navigation';
2
+ import type { Metadata } from 'next';
3
+ import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page';
4
+ import { getMDXComponents } from '@/components/mdx';
5
+ import { source } from '@/lib/source';
6
+
7
+ type PageProps = {
8
+ params: Promise<{
9
+ slug?: string[];
10
+ }>;
11
+ };
12
+
13
+ export default async function Page(props: PageProps) {
14
+ const params = await props.params;
15
+ const page = source.getPage(params.slug);
16
+ if (!page) notFound();
17
+
18
+ const MDX = page.data.body;
19
+
20
+ return (
21
+ <DocsPage toc={page.data.toc}>
22
+ <DocsTitle>{page.data.title}</DocsTitle>
23
+ <DocsDescription>{page.data.description}</DocsDescription>
24
+ <DocsBody>
25
+ <MDX components={getMDXComponents()} />
26
+ </DocsBody>
27
+ </DocsPage>
28
+ );
29
+ }
30
+
31
+ export async function generateStaticParams() {
32
+ return source.generateParams();
33
+ }
34
+
35
+ export async function generateMetadata(props: PageProps): Promise<Metadata> {
36
+ const params = await props.params;
37
+ const page = source.getPage(params.slug);
38
+ if (!page) notFound();
39
+
40
+ return {
41
+ title: page.data.title,
42
+ description: page.data.description,
43
+ };
44
+ }
@@ -0,0 +1,12 @@
1
+ import { DocsLayout } from 'fumadocs-ui/layouts/docs';
2
+ import type { ReactNode } from 'react';
3
+ import { baseOptions } from '@/lib/layout.shared';
4
+ import { source } from '@/lib/source';
5
+
6
+ export default function Layout({ children }: { children: ReactNode }) {
7
+ return (
8
+ <DocsLayout {...baseOptions} tree={source.getPageTree()}>
9
+ {children}
10
+ </DocsLayout>
11
+ );
12
+ }
@@ -0,0 +1,450 @@
1
+ :root {
2
+ --ld-bg: #f6f8fb;
3
+ --ld-ink: #101828;
4
+ --ld-muted: #667085;
5
+ --ld-panel: rgba(255, 255, 255, 0.9);
6
+ --ld-panel-soft: #f9fbff;
7
+ --ld-line: rgba(16, 24, 40, 0.12);
8
+ --ld-line-strong: rgba(16, 24, 40, 0.2);
9
+ --ld-accent: #2563eb;
10
+ --ld-accent-2: #0f766e;
11
+ --ld-accent-3: #b45309;
12
+ --ld-danger: #c2410c;
13
+ --ld-radius: 8px;
14
+ --ld-shadow: 0 18px 60px rgba(16, 24, 40, 0.1);
15
+ }
16
+
17
+ .dark {
18
+ --ld-bg: #101215;
19
+ --ld-ink: #edf2f7;
20
+ --ld-muted: #a7b0bd;
21
+ --ld-panel: rgba(22, 25, 31, 0.9);
22
+ --ld-panel-soft: #191d24;
23
+ --ld-line: rgba(237, 242, 247, 0.12);
24
+ --ld-line-strong: rgba(237, 242, 247, 0.2);
25
+ --ld-accent: #60a5fa;
26
+ --ld-accent-2: #2dd4bf;
27
+ --ld-accent-3: #f59e0b;
28
+ --ld-danger: #fb923c;
29
+ --ld-shadow: 0 18px 66px rgba(0, 0, 0, 0.34);
30
+ }
31
+
32
+ html,
33
+ body {
34
+ background: var(--ld-bg);
35
+ }
36
+
37
+ body {
38
+ color: var(--ld-ink);
39
+ background:
40
+ linear-gradient(120deg, color-mix(in oklab, var(--ld-accent) 10%, transparent), transparent 32%),
41
+ linear-gradient(300deg, color-mix(in oklab, var(--ld-accent-2) 9%, transparent), transparent 38%),
42
+ var(--ld-bg);
43
+ font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
44
+ -webkit-font-smoothing: antialiased;
45
+ }
46
+
47
+ header {
48
+ border-bottom: 1px solid var(--ld-line);
49
+ background: color-mix(in oklab, var(--ld-panel) 92%, transparent);
50
+ backdrop-filter: blur(18px);
51
+ }
52
+
53
+ #nd-sidebar {
54
+ border-inline-end: 1px solid var(--ld-line);
55
+ background: color-mix(in oklab, var(--ld-panel) 90%, transparent);
56
+ backdrop-filter: blur(18px);
57
+ }
58
+
59
+ article#nd-page {
60
+ border: 0;
61
+ border-radius: 0;
62
+ background: transparent;
63
+ box-sizing: border-box;
64
+ max-width: min(900px, 100vw) !important;
65
+ box-shadow: none;
66
+ }
67
+
68
+ article#nd-page > .prose {
69
+ max-width: 100% !important;
70
+ }
71
+
72
+ #nd-page p,
73
+ #nd-page li {
74
+ overflow-wrap: anywhere;
75
+ }
76
+
77
+ #nd-page h1,
78
+ #nd-page h2,
79
+ #nd-page h3 {
80
+ color: var(--ld-ink);
81
+ letter-spacing: 0;
82
+ overflow-wrap: anywhere;
83
+ }
84
+
85
+ #nd-page h2 {
86
+ padding-top: 14px;
87
+ border-top: 1px solid var(--ld-line);
88
+ }
89
+
90
+ #nd-page :where(code):not(pre code) {
91
+ border: 1px solid var(--ld-line);
92
+ border-radius: 6px;
93
+ background: color-mix(in oklab, var(--ld-panel-soft) 84%, var(--ld-accent) 7%);
94
+ padding: 0.12rem 0.34rem;
95
+ color: var(--ld-accent);
96
+ }
97
+
98
+ .ld-docs-hero {
99
+ position: relative;
100
+ display: grid;
101
+ gap: 18px;
102
+ margin: 0 0 32px;
103
+ overflow: hidden;
104
+ border: 1px solid var(--ld-line-strong);
105
+ border-radius: 8px;
106
+ background:
107
+ linear-gradient(135deg, color-mix(in oklab, var(--ld-accent) 16%, transparent), transparent 42%),
108
+ linear-gradient(315deg, color-mix(in oklab, var(--ld-accent-3) 12%, transparent), transparent 42%),
109
+ var(--ld-panel);
110
+ padding: clamp(22px, 4vw, 42px);
111
+ box-shadow: var(--ld-shadow);
112
+ }
113
+
114
+ .ld-docs-hero::after {
115
+ position: absolute;
116
+ inset: auto 0 0;
117
+ height: 70px;
118
+ content: '';
119
+ background:
120
+ linear-gradient(90deg, var(--ld-line) 1px, transparent 1px),
121
+ linear-gradient(0deg, var(--ld-line) 1px, transparent 1px);
122
+ background-size: 24px 24px;
123
+ mask-image: linear-gradient(to top, black, transparent);
124
+ }
125
+
126
+ .ld-hero-kicker {
127
+ width: fit-content;
128
+ border: 1px solid var(--ld-line-strong);
129
+ border-radius: 999px;
130
+ background: var(--ld-panel-soft);
131
+ padding: 5px 10px;
132
+ color: var(--ld-muted);
133
+ font-size: 0.78rem;
134
+ font-weight: 700;
135
+ letter-spacing: 0;
136
+ text-transform: uppercase;
137
+ }
138
+
139
+ .ld-docs-hero h1 {
140
+ max-width: 780px;
141
+ margin: 0;
142
+ color: var(--ld-ink);
143
+ font-size: clamp(2.2rem, 5vw, 4rem);
144
+ line-height: 0.98;
145
+ overflow-wrap: anywhere;
146
+ }
147
+
148
+ .ld-docs-hero p {
149
+ max-width: 700px;
150
+ margin: 0;
151
+ color: var(--ld-muted);
152
+ font-size: clamp(1rem, 1.7vw, 1.13rem);
153
+ }
154
+
155
+ .ld-hero-actions,
156
+ .ld-change-meta {
157
+ display: flex;
158
+ flex-wrap: wrap;
159
+ gap: 10px;
160
+ }
161
+
162
+ .ld-hero-action,
163
+ .ld-chip {
164
+ display: inline-flex;
165
+ min-height: 38px;
166
+ align-items: center;
167
+ border: 1px solid var(--ld-line-strong);
168
+ border-radius: var(--ld-radius);
169
+ padding: 8px 12px;
170
+ background: var(--ld-panel);
171
+ color: var(--ld-ink);
172
+ font-size: 0.92rem;
173
+ font-weight: 650;
174
+ text-decoration: none;
175
+ }
176
+
177
+ .ld-hero-action[data-primary='true'] {
178
+ border-color: var(--ld-accent);
179
+ background: var(--ld-accent);
180
+ color: #fff;
181
+ }
182
+
183
+ .ld-skill-grid,
184
+ .ld-term-grid {
185
+ display: grid;
186
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
187
+ gap: 12px;
188
+ margin: 22px 0;
189
+ padding: 0;
190
+ }
191
+
192
+ .ld-skill-card,
193
+ .ld-term,
194
+ .ld-box {
195
+ position: relative;
196
+ list-style: none;
197
+ border: 1px solid var(--ld-line);
198
+ border-radius: var(--ld-radius);
199
+ background: var(--ld-panel);
200
+ box-shadow: 0 8px 28px rgba(16, 24, 40, 0.06);
201
+ }
202
+
203
+ .ld-skill-card,
204
+ .ld-term,
205
+ .ld-box {
206
+ padding: 15px;
207
+ }
208
+
209
+ .ld-skill-card {
210
+ min-height: 134px;
211
+ }
212
+
213
+ .ld-skill-card::before,
214
+ .ld-box::before {
215
+ display: block;
216
+ width: 32px;
217
+ height: 3px;
218
+ margin-bottom: 14px;
219
+ border-radius: 999px;
220
+ background: var(--ld-accent);
221
+ content: '';
222
+ }
223
+
224
+ .ld-skill-card code {
225
+ color: var(--ld-accent);
226
+ font-weight: 700;
227
+ white-space: normal;
228
+ overflow-wrap: anywhere;
229
+ }
230
+
231
+ .ld-skill-card span,
232
+ .ld-box span,
233
+ .ld-term span,
234
+ .ld-meta {
235
+ display: block;
236
+ margin-top: 8px;
237
+ color: var(--ld-muted);
238
+ font-size: 0.92rem;
239
+ line-height: 1.55;
240
+ }
241
+
242
+ .ld-box strong,
243
+ .ld-term strong {
244
+ display: block;
245
+ color: var(--ld-ink);
246
+ }
247
+
248
+ .ld-arch-map {
249
+ display: grid;
250
+ gap: 12px;
251
+ margin: 24px 0;
252
+ }
253
+
254
+ .ld-tier {
255
+ border: 1px solid var(--ld-line);
256
+ border-radius: 8px;
257
+ background: var(--ld-panel);
258
+ padding: 14px;
259
+ }
260
+
261
+ .ld-tier-title {
262
+ margin-bottom: 10px;
263
+ color: var(--ld-ink);
264
+ font-weight: 700;
265
+ }
266
+
267
+ .ld-boxes {
268
+ display: grid;
269
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
270
+ gap: 10px;
271
+ }
272
+
273
+ .ld-flow,
274
+ .ld-state-flow {
275
+ margin: 24px 0;
276
+ border: 1px solid var(--ld-line);
277
+ border-radius: 8px;
278
+ background: var(--ld-panel);
279
+ padding: 14px;
280
+ box-shadow: 0 8px 28px rgba(16, 24, 40, 0.06);
281
+ }
282
+
283
+ .ld-flow-title {
284
+ margin-bottom: 12px;
285
+ color: var(--ld-ink);
286
+ font-weight: 700;
287
+ }
288
+
289
+ .ld-flow-steps {
290
+ display: grid;
291
+ gap: 10px;
292
+ margin: 0;
293
+ padding: 0;
294
+ }
295
+
296
+ .ld-flow-step {
297
+ display: grid;
298
+ grid-template-columns: 42px minmax(0, 1fr);
299
+ gap: 12px;
300
+ align-items: start;
301
+ list-style: none;
302
+ border: 1px solid var(--ld-line);
303
+ border-radius: var(--ld-radius);
304
+ background: color-mix(in oklab, var(--ld-panel-soft) 84%, var(--ld-accent) 4%);
305
+ padding: 12px;
306
+ }
307
+
308
+ .ld-step-index {
309
+ display: inline-flex;
310
+ width: 32px;
311
+ height: 32px;
312
+ align-items: center;
313
+ justify-content: center;
314
+ border-radius: 999px;
315
+ background: var(--ld-accent);
316
+ color: #fff;
317
+ font-size: 0.78rem;
318
+ font-weight: 800;
319
+ }
320
+
321
+ .ld-flow-step strong,
322
+ .ld-state-node strong {
323
+ display: block;
324
+ color: var(--ld-ink);
325
+ }
326
+
327
+ .ld-flow-step span:not(.ld-step-index),
328
+ .ld-state-node span {
329
+ display: block;
330
+ margin-top: 6px;
331
+ color: var(--ld-muted);
332
+ font-size: 0.92rem;
333
+ line-height: 1.55;
334
+ }
335
+
336
+ .ld-state-row {
337
+ display: flex;
338
+ flex-wrap: wrap;
339
+ gap: 10px;
340
+ align-items: stretch;
341
+ }
342
+
343
+ .ld-state-group {
344
+ display: contents;
345
+ }
346
+
347
+ .ld-state-node {
348
+ min-width: min(180px, 100%);
349
+ flex: 1 1 180px;
350
+ border: 1px solid var(--ld-line);
351
+ border-radius: var(--ld-radius);
352
+ background: color-mix(in oklab, var(--ld-panel-soft) 84%, var(--ld-accent) 4%);
353
+ padding: 13px;
354
+ }
355
+
356
+ .ld-state-arrow {
357
+ display: inline-flex;
358
+ min-width: 22px;
359
+ align-items: center;
360
+ justify-content: center;
361
+ color: var(--ld-muted);
362
+ font-weight: 800;
363
+ }
364
+
365
+ .ld-flow-step[data-tone='green'] .ld-step-index,
366
+ .ld-state-node[data-tone='green'] {
367
+ border-color: color-mix(in oklab, var(--ld-accent-2) 36%, var(--ld-line));
368
+ }
369
+
370
+ .ld-flow-step[data-tone='green'] .ld-step-index {
371
+ background: var(--ld-accent-2);
372
+ }
373
+
374
+ .ld-flow-step[data-tone='amber'] .ld-step-index,
375
+ .ld-state-node[data-tone='amber'] {
376
+ border-color: color-mix(in oklab, var(--ld-accent-3) 36%, var(--ld-line));
377
+ }
378
+
379
+ .ld-flow-step[data-tone='amber'] .ld-step-index {
380
+ background: var(--ld-accent-3);
381
+ }
382
+
383
+ .ld-flow-step[data-tone='red'] .ld-step-index,
384
+ .ld-state-node[data-tone='red'] {
385
+ border-color: color-mix(in oklab, var(--ld-danger) 36%, var(--ld-line));
386
+ }
387
+
388
+ .ld-flow-step[data-tone='red'] .ld-step-index {
389
+ background: var(--ld-danger);
390
+ }
391
+
392
+ .ld-skill-card[data-tone='green']::before,
393
+ .ld-box[data-tone='green']::before {
394
+ background: var(--ld-accent-2);
395
+ }
396
+
397
+ .ld-skill-card[data-tone='amber']::before,
398
+ .ld-box[data-tone='amber']::before {
399
+ background: var(--ld-accent-3);
400
+ }
401
+
402
+ .ld-skill-card[data-tone='red']::before,
403
+ .ld-box[data-tone='red']::before {
404
+ background: var(--ld-danger);
405
+ }
406
+
407
+ @media (max-width: 640px) {
408
+ article#nd-page {
409
+ box-sizing: border-box;
410
+ width: 100vw !important;
411
+ max-width: 100vw !important;
412
+ margin-inline: 0 !important;
413
+ }
414
+
415
+ article#nd-page > .prose,
416
+ .ld-docs-hero,
417
+ .ld-skill-card,
418
+ .ld-term,
419
+ .ld-box,
420
+ .ld-tier,
421
+ .ld-flow,
422
+ .ld-state-flow,
423
+ .ld-flow-step,
424
+ .ld-state-node {
425
+ max-width: 100% !important;
426
+ }
427
+
428
+ .ld-flow-step {
429
+ grid-template-columns: 34px minmax(0, 1fr);
430
+ }
431
+
432
+ .ld-step-index {
433
+ width: 28px;
434
+ height: 28px;
435
+ }
436
+
437
+ .ld-state-row {
438
+ display: grid;
439
+ }
440
+
441
+ .ld-state-arrow {
442
+ min-height: 18px;
443
+ transform: rotate(90deg);
444
+ }
445
+
446
+ #nd-page p,
447
+ #nd-page li {
448
+ overflow-wrap: anywhere;
449
+ }
450
+ }
@@ -0,0 +1,15 @@
1
+ import 'fumadocs-ui/style.css';
2
+ import './global.css';
3
+
4
+ import { RootProvider } from 'fumadocs-ui/provider/next';
5
+ import type { ReactNode } from 'react';
6
+
7
+ export default function RootLayout({ children }: { children: ReactNode }) {
8
+ return (
9
+ <html lang="en" suppressHydrationWarning>
10
+ <body className="flex min-h-screen flex-col">
11
+ <RootProvider>{children}</RootProvider>
12
+ </body>
13
+ </html>
14
+ );
15
+ }
@@ -0,0 +1,5 @@
1
+ import { redirect } from 'next/navigation';
2
+
3
+ export default function Home() {
4
+ redirect('/docs');
5
+ }
@@ -0,0 +1,185 @@
1
+ export type ArchTone = 'blue' | 'green' | 'violet' | 'amber' | 'red';
2
+
3
+ export type ArchBox = {
4
+ title: string;
5
+ body: string;
6
+ tone?: ArchTone;
7
+ };
8
+
9
+ export type ArchTier = {
10
+ title: string;
11
+ boxes: ArchBox[];
12
+ };
13
+
14
+ export function DocsHero({
15
+ title,
16
+ eyebrow = 'Living documentation',
17
+ description,
18
+ primaryHref = '/docs/architecture',
19
+ primaryLabel = 'Open architecture',
20
+ secondaryHref = '/docs/glossary',
21
+ secondaryLabel = 'View glossary',
22
+ }: {
23
+ title: string;
24
+ eyebrow?: string;
25
+ description: string;
26
+ primaryHref?: string;
27
+ primaryLabel?: string;
28
+ secondaryHref?: string;
29
+ secondaryLabel?: string;
30
+ }) {
31
+ return (
32
+ <section className="ld-docs-hero">
33
+ <div className="ld-hero-kicker">{eyebrow}</div>
34
+ <h1>{title}</h1>
35
+ <p>{description}</p>
36
+ <div className="ld-hero-actions">
37
+ <a className="ld-hero-action" data-primary="true" href={primaryHref}>
38
+ {primaryLabel}
39
+ </a>
40
+ <a className="ld-hero-action" href={secondaryHref}>
41
+ {secondaryLabel}
42
+ </a>
43
+ </div>
44
+ </section>
45
+ );
46
+ }
47
+
48
+ export type SkillItem = {
49
+ name: string;
50
+ body: string;
51
+ tone?: ArchTone;
52
+ };
53
+
54
+ export type FlowStep = {
55
+ title: string;
56
+ body: string;
57
+ tone?: ArchTone;
58
+ };
59
+
60
+ export type StateNode = {
61
+ name: string;
62
+ description?: string;
63
+ tone?: ArchTone;
64
+ };
65
+
66
+ export function SkillGrid({ items }: { items: SkillItem[] }) {
67
+ return (
68
+ <ul className="ld-skill-grid">
69
+ {items.map((item) => (
70
+ <li className="ld-skill-card" data-tone={item.tone} key={item.name}>
71
+ <code>{item.name}</code>
72
+ <span>{item.body}</span>
73
+ </li>
74
+ ))}
75
+ </ul>
76
+ );
77
+ }
78
+
79
+ export function ArchMap({ tiers }: { tiers: ArchTier[] }) {
80
+ return (
81
+ <div className="ld-arch-map">
82
+ {tiers.map((tier) => (
83
+ <section className="ld-tier" key={tier.title}>
84
+ <div className="ld-tier-title">{tier.title}</div>
85
+ <div className="ld-boxes">
86
+ {tier.boxes.map((box) => (
87
+ <div className="ld-box" data-tone={box.tone} key={`${tier.title}-${box.title}`}>
88
+ <strong>{box.title}</strong>
89
+ <span>{box.body}</span>
90
+ </div>
91
+ ))}
92
+ </div>
93
+ </section>
94
+ ))}
95
+ </div>
96
+ );
97
+ }
98
+
99
+ export function FlowSteps({
100
+ title,
101
+ steps,
102
+ }: {
103
+ title?: string;
104
+ steps: FlowStep[];
105
+ }) {
106
+ return (
107
+ <section className="ld-flow">
108
+ {title ? <div className="ld-flow-title">{title}</div> : null}
109
+ <ol className="ld-flow-steps">
110
+ {steps.map((step, index) => (
111
+ <li className="ld-flow-step" data-tone={step.tone} key={`${index}-${step.title}`}>
112
+ <span className="ld-step-index">{String(index + 1).padStart(2, '0')}</span>
113
+ <div>
114
+ <strong>{step.title}</strong>
115
+ <span>{step.body}</span>
116
+ </div>
117
+ </li>
118
+ ))}
119
+ </ol>
120
+ </section>
121
+ );
122
+ }
123
+
124
+ export function StateFlow({
125
+ title,
126
+ states,
127
+ }: {
128
+ title?: string;
129
+ states: StateNode[];
130
+ }) {
131
+ return (
132
+ <section className="ld-state-flow">
133
+ {title ? <div className="ld-flow-title">{title}</div> : null}
134
+ <div className="ld-state-row">
135
+ {states.map((state, index) => (
136
+ <div className="ld-state-group" key={`${index}-${state.name}`}>
137
+ <div className="ld-state-node" data-tone={state.tone}>
138
+ <strong>{state.name}</strong>
139
+ {state.description ? <span>{state.description}</span> : null}
140
+ </div>
141
+ {index < states.length - 1 ? <span className="ld-state-arrow">{'->'}</span> : null}
142
+ </div>
143
+ ))}
144
+ </div>
145
+ </section>
146
+ );
147
+ }
148
+
149
+ export type TermItem = {
150
+ name: string;
151
+ description: string;
152
+ meta?: string;
153
+ };
154
+
155
+ export function TermGrid({ items }: { items: TermItem[] }) {
156
+ return (
157
+ <ul className="ld-term-grid">
158
+ {items.map((item) => (
159
+ <li className="ld-term" key={item.name}>
160
+ <strong>{item.name}</strong>
161
+ <span>{item.description}</span>
162
+ {item.meta ? <div className="ld-meta">{item.meta}</div> : null}
163
+ </li>
164
+ ))}
165
+ </ul>
166
+ );
167
+ }
168
+
169
+ export function ChangeMeta({
170
+ date,
171
+ source,
172
+ tests,
173
+ }: {
174
+ date?: string;
175
+ source?: string;
176
+ tests?: string;
177
+ }) {
178
+ return (
179
+ <div className="ld-change-meta">
180
+ {date ? <span className="ld-chip">Date: {date}</span> : null}
181
+ {source ? <span className="ld-chip">Source: {source}</span> : null}
182
+ {tests ? <span className="ld-chip">Tests: {tests}</span> : null}
183
+ </div>
184
+ );
185
+ }