@nanisoft/prism-llms 0.3.0 → 0.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.
- package/README.md +88 -0
- package/THIRD-PARTY-NOTICES.md +48 -0
- package/dist/data.json +3998 -375
- package/dist/demo-graph.d.ts +21 -12
- package/dist/demo-graph.js +37 -21
- package/dist/extractor.d.ts +24 -17
- package/dist/extractor.js +269 -153
- package/dist/index.d.ts +12 -7
- package/dist/index.js +9 -7
- package/dist/llms-full.txt +7988 -1989
- package/dist/llms.txt +97 -91
- package/dist/markdown.d.ts +69 -23
- package/dist/markdown.js +131 -72
- package/dist/md/blocks/app-shell-01.md +135 -0
- package/dist/md/blocks/auth-form-01.md +135 -0
- package/dist/md/blocks/cta-01.md +88 -0
- package/dist/md/blocks/data-table-01.md +196 -0
- package/dist/md/blocks/feature-grid-01.md +92 -0
- package/dist/md/blocks/hero-01.md +90 -0
- package/dist/md/blocks/instrument-panel-01.md +109 -0
- package/dist/md/blocks/logo-strip-01.md +97 -0
- package/dist/md/blocks/note-grid-01.md +102 -0
- package/dist/md/blocks/page-header-01.md +97 -0
- package/dist/md/blocks/pricing-01.md +91 -0
- package/dist/md/blocks/process-rail-01.md +106 -0
- package/dist/md/blocks/product-grid-01.md +113 -0
- package/dist/md/blocks/settings-panel-01.md +148 -0
- package/dist/md/blocks/site-footer.md +111 -0
- package/dist/md/blocks/site-header.md +119 -0
- package/dist/md/blocks/stack-grid-01.md +108 -0
- package/dist/md/blocks/stats-01.md +89 -0
- package/dist/md/blocks/status-ledger-01.md +121 -0
- package/dist/md/changelogs/prism-llms.md +206 -0
- package/dist/md/changelogs/prism-mcp-server.md +88 -0
- package/dist/md/changelogs/prism-tokens.md +126 -0
- package/dist/md/changelogs/prism-ui.md +429 -0
- package/dist/md/components/accordion.md +108 -0
- package/dist/md/components/alert.md +90 -7
- package/dist/md/components/avatar.md +89 -7
- package/dist/md/components/badge.md +74 -7
- package/dist/md/components/breadcrumb.md +84 -7
- package/dist/md/components/button.md +90 -7
- package/dist/md/components/card.md +90 -7
- package/dist/md/components/checkbox.md +101 -7
- package/dist/md/components/cta-link.md +98 -0
- package/dist/md/components/diagram.md +124 -0
- package/dist/md/components/dialog.md +128 -0
- package/dist/md/components/dropdown-menu.md +125 -0
- package/dist/md/components/fact-list.md +85 -0
- package/dist/md/components/field.md +116 -0
- package/dist/md/components/input.md +86 -7
- package/dist/md/components/kbd.md +77 -0
- package/dist/md/components/pagination.md +95 -7
- package/dist/md/components/popover.md +95 -7
- package/dist/md/components/product-mark.md +123 -0
- package/dist/md/components/product-switcher.md +88 -0
- package/dist/md/components/progress.md +88 -7
- package/dist/md/components/prose.md +91 -0
- package/dist/md/components/radio-group.md +111 -0
- package/dist/md/components/section.md +91 -0
- package/dist/md/components/select.md +143 -7
- package/dist/md/components/separator.md +77 -0
- package/dist/md/components/skeleton.md +71 -7
- package/dist/md/components/slider.md +90 -7
- package/dist/md/components/switch.md +104 -7
- package/dist/md/components/table.md +104 -7
- package/dist/md/components/tabs.md +105 -7
- package/dist/md/components/textarea.md +101 -0
- package/dist/md/components/tooltip.md +95 -7
- package/dist/md/components/typography.md +82 -7
- package/dist/md/content/about-content.md +36 -0
- package/dist/md/content/audience.md +43 -0
- package/dist/md/content/glossary.md +69 -0
- package/dist/md/content/product-vocabulary.md +53 -0
- package/dist/md/content/voice.md +52 -0
- package/dist/md/content/writing-mechanics.md +58 -0
- package/dist/md/foundation/colors.md +10 -0
- package/dist/md/foundation/iconography.md +14 -0
- package/dist/md/foundation/motion.md +10 -0
- package/dist/md/foundation/radii.md +9 -0
- package/dist/md/foundation/shadows.md +9 -0
- package/dist/md/foundation/spacings.md +8 -0
- package/dist/md/foundation/typography.md +9 -0
- package/dist/md/foundation/variables.md +9 -0
- package/dist/md/overview/architecture.md +76 -0
- package/dist/md/overview/brand.md +41 -0
- package/dist/md/overview/composition.md +77 -0
- package/dist/md/overview/quickstart.md +97 -0
- package/dist/md/overview/theming.md +89 -0
- package/dist/md/overview/using-llms.md +83 -0
- package/dist/md/pages/auth-page.md +149 -0
- package/dist/md/pages/blog-post-page.md +136 -0
- package/dist/md/pages/dashboard-page.md +241 -0
- package/dist/md/pages/marketing-page.md +199 -0
- package/dist/md/pages/not-found-page.md +105 -0
- package/dist/md/pages/settings-page.md +206 -0
- package/dist/prism-skill.md +50 -0
- package/dist/store.d.ts +203 -0
- package/dist/store.js +317 -0
- package/package.json +29 -26
- package/dist/demo-graph.d.ts.map +0 -1
- package/dist/demo-graph.js.map +0 -1
- package/dist/extractor.d.ts.map +0 -1
- package/dist/extractor.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/markdown.d.ts.map +0 -1
- package/dist/markdown.js.map +0 -1
- package/dist/md/blocks/component-demo.md +0 -19
- package/dist/md/blocks/page-header.md +0 -19
- package/dist/md/components/affix.md +0 -14
- package/dist/md/components/anchor.md +0 -14
- package/dist/md/components/auto-complete.md +0 -14
- package/dist/md/components/back-top.md +0 -14
- package/dist/md/components/border-beam.md +0 -14
- package/dist/md/components/calendar.md +0 -14
- package/dist/md/components/carousel.md +0 -14
- package/dist/md/components/cascader.md +0 -14
- package/dist/md/components/col.md +0 -14
- package/dist/md/components/collapse.md +0 -14
- package/dist/md/components/color-picker.md +0 -14
- package/dist/md/components/date-picker.md +0 -14
- package/dist/md/components/descriptions.md +0 -14
- package/dist/md/components/display-title.md +0 -20
- package/dist/md/components/divider.md +0 -14
- package/dist/md/components/drawer.md +0 -14
- package/dist/md/components/dropdown.md +0 -14
- package/dist/md/components/empty.md +0 -14
- package/dist/md/components/flex.md +0 -14
- package/dist/md/components/float-button.md +0 -14
- package/dist/md/components/form.md +0 -14
- package/dist/md/components/grid.md +0 -14
- package/dist/md/components/image.md +0 -14
- package/dist/md/components/input-number.md +0 -14
- package/dist/md/components/layout.md +0 -14
- package/dist/md/components/list.md +0 -14
- package/dist/md/components/listy.md +0 -14
- package/dist/md/components/masonry.md +0 -14
- package/dist/md/components/mentions.md +0 -14
- package/dist/md/components/menu.md +0 -14
- package/dist/md/components/modal.md +0 -14
- package/dist/md/components/popconfirm.md +0 -14
- package/dist/md/components/qrcode.md +0 -14
- package/dist/md/components/radio.md +0 -14
- package/dist/md/components/rate.md +0 -14
- package/dist/md/components/result.md +0 -14
- package/dist/md/components/row.md +0 -14
- package/dist/md/components/segmented.md +0 -14
- package/dist/md/components/space.md +0 -14
- package/dist/md/components/spin.md +0 -14
- package/dist/md/components/splitter.md +0 -14
- package/dist/md/components/statistic.md +0 -14
- package/dist/md/components/steps.md +0 -14
- package/dist/md/components/tag.md +0 -14
- package/dist/md/components/time-picker.md +0 -14
- package/dist/md/components/timeline.md +0 -14
- package/dist/md/components/tour.md +0 -14
- package/dist/md/components/transfer.md +0 -14
- package/dist/md/components/tree-select.md +0 -14
- package/dist/md/components/tree.md +0 -14
- package/dist/md/components/upload.md +0 -14
- package/dist/md/components/watermark.md +0 -14
- package/dist/md/docs/brand.md +0 -41
- package/dist/md/pages/blog-layout.md +0 -19
- package/dist/md/pages/docs-shell.md +0 -23
- package/dist/md/theme/blue-dark.md +0 -127
- package/dist/md/theme/blue-light.md +0 -129
- package/dist/md/theme/green-dark.md +0 -127
- package/dist/md/theme/green-light.md +0 -129
- package/dist/md/theme/lavender-dark.md +0 -127
- package/dist/md/theme/lavender-light.md +0 -129
- package/dist/md/theme/peach-dark.md +0 -127
- package/dist/md/theme/peach-light.md +0 -129
- package/dist/md/theme/rose-dark.md +0 -127
- package/dist/md/theme/rose-light.md +0 -129
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# NotFoundPage
|
|
2
|
+
|
|
3
|
+
A complete not-found screen: the status code as the heading of the page, one sentence about what happened, and the ways out.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { NotFoundPage } from '@nanisoft/prism-ui/pages/not-found-page'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
NotFoundPage is a complete not-found screen: the code, what happened, and the ways
|
|
12
|
+
out.
|
|
13
|
+
|
|
14
|
+
All four NaniSoft sites compose one, each in its own not-found route, and three of
|
|
15
|
+
them are the same six lines with a different product name on it: a display title
|
|
16
|
+
carrying the code, one muted sentence, and two or three links. The fourth wrote
|
|
17
|
+
the same thing in its own markup. Four hand-written screens for one shape.
|
|
18
|
+
|
|
19
|
+
It is a Page rather than a Block because it is a whole screen: it owns the
|
|
20
|
+
document's `h1`, it is what a router renders when a route does not resolve, and
|
|
21
|
+
the band's job is not separable from the screen's. There is one correct page here
|
|
22
|
+
and it is short.
|
|
23
|
+
|
|
24
|
+
## Guidelines
|
|
25
|
+
|
|
26
|
+
### When to use
|
|
27
|
+
|
|
28
|
+
Use NotFoundPage as the body of whatever route your framework names for a
|
|
29
|
+
not-found response: Next's `not-found.tsx`, a Nuxt error page, a route your own
|
|
30
|
+
router falls through to.
|
|
31
|
+
|
|
32
|
+
Use it for every status that means "this address is not a page here", not only
|
|
33
|
+
404. A 410 and a 404 are the same screen with a different code, and the code is a
|
|
34
|
+
prop.
|
|
35
|
+
|
|
36
|
+
### When not to use
|
|
37
|
+
|
|
38
|
+
Do not use it for a request that failed. That is an error page with a retry, and a
|
|
39
|
+
reader who sees "this page does not exist" when the page exists and did not load
|
|
40
|
+
will not believe you next time.
|
|
41
|
+
|
|
42
|
+
Do not use it for a permission failure the reader might be granted later. That is
|
|
43
|
+
a 403, and it needs a sign-in link rather than a way back to the landing.
|
|
44
|
+
|
|
45
|
+
### Best practices
|
|
46
|
+
|
|
47
|
+
- **The code is the `h1` and the sentence is not.** A not-found page whose `h1` is
|
|
48
|
+
"Page not found" gives a search engine and a screen reader nothing distinct to
|
|
49
|
+
index, and the code is the one string on the page that is the same for every
|
|
50
|
+
broken URL. The code takes the display step and the sentence takes the muted one,
|
|
51
|
+
which is the reverse of what a reader sees first and the right way round for
|
|
52
|
+
anything that reads the outline.
|
|
53
|
+
- Put the most useful destination first, and weight it as the primary action. A
|
|
54
|
+
not-found page that offers the homepage link before the documentation sends a
|
|
55
|
+
reader further from what they wanted.
|
|
56
|
+
- Leave `newTab` off every link. A reader who followed a broken link and is sent
|
|
57
|
+
to a new tab has to find their way back.
|
|
58
|
+
- Use the `children` slot for a search box or a list of recent posts, which is
|
|
59
|
+
what turns a dead end into a page.
|
|
60
|
+
|
|
61
|
+
### Content guidelines
|
|
62
|
+
|
|
63
|
+
- Write the sentence as a fact about the address, not as an apology. "No node
|
|
64
|
+
here" beats "Sorry, we could not find that page".
|
|
65
|
+
- Say whether the page might exist later if it does. "This page does not exist
|
|
66
|
+
(yet)" is one clause longer and saves a support ticket.
|
|
67
|
+
- Keep each link label to one or two words.
|
|
68
|
+
|
|
69
|
+
**The not-found screen: the code as the h1, one sentence, and the ways out.**
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { NotFoundPage } from '@nanisoft/prism-ui/pages/not-found-page'
|
|
73
|
+
|
|
74
|
+
/** The not-found screen: the code as the h1, one sentence, and the ways out. */
|
|
75
|
+
export default function NotFoundPageDemo() {
|
|
76
|
+
return (
|
|
77
|
+
<NotFoundPage
|
|
78
|
+
code="404"
|
|
79
|
+
title="No node here."
|
|
80
|
+
description="The estate is fully mapped. This URL is not in the graph."
|
|
81
|
+
linksLabel="Ways out"
|
|
82
|
+
links={[
|
|
83
|
+
{ label: 'Read the docs', href: '#docs' },
|
|
84
|
+
{ label: 'Back to the landing', href: '#landing' },
|
|
85
|
+
]}
|
|
86
|
+
/>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Props
|
|
92
|
+
|
|
93
|
+
**`code`** `string` · required · default: — — The status code, shown as the page's own `h1`. Required, and a string rather than a number because it is displayed, not computed: a Page never decides what code it is answering.
|
|
94
|
+
**`title`** `string` · required · default: — — The headline under the code: the sentence that says what happened. It is the part a reader actually reads, and it is the caller's because every product says it differently - "No node here", "This page does not exist (yet)".
|
|
95
|
+
**`description`** `string` · optional · default: — — One or two sentences under the headline, for anything a reader should know before they follow one of the links: that the URL may be mistyped, that the page is planned, that a search would find it.
|
|
96
|
+
**`links`** `readonly NotFoundLink[]` · required · default: — — The ways out, in the order a reader should see them. Put the destination most likely to help first; a not-found page that offers a homepage link before the documentation sends a reader further from what they wanted.
|
|
97
|
+
**`linksLabel`** `string` · required · default: — — The accessible name of the row of ways out. It is required, because it is a word a reader hears and a Page that ships no copy ships no reader-facing copy either. "Ways out" is the Page's own phrasing; a site that files its destinations differently names the same landmark differently.
|
|
98
|
+
**`children`** `ReactNode` · optional · default: — — A slot for whatever else the site wants to say here: a search box, a list of recent posts, a contact address.
|
|
99
|
+
**`className`** `string` · optional · default: — — Layout only, exactly as on every Component. Changing a Prism-owned visual property from here is prohibited.
|
|
100
|
+
|
|
101
|
+
## Composition
|
|
102
|
+
|
|
103
|
+
**`exports`** `NotFoundPage` — the public runtime names this Page promises
|
|
104
|
+
**`source`** `packages/ui/src/pages/not-found-page/index.tsx` — the file this Page is defined in
|
|
105
|
+
**`dependencies`** `CtaLink, Prose, Section` — the public Prism exports this item composes
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# SettingsPage
|
|
2
|
+
|
|
3
|
+
A full settings screen composing the app shell, a page header and tabs of grouped settings forms.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { SettingsPage } from '@nanisoft/prism-ui/pages/settings-page'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
SettingsPage is a complete settings screen. It composes the shell, a page header
|
|
12
|
+
and a set of tabs, where each tab is either a saved settings form or a read-only
|
|
13
|
+
panel. The page owns the sequence and the tab wiring only.
|
|
14
|
+
|
|
15
|
+
The page composes these parts:
|
|
16
|
+
|
|
17
|
+
| Region | Piece | Role |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| Frame | AppShell01 | the navigation rail, the top bar and the mobile navigation sheet |
|
|
20
|
+
| Header | PageHeader01 | the trail, the screen title and its actions |
|
|
21
|
+
| Tabs | Tabs, TabsList, TabsTrigger, TabsContent | the peer settings groups |
|
|
22
|
+
| Forms | SettingsPanel01 | the grouped and saved form for one tab |
|
|
23
|
+
|
|
24
|
+
A tab that carries `panel` renders `SettingsPanel01`: a titled card with grouped
|
|
25
|
+
sections, a save footer and one submit. A tab that carries `content` renders the
|
|
26
|
+
node as-is, which suits a read-only summary or a view that is not a form. Sections,
|
|
27
|
+
fields, options and labels are all props, and the page fetches nothing.
|
|
28
|
+
|
|
29
|
+
## Guidelines
|
|
30
|
+
|
|
31
|
+
### When to use
|
|
32
|
+
|
|
33
|
+
Use SettingsPage when a screen changes several settings that group naturally, and
|
|
34
|
+
each group can be saved on its own. It works when the tabs are stable and a reader
|
|
35
|
+
returns to one group rather than scanning the whole screen.
|
|
36
|
+
|
|
37
|
+
### When not to use
|
|
38
|
+
|
|
39
|
+
Do not use it for a single setting. One field behind a tab is a heavier frame
|
|
40
|
+
than the choice deserves; put the control on the screen that owns it.
|
|
41
|
+
|
|
42
|
+
Do not use it when the settings must be compared side by side. Tabs hide one
|
|
43
|
+
group to show another, so a choice that depends on another group's value belongs
|
|
44
|
+
on one page, not behind a tab.
|
|
45
|
+
|
|
46
|
+
### Best practices
|
|
47
|
+
|
|
48
|
+
- Keep one save per panel. A mixed model, where some fields save and others apply
|
|
49
|
+
immediately, makes the footer's promise unclear.
|
|
50
|
+
- Give every field a stable `id`, so the label is linked to the control.
|
|
51
|
+
- Use `content` for a read-only group. A panel with no `submitLabel` renders no
|
|
52
|
+
footer, which is the honest shape for a view that does not save.
|
|
53
|
+
- Set `defaultValue` to the group a reader is most likely to want, rather than
|
|
54
|
+
relying on the first tab by luck.
|
|
55
|
+
- Pass the same navigation node to both the rail and the sheet, and keep its ids
|
|
56
|
+
unique because AppShell01 renders it twice.
|
|
57
|
+
|
|
58
|
+
### Content guidelines
|
|
59
|
+
|
|
60
|
+
- A tab label is one word in sentence case: "General", "Notifications".
|
|
61
|
+
- A section title is one or two words and a field label is a short noun phrase.
|
|
62
|
+
- A description states the effect of the group, not a policy for it.
|
|
63
|
+
|
|
64
|
+
**The settings page, with a grouped form per tab.**
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
'use client'
|
|
68
|
+
|
|
69
|
+
import { SettingsPage } from '@nanisoft/prism-ui/pages/settings-page'
|
|
70
|
+
|
|
71
|
+
const LINKS = [
|
|
72
|
+
{ href: '#general', label: 'General', current: false },
|
|
73
|
+
{ href: '#settings', label: 'Settings', current: true },
|
|
74
|
+
{ href: '#members', label: 'Members', current: false },
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
/** The settings page, with a grouped form per tab. */
|
|
78
|
+
export default function SettingsPageDemo() {
|
|
79
|
+
return (
|
|
80
|
+
<SettingsPage
|
|
81
|
+
shell={{
|
|
82
|
+
navigationLabel: 'Primary',
|
|
83
|
+
brand: <span className="text-sm font-semibold">Northwind</span>,
|
|
84
|
+
breadcrumbs: [{ label: 'Settings', href: '#settings' }, { label: 'Workspace' }],
|
|
85
|
+
navigation: (
|
|
86
|
+
<ul className="flex flex-col gap-1 text-sm">
|
|
87
|
+
{LINKS.map((link) => (
|
|
88
|
+
<li key={link.href}>
|
|
89
|
+
<a
|
|
90
|
+
href={link.href}
|
|
91
|
+
className={
|
|
92
|
+
link.current
|
|
93
|
+
? 'bg-accent text-accent-foreground block rounded-md px-3 py-2 font-medium'
|
|
94
|
+
: 'text-muted-foreground hover:text-foreground block rounded-md px-3 py-2'
|
|
95
|
+
}
|
|
96
|
+
>
|
|
97
|
+
{link.label}
|
|
98
|
+
</a>
|
|
99
|
+
</li>
|
|
100
|
+
))}
|
|
101
|
+
</ul>
|
|
102
|
+
),
|
|
103
|
+
}}
|
|
104
|
+
header={{
|
|
105
|
+
title: 'Workspace settings',
|
|
106
|
+
description: 'Manage how this workspace behaves for everyone on the team.',
|
|
107
|
+
}}
|
|
108
|
+
tabs={[
|
|
109
|
+
{
|
|
110
|
+
value: 'general',
|
|
111
|
+
label: 'General',
|
|
112
|
+
panel: {
|
|
113
|
+
title: 'General',
|
|
114
|
+
description: 'Shown to everyone you collaborate with.',
|
|
115
|
+
submitLabel: 'Save changes',
|
|
116
|
+
secondaryAction: { label: 'Cancel' },
|
|
117
|
+
sections: [
|
|
118
|
+
{
|
|
119
|
+
id: 'identity',
|
|
120
|
+
title: 'Identity',
|
|
121
|
+
fields: [
|
|
122
|
+
{
|
|
123
|
+
kind: 'text',
|
|
124
|
+
id: 'settings-workspace-name',
|
|
125
|
+
label: 'Workspace name',
|
|
126
|
+
defaultValue: 'Northwind',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
kind: 'textarea',
|
|
130
|
+
id: 'settings-workspace-description',
|
|
131
|
+
label: 'Description',
|
|
132
|
+
placeholder: 'What does this workspace do?',
|
|
133
|
+
rows: 3,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
kind: 'select',
|
|
137
|
+
id: 'settings-workspace-region',
|
|
138
|
+
label: 'Data region',
|
|
139
|
+
placeholder: 'Choose a region',
|
|
140
|
+
defaultValue: 'eu-west',
|
|
141
|
+
options: [
|
|
142
|
+
{ label: 'Europe West', value: 'eu-west' },
|
|
143
|
+
{ label: 'US East', value: 'us-east' },
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
value: 'notifications',
|
|
153
|
+
label: 'Notifications',
|
|
154
|
+
panel: {
|
|
155
|
+
title: 'Notifications',
|
|
156
|
+
description: 'Choose what the workspace sends and when.',
|
|
157
|
+
submitLabel: 'Save changes',
|
|
158
|
+
sections: [
|
|
159
|
+
{
|
|
160
|
+
id: 'email',
|
|
161
|
+
title: 'Email',
|
|
162
|
+
fields: [
|
|
163
|
+
{
|
|
164
|
+
kind: 'switch',
|
|
165
|
+
id: 'settings-weekly-digest',
|
|
166
|
+
label: 'Weekly digest',
|
|
167
|
+
description: 'A summary of activity every Monday.',
|
|
168
|
+
defaultChecked: true,
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
kind: 'switch',
|
|
172
|
+
id: 'settings-mention-alerts',
|
|
173
|
+
label: 'Mention alerts',
|
|
174
|
+
description: 'Notify me when someone mentions my name.',
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
]}
|
|
182
|
+
/>
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Props
|
|
188
|
+
|
|
189
|
+
**`shell`** `Omit<ComponentProps<typeof AppShell01>, 'children'>` · required · default: — — The frame: rail, top bar and mobile navigation sheet.
|
|
190
|
+
**`header`** `ComponentProps<typeof PageHeader01>` · required · default: — — The page title band.
|
|
191
|
+
**`tabs`** `SettingsPageTab[]` · required · default: — — The tabs, in order. At least one is required.
|
|
192
|
+
**`defaultValue`** `string` · optional · default: — — The tab shown first, for uncontrolled tabs. Defaults to the first tab.
|
|
193
|
+
**`value`** `string` · optional · default: — — The controlled active tab.
|
|
194
|
+
**`onValueChange`** `(value: string) => void` · optional · default: —
|
|
195
|
+
|
|
196
|
+
## Composition
|
|
197
|
+
|
|
198
|
+
**`exports`** `SettingsPage` — the public runtime names this Page promises
|
|
199
|
+
**`source`** `packages/ui/src/pages/settings-page/index.tsx` — the file this Page is defined in
|
|
200
|
+
**`dependencies`** `AppShell01, PageHeader01, SettingsPanel01, Tabs` — the public Prism exports this item composes
|
|
201
|
+
|
|
202
|
+
## Blocks
|
|
203
|
+
|
|
204
|
+
- [AppShell01](https://prism.nanisoft.com/blocks/app-shell-01.md)
|
|
205
|
+
- [PageHeader01](https://prism.nanisoft.com/blocks/page-header-01.md)
|
|
206
|
+
- [SettingsPanel01](https://prism.nanisoft.com/blocks/settings-panel-01.md)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Prism agent skill
|
|
2
|
+
|
|
3
|
+
Prism is NaniSoft's design system: design tokens, a React component library, a
|
|
4
|
+
documentation site, and this agent surface. This is the fast path. The index is
|
|
5
|
+
[`/llms.txt`](https://prism.nanisoft.com/llms.txt) and every page in full is
|
|
6
|
+
[`/llms-full.txt`](https://prism.nanisoft.com/llms-full.txt); both are generated from the
|
|
7
|
+
checked catalogue and the authored pages.
|
|
8
|
+
|
|
9
|
+
## Start here
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import '@nanisoft/prism-ui/styles.css'
|
|
13
|
+
|
|
14
|
+
import { PrismProvider, PrismThemeScript } from '@nanisoft/prism-ui/provider'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Import the one stylesheet once. The provider is optional: the declarative axes
|
|
18
|
+
are `data-pack` on `<html>` and the `dark` class for mode.
|
|
19
|
+
|
|
20
|
+
## Import contract
|
|
21
|
+
|
|
22
|
+
- Components: `@nanisoft/prism-ui/components/<slug>`
|
|
23
|
+
- Blocks: `@nanisoft/prism-ui/blocks/<slug>`
|
|
24
|
+
- Pages: `@nanisoft/prism-ui/pages/<slug>`
|
|
25
|
+
|
|
26
|
+
Compound parts stay inside their module. Base UI and every internal path are
|
|
27
|
+
never a consumer import.
|
|
28
|
+
|
|
29
|
+
## MCP
|
|
30
|
+
|
|
31
|
+
The read-only MCP endpoint is `https://prism.nanisoft.com/mcp`. It exposes nine tools:
|
|
32
|
+
`list_items`, `get_item_doc`, `get_item_props`, `get_item_source`,
|
|
33
|
+
`get_theme_doc`, `list_pages`, `get_page`, `search_docs` and
|
|
34
|
+
`get_changelog`.
|
|
35
|
+
|
|
36
|
+
## Truth rules
|
|
37
|
+
|
|
38
|
+
- Prism is the one source of truth. A consumer composes; it never writes CSS and
|
|
39
|
+
never overrides a style.
|
|
40
|
+
- There is no override path. When Prism lacks a component, token or variant,
|
|
41
|
+
request it upstream.
|
|
42
|
+
- Generated code imports from `@nanisoft/prism-ui` only.
|
|
43
|
+
|
|
44
|
+
## This corpus
|
|
45
|
+
|
|
46
|
+
Generated from the catalogue and the authored pages: 34
|
|
47
|
+
Components, 19 Blocks and 6 Pages, plus the Overview,
|
|
48
|
+
Foundation, Content and Changelogs pages. The Changelogs pages are each
|
|
49
|
+
published package's own changelog, byte for byte; `get_changelog` returns one
|
|
50
|
+
package's, optionally one version of it.
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `PrismDocsStore` contract: the one type the MCP server validates at
|
|
3
|
+
* runtime, and the one runtime guard that produces it.
|
|
4
|
+
*
|
|
5
|
+
* Ticket 12 section 7 makes this file the canonical home. The store is a
|
|
6
|
+
* build-time projection of the catalogue, the authored pages and the token
|
|
7
|
+
* cascade; the MCP server imports both the type and `parsePrismDocsStore` and
|
|
8
|
+
* never redeclares either.
|
|
9
|
+
*
|
|
10
|
+
* `kind` is ticket 09's closed union. The JSON arrives as `unknown`, the guard
|
|
11
|
+
* narrows it structurally, and `kind` is validated through a local list that is
|
|
12
|
+
* tied to the catalogue's type with `satisfies` plus a type-equality assertion.
|
|
13
|
+
* A widened `kind: string` is rejected at runtime and at compile time, which is
|
|
14
|
+
* the bug the old package recorded.
|
|
15
|
+
*/
|
|
16
|
+
import type { CatalogKind, ComponentCategory } from '@nanisoft/prism-ui/catalog';
|
|
17
|
+
export declare const STORE_KINDS: readonly ["component", "block", "page"];
|
|
18
|
+
export declare const STORE_CATEGORIES: readonly ["Call to action", "Forms and inputs", "Feedback", "Layout", "Data display", "Typography", "Miscellaneous"];
|
|
19
|
+
export declare const STORE_STATUSES: readonly ["stable", "deprecated"];
|
|
20
|
+
/**
|
|
21
|
+
* The content Sections, in the reading order the site publishes them, and the
|
|
22
|
+
* same order `llms.txt` groups them in.
|
|
23
|
+
*
|
|
24
|
+
* These are the Section *directories*, so the list is the walk the corpus builder
|
|
25
|
+
* takes and the set of directories the site's gate checks. The three catalogue
|
|
26
|
+
* Sections are not here: an Item is a catalogue entry with a `kind`, and its page
|
|
27
|
+
* is emitted from the Catalogue rather than walked out of the content tree, so
|
|
28
|
+
* adding `components` to this list would make the walk look for a directory that
|
|
29
|
+
* is not one.
|
|
30
|
+
*
|
|
31
|
+
* **A Section's route is its directory, and the two were renames.** `docs` is
|
|
32
|
+
* `overview` and `foundations` is `foundation`, which is the rule that a prose
|
|
33
|
+
* Section is one body of knowledge and takes a singular route while a catalogue
|
|
34
|
+
* Section is a collection of many Items and takes a plural one. An agent holding
|
|
35
|
+
* a cached `llms.txt` from before the move still resolves every URL it names,
|
|
36
|
+
* because the site Worker redirects each of these routes permanently, and the
|
|
37
|
+
* corpus is rebuilt per release and points at the new ones. Nothing here is
|
|
38
|
+
* aliased: a page's `section` is the directory it is filed in, which is what
|
|
39
|
+
* `get_page` matches on, and a `Record<StoreSection, string>` over a list that
|
|
40
|
+
* had to be edited in the same commit as the rename is a second list that can be
|
|
41
|
+
* half done.
|
|
42
|
+
*/
|
|
43
|
+
export declare const STORE_SECTIONS: readonly ["overview", "foundation", "content", "changelogs"];
|
|
44
|
+
/**
|
|
45
|
+
* The label each content Section is read under, in every artifact that groups
|
|
46
|
+
* pages by Section.
|
|
47
|
+
*
|
|
48
|
+
* `Record<StoreSection, string>` rather than a separate list, because a Section
|
|
49
|
+
* added to `STORE_SECTIONS` with no label is a compile error here rather than a
|
|
50
|
+
* Section that `llms.txt`, `list_pages` and the Corpus each spell their own way.
|
|
51
|
+
* The keys are the Section directories themselves, so the label cannot be filed
|
|
52
|
+
* under a Section that does not exist.
|
|
53
|
+
*
|
|
54
|
+
* The label is the Section's name rather than its directory, which is the whole
|
|
55
|
+
* point of the pair: the directory is what the tree is called, and the name is
|
|
56
|
+
* what a reader and an agent are told. `llms.txt` groups under these headings and
|
|
57
|
+
* `list_pages` counts them, so a Section renamed without its label renamed here
|
|
58
|
+
* would be advertised under two names in two artifacts.
|
|
59
|
+
*/
|
|
60
|
+
export declare const STORE_SECTION_TITLES: Record<StoreSection, string>;
|
|
61
|
+
export declare const STORE_PACKS: readonly ["default", "blush", "mint", "lavender", "sky", "peach"];
|
|
62
|
+
export declare const STORE_MODES: readonly ["light", "dark"];
|
|
63
|
+
export declare const STORE_SCALE_GROUPS: readonly ["motion", "typography", "spacing", "shadow", "breakpoint", "container"];
|
|
64
|
+
export type StoreKind = (typeof STORE_KINDS)[number];
|
|
65
|
+
export type StoreStatus = (typeof STORE_STATUSES)[number];
|
|
66
|
+
export type StoreSection = (typeof STORE_SECTIONS)[number];
|
|
67
|
+
export type PackId = (typeof STORE_PACKS)[number];
|
|
68
|
+
export type Mode = (typeof STORE_MODES)[number];
|
|
69
|
+
export type PrismScaleGroup = (typeof STORE_SCALE_GROUPS)[number];
|
|
70
|
+
/** `'doc'` is a non-item page (a guide, a Foundation, a Content page). */
|
|
71
|
+
export type TokenGroup = 'semantic' | PrismScaleGroup;
|
|
72
|
+
export interface PrismDocsExample {
|
|
73
|
+
readonly title: string;
|
|
74
|
+
readonly code: string;
|
|
75
|
+
}
|
|
76
|
+
export interface PrismDocsStoreEntry {
|
|
77
|
+
readonly id: string;
|
|
78
|
+
readonly slug: string;
|
|
79
|
+
readonly kind: CatalogKind;
|
|
80
|
+
readonly name: string;
|
|
81
|
+
readonly category: ComponentCategory | null;
|
|
82
|
+
readonly status: StoreStatus;
|
|
83
|
+
readonly description: string;
|
|
84
|
+
/** The item's canonical site path, for example `/components/button`. */
|
|
85
|
+
readonly url: string;
|
|
86
|
+
/** The canonical path plus `.md`, for example `/components/button.md`. */
|
|
87
|
+
readonly mirror: string;
|
|
88
|
+
readonly source: string;
|
|
89
|
+
readonly exports: readonly string[];
|
|
90
|
+
/** The public import line ticket 11 section 9 fixes. */
|
|
91
|
+
readonly importLine: string;
|
|
92
|
+
/** The full per-item spec, byte-identical to the mirror file. */
|
|
93
|
+
readonly doc: string;
|
|
94
|
+
/** The `## Props` section body, for a Component. */
|
|
95
|
+
readonly props?: string;
|
|
96
|
+
/** The `## Composition` section body, for a Block or a Page. */
|
|
97
|
+
readonly composition?: string;
|
|
98
|
+
/** The verbatim demo plus its title, when a demo exists. */
|
|
99
|
+
readonly example?: PrismDocsExample;
|
|
100
|
+
readonly references: {
|
|
101
|
+
readonly blocks: readonly string[];
|
|
102
|
+
readonly pages: readonly string[];
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export interface PrismDocsPage {
|
|
106
|
+
readonly id: string;
|
|
107
|
+
/** The page's path below its Section, without the extension: `tokens/colors`. */
|
|
108
|
+
readonly slug: string;
|
|
109
|
+
/** The top-level Section directory the page sits in. */
|
|
110
|
+
readonly section: StoreSection;
|
|
111
|
+
readonly title: string;
|
|
112
|
+
readonly description: string;
|
|
113
|
+
/** The page's canonical site path, for example `/overview/quickstart`. */
|
|
114
|
+
readonly url: string;
|
|
115
|
+
readonly markdown: string;
|
|
116
|
+
readonly mirror: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* One version entry of a published package's changelog.
|
|
120
|
+
*
|
|
121
|
+
* `body` is the text under the version's own `## <version>` heading, sliced by
|
|
122
|
+
* the shared changelog rule and never re-levelled: the file is published whole
|
|
123
|
+
* and re-levelling a heading would be another transformation between the
|
|
124
|
+
* package's bytes and the agent's.
|
|
125
|
+
*/
|
|
126
|
+
export interface PrismChangelogRelease {
|
|
127
|
+
readonly version: string;
|
|
128
|
+
readonly body: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* One published package's changelog, projected from the generated file the site
|
|
132
|
+
* renders.
|
|
133
|
+
*
|
|
134
|
+
* This is the field the ninth read-only tool answers from, and it exists so that
|
|
135
|
+
* a breaking change in a published package is discoverable by an agent. The
|
|
136
|
+
* reference design system shipped a breaking module-system change that no agent
|
|
137
|
+
* using it could find, because its corpus had no changelog field and no tool
|
|
138
|
+
* could return one.
|
|
139
|
+
*
|
|
140
|
+
* `text` is the generated file verbatim, which is a byte-for-byte copy of the
|
|
141
|
+
* package's own `CHANGELOG.md`. `releases` is the shared rule's reading of those
|
|
142
|
+
* same bytes, and the two cannot disagree because the rule is the only thing
|
|
143
|
+
* that produces either.
|
|
144
|
+
*/
|
|
145
|
+
export interface PrismChangelog {
|
|
146
|
+
/** The published npm name, which is what an agent asks for. */
|
|
147
|
+
readonly package: string;
|
|
148
|
+
/** The route segment the changelog is published at: the unscoped name. */
|
|
149
|
+
readonly slug: string;
|
|
150
|
+
/** The site's route for it, and the mirror an agent can fetch instead. */
|
|
151
|
+
readonly route: string;
|
|
152
|
+
/** The file's own first heading, which names the package. */
|
|
153
|
+
readonly title: string;
|
|
154
|
+
/** Every version the file records, newest first as the generator writes it. */
|
|
155
|
+
readonly versions: readonly string[];
|
|
156
|
+
readonly releases: readonly PrismChangelogRelease[];
|
|
157
|
+
/** The generated file, byte for byte. */
|
|
158
|
+
readonly text: string;
|
|
159
|
+
}
|
|
160
|
+
export interface PrismSemanticToken {
|
|
161
|
+
readonly token: string;
|
|
162
|
+
readonly value: string;
|
|
163
|
+
}
|
|
164
|
+
export interface PrismScaleToken {
|
|
165
|
+
readonly token: string;
|
|
166
|
+
readonly value: string;
|
|
167
|
+
/** The Tailwind binding, when the token has a mirror custom property. */
|
|
168
|
+
readonly binding?: string;
|
|
169
|
+
}
|
|
170
|
+
export interface PrismThemeTokens {
|
|
171
|
+
readonly pack: PackId;
|
|
172
|
+
readonly mode: Mode;
|
|
173
|
+
readonly semantic: readonly PrismSemanticToken[];
|
|
174
|
+
}
|
|
175
|
+
export interface PrismTokensProjection {
|
|
176
|
+
readonly packs: readonly PackId[];
|
|
177
|
+
readonly modes: readonly Mode[];
|
|
178
|
+
readonly themes: readonly PrismThemeTokens[];
|
|
179
|
+
readonly scales: Record<PrismScaleGroup, readonly PrismScaleToken[]>;
|
|
180
|
+
}
|
|
181
|
+
export interface PrismDocsStore {
|
|
182
|
+
readonly version: string;
|
|
183
|
+
readonly items: readonly PrismDocsStoreEntry[];
|
|
184
|
+
readonly pages: readonly PrismDocsPage[];
|
|
185
|
+
/**
|
|
186
|
+
* One entry per published package that ships a changelog. Required rather than
|
|
187
|
+
* optional: the field is what makes a published breaking change discoverable
|
|
188
|
+
* by an agent, and a store that quietly omitted it would leave the tool that
|
|
189
|
+
* reads it answering for nothing while every other gate stayed green.
|
|
190
|
+
*/
|
|
191
|
+
readonly changelogs: readonly PrismChangelog[];
|
|
192
|
+
readonly tokens: PrismTokensProjection;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Narrow an `unknown` JSON payload to a `PrismDocsStore`, or throw with the
|
|
196
|
+
* offending path. This is the only place a `PrismDocsStore` is produced from
|
|
197
|
+
* JSON: nothing is assigned with `as`, and `kind` is never widened to `string`.
|
|
198
|
+
*
|
|
199
|
+
* The order of the fields is the order of the layers that have to have carried
|
|
200
|
+
* the change. `items` before `changelogs`, so a document with a widened `kind`
|
|
201
|
+
* reports the path a reader is more likely to be looking at.
|
|
202
|
+
*/
|
|
203
|
+
export declare function parsePrismDocsStore(raw: unknown): PrismDocsStore;
|