@nanisoft/prism-ui 1.2.0 → 1.4.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/dist/.tsbuildinfo +1 -1
- package/dist/blocks/index.d.ts +2 -0
- package/dist/blocks/index.d.ts.map +1 -1
- package/dist/blocks/index.js +1 -0
- package/dist/blocks/media-band-01/index.d.ts +3 -0
- package/dist/blocks/media-band-01/index.d.ts.map +1 -0
- package/dist/blocks/media-band-01/index.js +1 -0
- package/dist/blocks/media-band-01/media-band.d.ts +166 -0
- package/dist/blocks/media-band-01/media-band.d.ts.map +1 -0
- package/dist/blocks/media-band-01/media-band.js +55 -0
- package/dist/blocks/site-footer/site-footer.d.ts +23 -8
- package/dist/blocks/site-footer/site-footer.d.ts.map +1 -1
- package/dist/blocks/site-footer/site-footer.js +10 -4
- package/dist/blocks/site-navbar/index.d.ts +1 -1
- package/dist/blocks/site-navbar/index.d.ts.map +1 -1
- package/dist/blocks/site-navbar/mobile-nav.d.ts +25 -4
- package/dist/blocks/site-navbar/mobile-nav.d.ts.map +1 -1
- package/dist/blocks/site-navbar/mobile-nav.js +11 -4
- package/dist/blocks/site-navbar/nav-menu.d.ts +50 -0
- package/dist/blocks/site-navbar/nav-menu.d.ts.map +1 -0
- package/dist/blocks/site-navbar/nav-menu.js +44 -0
- package/dist/blocks/site-navbar/navbar-controls.d.ts +9 -3
- package/dist/blocks/site-navbar/navbar-controls.d.ts.map +1 -1
- package/dist/blocks/site-navbar/site-navbar.d.ts +54 -13
- package/dist/blocks/site-navbar/site-navbar.d.ts.map +1 -1
- package/dist/blocks/site-navbar/site-navbar.js +45 -10
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +10 -0
- package/dist/components/ui/calendar.d.ts.map +1 -1
- package/dist/components/ui/calendar.js +7 -2
- package/dist/components/ui/mini-calendar.js +1 -1
- package/dist/components/ui/product-mark.d.ts +26 -7
- package/dist/components/ui/product-mark.d.ts.map +1 -1
- package/dist/components/ui/product-mark.js +6 -4
- package/dist/components/ui/pulse-series.d.ts.map +1 -1
- package/dist/components/ui/pulse-series.js +1 -1
- package/dist/components/ui/section.d.ts +31 -1
- package/dist/components/ui/section.d.ts.map +1 -1
- package/dist/components/ui/section.js +22 -2
- package/dist/components/ui/sparkline.d.ts.map +1 -1
- package/dist/components/ui/sparkline.js +1 -2
- package/dist/styles.css +19 -0
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ChevronDown } from 'lucide-react';
|
|
4
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '../../components/ui/dropdown-menu.js';
|
|
5
|
+
/**
|
|
6
|
+
* One group of the site's own destinations, as a menu.
|
|
7
|
+
*
|
|
8
|
+
* A bar whose navigation is a row of links clubs into groups the moment a site
|
|
9
|
+
* outgrows the row: five destinations that are all "the parts of the library"
|
|
10
|
+
* beside four that are each a body of knowledge is a row a reader scans
|
|
11
|
+
* word by word rather than recognises at a glance. This is the second half of
|
|
12
|
+
* that row, and it is the one control in the row, because a group is not a
|
|
13
|
+
* destination: it is a place other destinations live behind.
|
|
14
|
+
*
|
|
15
|
+
* **The items are links, not commands, for the reason the sites menu states.**
|
|
16
|
+
* A menu item that navigated would be a command wearing a link's clothes, and
|
|
17
|
+
* a reader who middle-clicks a row that only looks like a link gets no new tab.
|
|
18
|
+
* Each item is rendered as the anchor itself rather than wrapping one, so the
|
|
19
|
+
* row is one tab stop and one target.
|
|
20
|
+
*
|
|
21
|
+
* **The menu is a closed group, and a closed group shows nothing.** A reader
|
|
22
|
+
* with scripting off sees the trigger and cannot open it, which is why the bar
|
|
23
|
+
* renders a group as a menu only on the row above the panel threshold: below
|
|
24
|
+
* it, the sheet lists every destination flat, and the bar's caller keeps
|
|
25
|
+
* whatever routes it cannot afford to hide out of a group. The trigger is
|
|
26
|
+
* filled when the reader is inside the group, so the place they are is on the
|
|
27
|
+
* row even with the menu shut.
|
|
28
|
+
*
|
|
29
|
+
* **The chevron rotates on the open state and on nothing else.** Something
|
|
30
|
+
* happened and the reader can see that it did, at the authored duration, and
|
|
31
|
+
* the rotation is the only motion here.
|
|
32
|
+
*/
|
|
33
|
+
export function NavMenu({ label, links, current }) {
|
|
34
|
+
return (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { "data-slot": "site-navbar-nav-trigger", "data-current": current ? 'true' : undefined, className: current
|
|
35
|
+
? 'group data-[popup-open]:bg-accent data-[popup-open]:text-accent-foreground bg-accent text-accent-foreground focus-visible:border-ring focus-visible:ring-ring gap-1 rounded-md px-2 py-1.5 text-sm font-medium transition-colors focus-visible:ring-[3px] focus-visible:outline-none'
|
|
36
|
+
: 'group data-[popup-open]:bg-accent data-[popup-open]:text-accent-foreground text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring gap-1 rounded-md px-2 py-1.5 text-sm font-medium transition-colors focus-visible:ring-[3px] focus-visible:outline-none', children: [label, _jsx(ChevronDown, { "aria-hidden": true, className: "group-data-[popup-open]:rotate-180 size-4 transition-transform duration-base ease-out" })] }), _jsx(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-44", children: links.map((link) => (_jsx(DropdownMenuItem, {
|
|
37
|
+
/*
|
|
38
|
+
* Rendered AS the link rather than wrapping one. A focusable menu
|
|
39
|
+
* item with an anchor inside it is two tab stops for one row, and a
|
|
40
|
+
* reader who middle-clicks a row that only looks like a link gets no
|
|
41
|
+
* new tab and no way to tell that the row was a link at all.
|
|
42
|
+
*/
|
|
43
|
+
render: _jsx("a", { href: link.href, target: link.newTab ? '_blank' : undefined, rel: link.newTab ? 'noopener noreferrer' : undefined, "aria-current": link.current ? 'page' : undefined, "data-current": link.current ? 'true' : undefined }), className: "data-[current]:bg-accent data-[current]:text-accent-foreground data-[current]:font-medium", children: link.label }, link.href))) })] }));
|
|
44
|
+
}
|
|
@@ -1,18 +1,24 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
1
2
|
import type { Mode, PackId } from '../../theming/index.js';
|
|
2
3
|
import type { SearchDialogMessages } from '../../components/ui/search-dialog.js';
|
|
3
4
|
import { type ThemePack } from './theme-menu.js';
|
|
4
5
|
import type { SwitcherProduct } from '../../components/ui/product-switcher.js';
|
|
5
|
-
import type {
|
|
6
|
+
import type { MobileNavEntry } from './mobile-nav.js';
|
|
6
7
|
/** What the control cluster was told to render. Every field is optional. */
|
|
7
8
|
export type NavbarControlsProps = {
|
|
8
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* The product whose mark heads the mobile panel. The drawn `mark` crosses
|
|
11
|
+
* this client boundary as rendered content, the same way a slot does, so a
|
|
12
|
+
* consumer's drawing stays server-drawn while the panel around it is not.
|
|
13
|
+
*/
|
|
9
14
|
product: {
|
|
10
15
|
id: string;
|
|
11
16
|
name: string;
|
|
12
17
|
pack?: PackId | null;
|
|
18
|
+
mark?: ReactNode;
|
|
13
19
|
};
|
|
14
20
|
/** The site's own destinations, for the panel below the row's threshold. */
|
|
15
|
-
nav: readonly
|
|
21
|
+
nav: readonly MobileNavEntry[];
|
|
16
22
|
/** The accessible name of the panel and of its trigger. */
|
|
17
23
|
navLabel: string;
|
|
18
24
|
/** The set of sites, or nothing for a site that is the only one. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navbar-controls.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/navbar-controls.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AAI7E,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAA;AAC3E,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"navbar-controls.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/navbar-controls.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AAI7E,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAA;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAIlD,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;OAIG;IACH,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAA;KAAE,CAAA;IAC7E,4EAA4E;IAC5E,GAAG,EAAE,SAAS,cAAc,EAAE,CAAA;IAC9B,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,6CAA6C;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,uEAAuE;IACvE,MAAM,CAAC,EAAE;QACP,QAAQ,EAAE,MAAM,CAAA;QAChB,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,oBAAoB,CAAA;KAC/B,CAAA;IACD,+DAA+D;IAC/D,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;KAAE,CAAA;IACvD,6EAA6E;IAC7E,IAAI,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IAChD,2CAA2C;IAC3C,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAA;IACnB,oDAAoD;IACpD,WAAW,EAAE,IAAI,CAAA;IACjB,mEAAmE;IACnE,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,sCAsDxD"}
|
|
@@ -31,7 +31,41 @@ export type SiteNavLink = {
|
|
|
31
31
|
* external: a cross-origin destination is not by itself a reason to open a tab.
|
|
32
32
|
*/
|
|
33
33
|
newTab?: boolean;
|
|
34
|
+
/** Forbidden: a destination carrying children is a `SiteNavGroup`, not a link. */
|
|
35
|
+
children?: never;
|
|
34
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* A group of destinations in the bar's own navigation, rendered as one trigger
|
|
39
|
+
* that opens a menu of them.
|
|
40
|
+
*
|
|
41
|
+
* The group is a place in the row rather than a route: it carries no `href`, and
|
|
42
|
+
* a caller whose group has an index page of its own lists that page among the
|
|
43
|
+
* `children` rather than on the group, so nothing is inventing a route. That is
|
|
44
|
+
* the same shape the site's own sidebar holds a folder to, and for the same
|
|
45
|
+
* reason: a group is where destinations live, not one.
|
|
46
|
+
*
|
|
47
|
+
* **A group hides its destinations until it is opened**, on the row above the
|
|
48
|
+
* panel threshold and nowhere else. The bar's narrow-viewport panel lists every
|
|
49
|
+
* destination flat, so a reader below the threshold meets no group at all, and a
|
|
50
|
+
* caller who cannot afford to hide a route behind a click leaves it out of a
|
|
51
|
+
* group: the search index, the sitemap and the page's own links are outside the
|
|
52
|
+
* bar and unaffected either way.
|
|
53
|
+
*/
|
|
54
|
+
export type SiteNavGroup = {
|
|
55
|
+
/** The word on the trigger, which is the group's own name. */
|
|
56
|
+
label: string;
|
|
57
|
+
/** The destinations behind the trigger, in the order a reader should meet them. */
|
|
58
|
+
children: readonly SiteNavLink[];
|
|
59
|
+
/**
|
|
60
|
+
* Marks the group as holding the page the reader is on, for a caller that
|
|
61
|
+
* composes the bar per page and marks each entry itself. A caller that passes
|
|
62
|
+
* `currentPath` leaves this off and the bar resolves it against the group's
|
|
63
|
+
* children.
|
|
64
|
+
*/
|
|
65
|
+
current?: boolean;
|
|
66
|
+
};
|
|
67
|
+
/** One entry in the bar's own navigation: a link, or a group of them. */
|
|
68
|
+
export type SiteNavEntry = SiteNavLink | SiteNavGroup;
|
|
35
69
|
/** The search the bar offers, which is a URL rather than an index. */
|
|
36
70
|
export type SiteNavSearch = {
|
|
37
71
|
/**
|
|
@@ -79,12 +113,12 @@ export type SiteNavMobileLabels = {
|
|
|
79
113
|
/** The props a SiteNavbar takes. */
|
|
80
114
|
export type SiteNavbarProps = {
|
|
81
115
|
/**
|
|
82
|
-
* The product this bar belongs to: the id, name and
|
|
83
|
-
* drawn from, and the mark that heads the mobile panel. The
|
|
84
|
-
* itself rather than a slot, because a bar whose brand
|
|
85
|
-
* every consumer has to reimplement.
|
|
116
|
+
* The product this bar belongs to: the id, name, pack and drawn mark its
|
|
117
|
+
* `ProductMark` is drawn from, and the mark that heads the mobile panel. The
|
|
118
|
+
* bar renders the mark itself rather than a slot, because a bar whose brand
|
|
119
|
+
* lockup is a slot is a bar every consumer has to reimplement.
|
|
86
120
|
*/
|
|
87
|
-
product: Pick<ProductMarkProps, 'id' | 'name' | 'pack'>;
|
|
121
|
+
product: Pick<ProductMarkProps, 'id' | 'name' | 'pack' | 'mark'>;
|
|
88
122
|
/** Where the brand lockup goes. @defaultValue '/' */
|
|
89
123
|
homeHref?: string;
|
|
90
124
|
/**
|
|
@@ -99,8 +133,13 @@ export type SiteNavbarProps = {
|
|
|
99
133
|
* control whose icon is a guess until it is pressed once.
|
|
100
134
|
*/
|
|
101
135
|
defaultMode: Mode;
|
|
102
|
-
/**
|
|
103
|
-
|
|
136
|
+
/**
|
|
137
|
+
* This site's own destinations: links, groups of links, or both in the order
|
|
138
|
+
* a reader should meet them. A link renders as itself; a group renders as one
|
|
139
|
+
* trigger opening its children as a menu. Omit for a bar that carries only
|
|
140
|
+
* the lockup.
|
|
141
|
+
*/
|
|
142
|
+
nav?: readonly SiteNavEntry[];
|
|
104
143
|
/**
|
|
105
144
|
* The accessible name of the site's navigation. Required, and required rather
|
|
106
145
|
* than defaulted because it is a word a reader hears: a Block that ships no copy
|
|
@@ -234,12 +273,14 @@ export type SiteNavbarProps = {
|
|
|
234
273
|
* with no release. This package ships no `will-change` anywhere, and the bar is not
|
|
235
274
|
* the place to start one.
|
|
236
275
|
*
|
|
237
|
-
* **It is a server Component
|
|
238
|
-
*
|
|
239
|
-
* single boundary, because a control's state is a reader's state
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
276
|
+
* **It is a server Component whose client islands are the ones a reader opens.** The
|
|
277
|
+
* lockup and the row's links are rendered on the server and ship no JavaScript; the
|
|
278
|
+
* controls are a single boundary, because a control's state is a reader's state, and
|
|
279
|
+
* a group in the navigation adds one island of its own for the same reason. A site
|
|
280
|
+
* that passes no `search`, `sites`, `theme`, `mode` or `nav`, and groups none of
|
|
281
|
+
* its destinations, renders the whole bar on the server and ships none, which is
|
|
282
|
+
* the arrangement a static site wants and the reason those props are optional
|
|
283
|
+
* rather than required.
|
|
243
284
|
*/
|
|
244
285
|
export declare function SiteNavbar({ product, homeHref, defaultPack, defaultMode, nav, navLabel, currentPath, sites, currentSiteId, sitesLabel, search, theme, mode, mobileLabels, actions, sticky, className, }: SiteNavbarProps): import("react").JSX.Element;
|
|
245
286
|
export default SiteNavbar;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"site-navbar.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/site-navbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AACrF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAA;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AAE7E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"site-navbar.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/site-navbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AACrF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAA;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AAE7E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAGjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,KAAK,CAAA;CACjB,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAA;IACb,mFAAmF;IACnF,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;IAChC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,YAAY,CAAA;AAErD,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,QAAQ,EAAE,oBAAoB,CAAA;IAC9B,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG;IACzB,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;CAC7B,CAAA;AAED,iDAAiD;AACjD,MAAM,MAAM,WAAW,GAAG;IACxB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAA;IAClB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAAG;IAChC,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,oCAAoC;AACpC,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;;OAKG;IACH,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;IAChE,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,WAAW,EAAE,IAAI,CAAA;IACjB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IAC7B;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,oEAAoE;IACpE,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB;;;;;;OAMG;IACH,YAAY,EAAE,mBAAmB,CAAA;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAc,EACd,WAAW,EACX,WAAW,EACX,GAAG,EACH,QAAQ,EACR,WAAW,EACX,KAAK,EACL,aAAa,EACb,UAAU,EACV,MAAM,EACN,KAAK,EACL,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,MAAa,EACb,SAAS,GACV,EAAE,eAAe,+BAuHjB;AAED,eAAe,UAAU,CAAA"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { ProductMark } from '../../components/ui/product-mark.js';
|
|
3
3
|
import { cn } from '../../lib/utils.js';
|
|
4
4
|
import { NavbarControls } from './navbar-controls.js';
|
|
5
|
+
import { NavMenu } from './nav-menu.js';
|
|
5
6
|
/**
|
|
6
7
|
* The bar at the top of a product site, with the controls a reader needs on every
|
|
7
8
|
* page of it.
|
|
@@ -73,18 +74,52 @@ import { NavbarControls } from './navbar-controls.js';
|
|
|
73
74
|
* with no release. This package ships no `will-change` anywhere, and the bar is not
|
|
74
75
|
* the place to start one.
|
|
75
76
|
*
|
|
76
|
-
* **It is a server Component
|
|
77
|
-
*
|
|
78
|
-
* single boundary, because a control's state is a reader's state
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
77
|
+
* **It is a server Component whose client islands are the ones a reader opens.** The
|
|
78
|
+
* lockup and the row's links are rendered on the server and ship no JavaScript; the
|
|
79
|
+
* controls are a single boundary, because a control's state is a reader's state, and
|
|
80
|
+
* a group in the navigation adds one island of its own for the same reason. A site
|
|
81
|
+
* that passes no `search`, `sites`, `theme`, `mode` or `nav`, and groups none of
|
|
82
|
+
* its destinations, renders the whole bar on the server and ships none, which is
|
|
83
|
+
* the arrangement a static site wants and the reason those props are optional
|
|
84
|
+
* rather than required.
|
|
82
85
|
*/
|
|
83
86
|
export function SiteNavbar({ product, homeHref = '/', defaultPack, defaultMode, nav, navLabel, currentPath, sites, currentSiteId, sitesLabel, search, theme, mode, mobileLabels, actions, sticky = true, className, }) {
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
const entries = nav ?? [];
|
|
88
|
+
/*
|
|
89
|
+
* The current mark reads the route as a place rather than as a string, so a
|
|
90
|
+
* reader on a page inside a destination is still on it: `/components/button`
|
|
91
|
+
* marks Components on the row, which is the question a reader asking "where
|
|
92
|
+
* am I" is asking. The boundary is the slash, so a Section whose segment is a
|
|
93
|
+
* prefix of another's (`/content` beside a hypothetical `/content-x`) never
|
|
94
|
+
* claims the other's pages.
|
|
95
|
+
*/
|
|
96
|
+
const under = (href) => currentPath !== undefined && (currentPath === href || currentPath.startsWith(`${href}/`));
|
|
97
|
+
const leafCurrent = (link) => link.current ?? under(link.href);
|
|
98
|
+
/**
|
|
99
|
+
* A group is current when the reader is on it or inside any of its children.
|
|
100
|
+
* A group is told apart from a link by `href`, which a link must carry and a
|
|
101
|
+
* group must not, so the narrowing is on the one key the two never share.
|
|
102
|
+
*/
|
|
103
|
+
const entryCurrent = (entry) => entry.current ??
|
|
104
|
+
('href' in entry
|
|
105
|
+
? under(entry.href)
|
|
106
|
+
: entry.children.some((child) => leafCurrent(child)));
|
|
107
|
+
return (_jsx("header", { "data-slot": "site-navbar", className: cn('border-border bg-background w-full border-b', sticky && 'sticky top-0 z-20', className), children: _jsxs("div", { className: "mx-auto flex h-14 w-full max-w-page items-center gap-2 px-6", children: [_jsx("a", { href: homeHref, className: "focus-visible:border-ring focus-visible:ring-ring shrink-0 rounded-sm focus-visible:ring-[3px] focus-visible:outline-none", children: _jsx(ProductMark, { id: product.id, name: product.name, pack: product.pack, mark: product.mark, size: "sm" }) }), entries.length > 0 ? (_jsx("nav", { "aria-label": navLabel, className: "hidden items-center lg:flex", children: entries.map((entry) =>
|
|
108
|
+
/*
|
|
109
|
+
* A group is the one control in the row, because it is the one
|
|
110
|
+
* entry that is a place rather than a destination, and its menu is
|
|
111
|
+
* a client island for the same reason the controls cluster is:
|
|
112
|
+
* whether it is open is a reader's state. The links around it stay
|
|
113
|
+
* server-rendered anchors, so a bar whose row is all links still
|
|
114
|
+
* ships a navigation with no JavaScript in it.
|
|
115
|
+
*/
|
|
116
|
+
'href' in entry ? (_jsx("a", { href: entry.href, "aria-current": entryCurrent(entry) ? 'page' : undefined, rel: entry.newTab ? 'noopener noreferrer' : undefined, target: entry.newTab ? '_blank' : undefined, className: entryCurrent(entry)
|
|
87
117
|
? 'bg-accent text-accent-foreground focus-visible:border-ring focus-visible:ring-ring rounded-md px-2 py-1.5 text-sm font-medium transition-colors focus-visible:ring-[3px] focus-visible:outline-none'
|
|
88
|
-
: 'text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring rounded-md px-2 py-1.5 text-sm font-medium transition-colors focus-visible:ring-[3px] focus-visible:outline-none', children:
|
|
118
|
+
: 'text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring rounded-md px-2 py-1.5 text-sm font-medium transition-colors focus-visible:ring-[3px] focus-visible:outline-none', children: entry.label }, entry.href)) : (_jsx(NavMenu, { label: entry.label, current: entryCurrent(entry), links: entry.children.map((child) => ({ ...child, current: leafCurrent(child) })) }, entry.label))) })) : null, _jsx(NavbarControls, { product: product, nav: entries.map((entry) => 'href' in entry
|
|
119
|
+
? { ...entry, current: entryCurrent(entry) }
|
|
120
|
+
: {
|
|
121
|
+
label: entry.label,
|
|
122
|
+
children: entry.children.map((child) => ({ ...child, current: leafCurrent(child) })),
|
|
123
|
+
}), navLabel: navLabel, sites: sites, currentSiteId: currentSiteId, sitesLabel: sitesLabel, search: search, theme: theme, mode: mode, mobileLabels: mobileLabels, defaultPack: defaultPack, defaultMode: defaultMode, actions: actions })] }) }));
|
|
89
124
|
}
|
|
90
125
|
export default SiteNavbar;
|
package/dist/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,aAAa,iDAAkD,CAAA;AAC5E,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,eAAO,MAAM,oBAAoB,sHAQvB,CAAA;AACV,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA;AAErE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAClC,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,MAAM,EAAE,QAAQ,GAAG,YAAY,CAAA;CAChC;AAED,eAAO,MAAM,OAAO,EAAE,SAAS,WAAW,
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,aAAa,iDAAkD,CAAA;AAC5E,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,eAAO,MAAM,oBAAoB,sHAQvB,CAAA;AACV,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA;AAErE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAClC,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,MAAM,EAAE,QAAQ,GAAG,YAAY,CAAA;CAChC;AAED,eAAO,MAAM,OAAO,EAAE,SAAS,WAAW,EAkhGzC,CAAA;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,KAAK,GAAE,SAAS,WAAW,EAAY,GAAG,WAAW,EAAE,CAEnF;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAE1D,CAAA"}
|
package/dist/catalog.js
CHANGED
|
@@ -1796,6 +1796,16 @@ export const catalog = [
|
|
|
1796
1796
|
exports: ['Gallery01'],
|
|
1797
1797
|
status: 'stable',
|
|
1798
1798
|
},
|
|
1799
|
+
{
|
|
1800
|
+
name: 'MediaBand01',
|
|
1801
|
+
slug: 'media-band-01',
|
|
1802
|
+
kind: 'block',
|
|
1803
|
+
category: null,
|
|
1804
|
+
description: 'An editorial band: one media slot held at a caller ratio beside one title, description and optional destination, with the copy always on a solid surface.',
|
|
1805
|
+
source: 'src/blocks/media-band-01/index.tsx',
|
|
1806
|
+
exports: ['MediaBand01'],
|
|
1807
|
+
status: 'stable',
|
|
1808
|
+
},
|
|
1799
1809
|
{
|
|
1800
1810
|
name: 'Download01',
|
|
1801
1811
|
slug: 'download-01',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../../src/components/ui/calendar.tsx"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS;IACtC,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAA;AAED,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;OAQG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB,gEAAgE;IAChE,aAAa,EAAE,gBAAgB,CAAA;IAC/B;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACxC,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAA;IACrB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;;;OAOG;IACH,KAAK,EAAE,IAAI,CAAA;IACX,mFAAmF;IACnF,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAA;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IACnB,kFAAkF;IAClF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IACpC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAA;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;IACjC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,mBAAmB;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;
|
|
1
|
+
{"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../../src/components/ui/calendar.tsx"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS;IACtC,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAA;AAED,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;OAQG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB,gEAAgE;IAChE,aAAa,EAAE,gBAAgB,CAAA;IAC/B;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACxC,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAA;IACrB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;;;OAOG;IACH,KAAK,EAAE,IAAI,CAAA;IACX,mFAAmF;IACnF,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAA;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IACnB,kFAAkF;IAClF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IACpC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAA;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;IACjC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,mBAAmB;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA6ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,iBAAS,QAAQ,CAAC,EAChB,KAAK,EACL,UAAU,EACV,aAAa,EACb,YAAgB,EAChB,aAAa,EACb,SAAS,EACT,KAAK,EACL,aAAa,EACb,KAAY,EACZ,aAAa,EACb,cAAc,EACd,QAAQ,EACR,KAAK,EACL,QAAgB,EAChB,IAAI,EACJ,IAAI,EACJ,SAAS,GACV,EAAE,aAAa,+BAyPf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|
|
@@ -35,7 +35,12 @@ const DAY_CELL =
|
|
|
35
35
|
// was added to it, and the fuller grid kept the 36px cell that is the same cell at
|
|
36
36
|
// a different size. A month grid is the densest control in the package and the one
|
|
37
37
|
// most worked with a thumb, so it is the last place the floor can be argued about.
|
|
38
|
-
|
|
38
|
+
//
|
|
39
|
+
// The cell is centred by the table, not by a `flex` utility: a `display: flex` on
|
|
40
|
+
// a `<th>` or a `<td>` takes the cell out of the table's column layout, and the
|
|
41
|
+
// month drew as one stacked column at four times its height before the utility
|
|
42
|
+
// came off.
|
|
43
|
+
'text-foreground hover:bg-accent hover:text-accent-foreground h-9 cursor-pointer rounded-md p-0 align-middle text-center text-sm tabular-nums outline-none transition-colors duration-fast ease-out pointer-coarse:h-11 focus-visible:ring-ring focus-visible:ring-[3px]';
|
|
39
44
|
/**
|
|
40
45
|
* The two paging controls.
|
|
41
46
|
*
|
|
@@ -226,7 +231,7 @@ function Calendar({ label, monthLabel, weekdayLabels, firstWeekday = 0, previous
|
|
|
226
231
|
const focusedIso = iso(focused);
|
|
227
232
|
const chosenIso = value === null ? null : iso(value);
|
|
228
233
|
const todayIso = today === undefined ? null : iso(today);
|
|
229
|
-
return (_jsxs("div", { "data-slot": "calendar", className: cn('bg-popover text-popover-foreground w-64 rounded-md border p-3 shadow-md', className), children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-1", children: [_jsx("button", { type: "button", "data-slot": "calendar-previous", "aria-label": previousLabel, disabled: disabled, onClick: () => onMonthChange(shiftMonth(month, -1)), className: cn(NAV_CONTROL, 'disabled:pointer-events-none disabled:opacity-50'), children: _jsx(ChevronLeftIcon, { className: "size-4" }) }), _jsx("div", { "data-slot": "calendar-caption", "aria-live": "polite", className: "text-foreground text-sm font-medium tabular-nums", children: monthLabel }), _jsx("button", { type: "button", "data-slot": "calendar-next", "aria-label": nextLabel, disabled: disabled, onClick: () => onMonthChange(shiftMonth(month, 1)), className: cn(NAV_CONTROL, 'disabled:pointer-events-none disabled:opacity-50'), children: _jsx(ChevronRightIcon, { className: "size-4" }) })] }), _jsx("div", { ref: gridRef, children: _jsxs("table", { "data-slot": "calendar-grid", role: "grid", "aria-label": label, className: "w-full border-collapse tabular-nums", children: [_jsx("thead", { children: _jsx("tr", { children: weekdayLabels.map((weekday, column) => (_jsx("th", { scope: "col", "data-slot": "calendar-weekday", className: "text-muted-foreground
|
|
234
|
+
return (_jsxs("div", { "data-slot": "calendar", className: cn('bg-popover text-popover-foreground w-64 rounded-md border p-3 shadow-md', className), children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-1", children: [_jsx("button", { type: "button", "data-slot": "calendar-previous", "aria-label": previousLabel, disabled: disabled, onClick: () => onMonthChange(shiftMonth(month, -1)), className: cn(NAV_CONTROL, 'disabled:pointer-events-none disabled:opacity-50'), children: _jsx(ChevronLeftIcon, { className: "size-4" }) }), _jsx("div", { "data-slot": "calendar-caption", "aria-live": "polite", className: "text-foreground text-sm font-medium tabular-nums", children: monthLabel }), _jsx("button", { type: "button", "data-slot": "calendar-next", "aria-label": nextLabel, disabled: disabled, onClick: () => onMonthChange(shiftMonth(month, 1)), className: cn(NAV_CONTROL, 'disabled:pointer-events-none disabled:opacity-50'), children: _jsx(ChevronRightIcon, { className: "size-4" }) })] }), _jsx("div", { ref: gridRef, children: _jsxs("table", { "data-slot": "calendar-grid", role: "grid", "aria-label": label, className: "w-full border-collapse tabular-nums", children: [_jsx("thead", { children: _jsx("tr", { children: weekdayLabels.map((weekday, column) => (_jsx("th", { scope: "col", "data-slot": "calendar-weekday", className: "text-muted-foreground h-8 p-0 align-middle text-center text-xs font-medium", children: weekday }, `${weekday}-${column}`))) }) }), _jsx("tbody", { children: Array.from({ length: 6 }, (_, row) => (_jsx("tr", { children: cells.slice(row * 7, row * 7 + 7).map((date) => {
|
|
230
235
|
const key = iso(date);
|
|
231
236
|
if (!sameMonth(date, month)) {
|
|
232
237
|
// The cells that pad the month out. They are hidden from the
|
|
@@ -243,7 +243,7 @@ function MiniCalendar({ selected, onSelect, month, defaultMonth, onMonthChange,
|
|
|
243
243
|
default:
|
|
244
244
|
}
|
|
245
245
|
};
|
|
246
|
-
return (_jsx("div", { ref: gridRef, "data-slot": "mini-calendar", className: cn('bg-card text-card-foreground w-64 rounded-md border p-3 shadow-sm', className), children: _jsxs("table", { "data-slot": "mini-calendar-grid", role: "grid", "aria-label": label, className: "w-full border-collapse tabular-nums", children: [_jsx("caption", { "data-slot": "mini-calendar-caption", className: "mb-2", children: _jsxs("span", { className: "flex items-center justify-between gap-1", children: [_jsx("button", { type: "button", "data-slot": "mini-calendar-previous", "aria-label": previousLabel, onClick: () => move(shiftMonth(shown, -1)), className: NAV_CONTROL, children: _jsx(ChevronLeftIcon, { className: "size-4", "aria-hidden": "true" }) }), _jsx("span", { "data-slot": "mini-calendar-month", "aria-live": "polite", className: "text-foreground text-sm font-medium", children: monthText }), _jsx("button", { type: "button", "data-slot": "mini-calendar-next", "aria-label": nextLabel, onClick: () => move(shiftMonth(shown, 1)), className: NAV_CONTROL, children: _jsx(ChevronRightIcon, { className: "size-4", "aria-hidden": "true" }) })] }) }), _jsx("thead", { children: _jsx("tr", { children: headings.map((heading) => (_jsx("th", { scope: "col", abbr: heading.long, "data-slot": "mini-calendar-weekday", className: "text-muted-foreground
|
|
246
|
+
return (_jsx("div", { ref: gridRef, "data-slot": "mini-calendar", className: cn('bg-card text-card-foreground w-64 rounded-md border p-3 shadow-sm', className), children: _jsxs("table", { "data-slot": "mini-calendar-grid", role: "grid", "aria-label": label, className: "w-full border-collapse tabular-nums", children: [_jsx("caption", { "data-slot": "mini-calendar-caption", className: "mb-2", children: _jsxs("span", { className: "flex items-center justify-between gap-1", children: [_jsx("button", { type: "button", "data-slot": "mini-calendar-previous", "aria-label": previousLabel, onClick: () => move(shiftMonth(shown, -1)), className: NAV_CONTROL, children: _jsx(ChevronLeftIcon, { className: "size-4", "aria-hidden": "true" }) }), _jsx("span", { "data-slot": "mini-calendar-month", "aria-live": "polite", className: "text-foreground text-sm font-medium", children: monthText }), _jsx("button", { type: "button", "data-slot": "mini-calendar-next", "aria-label": nextLabel, onClick: () => move(shiftMonth(shown, 1)), className: NAV_CONTROL, children: _jsx(ChevronRightIcon, { className: "size-4", "aria-hidden": "true" }) })] }) }), _jsx("thead", { children: _jsx("tr", { children: headings.map((heading) => (_jsx("th", { scope: "col", abbr: heading.long, "data-slot": "mini-calendar-weekday", className: "text-muted-foreground h-8 p-0 align-middle text-center text-xs font-medium", children: heading.short }, heading.long))) }) }), _jsx("tbody", { children: Array.from({ length: 6 }, (_, row) => (_jsx("tr", { children: cells.slice(row * 7, row * 7 + 7).map((date) => {
|
|
247
247
|
const key = iso(date);
|
|
248
248
|
if (!sameMonth(date, shown)) {
|
|
249
249
|
// The cells that pad the month out. Hidden from the accessibility
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
1
2
|
import type { PackId } from '../../theming/index.js';
|
|
2
3
|
/**
|
|
3
4
|
* The three sizes a product mark is drawn at: the mark's diameter and the name
|
|
@@ -32,10 +33,11 @@ export type ProductMarkSize = keyof typeof SIZES;
|
|
|
32
33
|
* The props a ProductMark takes.
|
|
33
34
|
*
|
|
34
35
|
* There is no product directory in this package. A product's identity is the
|
|
35
|
-
* consumer's data, so the Component takes the
|
|
36
|
-
*
|
|
37
|
-
* and `
|
|
38
|
-
*
|
|
36
|
+
* consumer's data, so the Component takes the facts the mark is drawn from and
|
|
37
|
+
* owns none of them: `id` for the markup, `name` for the second part, `pack`
|
|
38
|
+
* for the hue, and `mark` for the drawing itself when the identity has one.
|
|
39
|
+
* Where the set of products is published is the consumer's decision, and Prism
|
|
40
|
+
* ships the mark rather than a list of products.
|
|
39
41
|
*/
|
|
40
42
|
export type ProductMarkProps = {
|
|
41
43
|
/**
|
|
@@ -63,6 +65,21 @@ export type ProductMarkProps = {
|
|
|
63
65
|
* core resolves the base pack's `primary` from the page.
|
|
64
66
|
*/
|
|
65
67
|
pack?: PackId | null;
|
|
68
|
+
/**
|
|
69
|
+
* The product's drawn mark, when its identity includes one: the logo in
|
|
70
|
+
* place of the disc. The node is the consumer's drawing and this Component
|
|
71
|
+
* owns none of it, exactly as it owns none of the name; it is drawn inside
|
|
72
|
+
* the sized slot the disc occupies, so a `viewBox` drawing that fills its
|
|
73
|
+
* box arrives at every drawn size from one node. Ink strokes drawn in
|
|
74
|
+
* `currentColor` and accents drawn through a token class keep the drawing
|
|
75
|
+
* reachable by the cascade and by a pack boundary the same way the disc is.
|
|
76
|
+
*
|
|
77
|
+
* The drawing is hidden from assistive technology, as the disc is: the name
|
|
78
|
+
* is the mark's announced half either way. Omit it for the two-colour disc,
|
|
79
|
+
* which remains the mark of a product whose identity is a hue rather than a
|
|
80
|
+
* drawing.
|
|
81
|
+
*/
|
|
82
|
+
mark?: ReactNode;
|
|
66
83
|
/**
|
|
67
84
|
* Which of the three drawn sizes to use. @defaultValue 'md'
|
|
68
85
|
*/
|
|
@@ -75,8 +92,10 @@ export type ProductMarkProps = {
|
|
|
75
92
|
className?: string;
|
|
76
93
|
};
|
|
77
94
|
/**
|
|
78
|
-
* A product's two-part
|
|
79
|
-
*
|
|
95
|
+
* A product's two-part mark: the shape, beside the product's name in the brand
|
|
96
|
+
* ink. The shape is a disc by default, a hairline ring in the brand ink around
|
|
97
|
+
* a core in the pack's own fill, and it is the product's own drawing when
|
|
98
|
+
* `mark` carries one.
|
|
80
99
|
*
|
|
81
100
|
* Two parts, and both colours come from tokens, which is the whole reason this
|
|
82
101
|
* is promoted out of the two hand-written copies it replaces. The ring is
|
|
@@ -110,6 +129,6 @@ export type ProductMarkProps = {
|
|
|
110
129
|
* The disc is `aria-hidden` and the name is not, so the mark adds a shape beside
|
|
111
130
|
* the word rather than a second reading of it.
|
|
112
131
|
*/
|
|
113
|
-
declare function ProductMark({ id, name, pack, size, className }: ProductMarkProps): import("react").JSX.Element;
|
|
132
|
+
declare function ProductMark({ id, name, pack, mark, size, className }: ProductMarkProps): import("react").JSX.Element;
|
|
114
133
|
export { ProductMark };
|
|
115
134
|
//# sourceMappingURL=product-mark.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-mark.d.ts","sourceRoot":"","sources":["../../../src/components/ui/product-mark.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AA2B3C;;;;;;;;GAQG;AACH,QAAA,MAAM,KAAK;;;;;;;;;;;;;CAID,CAAA;AAEV;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,KAAK,CAAA;AAEhD
|
|
1
|
+
{"version":3,"file":"product-mark.d.ts","sourceRoot":"","sources":["../../../src/components/ui/product-mark.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AA2B3C;;;;;;;;GAQG;AACH,QAAA,MAAM,KAAK;;;;;;;;;;;;;CAID,CAAA;AAEV;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,KAAK,CAAA;AAEhD;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAA;IACV;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;;;;;;;;;;;;;OAaG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,eAAe,CAAA;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,iBAAS,WAAW,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAW,EAAE,SAAS,EAAE,EAAE,gBAAgB,+BAsCtF;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -36,8 +36,10 @@ const SIZES = {
|
|
|
36
36
|
lg: { mark: 'size-6', name: 'text-base' },
|
|
37
37
|
};
|
|
38
38
|
/**
|
|
39
|
-
* A product's two-part
|
|
40
|
-
*
|
|
39
|
+
* A product's two-part mark: the shape, beside the product's name in the brand
|
|
40
|
+
* ink. The shape is a disc by default, a hairline ring in the brand ink around
|
|
41
|
+
* a core in the pack's own fill, and it is the product's own drawing when
|
|
42
|
+
* `mark` carries one.
|
|
41
43
|
*
|
|
42
44
|
* Two parts, and both colours come from tokens, which is the whole reason this
|
|
43
45
|
* is promoted out of the two hand-written copies it replaces. The ring is
|
|
@@ -71,12 +73,12 @@ const SIZES = {
|
|
|
71
73
|
* The disc is `aria-hidden` and the name is not, so the mark adds a shape beside
|
|
72
74
|
* the word rather than a second reading of it.
|
|
73
75
|
*/
|
|
74
|
-
function ProductMark({ id, name, pack, size = 'md', className }) {
|
|
76
|
+
function ProductMark({ id, name, pack, mark, size = 'md', className }) {
|
|
75
77
|
const drawn = SIZES[size];
|
|
76
78
|
// `default` is the absence of a pack id, spelled the way the token build
|
|
77
79
|
// spells it, so a base-pack product resolves `primary` from the page rather
|
|
78
80
|
// than from an attribute that matches no emitted rule.
|
|
79
81
|
const boundary = pack && pack !== 'default' ? pack : undefined;
|
|
80
|
-
return (_jsxs("span", { "data-slot": "product-mark", "data-pack": boundary, className: cn('inline-flex items-center gap-2', className), children: [_jsx("span", { "data-slot": "product-mark-disc", "data-product": id, "aria-hidden": true, className: cn('inline-block shrink-0 rounded-full border border-brand-ink', drawn.mark, pack ? 'bg-primary' : SPECTRUM) }), _jsx("span", { "data-slot": "product-mark-name", className: cn('font-medium text-brand-ink', drawn.name), children: name })] }));
|
|
82
|
+
return (_jsxs("span", { "data-slot": "product-mark", "data-pack": boundary, className: cn('inline-flex items-center gap-2', className), children: [mark ? (_jsx("span", { "data-slot": "product-mark-drawn", "data-product": id, "aria-hidden": true, className: cn('inline-block shrink-0', drawn.mark), children: mark })) : (_jsx("span", { "data-slot": "product-mark-disc", "data-product": id, "aria-hidden": true, className: cn('inline-block shrink-0 rounded-full border border-brand-ink', drawn.mark, pack ? 'bg-primary' : SPECTRUM) })), _jsx("span", { "data-slot": "product-mark-name", className: cn('font-medium text-brand-ink', drawn.name), children: name })] }));
|
|
81
83
|
}
|
|
82
84
|
export { ProductMark };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pulse-series.d.ts","sourceRoot":"","sources":["../../../src/components/ui/pulse-series.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAA;IACV,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED;;;;;;;GAOG;AACH,KAAK,iBAAiB,GAClB;IACE;;;;OAIG;IACH,UAAU,EAAE,IAAI,CAAA;IAChB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,GACD;IACE,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB,CAAA;AAEL,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG;IACjD;;;;OAIG;IACD,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAA;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAoCH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,iBAAS,WAAW,CAAC,EACnB,IAAI,EACJ,QAAQ,EACR,IAAY,EACZ,KAAK,EACL,UAAkB,EAClB,SAAS,GACV,EAAE,gBAAgB,+
|
|
1
|
+
{"version":3,"file":"pulse-series.d.ts","sourceRoot":"","sources":["../../../src/components/ui/pulse-series.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAA;IACV,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED;;;;;;;GAOG;AACH,KAAK,iBAAiB,GAClB;IACE;;;;OAIG;IACH,UAAU,EAAE,IAAI,CAAA;IAChB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,GACD;IACE,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB,CAAA;AAEL,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG;IACjD;;;;OAIG;IACD,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAA;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAoCH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,iBAAS,WAAW,CAAC,EACnB,IAAI,EACJ,QAAQ,EACR,IAAY,EACZ,KAAK,EACL,UAAkB,EAClB,SAAS,GACV,EAAE,gBAAgB,+BAiJlB;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -81,7 +81,7 @@ function PulseSeries({ bars, baseline, scan = false, label, decorative = false,
|
|
|
81
81
|
const tallest = Math.max(...bars.map((bar) => bar.value), 0);
|
|
82
82
|
const slot = bars.length ? roomX / bars.length : roomX;
|
|
83
83
|
const barWidth = Math.max(2, Math.min(MAX_BAR_WIDTH, slot * (1 / (1 + BAR_GAP))));
|
|
84
|
-
return (_jsxs("svg", { "data-slot": "pulse-series", "data-columns": bars.length, "data-scan": scan || undefined, viewBox: `0 0 ${CANVAS_WIDTH} ${CANVAS_HEIGHT}`, xmlns: "http://www.w3.org/2000/svg", role: decorative ? undefined : 'img', "aria-label": decorative ? undefined : label, "aria-hidden": decorative || undefined, className: cn('h-auto w-full', className), children: [scan ? (_jsx("g", { "data-slot": "pulse-series-scan", "aria-hidden": true, children: _jsxs("g", { className: "prism-ambient-scan", style: { '--ambient-scan-distance': `${roomX
|
|
84
|
+
return (_jsxs("svg", { "data-slot": "pulse-series", "data-columns": bars.length, "data-scan": scan || undefined, viewBox: `0 0 ${CANVAS_WIDTH} ${CANVAS_HEIGHT}`, xmlns: "http://www.w3.org/2000/svg", role: decorative ? undefined : 'img', "aria-label": decorative ? undefined : label, "aria-hidden": decorative || undefined, className: cn('h-auto w-full', className), children: [scan ? (_jsx("g", { "data-slot": "pulse-series-scan", "aria-hidden": true, transform: `translate(${PADDING} 0)`, children: _jsxs("g", { className: "prism-ambient-scan", style: { '--ambient-scan-distance': `${roomX}px` }, children: [_jsx("rect", { "data-slot": "pulse-series-scan-wash", x: -slot / 2, y: PADDING_TOP - 12, width: slot, height: baselineY - PADDING_TOP + 12, className: "fill-brand-ink/10" }), _jsx("line", { "data-slot": "pulse-series-scan-line", x1: 0, y1: PADDING_TOP - 12, x2: 0, y2: baselineY, strokeWidth: 1, className: "stroke-brand-ink/60" })] }) })) : null, bars.map((bar, index) => {
|
|
85
85
|
const centre = PADDING + slot * (index + 0.5);
|
|
86
86
|
// A column of value zero is drawn as a hairline rather than as nothing,
|
|
87
87
|
// because a gap in a series is a missing reading and a missing reading
|
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The three vertical rhythms a Section can be composed at.
|
|
4
|
+
*
|
|
5
|
+
* `default` is the rhythm every existing block already composes, so a Block that
|
|
6
|
+
* does not pass a size renders exactly what it rendered before this prop existed.
|
|
7
|
+
* `compact` is for a transition band: a strip of facts or a line of status whose
|
|
8
|
+
* job is to separate two larger bands rather than to be one. `tall` is for a band
|
|
9
|
+
* that is a statement: a hero, a manifesto, or an editorial moment that needs the
|
|
10
|
+
* page to stop for it.
|
|
11
|
+
*
|
|
12
|
+
* Three and not a number, for the reason every closed union in this package is
|
|
13
|
+
* closed: a `padding: number` prop hands a consumer a spacing scale to reproduce,
|
|
14
|
+
* and the first consumer to pass 73 has a rhythm nobody authored. The names say
|
|
15
|
+
* what the band is for, which is the decision a caller actually makes.
|
|
16
|
+
*/
|
|
17
|
+
export type SectionSize = 'compact' | 'default' | 'tall';
|
|
2
18
|
/**
|
|
3
19
|
* Container primitive. Every block composes its own section from this so vertical
|
|
4
20
|
* rhythm stays consistent across the catalog instead of being re-invented per block.
|
|
@@ -17,8 +33,22 @@ import type { ReactNode } from 'react';
|
|
|
17
33
|
* Tailwind's extractor reads this file, comments included, so a utility quoted in
|
|
18
34
|
* a JSDoc block is a utility the shipped stylesheet emits. A record of a retired
|
|
19
35
|
* class written as a class is a second copy of the tree nobody edits.
|
|
36
|
+
*
|
|
37
|
+
* **`size` is the band's job, not a spacing slider.** See `SectionSize`: a
|
|
38
|
+
* transition band, an ordinary band and a statement are three different amounts
|
|
39
|
+
* of room, and a page that gives all three the same amount reads as one band
|
|
40
|
+
* repeated. The prop exists so the choice is made once in the design system
|
|
41
|
+
* rather than five times in five site stylesheets.
|
|
20
42
|
*/
|
|
21
|
-
export declare function Section({ className, children, ...props }: React.ComponentProps<'section'>
|
|
43
|
+
export declare function Section({ size, className, children, ...props }: React.ComponentProps<'section'> & {
|
|
44
|
+
/**
|
|
45
|
+
* The band's vertical rhythm. Defaults to `default`, which is the rhythm every
|
|
46
|
+
* existing Block already composes. See `SectionSize`.
|
|
47
|
+
*
|
|
48
|
+
* @defaultValue 'default'
|
|
49
|
+
*/
|
|
50
|
+
size?: SectionSize;
|
|
51
|
+
}): import("react").JSX.Element;
|
|
22
52
|
/**
|
|
23
53
|
* The six heading levels a block can be composed at.
|
|
24
54
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"section.d.ts","sourceRoot":"","sources":["../../../src/components/ui/section.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC
|
|
1
|
+
{"version":3,"file":"section.d.ts","sourceRoot":"","sources":["../../../src/components/ui/section.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAA;AAiBxD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAgB,EAChB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG;IACnC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,WAAW,CAAA;CACnB,+BAMA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAKlE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAG5D;AAoBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAE5D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,OAAO,EACP,KAAK,EACL,EAAE,EAAE,OAAc,EAClB,WAAW,EACX,KAAgB,EAChB,EAAE,EACF,SAAS,GACV,EAAE;IACD;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,KAAK,EAAE,SAAS,CAAA;IAChB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAA;IACzB;;;;;;;;;;;;OAYG;IACH,EAAE,CAAC,EAAE,YAAY,CAAA;IACjB;;;;;;;;;;;OAWG;IACH,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,+BAgCA"}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from '../../lib/utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* The padding each rhythm sets.
|
|
5
|
+
*
|
|
6
|
+
* `default` is byte-identical to the string this Component rendered before the
|
|
7
|
+
* prop existed, so adding the prop cannot move a band that did not ask to move.
|
|
8
|
+
* The other two are on the same quarter-rem grid: `compact` is 3rem to 4rem and
|
|
9
|
+
* `tall` is 5rem to 8rem, which are the same two statements the four consumer
|
|
10
|
+
* sites had been writing by hand in their own stylesheets.
|
|
11
|
+
*/
|
|
12
|
+
const SECTION_SIZE = {
|
|
13
|
+
compact: 'py-12 sm:py-16',
|
|
14
|
+
default: 'py-16 sm:py-24',
|
|
15
|
+
tall: 'py-20 sm:py-32',
|
|
16
|
+
};
|
|
3
17
|
/**
|
|
4
18
|
* Container primitive. Every block composes its own section from this so vertical
|
|
5
19
|
* rhythm stays consistent across the catalog instead of being re-invented per block.
|
|
@@ -18,9 +32,15 @@ import { cn } from '../../lib/utils.js';
|
|
|
18
32
|
* Tailwind's extractor reads this file, comments included, so a utility quoted in
|
|
19
33
|
* a JSDoc block is a utility the shipped stylesheet emits. A record of a retired
|
|
20
34
|
* class written as a class is a second copy of the tree nobody edits.
|
|
35
|
+
*
|
|
36
|
+
* **`size` is the band's job, not a spacing slider.** See `SectionSize`: a
|
|
37
|
+
* transition band, an ordinary band and a statement are three different amounts
|
|
38
|
+
* of room, and a page that gives all three the same amount reads as one band
|
|
39
|
+
* repeated. The prop exists so the choice is made once in the design system
|
|
40
|
+
* rather than five times in five site stylesheets.
|
|
21
41
|
*/
|
|
22
|
-
export function Section({ className, children, ...props }) {
|
|
23
|
-
return (_jsx("section", { className: cn(
|
|
42
|
+
export function Section({ size = 'default', className, children, ...props }) {
|
|
43
|
+
return (_jsx("section", { className: cn(SECTION_SIZE[size], className), ...props, children: _jsx("div", { className: "mx-auto w-full max-w-page px-6 lg:px-8", children: children }) }));
|
|
24
44
|
}
|
|
25
45
|
/** The six levels in outline order, so a level can be stepped rather than compared. */
|
|
26
46
|
const LEVELS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sparkline.d.ts","sourceRoot":"","sources":["../../../src/components/ui/sparkline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAE3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"sparkline.d.ts","sourceRoot":"","sources":["../../../src/components/ui/sparkline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAE3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AA0C/C,uCAAuC;AACvC,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAChF;;;;;;;;OAQG;IACH,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB;;;;;;;;;OASG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,iBAAS,SAAS,CAAC,EACjB,SAAS,EACT,MAAM,EACN,KAAK,EACL,IAAgB,EAChB,KAAU,EACV,MAAW,EACX,aAAqB,EACrB,GAAG,KAAK,EACT,EAAE,cAAc,+BAoGhB;AAED,OAAO,EAAE,SAAS,EAAE,CAAA"}
|