@designtools/docs 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/LICENSE +21 -0
- package/README.md +155 -2
- package/dist/a11y-panel.d.ts +58 -0
- package/dist/a11y-panel.js +75 -0
- package/dist/adherence-summary.d.ts +9 -0
- package/dist/adherence-summary.js +27 -0
- package/dist/agent-view.d.ts +19 -0
- package/dist/agent-view.js +23 -0
- package/dist/anatomy.d.ts +12 -0
- package/dist/anatomy.js +39 -0
- package/dist/ask-claude.d.ts +14 -0
- package/dist/ask-claude.js +40 -0
- package/dist/cli.js +322 -0
- package/dist/code-view.d.ts +17 -0
- package/dist/code-view.js +42 -0
- package/dist/examples.d.ts +25 -0
- package/dist/examples.js +48 -0
- package/dist/glossary.d.ts +5 -0
- package/dist/glossary.js +21 -0
- package/dist/imagery.d.ts +6 -0
- package/dist/imagery.js +17 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +34 -0
- package/dist/lib/adherence-types.d.ts +168 -0
- package/dist/lib/adherence-types.js +13 -0
- package/dist/lib/boundary.d.ts +16 -0
- package/dist/lib/boundary.js +15 -0
- package/dist/lib/contrast.d.ts +8 -0
- package/dist/lib/contrast.js +42 -0
- package/dist/lib/cx.d.ts +24 -0
- package/dist/lib/cx.js +26 -0
- package/dist/lib/jsx.d.ts +6 -0
- package/dist/lib/jsx.js +29 -0
- package/dist/lib/live.d.ts +10 -0
- package/dist/lib/live.js +10 -0
- package/dist/lib/lookup.d.ts +35 -0
- package/dist/lib/lookup.js +42 -0
- package/dist/lib/manifest-types.d.ts +253 -0
- package/dist/lib/manifest-types.js +14 -0
- package/dist/lib/manifest.d.ts +98 -0
- package/dist/lib/manifest.js +173 -0
- package/dist/lib/markdown.d.ts +50 -0
- package/dist/lib/markdown.js +286 -0
- package/dist/lib/measure.d.ts +12 -0
- package/dist/lib/measure.js +62 -0
- package/dist/lib/pseudo.d.ts +11 -0
- package/dist/lib/pseudo.js +71 -0
- package/dist/lib/registry.d.ts +21 -0
- package/dist/lib/registry.js +11 -0
- package/dist/lib/search.d.ts +44 -0
- package/dist/lib/search.js +62 -0
- package/dist/lib/standards.d.ts +17 -0
- package/dist/lib/standards.js +81 -0
- package/dist/lib/status.d.ts +6 -0
- package/dist/lib/status.js +17 -0
- package/dist/lib/terms.d.ts +15 -0
- package/dist/lib/terms.js +20 -0
- package/dist/lib/text.d.ts +8 -0
- package/dist/lib/text.js +9 -0
- package/dist/lib/ui.d.ts +100 -0
- package/dist/lib/ui.js +89 -0
- package/dist/lib/vision.d.ts +18 -0
- package/dist/lib/vision.js +27 -0
- package/dist/logo-usage.d.ts +14 -0
- package/dist/logo-usage.js +45 -0
- package/dist/next/config.d.ts +105 -0
- package/dist/next/config.js +1 -0
- package/dist/next/index.d.ts +65 -0
- package/dist/next/index.js +66 -0
- package/dist/next/markdown.d.ts +20 -0
- package/dist/next/markdown.js +95 -0
- package/dist/next/pages.d.ts +6 -0
- package/dist/next/pages.js +188 -0
- package/dist/next/prose.d.ts +9 -0
- package/dist/next/prose.js +39 -0
- package/dist/next/proxy.d.ts +19 -0
- package/dist/next/proxy.js +56 -0
- package/dist/next/site.d.ts +53 -0
- package/dist/next/site.js +136 -0
- package/dist/page-actions.d.ts +9 -0
- package/dist/page-actions.js +32 -0
- package/dist/pattern.d.ts +11 -0
- package/dist/pattern.js +22 -0
- package/dist/playground.d.ts +62 -0
- package/dist/playground.js +111 -0
- package/dist/preview-frame.d.ts +31 -0
- package/dist/preview-frame.js +63 -0
- package/dist/props-table.d.ts +10 -0
- package/dist/props-table.js +45 -0
- package/dist/rule.d.ts +16 -0
- package/dist/rule.js +37 -0
- package/dist/scale.d.ts +9 -0
- package/dist/scale.js +58 -0
- package/dist/search.d.ts +16 -0
- package/dist/search.js +46 -0
- package/dist/shell.d.ts +92 -0
- package/dist/shell.js +201 -0
- package/dist/standards.d.ts +13 -0
- package/dist/standards.js +19 -0
- package/dist/styles.css +3708 -0
- package/dist/swatches.d.ts +28 -0
- package/dist/swatches.js +100 -0
- package/dist/theme-switch.d.ts +20 -0
- package/dist/theme-switch.js +68 -0
- package/dist/type-ramp.d.ts +10 -0
- package/dist/type-ramp.js +31 -0
- package/dist/usage.d.ts +13 -0
- package/dist/usage.js +55 -0
- package/dist/variant-matrix.d.ts +15 -0
- package/dist/variant-matrix.js +58 -0
- package/dist/voice-terms.d.ts +5 -0
- package/dist/voice-terms.js +14 -0
- package/dist/workbench.d.ts +33 -0
- package/dist/workbench.js +274 -0
- package/package.json +107 -3
- package/src/a11y-panel.tsx +297 -0
- package/src/adherence-summary.tsx +134 -0
- package/src/agent-view.tsx +54 -0
- package/src/anatomy.tsx +119 -0
- package/src/ask-claude.tsx +90 -0
- package/src/code-view.tsx +112 -0
- package/src/css.d.ts +1 -0
- package/src/examples.tsx +141 -0
- package/src/glossary.tsx +70 -0
- package/src/imagery.tsx +64 -0
- package/src/index.ts +35 -0
- package/src/lib/adherence-types.ts +181 -0
- package/src/lib/boundary.tsx +21 -0
- package/src/lib/contrast.ts +44 -0
- package/src/lib/cx.ts +30 -0
- package/src/lib/jsx.ts +29 -0
- package/src/lib/live.tsx +15 -0
- package/src/lib/lookup.tsx +50 -0
- package/src/lib/manifest-types.ts +284 -0
- package/src/lib/manifest.ts +228 -0
- package/src/lib/markdown.ts +288 -0
- package/src/lib/measure.tsx +101 -0
- package/src/lib/pseudo.ts +74 -0
- package/src/lib/registry.tsx +29 -0
- package/src/lib/search.ts +99 -0
- package/src/lib/standards.ts +82 -0
- package/src/lib/status.tsx +32 -0
- package/src/lib/terms.tsx +53 -0
- package/src/lib/text.tsx +27 -0
- package/src/lib/ui.tsx +291 -0
- package/src/lib/vision.tsx +44 -0
- package/src/logo-usage.tsx +140 -0
- package/src/next/config.ts +101 -0
- package/src/next/index.tsx +103 -0
- package/src/next/markdown.ts +119 -0
- package/src/next/pages.tsx +483 -0
- package/src/next/prose.tsx +97 -0
- package/src/next/proxy.ts +55 -0
- package/src/next/site.ts +173 -0
- package/src/page-actions.tsx +92 -0
- package/src/pattern.tsx +72 -0
- package/src/playground.tsx +357 -0
- package/src/preview-frame.tsx +131 -0
- package/src/props-table.tsx +154 -0
- package/src/rule.tsx +165 -0
- package/src/scale.tsx +175 -0
- package/src/search.tsx +155 -0
- package/src/shell.tsx +569 -0
- package/src/standards.tsx +58 -0
- package/src/styles.css +157 -0
- package/src/swatches.tsx +298 -0
- package/src/theme-switch.tsx +90 -0
- package/src/type-ramp.tsx +150 -0
- package/src/usage.tsx +148 -0
- package/src/variant-matrix.tsx +178 -0
- package/src/voice-terms.tsx +37 -0
- package/src/workbench.tsx +587 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import "../styles.css";
|
|
2
|
+
import type { Metadata } from "next";
|
|
3
|
+
import { notFound } from "next/navigation";
|
|
4
|
+
import type { ReactNode } from "react";
|
|
5
|
+
import { findBySlug, slugOf } from "../lib/manifest";
|
|
6
|
+
import { PreviewExample, PreviewSurface } from "../preview-frame";
|
|
7
|
+
import { DocsShell } from "../shell";
|
|
8
|
+
import type { DocsConfig } from "./config";
|
|
9
|
+
import { manifestFiles, manifestRoute, markdownRoute } from "./markdown";
|
|
10
|
+
import { DocsPageView } from "./pages";
|
|
11
|
+
import { allSlugs, metaOf, navOf, resolve, siteOf } from "./site";
|
|
12
|
+
|
|
13
|
+
export { Live } from "../lib/live";
|
|
14
|
+
export { DocsSection } from "../shell";
|
|
15
|
+
export type { BuiltInPage, DocsConfig, EditorialPage, WorkbenchSetup } from "./config";
|
|
16
|
+
export { Markdown as Prose } from "./prose";
|
|
17
|
+
export { markdownFor } from "./markdown";
|
|
18
|
+
export { docsMatcher, docsProxy, prefersMarkdown } from "./proxy";
|
|
19
|
+
|
|
20
|
+
type SlugParams = { params: Promise<{ slug?: string[] }> };
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A whole docs site from one config, for the Next App Router. Each export is
|
|
24
|
+
* what one route file re-exports, so a project's docs are a handful of
|
|
25
|
+
* one-line files:
|
|
26
|
+
*
|
|
27
|
+
* - `(docs)/layout.tsx`: `export default docs.Layout`
|
|
28
|
+
* - `(docs)/[[...slug]]/page.tsx`: `export default docs.Page`, with `generateStaticParams` and `generateMetadata`
|
|
29
|
+
* - `md/[[...path]]/route.ts`: `export const GET = docs.markdown`
|
|
30
|
+
* - `manifest/[file]/route.ts`: `export const GET = docs.manifest`, with `generateStaticParams = docs.manifestParams`
|
|
31
|
+
* - `preview/[slug]/[example]/page.tsx`: `export default docs.Preview`
|
|
32
|
+
*
|
|
33
|
+
* The same files serve the docs inside a product's app or as a standalone app.
|
|
34
|
+
*/
|
|
35
|
+
export function createDocs(config: DocsConfig) {
|
|
36
|
+
const site = siteOf(config);
|
|
37
|
+
const nav = navOf(site);
|
|
38
|
+
const Registry = config.registry;
|
|
39
|
+
|
|
40
|
+
function Layout({ children }: { children: ReactNode }) {
|
|
41
|
+
return (
|
|
42
|
+
<Registry>
|
|
43
|
+
<DocsShell
|
|
44
|
+
manifest={site.components}
|
|
45
|
+
rules={site.rules}
|
|
46
|
+
patterns={site.patterns}
|
|
47
|
+
terms={site.taxonomy}
|
|
48
|
+
title={site.title}
|
|
49
|
+
logo={config.logo}
|
|
50
|
+
basePath={site.base}
|
|
51
|
+
brand={nav.brand}
|
|
52
|
+
foundations={nav.foundations}
|
|
53
|
+
standards={nav.standards}
|
|
54
|
+
hero={config.hero}
|
|
55
|
+
>
|
|
56
|
+
{children}
|
|
57
|
+
</DocsShell>
|
|
58
|
+
</Registry>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function Page({ params }: SlugParams) {
|
|
63
|
+
const page = resolve(site, (await params).slug);
|
|
64
|
+
if (!page) notFound();
|
|
65
|
+
return <DocsPageView site={site} page={page} />;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function generateMetadata({ params }: SlugParams): Promise<Metadata> {
|
|
69
|
+
const page = resolve(site, (await params).slug);
|
|
70
|
+
return page ? metaOf(site, page) : {};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** One example on its own, outside the shell: what the preview frame shows, and the target for visual regression. */
|
|
74
|
+
async function Preview({ params, searchParams }: { params: Promise<{ slug: string; example: string }>; searchParams: Promise<{ theme?: string }> }) {
|
|
75
|
+
const { slug, example } = await params;
|
|
76
|
+
const { theme } = await searchParams;
|
|
77
|
+
const entry = findBySlug(site.components, slug);
|
|
78
|
+
if (!entry?.examples) notFound();
|
|
79
|
+
return (
|
|
80
|
+
<Registry>
|
|
81
|
+
<PreviewSurface theme={theme}>
|
|
82
|
+
<PreviewExample entry={entry} example={decodeURIComponent(example)} />
|
|
83
|
+
</PreviewSurface>
|
|
84
|
+
</Registry>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
site,
|
|
90
|
+
Layout,
|
|
91
|
+
Page,
|
|
92
|
+
generateMetadata,
|
|
93
|
+
generateStaticParams: () => allSlugs(site).map((slug) => ({ slug })),
|
|
94
|
+
Preview,
|
|
95
|
+
previewParams: () =>
|
|
96
|
+
site.components.components.flatMap((c) =>
|
|
97
|
+
c.examples ? [c.examples.canonical, ...c.examples.do, ...c.examples.dont, ...c.examples.other].filter(Boolean).map((e) => ({ slug: slugOf(c), example: e!.name })) : [],
|
|
98
|
+
),
|
|
99
|
+
markdown: markdownRoute(site),
|
|
100
|
+
manifest: manifestRoute(site),
|
|
101
|
+
manifestParams: () => Object.keys(manifestFiles(site)).map((name) => ({ file: `${name}.json` })),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { groupByCategory, slugOf } from "../lib/manifest";
|
|
2
|
+
import {
|
|
3
|
+
adherenceMarkdown,
|
|
4
|
+
assetsMarkdown,
|
|
5
|
+
coloursMarkdown,
|
|
6
|
+
componentMarkdown,
|
|
7
|
+
editorialHeader,
|
|
8
|
+
generatedHeader,
|
|
9
|
+
glossaryMarkdown,
|
|
10
|
+
manifestLinks,
|
|
11
|
+
patternMarkdown,
|
|
12
|
+
ruleMarkdown,
|
|
13
|
+
scaleMarkdown,
|
|
14
|
+
standardsMarkdown,
|
|
15
|
+
systemMarkdown,
|
|
16
|
+
typeMarkdown,
|
|
17
|
+
} from "../lib/markdown";
|
|
18
|
+
import { navOf, resolve, type Site } from "./site";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The markdown form of a docs page, generated from the manifest rather than
|
|
22
|
+
* converted from HTML, or nothing when there is no such page. `context` is the
|
|
23
|
+
* whole system in one file.
|
|
24
|
+
*/
|
|
25
|
+
export function markdownFor(site: Site, path: string): string | undefined {
|
|
26
|
+
const { base, title, components, tokens, rules, patterns, taxonomy, assets, config } = site;
|
|
27
|
+
const generated = (md: string) => generatedHeader(config.provenance ?? "") + md;
|
|
28
|
+
if (path === "context")
|
|
29
|
+
return systemMarkdown({ components, tokens, rules: rules.rules, patterns: patterns.patterns, terms: taxonomy.terms }, title, config.provenance ?? "");
|
|
30
|
+
|
|
31
|
+
const page = resolve(site, path ? path.split("/") : []);
|
|
32
|
+
if (!page) return undefined;
|
|
33
|
+
switch (page.kind) {
|
|
34
|
+
case "overview": {
|
|
35
|
+
const nav = navOf(site);
|
|
36
|
+
const links = (list: { label: string; href: string }[]) => list.map((l) => `[${l.label}](${l.href}.md)`).join(", ");
|
|
37
|
+
return generated(
|
|
38
|
+
[
|
|
39
|
+
`# ${title}`,
|
|
40
|
+
"",
|
|
41
|
+
"The brand and the design system in one place. Every page here has a markdown form: add `.md` to its URL.",
|
|
42
|
+
"",
|
|
43
|
+
"## Pages",
|
|
44
|
+
"",
|
|
45
|
+
...(nav.brand.length ? [`- Brand: ${links(nav.brand)}`] : []),
|
|
46
|
+
`- Foundations: ${links(nav.foundations)}`,
|
|
47
|
+
...(rules.rules.length ? [`- [Rules](${base}/rules.md)`] : []),
|
|
48
|
+
...patterns.patterns.map((p) => `- Pattern: [${p.name}](${base}/patterns/${p.id}.md)`),
|
|
49
|
+
...groupByCategory(components).flatMap((g) =>
|
|
50
|
+
g.components.map((c) => `- ${g.category}: [${c.name}](${base}/components/${slugOf(c)}.md), ${c.status ?? "status not set"}`),
|
|
51
|
+
),
|
|
52
|
+
...(nav.standards.length ? [`- Standards: ${links(nav.standards)}`] : []),
|
|
53
|
+
`- Everything in [one file](${base}/context.md)`,
|
|
54
|
+
"",
|
|
55
|
+
manifestLinks(`${base}/manifest`),
|
|
56
|
+
].join("\n"),
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
case "editorial":
|
|
60
|
+
return `${editorialHeader(page.page.by)}# ${page.page.title}\n\n${page.page.lead ? `${page.page.lead}\n\n` : ""}${typeof page.page.body === "string" ? page.page.body : page.page.markdown}\n`;
|
|
61
|
+
case "logo":
|
|
62
|
+
return generated(
|
|
63
|
+
assetsMarkdown(assets.assets.filter((a) => a.kind === "logo")) +
|
|
64
|
+
"\n" +
|
|
65
|
+
rules.rules
|
|
66
|
+
.filter((r) => r.kind === "brand")
|
|
67
|
+
.map(ruleMarkdown)
|
|
68
|
+
.join("\n"),
|
|
69
|
+
);
|
|
70
|
+
case "imagery":
|
|
71
|
+
return generated(assetsMarkdown(assets.assets.filter((a) => a.kind !== "logo")));
|
|
72
|
+
case "voice":
|
|
73
|
+
return generated(glossaryMarkdown(taxonomy.terms.filter((t) => t.kind === "product" || t.wrong?.length)));
|
|
74
|
+
case "colour":
|
|
75
|
+
return generated(coloursMarkdown(tokens));
|
|
76
|
+
case "type":
|
|
77
|
+
return generated(typeMarkdown(tokens));
|
|
78
|
+
case "scale":
|
|
79
|
+
return generated(scaleMarkdown(tokens));
|
|
80
|
+
case "rules":
|
|
81
|
+
return generated(["# Rules", "", ...rules.rules.map(ruleMarkdown)].join("\n"));
|
|
82
|
+
case "pattern":
|
|
83
|
+
return generated(patternMarkdown(page.pattern, 1));
|
|
84
|
+
case "component":
|
|
85
|
+
return generated(componentMarkdown(page.entry, 1));
|
|
86
|
+
case "standards":
|
|
87
|
+
return generated(`${config.baselines ? standardsMarkdown(config.baselines) : ""}\n${config.adherence ? adherenceMarkdown(config.adherence) : ""}`);
|
|
88
|
+
case "vocabulary":
|
|
89
|
+
return generated(glossaryMarkdown(taxonomy.terms));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The route handler for `md/[[...path]]`: the page's markdown with `Vary: Accept` and its canonical link, or a markdown 404. */
|
|
94
|
+
export function markdownRoute(site: Site) {
|
|
95
|
+
return async function GET(_: Request, { params }: { params: Promise<{ path?: string[] }> }) {
|
|
96
|
+
const path = ((await params).path ?? []).join("/").replace(/\.md$/, "");
|
|
97
|
+
const page = markdownFor(site, path);
|
|
98
|
+
const canonical = `${site.base}${path ? `/${path}` : ""}`;
|
|
99
|
+
return new Response(page ?? `# Not found\n\nThere is no page at \`${canonical}\`. The index is at [${site.base}.md](${site.base}.md).\n`, {
|
|
100
|
+
status: page ? 200 : 404,
|
|
101
|
+
headers: { "content-type": "text/markdown; charset=utf-8", vary: "Accept", link: `<${canonical}>; rel="canonical"` },
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** The route handler for `manifest/[file]`: each manifest file as JSON, so an agent outside the repo gets the exact data. */
|
|
107
|
+
export function manifestRoute(site: Site) {
|
|
108
|
+
const files = manifestFiles(site);
|
|
109
|
+
return async function GET(_: Request, { params }: { params: Promise<{ file: string }> }) {
|
|
110
|
+
const { file } = await params;
|
|
111
|
+
const data = files[file.replace(/\.json$/, "")];
|
|
112
|
+
if (!data) return new Response(`# Not found\n\nNo manifest file called ${file}.\n`, { status: 404, headers: { "content-type": "text/markdown; charset=utf-8" } });
|
|
113
|
+
return Response.json(data);
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function manifestFiles(site: Site): Record<string, unknown> {
|
|
118
|
+
return Object.fromEntries(Object.entries(site.config.manifest).filter(([, v]) => v !== undefined));
|
|
119
|
+
}
|