shelving 1.236.2 → 1.237.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/extract/IndexExtractor.js +9 -2
- package/extract/MergingExtractor.d.ts +3 -1
- package/extract/MergingExtractor.js +41 -3
- package/extract/TypescriptExtractor.d.ts +1 -0
- package/extract/TypescriptExtractor.js +12 -2
- package/package.json +1 -1
- package/ui/README.md +19 -274
- package/ui/app/App.d.ts +1 -0
- package/ui/app/App.js +1 -0
- package/ui/app/App.md +58 -0
- package/ui/app/App.tsx +1 -0
- package/ui/block/Card.d.ts +1 -0
- package/ui/block/Card.js +1 -0
- package/ui/block/Card.md +85 -0
- package/ui/block/Card.tsx +1 -0
- package/ui/block/Heading.d.ts +1 -0
- package/ui/block/Heading.js +1 -0
- package/ui/block/Heading.md +70 -0
- package/ui/block/Heading.tsx +1 -0
- package/ui/block/List.d.ts +1 -0
- package/ui/block/List.js +1 -0
- package/ui/block/List.md +51 -0
- package/ui/block/List.tsx +1 -0
- package/ui/block/Panel.d.ts +1 -0
- package/ui/block/Panel.js +1 -0
- package/ui/block/Panel.md +50 -0
- package/ui/block/Panel.tsx +1 -0
- package/ui/block/Paragraph.d.ts +1 -0
- package/ui/block/Paragraph.js +1 -0
- package/ui/block/Paragraph.md +48 -0
- package/ui/block/Paragraph.tsx +1 -0
- package/ui/block/Prose.d.ts +1 -0
- package/ui/block/Prose.js +1 -0
- package/ui/block/Prose.md +49 -0
- package/ui/block/Prose.tsx +1 -0
- package/ui/block/Section.d.ts +6 -0
- package/ui/block/Section.js +6 -0
- package/ui/block/Section.md +56 -0
- package/ui/block/Section.tsx +6 -0
- package/ui/block/Subheading.d.ts +1 -0
- package/ui/block/Subheading.js +1 -0
- package/ui/block/Subheading.md +58 -0
- package/ui/block/Subheading.tsx +1 -0
- package/ui/block/Table.d.ts +1 -0
- package/ui/block/Table.js +1 -0
- package/ui/block/Table.md +54 -0
- package/ui/block/Table.tsx +1 -0
- package/ui/block/Title.d.ts +1 -0
- package/ui/block/Title.js +1 -0
- package/ui/block/Title.md +57 -0
- package/ui/block/Title.tsx +1 -0
- package/ui/dialog/Dialog.d.ts +1 -0
- package/ui/dialog/Dialog.js +1 -0
- package/ui/dialog/Dialog.md +73 -0
- package/ui/dialog/Dialog.tsx +1 -0
- package/ui/dialog/Modal.d.ts +1 -0
- package/ui/dialog/Modal.js +1 -0
- package/ui/dialog/Modal.md +40 -0
- package/ui/dialog/Modal.tsx +1 -0
- package/ui/docs/DocumentationButtons.d.ts +2 -0
- package/ui/docs/DocumentationButtons.js +2 -0
- package/ui/docs/DocumentationButtons.md +38 -0
- package/ui/docs/DocumentationButtons.tsx +2 -0
- package/ui/docs/DocumentationCard.d.ts +1 -0
- package/ui/docs/DocumentationCard.js +1 -0
- package/ui/docs/DocumentationCard.md +35 -0
- package/ui/docs/DocumentationCard.tsx +1 -0
- package/ui/docs/DocumentationKind.d.ts +1 -1
- package/ui/docs/DocumentationKind.js +9 -4
- package/ui/docs/DocumentationKind.tsx +10 -5
- package/ui/docs/DocumentationPage.d.ts +1 -0
- package/ui/docs/DocumentationPage.js +2 -0
- package/ui/docs/DocumentationPage.md +46 -0
- package/ui/docs/DocumentationPage.tsx +2 -0
- package/ui/form/Button.d.ts +1 -0
- package/ui/form/Button.js +1 -0
- package/ui/form/Button.md +88 -0
- package/ui/form/Button.tsx +1 -0
- package/ui/form/Field.d.ts +6 -1
- package/ui/form/Field.js +6 -1
- package/ui/form/Field.md +59 -0
- package/ui/form/Field.tsx +6 -1
- package/ui/form/Form.d.ts +1 -0
- package/ui/form/Form.md +118 -0
- package/ui/form/Form.tsx +1 -0
- package/ui/form/FormStore.md +47 -0
- package/ui/form/SchemaInput.d.ts +1 -0
- package/ui/form/SchemaInput.md +64 -0
- package/ui/form/SchemaInput.tsx +1 -0
- package/ui/inline/Code.d.ts +1 -0
- package/ui/inline/Code.js +1 -0
- package/ui/inline/Code.md +58 -0
- package/ui/inline/Code.tsx +1 -0
- package/ui/inline/Link.d.ts +1 -0
- package/ui/inline/Link.js +1 -0
- package/ui/inline/Link.md +47 -0
- package/ui/inline/Link.tsx +1 -0
- package/ui/inline/Mark.d.ts +1 -0
- package/ui/inline/Mark.js +1 -0
- package/ui/inline/Mark.md +40 -0
- package/ui/inline/Mark.tsx +1 -0
- package/ui/inline/Strong.d.ts +1 -0
- package/ui/inline/Strong.js +1 -0
- package/ui/inline/Strong.md +34 -0
- package/ui/inline/Strong.tsx +1 -0
- package/ui/layout/CenteredLayout.d.ts +1 -0
- package/ui/layout/CenteredLayout.js +1 -0
- package/ui/layout/CenteredLayout.md +38 -0
- package/ui/layout/CenteredLayout.tsx +1 -0
- package/ui/layout/SidebarLayout.d.ts +1 -0
- package/ui/layout/SidebarLayout.js +1 -0
- package/ui/layout/SidebarLayout.md +65 -0
- package/ui/layout/SidebarLayout.tsx +1 -0
- package/ui/menu/Menu.d.ts +2 -0
- package/ui/menu/Menu.js +2 -0
- package/ui/menu/Menu.md +51 -0
- package/ui/menu/Menu.tsx +2 -0
- package/ui/menu/MenuItem.md +54 -0
- package/ui/misc/Catcher.d.ts +1 -0
- package/ui/misc/Catcher.js +1 -0
- package/ui/misc/Catcher.md +41 -0
- package/ui/misc/Catcher.tsx +1 -0
- package/ui/misc/Loading.d.ts +1 -0
- package/ui/misc/Loading.js +1 -0
- package/ui/misc/Loading.md +28 -0
- package/ui/misc/Loading.tsx +1 -0
- package/ui/misc/Mapper.md +40 -0
- package/ui/misc/Markup.d.ts +1 -0
- package/ui/misc/Markup.js +1 -0
- package/ui/misc/Markup.md +34 -0
- package/ui/misc/Markup.tsx +1 -0
- package/ui/misc/StatusIcon.d.ts +1 -0
- package/ui/misc/StatusIcon.js +1 -0
- package/ui/misc/StatusIcon.md +25 -0
- package/ui/misc/StatusIcon.tsx +1 -0
- package/ui/misc/Tag.d.ts +1 -0
- package/ui/misc/Tag.js +1 -0
- package/ui/misc/Tag.md +47 -0
- package/ui/misc/Tag.tsx +1 -0
- package/ui/notice/Notice.d.ts +1 -0
- package/ui/notice/Notice.js +1 -0
- package/ui/notice/Notice.md +53 -0
- package/ui/notice/Notice.tsx +1 -0
- package/ui/notice/Notices.d.ts +1 -0
- package/ui/notice/Notices.js +1 -0
- package/ui/notice/Notices.md +59 -0
- package/ui/notice/Notices.tsx +1 -0
- package/ui/page/HTML.d.ts +1 -0
- package/ui/page/HTML.js +1 -0
- package/ui/page/HTML.md +36 -0
- package/ui/page/HTML.tsx +1 -0
- package/ui/page/Head.d.ts +1 -0
- package/ui/page/Head.js +1 -0
- package/ui/page/Head.md +26 -0
- package/ui/page/Head.tsx +1 -0
- package/ui/page/Page.d.ts +1 -0
- package/ui/page/Page.js +1 -0
- package/ui/page/Page.md +42 -0
- package/ui/page/Page.tsx +1 -0
- package/ui/router/Navigation.d.ts +1 -0
- package/ui/router/Navigation.js +1 -0
- package/ui/router/Navigation.md +41 -0
- package/ui/router/Navigation.tsx +1 -0
- package/ui/router/NavigationStore.md +34 -0
- package/ui/router/Router.d.ts +1 -0
- package/ui/router/Router.js +1 -0
- package/ui/router/Router.md +143 -0
- package/ui/router/Router.tsx +1 -0
- package/ui/style/TINT_CLASS.md +55 -0
- package/ui/transition/CollapseTransition.d.ts +1 -0
- package/ui/transition/CollapseTransition.js +1 -0
- package/ui/transition/CollapseTransition.md +34 -0
- package/ui/transition/CollapseTransition.tsx +1 -0
- package/ui/transition/FadeTransition.d.ts +1 -0
- package/ui/transition/FadeTransition.js +1 -0
- package/ui/transition/FadeTransition.md +36 -0
- package/ui/transition/FadeTransition.tsx +1 -0
- package/ui/transition/HorizontalTransition.d.ts +1 -0
- package/ui/transition/HorizontalTransition.js +1 -0
- package/ui/transition/HorizontalTransition.md +44 -0
- package/ui/transition/HorizontalTransition.tsx +1 -0
- package/ui/transition/Transition.d.ts +1 -0
- package/ui/transition/Transition.js +1 -0
- package/ui/transition/Transition.md +70 -0
- package/ui/transition/Transition.tsx +1 -0
- package/ui/transition/VerticalTransition.d.ts +1 -0
- package/ui/transition/VerticalTransition.js +1 -0
- package/ui/transition/VerticalTransition.md +34 -0
- package/ui/transition/VerticalTransition.tsx +1 -0
- package/ui/tree/TreeApp.d.ts +1 -0
- package/ui/tree/TreeApp.js +1 -0
- package/ui/tree/TreeApp.md +59 -0
- package/ui/tree/TreeApp.tsx +1 -0
- package/ui/tree/TreeMenu.d.ts +1 -0
- package/ui/tree/TreeMenu.js +1 -0
- package/ui/tree/TreeMenu.md +35 -0
- package/ui/tree/TreeMenu.tsx +1 -0
- package/ui/tree/TreeSidebar.d.ts +1 -0
- package/ui/tree/TreeSidebar.js +1 -0
- package/ui/tree/TreeSidebar.md +24 -0
- package/ui/tree/TreeSidebar.tsx +1 -0
- package/ui/util/getClass.md +55 -0
- package/ui/util/notify.md +50 -0
- package/ui/util/requireContext.md +24 -0
- package/ui/app/README.md +0 -32
- package/ui/block/README.md +0 -144
- package/ui/dialog/README.md +0 -80
- package/ui/docs/README.md +0 -71
- package/ui/form/README.md +0 -165
- package/ui/inline/README.md +0 -86
- package/ui/layout/README.md +0 -71
- package/ui/menu/README.md +0 -33
- package/ui/misc/README.md +0 -121
- package/ui/notice/README.md +0 -94
- package/ui/page/README.md +0 -56
- package/ui/router/README.md +0 -186
- package/ui/transition/README.md +0 -80
- package/ui/tree/README.md +0 -78
- package/ui/util/README.md +0 -153
package/ui/misc/README.md
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
# Misc
|
|
2
|
-
|
|
3
|
-
Cross-cutting utilities and components that don't belong to a single content category. These are the primitives other components in [ui](/ui) are built from — error handling, status colouring, markdown rendering, element dispatch, and page metadata.
|
|
4
|
-
|
|
5
|
-
## Error boundaries
|
|
6
|
-
|
|
7
|
-
`Catcher` is a React class component that catches errors thrown anywhere in its subtree and replaces the failed region with a fallback UI. Pass `as` to supply a custom error renderer; it defaults to `ErrorNotice` (an inline error notice with a retry button). `PageCatcher` is a convenience wrapper that uses `ErrorPage` instead — a full-page error display inside a `<CenteredLayout>`.
|
|
8
|
-
|
|
9
|
-
`RetryButton` reads the retry callback from the nearest `Catcher` via context and renders a `<Button>`. Returns `null` when there is no parent catcher.
|
|
10
|
-
|
|
11
|
-
`ErrorNotice` and `ErrorPage` can be used standalone when you need to display a known error without a boundary.
|
|
12
|
-
|
|
13
|
-
```tsx
|
|
14
|
-
import { PageCatcher, Catcher, ErrorNotice } from "shelving/ui";
|
|
15
|
-
|
|
16
|
-
// Catch and display errors for a whole page
|
|
17
|
-
<PageCatcher>
|
|
18
|
-
<MyPage />
|
|
19
|
-
</PageCatcher>
|
|
20
|
-
|
|
21
|
-
// Localised error boundary inside a panel
|
|
22
|
-
<Catcher as={ErrorNotice}>
|
|
23
|
-
<LiveFeed />
|
|
24
|
-
</Catcher>
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Status and colour
|
|
28
|
-
|
|
29
|
-
`Status` is the type (`"loading" | "info" | "success" | "warning" | "danger" | "error"`) and `StatusProps` is the matching props interface — a `status="error"` prop plus boolean aliases (`<Notice error>`). Use these as the canonical vocabulary for component state everywhere in the UI.
|
|
30
|
-
|
|
31
|
-
`getStatusClass` maps a `Status` string or `StatusProps` object to a CSS module class. Compose it with other class helpers when building components that need status colouring.
|
|
32
|
-
|
|
33
|
-
`Color` (from [ui/style](../style/)) exports `ColorProps` — a `color` prop taking a raw hue (`"red"`, `"blue"`, `"purple"`, `"green"`, etc.) — and `getColorClass`. Use `status` for semantic meaning and `color` for purely decorative differentiation.
|
|
34
|
-
|
|
35
|
-
`getTypographyClass` (from `Typography`) returns a class for the `size` prop (`size="small"` … `size="xxlarge"`), the `tint` prop, and the font-family (`code`, `sans`, `serif`, …) and alignment variants. Compose into components that need typography overrides without wrapping in an extra element.
|
|
36
|
-
|
|
37
|
-
## Loading spinner
|
|
38
|
-
|
|
39
|
-
`Loading` renders an animated SVG spinner. `LOADING` is a pre-keyed `<Loading />` constant — use it directly to avoid unnecessary reconciliation overhead.
|
|
40
|
-
|
|
41
|
-
```tsx
|
|
42
|
-
import { LOADING } from "shelving/ui";
|
|
43
|
-
|
|
44
|
-
{busy ? LOADING : children}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Status icon
|
|
48
|
-
|
|
49
|
-
`StatusIcon` picks the right icon for a given status and sizes it via the `size` prop (`"small"`, `"normal"`, `"large"`, `"xlarge"`, or `"xxlarge"`; defaults to the current line height). `info` is the default when no `status` prop is set.
|
|
50
|
-
|
|
51
|
-
```tsx
|
|
52
|
-
import { StatusIcon } from "shelving/ui";
|
|
53
|
-
|
|
54
|
-
<StatusIcon status="success" size="large" />
|
|
55
|
-
<StatusIcon status="error" />
|
|
56
|
-
<StatusIcon status="loading" size="small" />
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Tag
|
|
60
|
-
|
|
61
|
-
`Tag` is a small inline label. It accepts both `StatusProps` and `ColorProps`, plus `href` or `onClick` from `ClickableProps`, so it can be static or interactive.
|
|
62
|
-
|
|
63
|
-
```tsx
|
|
64
|
-
import { Tag } from "shelving/ui";
|
|
65
|
-
|
|
66
|
-
<Tag success>Active</Tag>
|
|
67
|
-
<Tag warning href="/billing">Overdue</Tag>
|
|
68
|
-
<Tag color="purple" size="small">Beta</Tag>
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Markup renderer
|
|
72
|
-
|
|
73
|
-
`Markup` parses a markup string and renders the resulting React nodes. It defaults to the full block + inline rule set and resolves links against the current `<Meta>` context. Wrap in `<Prose>` for longform typography.
|
|
74
|
-
|
|
75
|
-
```tsx
|
|
76
|
-
import { Prose, Markup } from "shelving/ui";
|
|
77
|
-
|
|
78
|
-
<Prose>
|
|
79
|
-
<Markup>{article.body}</Markup>
|
|
80
|
-
</Prose>
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Override any `MarkupOptions` prop directly on `<Markup>` when you need a custom rule set or a specific base URL.
|
|
84
|
-
|
|
85
|
-
## Element dispatch: `createMapper`
|
|
86
|
-
|
|
87
|
-
`createMapper` creates a `[Mapping, Mapper]` component pair backed by a private React context. `Mapper` walks a pre-walked element tree and replaces each matching element type with the registered component. `Mapping` lets a subtree override or extend the dispatch table.
|
|
88
|
-
|
|
89
|
-
This is the right tool when a component renders a tree of typed elements and callers need to swap in their own renderers for specific types.
|
|
90
|
-
|
|
91
|
-
```tsx
|
|
92
|
-
import { createMapper } from "shelving/ui";
|
|
93
|
-
|
|
94
|
-
const [TreeMapping, TreeMapper] = createMapper({
|
|
95
|
-
"tree-element": TreeRow,
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// In a consumer:
|
|
99
|
-
<TreeMapper>{walkElements(children)}</TreeMapper>
|
|
100
|
-
|
|
101
|
-
// Override one entry in a subtree:
|
|
102
|
-
<TreeMapping mapping={{ "tree-element": SpecialTreeRow }}>
|
|
103
|
-
<TreeMapper>{walkElements(children)}</TreeMapper>
|
|
104
|
-
</TreeMapping>
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## Page metadata context
|
|
108
|
-
|
|
109
|
-
`MetaContext` is the raw React context holding the current `Meta` (URL, base root, and other page-level properties). It is published by `<HTML>` and consumed internally by `<Markup>`, `<Link>`, `<Router>`, and similar components.
|
|
110
|
-
|
|
111
|
-
`requireMeta` reads the context and optionally merges in override props — use this in components that need to resolve URLs against the current page.
|
|
112
|
-
|
|
113
|
-
`requireMetaURL` resolves the current `url` against the meta `root` and returns the meta extended with the site-root-relative `path` and the extracted query `params`. Throws if `url` is unset or sits on a different origin to `root`.
|
|
114
|
-
|
|
115
|
-
## See also
|
|
116
|
-
|
|
117
|
-
- [ui/block](/ui/block) — block content components that compose with `Tag`, `Markup`, and `Prose`
|
|
118
|
-
- [ui/inline](/ui/inline) — inline content components
|
|
119
|
-
- [ui/notice](/ui/notice) — `Notice` component used inside `ErrorNotice`
|
|
120
|
-
- [ui/router](/ui/router) — `<Router>` and `<Navigation>` that publish into `MetaContext`
|
|
121
|
-
- [markup](/markup) — the markup parser and rule set underlying `<Markup>`
|
package/ui/notice/README.md
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# Notices
|
|
2
|
-
|
|
3
|
-
Inline and global toast-style notices for user feedback. `<Notice>` is a standalone status banner; `<Notices>` is the global list that listens for dispatched events and shows them automatically.
|
|
4
|
-
|
|
5
|
-
## Concepts
|
|
6
|
-
|
|
7
|
-
**`<Notice>`** renders an `<aside>` with a status icon and a message. It accepts a `status` prop (`"info"`, `"success"`, `"error"`, `"danger"`, `"loading"`, etc.) and maps it to the appropriate colour and ARIA role. The icon defaults to `<StatusIcon>` but can be replaced or hidden.
|
|
8
|
-
|
|
9
|
-
**`<Message>`** is a lighter variant — a `<p>` tag with the same status colours, for short inline feedback inside a form or card rather than a banner.
|
|
10
|
-
|
|
11
|
-
**`<Notices>`** renders the global list of active notices. It subscribes to `"notice"` events on `window` (dispatched by the `notify` helpers in [ui/util](/ui/util)) and shows each one as a `<Notice>`. Notices auto-dismiss after 5 seconds unless they carry a `"loading"` status.
|
|
12
|
-
|
|
13
|
-
**`NoticeStore` and `NoticesStore`** are the reactive stores behind `<Notices>`. `NoticesStore` is an `ArrayStore<NoticeStore>` that manages the list. Each `NoticeStore` is a `DataStore` holding one notice's message and status, and removes itself from the list when it closes.
|
|
14
|
-
|
|
15
|
-
## Basic usage
|
|
16
|
-
|
|
17
|
-
Place `<Notice>` anywhere to show inline status feedback.
|
|
18
|
-
|
|
19
|
-
```tsx
|
|
20
|
-
import { Notice } from "shelving/ui";
|
|
21
|
-
|
|
22
|
-
<Notice status="success">Your changes have been saved.</Notice>
|
|
23
|
-
<Notice status="error">Something went wrong.</Notice>
|
|
24
|
-
<Notice status="loading" />
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
When `status` is omitted, `<Notice>` defaults to `"info"` if `children` is present, or `"loading"` if not.
|
|
28
|
-
|
|
29
|
-
Use `<Message>` for shorter inline feedback inside paragraphs or forms.
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
import { Message } from "shelving/ui";
|
|
33
|
-
|
|
34
|
-
<Message status="error">This field is required.</Message>
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Global notices
|
|
38
|
-
|
|
39
|
-
Mount `<Notices>` once near the root of your app. It renders at that point in the DOM and listens automatically.
|
|
40
|
-
|
|
41
|
-
```tsx
|
|
42
|
-
import { Notices } from "shelving/ui";
|
|
43
|
-
|
|
44
|
-
export function AppLayout({ children }) {
|
|
45
|
-
return (
|
|
46
|
-
<>
|
|
47
|
-
{children}
|
|
48
|
-
<Notices />
|
|
49
|
-
</>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Dispatch notices from anywhere — no context required:
|
|
55
|
-
|
|
56
|
-
```tsx
|
|
57
|
-
import { notifySuccess, notifyError, callNotified } from "shelving/ui";
|
|
58
|
-
|
|
59
|
-
// Direct dispatch.
|
|
60
|
-
notifySuccess("Profile updated.");
|
|
61
|
-
notifyError("Could not connect.");
|
|
62
|
-
|
|
63
|
-
// Wrap an async callback — dispatches success or error automatically.
|
|
64
|
-
callNotified(async () => {
|
|
65
|
-
await saveProfile(data);
|
|
66
|
-
return "Profile updated.";
|
|
67
|
-
});
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Programmatic control via `NoticesStore`
|
|
71
|
-
|
|
72
|
-
The global `NOTICES` singleton is exported for advanced use — for example, keeping a reference to a specific notice so you can update or close it manually.
|
|
73
|
-
|
|
74
|
-
```tsx
|
|
75
|
-
import { NOTICES } from "shelving/ui";
|
|
76
|
-
|
|
77
|
-
// Show a loading notice and hold a reference to it.
|
|
78
|
-
const notice = NOTICES.show(undefined, "loading");
|
|
79
|
-
|
|
80
|
-
await uploadFile(file);
|
|
81
|
-
|
|
82
|
-
// Update the same notice in place.
|
|
83
|
-
notice.show("Upload complete.", "success");
|
|
84
|
-
|
|
85
|
-
// Or close it immediately.
|
|
86
|
-
notice.close();
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
`NoticeStore` implements `AsyncDisposable`, so it can be used in an `await using` block to close automatically when the scope exits.
|
|
90
|
-
|
|
91
|
-
## See also
|
|
92
|
-
|
|
93
|
-
- [ui/util](/ui/util) — `notify`, `notifySuccess`, `notifyError`, `callNotified`, and `subscribeNotices`
|
|
94
|
-
- [store](/store) — `ArrayStore` and `DataStore` that `NoticesStore` and `NoticeStore` extend
|
package/ui/page/README.md
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# Page
|
|
2
|
-
|
|
3
|
-
Document-level components for the HTML shell and per-page metadata. These three components own the `<html>`, `<head>`, and per-page `<title>` / `<meta>` output for a shelving app.
|
|
4
|
-
|
|
5
|
-
## Components
|
|
6
|
-
|
|
7
|
-
| Component | Purpose |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `<HTML>` | Renders the full `<html>` document shell with `<head>` and `<body>`. Use this as the outermost wrapper for SSR. |
|
|
10
|
-
| `<Page>` | Wraps one page inside the app. Merges per-page meta props into context and emits hoistable head tags (title, description, meta, links, scripts) that React 19 lifts into `<head>`. Also updates `window.history` to match the page URL. |
|
|
11
|
-
| `<Head>` | Low-level: emits the hoistable tags from the current `Meta` context. `<Page>` renders it automatically — you rarely need it directly. |
|
|
12
|
-
|
|
13
|
-
`<HTML>` and `<Page>` both accept `PossibleMeta` props (`app`, `root`, `url`, `title`, `description`, `language`, `tags`, `links`, `stylesheets`, `modules`, `scripts`) and merge them into the context they provide to children.
|
|
14
|
-
|
|
15
|
-
## SSR usage
|
|
16
|
-
|
|
17
|
-
```tsx
|
|
18
|
-
import { HTML, Page } from "shelving/ui";
|
|
19
|
-
import { Navigation, Router } from "shelving/ui";
|
|
20
|
-
|
|
21
|
-
// Server-side render — pass the request URL to <HTML>.
|
|
22
|
-
renderToString(
|
|
23
|
-
<HTML app="My App" root="https://example.com/" url={requestUrl} language="en">
|
|
24
|
-
<Navigation>
|
|
25
|
-
<Router routes={{
|
|
26
|
-
"/": HomePage,
|
|
27
|
-
"/about": AboutPage,
|
|
28
|
-
}}/>
|
|
29
|
-
</Navigation>
|
|
30
|
-
</HTML>
|
|
31
|
-
);
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Per-page metadata
|
|
35
|
-
|
|
36
|
-
```tsx
|
|
37
|
-
function UserPage({ id }: { id: string }) {
|
|
38
|
-
return (
|
|
39
|
-
<Page title="User profile" url={`/users/${id}`} description="View user details.">
|
|
40
|
-
<Section>…</Section>
|
|
41
|
-
</Page>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
The title is composed with the app name from the surrounding context: `"User profile - My App"`.
|
|
47
|
-
|
|
48
|
-
## How hoisting works
|
|
49
|
-
|
|
50
|
-
`<Page>` renders `<Head>` inline. React 19 automatically hoists `<title>`, `<meta>`, `<link>`, and `<script>` elements into the document `<head>`, so you don't need a portal. `<base>` is the exception — it is not hoistable and lives only in `<HTML>`.
|
|
51
|
-
|
|
52
|
-
## See also
|
|
53
|
-
|
|
54
|
-
- [`app`](/ui/app) — `<App>` for client-side-only roots (no `<html>` shell needed)
|
|
55
|
-
- [`router`](/ui/router) — `<Navigation>` and `<Router>` for URL-driven rendering
|
|
56
|
-
- [`layout`](/ui/layout) — layouts that go inside `<Page>`
|
package/ui/router/README.md
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
# Router
|
|
2
|
-
|
|
3
|
-
Client-side routing for shelving apps.
|
|
4
|
-
|
|
5
|
-
Two pieces:
|
|
6
|
-
|
|
7
|
-
| Component | Job |
|
|
8
|
-
| --------------- | ---------------------------------------------------------------------------------------------- |
|
|
9
|
-
| `<Navigation>` | One per app. Owns URL state, intercepts link clicks, listens for `popstate`. |
|
|
10
|
-
| `<Router>` | Pure matcher. Reads URL from `<Meta>`, matches `routes`, renders the matched element. |
|
|
11
|
-
|
|
12
|
-
Plus `requireNavigation()` for imperative `forward()` / `redirect()` calls from anywhere in the tree.
|
|
13
|
-
|
|
14
|
-
`<Router>` reads URL state from `<Meta>`, so it works with no `<Navigation>` at all (SSR, static rendering, tests). `<Navigation>` is what publishes a *live* URL into `<Meta>` on the client.
|
|
15
|
-
|
|
16
|
-
## Basic setup
|
|
17
|
-
|
|
18
|
-
```tsx
|
|
19
|
-
<HTML url={initialUrl} root="https://example.com/">
|
|
20
|
-
<Navigation>
|
|
21
|
-
<Router routes={{
|
|
22
|
-
"/": HomePage,
|
|
23
|
-
"/users/{id}": UserPage,
|
|
24
|
-
"/about": AboutPage,
|
|
25
|
-
}}/>
|
|
26
|
-
</Navigation>
|
|
27
|
-
</HTML>
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
- Route keys are `AbsolutePath` strings starting with `/`.
|
|
31
|
-
- Placeholders (`{id}`, `:id`, `[id]`, `${id}`, `{{id}}`) are passed to function/component routes as props (merged with URL `?query` params; placeholders win on conflict).
|
|
32
|
-
- A string value (e.g. `"/users/123"`) is a redirect — visiting the key path navigates to the target.
|
|
33
|
-
- `<Router>` itself accepts `PossibleMeta` props (`url`, `base`, etc.) to override the surrounding context.
|
|
34
|
-
|
|
35
|
-
## Route value types
|
|
36
|
-
|
|
37
|
-
| Value | Behaviour |
|
|
38
|
-
| --------------------- | ---------------------------------------------------------------------- |
|
|
39
|
-
| `RouteComponent` | Rendered as `<Component {...params}/>` with merged placeholder + query. |
|
|
40
|
-
| `AbsolutePath` string | Redirects to that path (placeholders resolved against the source). |
|
|
41
|
-
| `ReactElement` | Rendered as-is — use for layout wrapping or composing inner routers. |
|
|
42
|
-
|
|
43
|
-
## Placeholder syntax
|
|
44
|
-
|
|
45
|
-
All forms produce the same matched value — pick whichever reads best:
|
|
46
|
-
|
|
47
|
-
| Form | Single segment | Catchall (one+ segments, also matches empty) |
|
|
48
|
-
| ----------------- | ---------------------- | -------------------------------------------- |
|
|
49
|
-
| Anonymous | `*` (named `"0"`) | `**` / `***` / `****` (named `"0"`) |
|
|
50
|
-
| Colon | `:name` | `:name*` / `:name**` |
|
|
51
|
-
| Single brace | `{name}` | `{...name}` / `{name*}` / `{....name}` |
|
|
52
|
-
| Square bracket | `[name]` | `[...name]` / `[name*]` |
|
|
53
|
-
| Dollar brace | `${name}` | `${...name}` / `${name*}` |
|
|
54
|
-
| Double brace | `{{name}}` | `{{...name}}` / `{{name*}}` |
|
|
55
|
-
|
|
56
|
-
Modifier chars are tolerant: one-or-more stars and three-or-more dots are all equivalent. So `{path*}`, `{path**}`, `{...path}`, and `{....path}` all behave the same.
|
|
57
|
-
|
|
58
|
-
Catchall placeholders allow empty values, so a trailing catchall matches the trailing-slash-absent variant too — `/files/{...path}` matches both `/files`, `/files/`, and `/files/a/b/c`.
|
|
59
|
-
|
|
60
|
-
## Layout wrapping
|
|
61
|
-
|
|
62
|
-
Put layout JSX as the route value with another `<Router>` inside.
|
|
63
|
-
|
|
64
|
-
```tsx
|
|
65
|
-
const SIDEBARRED_ROUTES = {
|
|
66
|
-
"/users": <UsersPage/>,
|
|
67
|
-
"/users/{id}": <UserPage/>,
|
|
68
|
-
"/settings": <SettingsPage/>,
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
<Router routes={{
|
|
72
|
-
"/": <HomePage/>,
|
|
73
|
-
"/{...path}": (
|
|
74
|
-
<SidebarLayout>
|
|
75
|
-
<Router routes={SIDEBARRED_ROUTES}/>
|
|
76
|
-
</SidebarLayout>
|
|
77
|
-
),
|
|
78
|
-
}}/>
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
The outer router matches everything, wraps in `<SidebarLayout>`, and hands off to the inner router. Since `<Router>` reads its URL from `<Meta>`, the inner router sees the same URL.
|
|
82
|
-
|
|
83
|
-
## Section / microsite pattern
|
|
84
|
-
|
|
85
|
-
A self-contained "section" of the app — its own URL prefix, its own routes — composes via a catchall + a function route value that hands the captured sub-path to a nested router.
|
|
86
|
-
|
|
87
|
-
```tsx
|
|
88
|
-
<Router routes={{
|
|
89
|
-
"/": <HomePage/>,
|
|
90
|
-
"/users/{...path}": ({ path = "/" }) => (
|
|
91
|
-
<Router routes={{
|
|
92
|
-
"/": UsersPage,
|
|
93
|
-
"/{id}": UserPage,
|
|
94
|
-
}} url={path}/>
|
|
95
|
-
),
|
|
96
|
-
}}/>
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
The outer router captures everything under `/users` into the `path` placeholder, then the inner router treats `path` as its starting URL. The inner router's `"/"` matches the bare `/users`; `/{id}` matches `/users/123`.
|
|
100
|
-
|
|
101
|
-
Pull that out into a dedicated component for readability:
|
|
102
|
-
|
|
103
|
-
```tsx
|
|
104
|
-
const USER_ROUTES = {
|
|
105
|
-
"/": UsersPage,
|
|
106
|
-
"/{id}": UserPage,
|
|
107
|
-
"/{id}/edit": UserEditPage,
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export function UserRouter({ path = "/" }: { path?: AbsolutePath }) {
|
|
111
|
-
return <Router routes={USER_ROUTES} url={path}/>;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// then at the call site:
|
|
115
|
-
<Router routes={{
|
|
116
|
-
"/": <HomePage/>,
|
|
117
|
-
"/users/{...path}": ({ path }) => <UserRouter path={path}/>,
|
|
118
|
-
"/blog/{...path}": ({ path }) => <BlogRouter path={path}/>,
|
|
119
|
-
}}/>
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Each section module owns its routes and exposes one component. The top-level router stays a flat list of section prefixes.
|
|
123
|
-
|
|
124
|
-
## Stacking layouts and sections
|
|
125
|
-
|
|
126
|
-
The two patterns compose. Wrap a bunch of routes in a layout, then route further inside it:
|
|
127
|
-
|
|
128
|
-
```tsx
|
|
129
|
-
const SIDEBARRED_ROUTES = {
|
|
130
|
-
"/": <Dashboard/>,
|
|
131
|
-
"/users/{...path}": ({ path }) => <UserRouter path={path}/>,
|
|
132
|
-
"/blog/{...path}": ({ path }) => <BlogRouter path={path}/>,
|
|
133
|
-
"/settings": <SettingsPage/>,
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
<Router routes={{
|
|
137
|
-
"/login": <LoginPage/>, // no sidebar
|
|
138
|
-
"/{...path}": ( // everything else wrapped
|
|
139
|
-
<SidebarLayout>
|
|
140
|
-
<Router routes={SIDEBARRED_ROUTES}/>
|
|
141
|
-
</SidebarLayout>
|
|
142
|
-
),
|
|
143
|
-
}}/>
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
`/login` skips the sidebar. Every other path goes through `<SidebarLayout>` and then the inner router decides what to render — including handing off to section routers via the catchall pattern.
|
|
147
|
-
|
|
148
|
-
## Navigation
|
|
149
|
-
|
|
150
|
-
Inside a component, get the navigation store for imperative URL changes:
|
|
151
|
-
|
|
152
|
-
```tsx
|
|
153
|
-
const nav = requireNavigation();
|
|
154
|
-
nav.forward("/users/123"); // push history
|
|
155
|
-
nav.redirect("/login"); // replace history
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
Same-origin anchor clicks are intercepted automatically and turned into `forward()` calls. Add a `download` attribute to opt out.
|
|
159
|
-
|
|
160
|
-
## `<NavigationIsolate>`
|
|
161
|
-
|
|
162
|
-
Force a full remount of children whenever the URL changes:
|
|
163
|
-
|
|
164
|
-
```tsx
|
|
165
|
-
<NavigationIsolate>
|
|
166
|
-
<ExpensiveStatefulThing/>
|
|
167
|
-
</NavigationIsolate>
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## SSR / static rendering
|
|
171
|
-
|
|
172
|
-
`<Router>` has no client requirements — it reads from `<Meta>` and re-renders when context changes. For static rendering, set `url` and `root` on the outer wrapper and skip `<Navigation>`:
|
|
173
|
-
|
|
174
|
-
```tsx
|
|
175
|
-
renderToString(
|
|
176
|
-
<HTML url={path} root="https://example.com/">
|
|
177
|
-
<Router routes={…}/>
|
|
178
|
-
</HTML>
|
|
179
|
-
);
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
For client-side SPAs, wrap the same tree in `<Navigation>` for live URL updates.
|
|
183
|
-
|
|
184
|
-
## Base paths
|
|
185
|
-
|
|
186
|
-
`root="https://example.com/app/"` is supported. The base path prefix is stripped from the URL before route matching via `matchURLPrefix`. URLs that fall outside the base render as `null` from the router.
|
package/ui/transition/README.md
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# Transition
|
|
2
|
-
|
|
3
|
-
React 19 View Transition wrappers for animated enter and leave effects. Each component wraps its children in React's `<ViewTransition>` and applies a named CSS transition class, so swapping content between renders produces a smooth animation.
|
|
4
|
-
|
|
5
|
-
## Components
|
|
6
|
-
|
|
7
|
-
| Component | Default transition | Forward / back |
|
|
8
|
-
|---|---|---|
|
|
9
|
-
| `<FadeTransition>` | `fade` | — |
|
|
10
|
-
| `<CollapseTransition>` | `collapse` | — |
|
|
11
|
-
| `<VerticalTransition>` | `slideDown` | forward: `slideDown`, back: `slideUp` |
|
|
12
|
-
| `<HorizontalTransition>` | `slideRight` | forward: `slideRight`, back: `slideLeft` |
|
|
13
|
-
| `<Transition>` | configurable | configurable |
|
|
14
|
-
|
|
15
|
-
`<VerticalTransition>` and `<HorizontalTransition>` are direction-aware: they read the transition type set by `setTransitionType()` and choose the correct slide direction.
|
|
16
|
-
|
|
17
|
-
## Basic usage
|
|
18
|
-
|
|
19
|
-
Wrap any content that should animate when it mounts or unmounts:
|
|
20
|
-
|
|
21
|
-
```tsx
|
|
22
|
-
import { FadeTransition } from "shelving/ui";
|
|
23
|
-
|
|
24
|
-
function Panel({ visible }: { visible: boolean }) {
|
|
25
|
-
return visible ? (
|
|
26
|
-
<FadeTransition>
|
|
27
|
-
<div className="panel">…</div>
|
|
28
|
-
</FadeTransition>
|
|
29
|
-
) : null;
|
|
30
|
-
}
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Direction-aware routing transitions
|
|
34
|
-
|
|
35
|
-
Set the transition type before a navigation, then wrap routed content in the appropriate transition:
|
|
36
|
-
|
|
37
|
-
```tsx
|
|
38
|
-
import { HorizontalTransition, setTransitionType } from "shelving/ui";
|
|
39
|
-
|
|
40
|
-
function navigate(direction: "forward" | "back") {
|
|
41
|
-
startTransition(() => {
|
|
42
|
-
setTransitionType(direction);
|
|
43
|
-
nav.forward(nextUrl);
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// In the layout:
|
|
48
|
-
<HorizontalTransition>
|
|
49
|
-
<Router routes={ROUTES}/>
|
|
50
|
-
</HorizontalTransition>
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
When `direction` is `"forward"` the content slides right; when `"back"` it slides left.
|
|
54
|
-
|
|
55
|
-
## Overlay variant
|
|
56
|
-
|
|
57
|
-
Add `overlay` to raise the transition group above surrounding content during animation (`z-index: 100`):
|
|
58
|
-
|
|
59
|
-
```tsx
|
|
60
|
-
<FadeTransition overlay>
|
|
61
|
-
<Notification/>
|
|
62
|
-
</FadeTransition>
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Custom transitions
|
|
66
|
-
|
|
67
|
-
Use `<Transition>` directly to specify any transition class names:
|
|
68
|
-
|
|
69
|
-
```tsx
|
|
70
|
-
<Transition default="zoom" forward="zoomIn" back="zoomOut">
|
|
71
|
-
{children}
|
|
72
|
-
</Transition>
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Class names must correspond to `::view-transition-class()` rules in your CSS.
|
|
76
|
-
|
|
77
|
-
## See also
|
|
78
|
-
|
|
79
|
-
- [`router`](/ui/router) — `<Navigation>` triggers route changes that transitions animate
|
|
80
|
-
- [`dialog`](/ui/dialog) — animate dialog enter and leave
|
package/ui/tree/README.md
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# Tree components
|
|
2
|
-
|
|
3
|
-
Shell components for a tree-based documentation site. Given a `TreeElement` from [extract](/extract), these components produce a complete site: a sidebar menu, client-side routing, and a rendered page for every element.
|
|
4
|
-
|
|
5
|
-
## Concepts
|
|
6
|
-
|
|
7
|
-
**`<TreeApp>` is the entry point.** It wraps `<App>` with error catching and a sidebar layout, then wires `<Navigation>` and a `<Router>` covering two routes: `/` renders the root via `<TreePage>`, and `/{...path}` passes every deeper URL to `<TreePage>` as well. The sidebar is always a `<TreeSidebar>`.
|
|
8
|
-
|
|
9
|
-
**`<TreeRouter>` resolves and dispatches.** It resolves the current URL to an element with a single `map.get(path)` against the flattened tree (provided by `<TreeProvider>`), then hands the matched element to the right page renderer via `<TreeRouterMapper>`. It throws `NotFoundError` if nothing matches and no `fallback` is given.
|
|
10
|
-
|
|
11
|
-
**`<TreeMenu>` and `<TreeSidebar>` build navigation.** `<TreeSidebar>` renders a single home link for the root, then its children via `<TreeMenuMapper>`. `<TreeMenu>` renders a menu from a tree element's children directly. Only generic `tree-element` nodes appear — code symbols are kept off the navigation.
|
|
12
|
-
|
|
13
|
-
**`<TreeCards>` renders a card list.** It dispatches each child element to a card renderer via `<TreeCardMapper>`; each card links straight to its element's stamped `path`. Used by the page renderers in [ui/docs](/ui/docs) to fill out directory and file pages.
|
|
14
|
-
|
|
15
|
-
**`<TreeProvider>` flattens the tree — the one transform the UI runs on.** It flattens the tree once (via `flattenTree()`), which stamps a canonical `path` on every element and indexes them into a map keyed by both flat name and canonical path, then shares it on `TreeContext`. Descendants read it with `useTreeMap()`: the router resolves a URL with `map.get(path)`, and cross-references (`<TreeButton>`, breadcrumbs) resolve by flat key (`"Store"`, `"Store.get"`) or canonical path (`"/schema/BooleanSchema"`) and link to the resolved element's `path`. Nested providers merge their maps, so links resolve across a combined set of trees.
|
|
16
|
-
|
|
17
|
-
**`<TreeBreadcrumbs>` renders an ancestor trail.** Given a page's `path`, it looks each ancestor prefix up in the tree map (so it needs a `<TreeProvider>` above) and renders a `<nav>` of links separated by `›` icons, with section-level block spacing (`BLOCK_CLASS`, overridable via the `space` prop). Works with any tree — the current page is omitted (the page title already names it).
|
|
18
|
-
|
|
19
|
-
**Mappings — override any renderer.** Each dispatch layer is backed by a `[Mapping, Mapper]` pair created by `createMapper()`. Wrap any subtree with a `*Mapping` component to swap the renderer for a specific element type without touching anything else.
|
|
20
|
-
|
|
21
|
-
| Exported pair | Element types covered | What it overrides |
|
|
22
|
-
|---|---|---|
|
|
23
|
-
| `TreePageMapping` / `TreePageMapper` | `tree-element`, `tree-documentation` | Full-page renderer |
|
|
24
|
-
| `TreeMenuMapping` / `TreeMenuMapper` | `tree-element`, `tree-documentation` | Sidebar menu item |
|
|
25
|
-
| `TreeCardMapping` / `TreeCardMapper` | `tree-element`, `tree-documentation` | Card in a listing |
|
|
26
|
-
|
|
27
|
-
## Basic usage
|
|
28
|
-
|
|
29
|
-
```tsx
|
|
30
|
-
import { TreeApp } from "shelving/ui";
|
|
31
|
-
|
|
32
|
-
// tree is a TreeElement returned by DirectoryExtractor.
|
|
33
|
-
<TreeApp tree={tree} />
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
That single line produces a complete documentation site.
|
|
37
|
-
|
|
38
|
-
## Adding custom routes
|
|
39
|
-
|
|
40
|
-
Pass extra routes to `<TreeApp>`. They are merged before the tree routes, so they take precedence on conflicts.
|
|
41
|
-
|
|
42
|
-
```tsx
|
|
43
|
-
<TreeApp tree={tree} routes={{ "/changelog": ChangelogPage }} />
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Overriding a renderer
|
|
47
|
-
|
|
48
|
-
Wrap the app (or any subtree) with a `*Mapping` component to replace the renderer for one element type.
|
|
49
|
-
|
|
50
|
-
```tsx
|
|
51
|
-
import { TreeApp, TreePageMapping } from "shelving/ui";
|
|
52
|
-
|
|
53
|
-
<TreePageMapping mapping={{ "tree-element": MyTreePage }}>
|
|
54
|
-
<TreeApp tree={tree} />
|
|
55
|
-
</TreePageMapping>
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
The same pattern works for `TreeMenuMapping` (sidebar items) and `TreeCardMapping` (cards inside directory listings).
|
|
59
|
-
|
|
60
|
-
## Using menu and sidebar components directly
|
|
61
|
-
|
|
62
|
-
For finer layout control, use `<TreeSidebar>` or `<TreeMenu>` outside `<TreeApp>`.
|
|
63
|
-
|
|
64
|
-
```tsx
|
|
65
|
-
import { TreeMenu, TreeSidebar } from "shelving/ui";
|
|
66
|
-
|
|
67
|
-
// A home link + children menu combined — the default sidebar.
|
|
68
|
-
<TreeSidebar tree={root} />
|
|
69
|
-
|
|
70
|
-
// Just the navigation menu from a subtree's children.
|
|
71
|
-
<TreeMenu tree={section} path="/docs" />
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## See also
|
|
75
|
-
|
|
76
|
-
- [extract](/extract) — builds the `TreeElement` tree that `<TreeApp>` consumes
|
|
77
|
-
- [ui/docs](/ui/docs) — the default page and card renderers dispatched by the mappers
|
|
78
|
-
- [ui/router](/ui/router) — `<Navigation>` and `<Router>` wired inside `<TreeApp>`
|