@bapla/site-theme 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/LICENSE +21 -0
- package/README.md +169 -2
- package/dist/base.css +331 -0
- package/dist/chunk-RYCW4YWV.js +69 -0
- package/dist/imgproxy-rioGvvyv.d.ts +189 -0
- package/dist/index.d.ts +220 -0
- package/dist/index.js +904 -0
- package/dist/server.d.ts +26 -0
- package/dist/server.js +31 -0
- package/package.json +65 -4
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, ComponentType } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* What the delivery API of Bapla Websites serves, as this package reads it.
|
|
6
|
+
* Field names follow the API (snake_case).
|
|
7
|
+
*/
|
|
8
|
+
type Shade = '50' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | '950';
|
|
9
|
+
/** A colour ramp, `#rrggbb` per shade. */
|
|
10
|
+
type Ramp = Record<Shade, string>;
|
|
11
|
+
interface Font {
|
|
12
|
+
/** The Fontsource id, e.g. `inter`, `playfair-display`. */
|
|
13
|
+
id: string;
|
|
14
|
+
family: string;
|
|
15
|
+
fallback: 'sans-serif' | 'serif' | 'monospace';
|
|
16
|
+
}
|
|
17
|
+
type TypeLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p';
|
|
18
|
+
interface TypeStyle {
|
|
19
|
+
/** A CSS length, e.g. `2.5rem`. */
|
|
20
|
+
size: string;
|
|
21
|
+
weight: number;
|
|
22
|
+
line_height: number;
|
|
23
|
+
/** A CSS length, e.g. `-0.01em`. */
|
|
24
|
+
letter_spacing: string;
|
|
25
|
+
}
|
|
26
|
+
/** The site's Appearance configuration, defaults resolved by the API. */
|
|
27
|
+
interface ResolvedAppearance {
|
|
28
|
+
mode: 'light' | 'dark' | 'both';
|
|
29
|
+
colors: {
|
|
30
|
+
primary: Ramp;
|
|
31
|
+
secondary: Ramp;
|
|
32
|
+
accent: Ramp;
|
|
33
|
+
neutral: Ramp;
|
|
34
|
+
background: string;
|
|
35
|
+
text: string;
|
|
36
|
+
};
|
|
37
|
+
fonts: {
|
|
38
|
+
body: Font;
|
|
39
|
+
heading: Font;
|
|
40
|
+
};
|
|
41
|
+
type: Record<TypeLevel, TypeStyle>;
|
|
42
|
+
/** A CSS length, e.g. `0.5rem`. */
|
|
43
|
+
radius: string;
|
|
44
|
+
}
|
|
45
|
+
/** A media as the delivery API serves it, on the site's own domain. */
|
|
46
|
+
interface MediaValue {
|
|
47
|
+
id: string;
|
|
48
|
+
/** `/_media/web_med_…/name.jpg` */
|
|
49
|
+
url: string;
|
|
50
|
+
filename: string;
|
|
51
|
+
mime: string;
|
|
52
|
+
width: number | null;
|
|
53
|
+
height: number | null;
|
|
54
|
+
alt: string | null;
|
|
55
|
+
/** Fractions of the width and the height, 0 to 1. */
|
|
56
|
+
focal_point: {
|
|
57
|
+
x: number;
|
|
58
|
+
y: number;
|
|
59
|
+
} | null;
|
|
60
|
+
}
|
|
61
|
+
/** A `link` field's value. `url` may still be a node id the API did not resolve. */
|
|
62
|
+
interface LinkValue {
|
|
63
|
+
url: string;
|
|
64
|
+
label: string | null;
|
|
65
|
+
new_tab: boolean;
|
|
66
|
+
}
|
|
67
|
+
/** A node of a blocks tree. */
|
|
68
|
+
interface Block {
|
|
69
|
+
id: string;
|
|
70
|
+
type: string;
|
|
71
|
+
props?: Record<string, unknown>;
|
|
72
|
+
children?: Block[];
|
|
73
|
+
}
|
|
74
|
+
/** A ProseMirror node, as Tiptap writes it. */
|
|
75
|
+
interface RichTextNode {
|
|
76
|
+
type: string;
|
|
77
|
+
attrs?: Record<string, unknown>;
|
|
78
|
+
marks?: {
|
|
79
|
+
type: string;
|
|
80
|
+
attrs?: Record<string, unknown>;
|
|
81
|
+
}[];
|
|
82
|
+
content?: RichTextNode[];
|
|
83
|
+
text?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface MediaTransform {
|
|
87
|
+
w?: number;
|
|
88
|
+
h?: number;
|
|
89
|
+
fit?: 'cover' | 'contain' | 'inside';
|
|
90
|
+
fm?: 'webp' | 'avif' | 'jpeg' | 'png';
|
|
91
|
+
/** Quality of a lossy format, 1 to 100 (80). */
|
|
92
|
+
q?: number;
|
|
93
|
+
}
|
|
94
|
+
/** The widths offered in a `srcset`. */
|
|
95
|
+
declare const MEDIA_WIDTHS: number[];
|
|
96
|
+
/**
|
|
97
|
+
* A media's address on the site's own domain, `/_media/<id>/<name>`, with
|
|
98
|
+
* the transformation asked for: the site relays it to the app, which reads
|
|
99
|
+
* the storage. No storage domain, no signed link in a page.
|
|
100
|
+
*/
|
|
101
|
+
declare function mediaUrl(media: Pick<MediaValue, 'id' | 'url' | 'filename'>, transform?: MediaTransform): string;
|
|
102
|
+
/** A media field's value: the object the API expanded, or an id left to `resolve`. */
|
|
103
|
+
declare function readMedia(value: unknown, resolve: (id: string) => MediaValue | null): MediaValue | null;
|
|
104
|
+
/** The `object-position` of a focal point. */
|
|
105
|
+
declare function objectPosition(focal: MediaValue['focal_point']): string | undefined;
|
|
106
|
+
|
|
107
|
+
/** What a block component receives. */
|
|
108
|
+
interface BlockProps<P extends Record<string, unknown> = Record<string, unknown>> {
|
|
109
|
+
block: Block;
|
|
110
|
+
props: P;
|
|
111
|
+
/** The block's children, rendered. */
|
|
112
|
+
children: ReactNode;
|
|
113
|
+
/** Renders a list of blocks with the same components: for a block that lays out its children itself. */
|
|
114
|
+
render: (blocks: Block[] | undefined) => ReactNode;
|
|
115
|
+
}
|
|
116
|
+
type BlockComponent = ComponentType<BlockProps<any>>;
|
|
117
|
+
/** The interface's words. French by default; a site in another language passes its own. */
|
|
118
|
+
interface ThemeLabels {
|
|
119
|
+
mainNavigation: string;
|
|
120
|
+
menu: string;
|
|
121
|
+
submenu: (label: string) => string;
|
|
122
|
+
breadcrumb: string;
|
|
123
|
+
carousel: string;
|
|
124
|
+
previous: string;
|
|
125
|
+
next: string;
|
|
126
|
+
slide: (index: number, count: number) => string;
|
|
127
|
+
goToSlide: (index: number) => string;
|
|
128
|
+
pause: string;
|
|
129
|
+
play: string;
|
|
130
|
+
embed: string;
|
|
131
|
+
}
|
|
132
|
+
declare const frenchLabels: ThemeLabels;
|
|
133
|
+
/** A media's URL for a transform: `/_media?…` by default, the signed companion with `imgproxyUrls()`. */
|
|
134
|
+
type ImageUrl = (media: MediaValue, transform?: MediaTransform) => string;
|
|
135
|
+
/** A size by name (`card`), what `<Image size="card">` asks for. */
|
|
136
|
+
interface ImageSize {
|
|
137
|
+
w?: number;
|
|
138
|
+
h?: number;
|
|
139
|
+
fit?: 'inside' | 'cover';
|
|
140
|
+
q?: number;
|
|
141
|
+
}
|
|
142
|
+
/** The sizes every site has; a site adds or replaces them with `imageSizes`. */
|
|
143
|
+
declare const defaultImageSizes: Record<string, ImageSize>;
|
|
144
|
+
interface SiteTheme {
|
|
145
|
+
/** Replacements and additions, by block type. */
|
|
146
|
+
components: Record<string, BlockComponent>;
|
|
147
|
+
/** A destination the API left as an id (`web_nod_…`): its path, or null to render the link inert. */
|
|
148
|
+
resolveLink: (url: string) => string | null;
|
|
149
|
+
/** A media the API left as an id (`web_med_…`). */
|
|
150
|
+
resolveMedia: (id: string) => MediaValue | null;
|
|
151
|
+
/** How an image's URL is built. */
|
|
152
|
+
imageUrl: ImageUrl;
|
|
153
|
+
/** Image sizes by name. */
|
|
154
|
+
imageSizes: Record<string, ImageSize>;
|
|
155
|
+
labels: ThemeLabels;
|
|
156
|
+
}
|
|
157
|
+
interface BlocksProviderProps {
|
|
158
|
+
components?: Record<string, BlockComponent>;
|
|
159
|
+
resolveLink?: SiteTheme['resolveLink'];
|
|
160
|
+
resolveMedia?: SiteTheme['resolveMedia'];
|
|
161
|
+
/** Signed URLs at the image companion: `imgproxyUrls()` of `@bapla/site-theme/server`. */
|
|
162
|
+
imageUrl?: ImageUrl;
|
|
163
|
+
/** Sizes added or replaced by name: `{ card: { w: 300, h: 300, fit: 'cover' } }`. */
|
|
164
|
+
imageSizes?: Record<string, ImageSize>;
|
|
165
|
+
labels?: Partial<ThemeLabels>;
|
|
166
|
+
children: ReactNode;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Replaces or adds block components, and says how ids are resolved. Nested
|
|
170
|
+
* providers add to the one above them.
|
|
171
|
+
*/
|
|
172
|
+
declare function BlocksProvider({ components, resolveLink, resolveMedia, imageUrl, imageSizes, labels, children }: BlocksProviderProps): react.JSX.Element;
|
|
173
|
+
declare function useSiteTheme(): SiteTheme;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The path of an image at the site's image companion (imgproxy on `/_img`,
|
|
177
|
+
* `features/websites.md` §5.9), before its signature:
|
|
178
|
+
* `/rs:fill:400:300:0/g:fp:0.5:0.3/q:80/plain/web_med_…/photo.jpg@webp`.
|
|
179
|
+
*
|
|
180
|
+
* The same translation as the app's `ImgproxyUrl`: `inside` is imgproxy's
|
|
181
|
+
* `fit`, `cover` its `fill` around the focal point; never enlarged; the
|
|
182
|
+
* source is the media's id and name, relative to the companion's origin.
|
|
183
|
+
* Signing needs the site's key: `imgproxyUrls()` of `@bapla/site-theme/server`.
|
|
184
|
+
*/
|
|
185
|
+
declare function imgproxyPath(media: Pick<MediaValue, 'id' | 'filename' | 'focal_point'>, transform?: MediaTransform): string;
|
|
186
|
+
/** Images the companion transforms: not SVG, not GIF (animated), not video. */
|
|
187
|
+
declare function isTransformable(media: Pick<MediaValue, 'mime'>): boolean;
|
|
188
|
+
|
|
189
|
+
export { type Block as B, type Font as F, type ImageSize as I, type LinkValue as L, type MediaValue as M, type ResolvedAppearance as R, type Shade as S, type ThemeLabels as T, type BlockComponent as a, type BlockProps as b, BlocksProvider as c, type BlocksProviderProps as d, type ImageUrl as e, MEDIA_WIDTHS as f, type MediaTransform as g, type Ramp as h, type RichTextNode as i, type SiteTheme as j, type TypeLevel as k, type TypeStyle as l, defaultImageSizes as m, frenchLabels as n, imgproxyPath as o, isTransformable as p, mediaUrl as q, objectPosition as r, readMedia as s, useSiteTheme as u };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { B as Block, R as ResolvedAppearance, F as Font, a as BlockComponent, b as BlockProps, M as MediaValue, L as LinkValue } from './imgproxy-rioGvvyv.js';
|
|
2
|
+
export { c as BlocksProvider, d as BlocksProviderProps, I as ImageSize, e as ImageUrl, f as MEDIA_WIDTHS, g as MediaTransform, h as Ramp, i as RichTextNode, S as Shade, j as SiteTheme, T as ThemeLabels, k as TypeLevel, l as TypeStyle, m as defaultImageSizes, n as frenchLabels, o as imgproxyPath, p as isTransformable, q as mediaUrl, r as objectPosition, s as readMedia, u as useSiteTheme } from './imgproxy-rioGvvyv.js';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A menu item, as the delivery API serves a menu (`features/websites.md`
|
|
8
|
+
* §5.8): the tree already resolved, disabled items gone, dynamic items
|
|
9
|
+
* already expanded — a labelled one as a heading over them, an unlabelled
|
|
10
|
+
* one in their place. Everything that depends on its shape reads it from
|
|
11
|
+
* here.
|
|
12
|
+
*/
|
|
13
|
+
interface MenuItem {
|
|
14
|
+
id: string;
|
|
15
|
+
kind: 'link' | 'heading' | 'panel';
|
|
16
|
+
label: string;
|
|
17
|
+
/** Null: a heading, a panel, or a link to a node no longer published (inert). */
|
|
18
|
+
url: string | null;
|
|
19
|
+
new_tab: boolean;
|
|
20
|
+
/** A link whose node is gone or unpublished — for an editor's preview. */
|
|
21
|
+
broken?: boolean;
|
|
22
|
+
/** The current page, or one of its ancestors. */
|
|
23
|
+
active?: boolean;
|
|
24
|
+
data: Record<string, unknown>;
|
|
25
|
+
/** `kind = panel` only: the blocks of the mega menu. */
|
|
26
|
+
panel: Block[] | null;
|
|
27
|
+
children: MenuItem[];
|
|
28
|
+
}
|
|
29
|
+
interface BreadcrumbItem {
|
|
30
|
+
label: string;
|
|
31
|
+
url: string | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** The font stack: the variable build first (Fontsource names it `<Family> Variable`), then the static one. */
|
|
35
|
+
declare function fontStack(font: Font): string;
|
|
36
|
+
/**
|
|
37
|
+
* The stylesheet a site gets from its Appearance: a Tailwind CSS 4 `@theme`
|
|
38
|
+
* block — so `bg-primary-600`, `font-heading`, `text-h2` exist — and the
|
|
39
|
+
* base rules of the body, the headings and the paragraphs.
|
|
40
|
+
*
|
|
41
|
+
* Written into the site's CSS at build time, after `@import "tailwindcss"`.
|
|
42
|
+
*/
|
|
43
|
+
declare function themeCss(appearance: ResolvedAppearance): string;
|
|
44
|
+
/**
|
|
45
|
+
* The font packages a site imports at build time: fonts are self-hosted,
|
|
46
|
+
* never fetched from Google Fonts or a CDN by the page.
|
|
47
|
+
*
|
|
48
|
+
* Variable builds by default (`@fontsource-variable/<id>`); with
|
|
49
|
+
* `variable: false`, the static weights the Appearance uses
|
|
50
|
+
* (`@fontsource/<id>/<weight>.css`).
|
|
51
|
+
*/
|
|
52
|
+
declare function fontImports(appearance: ResolvedAppearance, options?: {
|
|
53
|
+
variable?: boolean;
|
|
54
|
+
}): string[];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A blocks tree, `{id, type, props, children}`, rendered with the standard
|
|
58
|
+
* components and those the provider adds. A type nobody renders renders
|
|
59
|
+
* nothing: content written for a theme's block does not break another theme.
|
|
60
|
+
*/
|
|
61
|
+
declare function Blocks({ blocks }: {
|
|
62
|
+
blocks: Block[] | null | undefined;
|
|
63
|
+
}): react.JSX.Element;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The standard blocks of `websites` (`BlockCatalog`), by type. A theme
|
|
67
|
+
* replaces one, or adds its own, through `BlocksProvider`.
|
|
68
|
+
*/
|
|
69
|
+
declare const standardBlocks: Record<string, BlockComponent>;
|
|
70
|
+
|
|
71
|
+
declare function Section({ props, children }: BlockProps): react.JSX.Element;
|
|
72
|
+
/**
|
|
73
|
+
* Three modes: `equal` (as many equal columns as `columns`), `auto` (as
|
|
74
|
+
* many as fit `min_width`), `custom` (each column its `width`, in twelfths
|
|
75
|
+
* or in percent). Stacked into one column below `stack_below`.
|
|
76
|
+
*
|
|
77
|
+
* The layout is set through custom properties, so a media query of
|
|
78
|
+
* `base.css` can stack it and a theme can override it with a class.
|
|
79
|
+
*/
|
|
80
|
+
declare function Grid({ block, props, children }: BlockProps): react.JSX.Element;
|
|
81
|
+
declare function Column({ props, children }: BlockProps): react.JSX.Element;
|
|
82
|
+
declare function Divider({ props }: BlockProps): react.JSX.Element;
|
|
83
|
+
declare function Spacer({ props }: BlockProps): react.JSX.Element;
|
|
84
|
+
|
|
85
|
+
declare function Text({ props }: BlockProps): react.JSX.Element;
|
|
86
|
+
declare function MediaBlock({ props }: BlockProps): react.JSX.Element | null;
|
|
87
|
+
declare function Button({ props }: BlockProps): react.JSX.Element | null;
|
|
88
|
+
/** The player address of a known service, or null: an unknown address is shown as a link, never framed. */
|
|
89
|
+
declare function embedUrl(address: string): string | null;
|
|
90
|
+
declare function Embed({ props }: BlockProps): react.JSX.Element | null;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Slides, one child block each (WAI-ARIA carousel pattern): arrows and dots
|
|
94
|
+
* are buttons, the arrow keys move, autoplay stops on hover, on focus, on
|
|
95
|
+
* its pause button, and never starts when motion is reduced.
|
|
96
|
+
*/
|
|
97
|
+
declare function Carousel({ block, props, render }: BlockProps): react.JSX.Element | null;
|
|
98
|
+
/**
|
|
99
|
+
* Tabs (WAI-ARIA tabs pattern, automatic activation): one tab stop, the
|
|
100
|
+
* arrow keys move between tabs, Home and End go to the ends.
|
|
101
|
+
*/
|
|
102
|
+
declare function Tabs({ block, props, render }: BlockProps): react.JSX.Element | null;
|
|
103
|
+
/** Panels that fold (WAI-ARIA accordion pattern): each header is a button. */
|
|
104
|
+
declare function Accordion({ block, props, render }: BlockProps): react.JSX.Element;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* A rich text field, from its ProseMirror JSON — the nodes and marks of
|
|
108
|
+
* the presets the API accepts. No Tiptap on the site, no HTML string: an
|
|
109
|
+
* unknown node renders its content, or nothing.
|
|
110
|
+
*/
|
|
111
|
+
declare function RichText({ doc, className }: {
|
|
112
|
+
doc: unknown;
|
|
113
|
+
className?: string;
|
|
114
|
+
}): react.JSX.Element | null;
|
|
115
|
+
|
|
116
|
+
interface MediaProps {
|
|
117
|
+
media: MediaValue;
|
|
118
|
+
/** Replaces the media's own alternative text. An empty string marks it decorative. */
|
|
119
|
+
alt?: string | null;
|
|
120
|
+
/** The `sizes` of the `srcset`. */
|
|
121
|
+
sizes?: string;
|
|
122
|
+
/** Crops to the box (`object-fit: cover`) around the focal point. */
|
|
123
|
+
cover?: boolean;
|
|
124
|
+
/** Above the fold: loaded eagerly. */
|
|
125
|
+
priority?: boolean;
|
|
126
|
+
className?: string;
|
|
127
|
+
style?: CSSProperties;
|
|
128
|
+
}
|
|
129
|
+
/** An image with its `srcset` (the theme's `imageUrl`: the companion, or `/_media`), or a video. */
|
|
130
|
+
declare function Media({ media, alt, sizes, cover, priority, className, style }: MediaProps): react.JSX.Element;
|
|
131
|
+
|
|
132
|
+
type Format = 'avif' | 'webp';
|
|
133
|
+
interface ImageProps {
|
|
134
|
+
media: MediaValue;
|
|
135
|
+
/** A size by name — `card`, `thumbnail`, or one of the site's `imageSizes`. */
|
|
136
|
+
size?: string;
|
|
137
|
+
/** The box, in CSS pixels; with `size`, replaces its value. */
|
|
138
|
+
w?: number;
|
|
139
|
+
h?: number;
|
|
140
|
+
/** `inside` (the whole image in the box) or `cover` (the box filled, cropped around the focal point). */
|
|
141
|
+
fit?: 'inside' | 'cover';
|
|
142
|
+
q?: number;
|
|
143
|
+
/** Replaces the media's own alternative text; an empty string marks it decorative. */
|
|
144
|
+
alt?: string | null;
|
|
145
|
+
/**
|
|
146
|
+
* Responsive widths: a `srcset` in `w` descriptors, with `sizes`. Without
|
|
147
|
+
* them, the image is the box at 1x and 2x.
|
|
148
|
+
*/
|
|
149
|
+
widths?: number[];
|
|
150
|
+
sizes?: string;
|
|
151
|
+
/** A `<picture>` with a source per modern format, the `<img>` in the source's own as a fallback. */
|
|
152
|
+
formats?: Format[];
|
|
153
|
+
/** Above the fold: loaded eagerly, fetched first. */
|
|
154
|
+
priority?: boolean;
|
|
155
|
+
className?: string;
|
|
156
|
+
style?: CSSProperties;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* An image at the size asked for: by name (`<Image media={m} size="card" />`)
|
|
160
|
+
* or by its box (`w`, `h`, `fit`), in an `<img>` with 1x/2x or responsive
|
|
161
|
+
* widths, or a `<picture>` with AVIF and WebP sources. Its URLs are the
|
|
162
|
+
* theme's: signed at the image companion when the site has one
|
|
163
|
+
* (`imgproxyUrls()`), `/_media?w=…` otherwise. Never enlarged: the
|
|
164
|
+
* candidates stop at the source's size.
|
|
165
|
+
*/
|
|
166
|
+
declare function Image({ media, size, w, h, fit, q, alt, widths, sizes, formats, priority, className, style }: ImageProps): react.JSX.Element;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* The `href` of a destination, or null when it must not be followed: what
|
|
170
|
+
* the API accepts (a path, an anchor, `mailto:`, `tel:`, `http(s)`), checked
|
|
171
|
+
* again here; a node id goes through `resolve`.
|
|
172
|
+
*/
|
|
173
|
+
declare function safeHref(url: unknown, resolve?: (url: string) => string | null): string | null;
|
|
174
|
+
/** A `link` field's value, read loosely: the API sends an object, older content may hold a string. */
|
|
175
|
+
declare function readLink(value: unknown): LinkValue | null;
|
|
176
|
+
/** The attributes of an anchor that opens in a new tab. */
|
|
177
|
+
declare function targetProps(newTab: boolean): {
|
|
178
|
+
target?: string;
|
|
179
|
+
rel?: string;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
interface NavBarProps {
|
|
183
|
+
items: MenuItem[];
|
|
184
|
+
/** The `aria-label` of the `<nav>`; « Navigation principale » by default. */
|
|
185
|
+
label?: string;
|
|
186
|
+
/** Before the list: the site's logo and name, as a link home. */
|
|
187
|
+
brand?: ReactNode;
|
|
188
|
+
className?: string;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* The site's navigation bar (disclosure navigation pattern, not an ARIA
|
|
192
|
+
* menu): links are links, an item with children has a button that shows
|
|
193
|
+
* them, Escape closes and gives the focus back, leaving the bar closes
|
|
194
|
+
* everything. A `panel` item opens a mega menu, its blocks rendered with the
|
|
195
|
+
* item in context (`menu_links`). Below the `md` width, the list folds
|
|
196
|
+
* behind a « Menu » button.
|
|
197
|
+
*/
|
|
198
|
+
declare function NavBar({ items, label, brand, className }: NavBarProps): react.JSX.Element;
|
|
199
|
+
|
|
200
|
+
/** The trail to the current page, the last item being it. */
|
|
201
|
+
declare function Breadcrumb({ items, className }: {
|
|
202
|
+
items: BreadcrumbItem[];
|
|
203
|
+
className?: string;
|
|
204
|
+
}): react.JSX.Element | null;
|
|
205
|
+
|
|
206
|
+
declare function MenuItemLink({ item, className }: {
|
|
207
|
+
item: MenuItem;
|
|
208
|
+
className?: string;
|
|
209
|
+
}): react.JSX.Element;
|
|
210
|
+
/**
|
|
211
|
+
* In a mega menu's panel: the links under the panel's item — or under one
|
|
212
|
+
* of its descendants, named by `item` — two levels deep.
|
|
213
|
+
*/
|
|
214
|
+
declare function MenuLinks({ props }: BlockProps): react.JSX.Element | null;
|
|
215
|
+
|
|
216
|
+
/** The menu item whose panel is being rendered: what `menu_links` lists. */
|
|
217
|
+
declare const MenuItemContext: react.Context<MenuItem | null>;
|
|
218
|
+
declare function useMenuItem(): MenuItem | null;
|
|
219
|
+
|
|
220
|
+
export { Accordion, Block, BlockComponent, BlockProps, Blocks, Breadcrumb, type BreadcrumbItem, Button, Carousel, Column, Divider, Embed, Font, Grid, Image, type ImageProps, LinkValue, Media, MediaBlock, type MediaProps, MediaValue, type MenuItem, MenuItemContext, MenuItemLink, MenuLinks, NavBar, type NavBarProps, ResolvedAppearance, RichText, Section, Spacer, Tabs, Text, embedUrl, fontImports, fontStack, readLink, safeHref, standardBlocks, targetProps, themeCss, useMenuItem };
|