@softure-ai/theme-notion 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +80 -4
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/messages/en.d.ts +3 -0
- package/dist/messages/en.d.ts.map +1 -1
- package/dist/messages/en.js +1 -0
- package/dist/messages/en.js.map +1 -1
- package/dist/messages/index.d.ts +3 -0
- package/dist/messages/index.d.ts.map +1 -1
- package/dist/notion/DetailTable.d.ts +15 -0
- package/dist/notion/DetailTable.d.ts.map +1 -0
- package/dist/notion/DetailTable.js +20 -0
- package/dist/notion/DetailTable.js.map +1 -0
- package/dist/notion/FoldRow.d.ts +23 -0
- package/dist/notion/FoldRow.d.ts.map +1 -0
- package/dist/notion/FoldRow.js +14 -0
- package/dist/notion/FoldRow.js.map +1 -0
- package/dist/notion/MarkPopover.d.ts +19 -0
- package/dist/notion/MarkPopover.d.ts.map +1 -0
- package/dist/notion/MarkPopover.js +22 -0
- package/dist/notion/MarkPopover.js.map +1 -0
- package/dist/notion/PageHeader.d.ts +2 -1
- package/dist/notion/PageHeader.d.ts.map +1 -1
- package/dist/notion/PageHeader.js +2 -2
- package/dist/notion/PageHeader.js.map +1 -1
- package/dist/notion/SidePanel.d.ts +13 -0
- package/dist/notion/SidePanel.d.ts.map +1 -0
- package/dist/notion/SidePanel.js +28 -0
- package/dist/notion/SidePanel.js.map +1 -0
- package/dist/notion/Stats.d.ts +45 -0
- package/dist/notion/Stats.d.ts.map +1 -0
- package/dist/notion/Stats.js +31 -0
- package/dist/notion/Stats.js.map +1 -0
- package/dist/notion/TabBar.d.ts +15 -0
- package/dist/notion/TabBar.d.ts.map +1 -0
- package/dist/notion/TabBar.js +6 -0
- package/dist/notion/TabBar.js.map +1 -0
- package/dist/notion/tones.d.ts +8 -0
- package/dist/notion/tones.d.ts.map +1 -0
- package/dist/notion/tones.js +37 -0
- package/dist/notion/tones.js.map +1 -0
- package/package.json +2 -2
- package/src/index.ts +17 -0
- package/src/messages/en.ts +1 -0
- package/src/notion/DetailTable.tsx +46 -0
- package/src/notion/FoldRow.tsx +78 -0
- package/src/notion/MarkPopover.tsx +84 -0
- package/src/notion/PageHeader.tsx +4 -2
- package/src/notion/SidePanel.tsx +73 -0
- package/src/notion/Stats.tsx +145 -0
- package/src/notion/TabBar.tsx +47 -0
- package/src/notion/tones.ts +45 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,48 @@ Newest first. Each version lists what changed for an app that uses the theme. Wh
|
|
|
4
4
|
production, the version gets a line `verified in: <app>@<commit>` ([docs/05](../../docs/05-adoption-playbook.md),
|
|
5
5
|
"Definition of done").
|
|
6
6
|
|
|
7
|
+
## 0.2.0
|
|
8
|
+
|
|
9
|
+
- Needs `@softure-ai/theme-kit` `^0.1.2` (was `^0.1.0`): the version that ships `base.css` and `maplibre.css`, which
|
|
10
|
+
both wirings in the README import.
|
|
11
|
+
- README (#718): both wirings import the kit's `base.css` (the page base on `body`) and, for an app with MapLibre maps,
|
|
12
|
+
`maplibre.css`. Needs `@softure-ai/theme-kit` with those files (the next kit release). An app that kept its own
|
|
13
|
+
`body` rule (`margin: 0`, `background: var(--background)`, `color: var(--foreground)`,
|
|
14
|
+
`font-family: --theme(--font-sans)`) or `body .maplibregl-map { font-family: … }` replaces them with the two
|
|
15
|
+
`@import` lines after `theme.css`.
|
|
16
|
+
- `TabBar` (#723): a screen's tabs as line tabs where each tab is a link (`<a href>`), so the shown tab lives in the
|
|
17
|
+
address and a link, a form's return or a reload land on the same tab. Optional icon before the label and count
|
|
18
|
+
after it (0 included); the current link carries `aria-current="page"`; the row scrolls sideways on a phone.
|
|
19
|
+
`data-slot="tab-bar"`, `data-tab` and `data-slot="tab-bar-count"` mark the parts. An app that keeps its own copy
|
|
20
|
+
replaces it with `import { TabBar } from "@softure-ai/theme-notion"`; the props are the same (`label`, `tabs`,
|
|
21
|
+
`current`). For client-state tabs keep `Tabs`.
|
|
22
|
+
- Tones (#720): `TONES`, `Tone` (`default`, `success`, `warning`, `danger`, `muted`), `TONE_COLORS` (a tone's palette
|
|
23
|
+
colour, `null` for `default`) and the literal class maps `TONE_TEXT` (`text-*`), `TONE_FILL` (`bg-*`) and
|
|
24
|
+
`TONE_EDGE` (`border-l-*`), generated by the shipped `theme.css`. Migration for an app with its own tone files:
|
|
25
|
+
delete its `Tone` type and class maps, import them from the package, keep only the app's meaning-to-tone table,
|
|
26
|
+
and drop any `@source` the app added for those class names.
|
|
27
|
+
- `SidePanel` (#724): a non-modal panel at a side of a canvas (a map) that leaves the canvas usable, unlike the modal
|
|
28
|
+
`Sheet`. Layouts `over`, `beside`, `left`, `list`; hidden while closed, focus moves in when it opens, Escape and the
|
|
29
|
+
close button call `onClose`. An app that kept its own copy replaces it with the import (same props; `closeLabel` is
|
|
30
|
+
now optional, default "Close") and drops its own file.
|
|
31
|
+
- `PageHeader` takes `crumbsLabel` (#719): the accessible name of the breadcrumb it renders for `crumbs`, so an app
|
|
32
|
+
in another language replaces the built-in English "breadcrumb". Without it the markup is unchanged.
|
|
33
|
+
- `MarkPopover` (#725): a counted tag (`badgeVariants({ variant: "tag", color })` with an icon and a count) that opens
|
|
34
|
+
the design system's popover listing entries, on the browser's Popover API with no client state, phrasing
|
|
35
|
+
elements only (`data-slot="mark"`, `data-slot="mark-popover"`). An app with its own copy of this mark deletes it
|
|
36
|
+
and imports `MarkPopover` (and `MarkPopoverProps`) from `@softure-ai/theme-notion`: same props, same markup and
|
|
37
|
+
classes; its domain marks (warnings, tickets) keep passing their entries as `role="listitem"` spans.
|
|
38
|
+
- `StatsFold`, `StatCards` and `StatPills` (#722): a screen's summary figures, folded under a heading (native
|
|
39
|
+
`<details>`, closed by default), as a wrapping row of cards (label, figure in its tone, optional hint and aside tag,
|
|
40
|
+
`isFullWidth` / `isOneRow` layouts) and as "label **value**" tags. `data-slot`, `data-stat`, `data-tone` and
|
|
41
|
+
`data-layout` mark the parts. An app that kept these as its own code drops them and imports them from the package.
|
|
42
|
+
- `DetailTable` (#721): an item's details as a label and value table; rows without a value are left out, and nothing
|
|
43
|
+
renders when no row has one. On a phone the label sits above its value.
|
|
44
|
+
- `FoldRow` (#721): an item as one folding list row (chevron, title, facts, tone badges) that opens in place to a
|
|
45
|
+
`DetailTable` plus optional children; a native `<details>`, closed by default, no client state. `data-slot` names:
|
|
46
|
+
`fold-row`, `fold-row-summary`, `fold-row-heading`, `fold-row-fact`, `fold-row-badges`, `fold-row-content`,
|
|
47
|
+
`detail-table`.
|
|
48
|
+
|
|
7
49
|
## 0.1.1
|
|
8
50
|
|
|
9
51
|
- No change to the package itself: the first version published through the npm trusted publisher (OIDC) with
|
package/README.md
CHANGED
|
@@ -16,6 +16,8 @@ npm i @softure-ai/theme-notion tailwindcss @tailwindcss/postcss
|
|
|
16
16
|
@import "tailwindcss";
|
|
17
17
|
@import "@softure-ai/theme-notion/theme.css"; /* tokens, utilities, dark:, animations, the components' classes */
|
|
18
18
|
@import "@softure-ai/theme-notion/sft-bridge.css"; /* optional: pages of the SOFTURE packages in a PageFrame */
|
|
19
|
+
@import "@softure-ai/theme-kit/base.css"; /* body on the theme's background, text colour and font */
|
|
20
|
+
@import "@softure-ai/theme-kit/maplibre.css"; /* only if the app shows MapLibre maps */
|
|
19
21
|
```
|
|
20
22
|
|
|
21
23
|
`theme.css` names the package's components as Tailwind sources, so their classes are generated without the app
|
|
@@ -32,8 +34,16 @@ taking the scoped preflight instead of Tailwind's:
|
|
|
32
34
|
@import "tailwindcss/utilities.css" layer(utilities);
|
|
33
35
|
@import "@softure-ai/theme-notion/theme.css";
|
|
34
36
|
@import "@softure-ai/theme-notion/sft-bridge.css";
|
|
37
|
+
@import "@softure-ai/theme-kit/base.css"; /* nothing else styles body under the scoped preflight */
|
|
38
|
+
@import "@softure-ai/theme-kit/maplibre.css"; /* only if the app shows MapLibre maps */
|
|
35
39
|
```
|
|
36
40
|
|
|
41
|
+
`base.css` gives `body` the theme's background, text colour and sans font without the browser's 8 px margin, so a
|
|
42
|
+
page without a shell root, the dark scheme and the Radix portals mounted on `body` (select lists, menus, sheets) all
|
|
43
|
+
take the theme. `maplibre.css` puts the theme's sans font on MapLibre maps (markers, popups, the attribution), which
|
|
44
|
+
`maplibre-gl.css` sets to Helvetica. Both read the theme with `--theme()`, so they go through the app's Tailwind
|
|
45
|
+
after `theme.css`; the app's `globals.css` keeps only `@import` lines.
|
|
46
|
+
|
|
37
47
|
```tsx
|
|
38
48
|
import { Button, Badge, Status, PageHeader, TooltipProvider, Toaster } from "@softure-ai/theme-notion";
|
|
39
49
|
import { CircleCheck } from "lucide-react";
|
|
@@ -52,9 +62,9 @@ import { CircleCheck } from "lucide-react";
|
|
|
52
62
|
`light` the other way. `Toaster` follows the system unless it gets `theme="light" | "dark"`.
|
|
53
63
|
|
|
54
64
|
**Copy.** The components' built-in texts are accessible names in English (`notionMessages.en`). Pass the app's own
|
|
55
|
-
wording by props: `Breadcrumb aria-label`, `BreadcrumbEllipsis label`, `
|
|
56
|
-
`
|
|
57
|
-
`Spinner aria-label`, `CommandDialog title description`.
|
|
65
|
+
wording by props: `Breadcrumb aria-label`, `BreadcrumbEllipsis label`, `PageHeader crumbsLabel`,
|
|
66
|
+
`DialogContent closeLabel`, `SheetContent closeLabel`, `SidePanel closeLabel`, `Sidebar mobileTitle mobileDescription`,
|
|
67
|
+
`SidebarTrigger label`, `SidebarRail label`, `Spinner aria-label`, `CommandDialog title description`.
|
|
58
68
|
|
|
59
69
|
## Rules, in short
|
|
60
70
|
|
|
@@ -73,6 +83,18 @@ wording by props: `Breadcrumb aria-label`, `BreadcrumbEllipsis label`, `DialogCo
|
|
|
73
83
|
(button, field, menu item), `lg` 8 (callout, card), `xl` 10 (menu, select, dialog), `full` (switch).
|
|
74
84
|
- Icons: lucide at `ICON_STROKE_WIDTH` (1.75), 16 px in text; they inherit the text colour. No emoji in the interface.
|
|
75
85
|
- Statuses always carry a word and an icon, so states read apart without telling green from red.
|
|
86
|
+
- Figures, bar segments and box edges take a **tone** by what they mean: `default` (text colour), `success` (green,
|
|
87
|
+
done), `warning` (orange, to do), `danger` (red, owed or failing), `muted` (gray, out of play). `TONE_COLORS` gives
|
|
88
|
+
a tone's palette colour (`null` for `default`); `TONE_TEXT`, `TONE_FILL` and `TONE_EDGE` give literal class names
|
|
89
|
+
(`text-*`, `bg-*`, `border-l-*`) that the shipped `theme.css` already generates, so the app adds no `@source`. The
|
|
90
|
+
app keeps only its meaning-to-tone table:
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { TONE_TEXT, type Tone } from "@softure-ai/theme-notion";
|
|
94
|
+
|
|
95
|
+
const PAYMENT_TONE: Record<"paid" | "due" | "overdue", Tone> = { paid: "success", due: "warning", overdue: "danger" };
|
|
96
|
+
<span className={TONE_TEXT[PAYMENT_TONE.overdue]}>1 200</span>
|
|
97
|
+
```
|
|
76
98
|
|
|
77
99
|
## Components
|
|
78
100
|
|
|
@@ -81,7 +103,61 @@ avatar, badge, breadcrumb, button, button-group, card, checkbox, collapsible, co
|
|
|
81
103
|
field, input, input-group, item, kbd, label, popover, progress, scroll-area, select, separator, sheet, sidebar,
|
|
82
104
|
skeleton, sonner (`Toaster`), spinner, switch, table, tabs, textarea, tooltip. Compositions: `Status` (badge, icon,
|
|
83
105
|
word), `PageHeader` (breadcrumb, icon box, title, description, actions), `PropertyList` (fields of one record),
|
|
84
|
-
`
|
|
106
|
+
`DetailTable` (an item's details as a label and value table), `FoldRow` (a list row folding open to a `DetailTable`
|
|
107
|
+
and more, a native `<details>`), `PageFrame` (a page outside the app shell, the target of `sft-bridge.css`),
|
|
108
|
+
`SidePanel` (a non-modal panel at a side of a canvas, below), `TabBar` (a screen's tabs as links with an optional icon
|
|
109
|
+
and count, the shown tab in the address; `Tabs` keeps it in client state), `MarkPopover` (a counted tag that opens a
|
|
110
|
+
list of what it counts, below).
|
|
111
|
+
|
|
112
|
+
**`SidePanel`.** A panel next to a canvas (a map) that leaves the canvas usable, so a switch inside shows its effect
|
|
113
|
+
at once (`Sheet` is modal). It floats on `background` with `shadow-menu`, 24 rem wide, full width on a phone, with a
|
|
114
|
+
heading and a ghost close button. Layouts: `over` (over the canvas's right side), `left` (over its left side),
|
|
115
|
+
`beside` (after the canvas, which shrinks to at least 24 rem or half) and `list` (a 24 rem column before the canvas);
|
|
116
|
+
`beside` and `list` cover the whole canvas on a phone. While closed it is `hidden`. Focus moves into it when it opens;
|
|
117
|
+
Escape inside or the close button calls `onClose`, and the caller moves focus back to its opener.
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
<div className="relative flex h-full">
|
|
121
|
+
<button type="button" aria-controls="layers" aria-expanded={isOpen} onClick={() => setOpen(true)}>Layers</button>
|
|
122
|
+
<Map className="flex-1" />
|
|
123
|
+
<SidePanel id="layers" heading="Layers" layout="over" isOpen={isOpen} onClose={() => setOpen(false)}>
|
|
124
|
+
{/* switches */}
|
|
125
|
+
</SidePanel>
|
|
126
|
+
</div>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
A screen's summary figures: `StatsFold` (figures folded under a heading, closed by default, on native `<details>`),
|
|
130
|
+
`StatCards` (a wrapping row of figure cards: label, figure in its tone, optional `hint`, optional `aside` tag;
|
|
131
|
+
`isFullWidth` and `isOneRow` change the grid) and `StatPills` ("label **value**" tags in one row). Each figure takes a
|
|
132
|
+
`tone`; the app keeps only its own table of which meaning takes which tone.
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
<StatsFold title="Summary">
|
|
136
|
+
<StatCards
|
|
137
|
+
label="Totals"
|
|
138
|
+
cards={[
|
|
139
|
+
{ key: "paid", label: "Paid", value: "1,200", tone: "success" },
|
|
140
|
+
{ key: "owed", label: "Owed", value: "300", tone: "danger", hint: "2 invoices", aside: { text: "+5%" } },
|
|
141
|
+
]}
|
|
142
|
+
/>
|
|
143
|
+
<StatPills label="Counts" pills={[{ key: "late", label: "Late", value: "1", tone: "danger" }]} />
|
|
144
|
+
</StatsFold>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**`MarkPopover`.** A tag in a palette colour with an icon and a count; a click or Enter opens the design system's
|
|
148
|
+
popover listing the entries, Escape or a click outside closes it. It runs on the browser's Popover API (no client
|
|
149
|
+
state, no portal): the panel sits in the top layer, so a card's `overflow` never clips it, centred on a phone and
|
|
150
|
+
under its mark where CSS anchor positioning is supported. Only phrasing elements, so it fits inside a `<summary>` or
|
|
151
|
+
a paragraph; a click on the panel's text does not toggle an enclosing `<details>`, links and buttons inside still
|
|
152
|
+
work. The colour means the worst of what it lists; the copy is props.
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
<MarkPopover color="red" icon={TriangleAlert} count={2} label="2 open warnings, show the list"
|
|
156
|
+
heading="Open warnings" closeLabel="Close" buttonData={{ "data-kind": "warnings" }}>
|
|
157
|
+
<span role="listitem">Payment overdue</span>
|
|
158
|
+
<span role="listitem"><a href="/tickets">Tickets to buy</a></span>
|
|
159
|
+
</MarkPopover>
|
|
160
|
+
```
|
|
85
161
|
|
|
86
162
|
Deltas from stock shadcn:
|
|
87
163
|
|
package/dist/index.d.ts
CHANGED
|
@@ -39,9 +39,16 @@ export * from "./ui/tabs.js";
|
|
|
39
39
|
export * from "./ui/textarea.js";
|
|
40
40
|
export * from "./ui/tooltip.js";
|
|
41
41
|
export { ICON_STROKE_WIDTH } from "./notion/icon-stroke.js";
|
|
42
|
+
export { DetailTable, type DetailRow, type DetailTableProps } from "./notion/DetailTable.js";
|
|
43
|
+
export { FoldRow, type FoldRowBadge, type FoldRowProps } from "./notion/FoldRow.js";
|
|
42
44
|
export { PALETTE_COLORS, type PaletteColor } from "./notion/palette.js";
|
|
45
|
+
export { MarkPopover, type MarkPopoverProps } from "./notion/MarkPopover.js";
|
|
43
46
|
export { PageFrame, type PageFrameProps } from "./notion/PageFrame.js";
|
|
44
47
|
export { PageHeader, type PageCrumb, type PageHeaderProps } from "./notion/PageHeader.js";
|
|
45
48
|
export { PropertyList, type Property, type PropertyListProps } from "./notion/PropertyList.js";
|
|
49
|
+
export { SidePanel, type SidePanelLayout, type SidePanelProps } from "./notion/SidePanel.js";
|
|
50
|
+
export { StatCards, StatPills, StatsFold, type StatCard, type StatCardAside, type StatCardsProps, type StatPill, type StatPillsProps, type StatsFoldProps, } from "./notion/Stats.js";
|
|
46
51
|
export { Status, type StatusProps } from "./notion/Status.js";
|
|
52
|
+
export { TabBar, type TabBarItem, type TabBarProps } from "./notion/TabBar.js";
|
|
53
|
+
export { TONES, TONE_COLORS, TONE_EDGE, TONE_FILL, TONE_TEXT, type Tone } from "./notion/tones.js";
|
|
47
54
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1E,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,KAAK,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1E,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC7F,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,KAAK,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -41,9 +41,16 @@ export * from "./ui/tabs.js";
|
|
|
41
41
|
export * from "./ui/textarea.js";
|
|
42
42
|
export * from "./ui/tooltip.js";
|
|
43
43
|
export { ICON_STROKE_WIDTH } from "./notion/icon-stroke.js";
|
|
44
|
+
export { DetailTable } from "./notion/DetailTable.js";
|
|
45
|
+
export { FoldRow } from "./notion/FoldRow.js";
|
|
44
46
|
export { PALETTE_COLORS } from "./notion/palette.js";
|
|
47
|
+
export { MarkPopover } from "./notion/MarkPopover.js";
|
|
45
48
|
export { PageFrame } from "./notion/PageFrame.js";
|
|
46
49
|
export { PageHeader } from "./notion/PageHeader.js";
|
|
47
50
|
export { PropertyList } from "./notion/PropertyList.js";
|
|
51
|
+
export { SidePanel } from "./notion/SidePanel.js";
|
|
52
|
+
export { StatCards, StatPills, StatsFold, } from "./notion/Stats.js";
|
|
48
53
|
export { Status } from "./notion/Status.js";
|
|
54
|
+
export { TabBar } from "./notion/TabBar.js";
|
|
55
|
+
export { TONES, TONE_COLORS, TONE_EDGE, TONE_FILL, TONE_TEXT } from "./notion/tones.js";
|
|
49
56
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,oGAAoG;AACpG,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAuB,MAAM,qBAAqB,CAAC;AAE1E,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAqB,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAuB,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAwC,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAyC,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,MAAM,EAAoB,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,oGAAoG;AACpG,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAuB,MAAM,qBAAqB,CAAC;AAE1E,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAyC,MAAM,yBAAyB,CAAC;AAC7F,OAAO,EAAE,OAAO,EAAwC,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,cAAc,EAAqB,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAyB,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAuB,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAwC,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAyC,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,SAAS,EAA6C,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,GAOV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,MAAM,EAAoB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAqC,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAa,MAAM,mBAAmB,CAAC"}
|
package/dist/messages/en.d.ts
CHANGED
|
@@ -13,6 +13,9 @@ export declare const en: {
|
|
|
13
13
|
readonly sheet: {
|
|
14
14
|
readonly close: "Close";
|
|
15
15
|
};
|
|
16
|
+
readonly sidePanel: {
|
|
17
|
+
readonly close: "Close";
|
|
18
|
+
};
|
|
16
19
|
readonly sidebar: {
|
|
17
20
|
readonly mobileTitle: "Sidebar";
|
|
18
21
|
readonly mobileDescription: "Displays the mobile sidebar.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;CAQL,CAAC"}
|
package/dist/messages/en.js
CHANGED
|
@@ -6,6 +6,7 @@ export const en = {
|
|
|
6
6
|
breadcrumb: { label: "breadcrumb", more: "More" },
|
|
7
7
|
dialog: { close: "Close" },
|
|
8
8
|
sheet: { close: "Close" },
|
|
9
|
+
sidePanel: { close: "Close" },
|
|
9
10
|
sidebar: { mobileTitle: "Sidebar", mobileDescription: "Displays the mobile sidebar.", toggle: "Toggle Sidebar" },
|
|
10
11
|
spinner: { label: "Loading" },
|
|
11
12
|
command: { title: "Command Palette", description: "Search for a command to run..." },
|
package/dist/messages/en.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB,UAAU,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE;IACjD,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;IAC1B,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;IACzB,OAAO,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,8BAA8B,EAAE,MAAM,EAAE,gBAAgB,EAAE;IAChH,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;IAC7B,OAAO,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,gCAAgC,EAAE;CAC5E,CAAC"}
|
|
1
|
+
{"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB,UAAU,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE;IACjD,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;IAC1B,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;IACzB,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;IAC7B,OAAO,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,8BAA8B,EAAE,MAAM,EAAE,gBAAgB,EAAE;IAChH,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;IAC7B,OAAO,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,gCAAgC,EAAE;CAC5E,CAAC"}
|
package/dist/messages/index.d.ts
CHANGED
|
@@ -12,6 +12,9 @@ export declare const notionMessages: {
|
|
|
12
12
|
readonly sheet: {
|
|
13
13
|
readonly close: "Close";
|
|
14
14
|
};
|
|
15
|
+
readonly sidePanel: {
|
|
16
|
+
readonly close: "Close";
|
|
17
|
+
};
|
|
15
18
|
readonly sidebar: {
|
|
16
19
|
readonly mobileTitle: "Sidebar";
|
|
17
20
|
readonly mobileDescription: "Displays the mobile sidebar.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B,qGAAqG;AACrG,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B,qGAAqG;AACrG,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAS,CAAC;AAErC,MAAM,MAAM,cAAc,GAAG,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface DetailRow {
|
|
3
|
+
/** Unique within the table; kept on the row as `data-detail`. */
|
|
4
|
+
readonly key: string;
|
|
5
|
+
readonly label: string;
|
|
6
|
+
/** `null`, `undefined` or "": nothing to show, the row is left out. */
|
|
7
|
+
readonly value: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export interface DetailTableProps {
|
|
10
|
+
/** The table's accessible name. */
|
|
11
|
+
readonly label: string;
|
|
12
|
+
readonly rows: readonly DetailRow[];
|
|
13
|
+
}
|
|
14
|
+
export declare function DetailTable({ label, rows }: DetailTableProps): import("react").JSX.Element | null;
|
|
15
|
+
//# sourceMappingURL=DetailTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DetailTable.d.ts","sourceRoot":"","sources":["../../src/notion/DetailTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,SAAS;IACxB,iEAAiE;IACjE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,mCAAmC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;CACrC;AAgBD,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,gBAAgB,sCAe5D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// A row header in a narrow muted column, a quiet line under every row; on a phone the label sits above its value.
|
|
3
|
+
const DETAIL_TABLE_CLASS = [
|
|
4
|
+
"w-full border-collapse text-ui",
|
|
5
|
+
"[&_tr]:border-b [&_tr]:border-border",
|
|
6
|
+
"[&_th]:w-48 [&_th]:py-1.5 [&_th]:pr-3 [&_th]:text-left [&_th]:align-top [&_th]:font-normal [&_th]:text-muted-foreground",
|
|
7
|
+
"[&_td]:py-1.5 [&_td]:align-top [&_td]:wrap-anywhere",
|
|
8
|
+
"max-sm:[&_tr]:block max-sm:[&_tr]:py-1.5 max-sm:[&_th]:block max-sm:[&_th]:w-auto max-sm:[&_th]:py-0 max-sm:[&_td]:block max-sm:[&_td]:py-0",
|
|
9
|
+
].join(" ");
|
|
10
|
+
function hasValue(row) {
|
|
11
|
+
return row.value !== null && row.value !== undefined && row.value !== "";
|
|
12
|
+
}
|
|
13
|
+
// An item's details as a label and value table in the Notion table style; nothing renders when no row has a value.
|
|
14
|
+
export function DetailTable({ label, rows }) {
|
|
15
|
+
const shown = rows.filter(hasValue);
|
|
16
|
+
if (shown.length === 0)
|
|
17
|
+
return null;
|
|
18
|
+
return (_jsx("table", { "data-slot": "detail-table", className: DETAIL_TABLE_CLASS, "aria-label": label, children: _jsx("tbody", { children: shown.map((row) => (_jsxs("tr", { "data-detail": row.key, children: [_jsx("th", { scope: "row", children: row.label }), _jsx("td", { children: row.value })] }, row.key))) }) }));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=DetailTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DetailTable.js","sourceRoot":"","sources":["../../src/notion/DetailTable.tsx"],"names":[],"mappings":";AAgBA,kHAAkH;AAClH,MAAM,kBAAkB,GAAG;IACzB,gCAAgC;IAChC,sCAAsC;IACtC,yHAAyH;IACzH,qDAAqD;IACrD,6IAA6I;CAC9I,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,SAAS,QAAQ,CAAC,GAAc;IAC9B,OAAO,GAAG,CAAC,KAAK,KAAK,IAAI,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC;AAC3E,CAAC;AAED,mHAAmH;AACnH,MAAM,UAAU,WAAW,CAAC,EAAE,KAAK,EAAE,IAAI,EAAoB;IAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,CACL,6BAAiB,cAAc,EAAC,SAAS,EAAE,kBAAkB,gBAAc,KAAK,YAC9E,0BACG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAClB,6BAA+B,GAAG,CAAC,GAAG,aACpC,aAAI,KAAK,EAAC,KAAK,YAAE,GAAG,CAAC,KAAK,GAAM,EAChC,uBAAK,GAAG,CAAC,KAAK,GAAM,KAFb,GAAG,CAAC,GAAG,CAGX,CACN,CAAC,GACI,GACF,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { type DetailRow } from "./DetailTable.js";
|
|
3
|
+
import { type Tone } from "./tones.js";
|
|
4
|
+
export interface FoldRowBadge {
|
|
5
|
+
/** Unique within the row; kept on the badge as `data-badge`. */
|
|
6
|
+
readonly key: string;
|
|
7
|
+
readonly text: string;
|
|
8
|
+
readonly tone?: Tone;
|
|
9
|
+
}
|
|
10
|
+
export interface FoldRowProps {
|
|
11
|
+
readonly title: ReactNode;
|
|
12
|
+
/** Short facts after the title; left out when empty. */
|
|
13
|
+
readonly facts?: readonly ReactNode[];
|
|
14
|
+
/** Badges on the row's right, in order. */
|
|
15
|
+
readonly badges: readonly FoldRowBadge[];
|
|
16
|
+
/** The details table's accessible name. */
|
|
17
|
+
readonly detailsLabel: string;
|
|
18
|
+
readonly details: readonly DetailRow[];
|
|
19
|
+
/** More content under the table when opened. */
|
|
20
|
+
readonly children?: ReactNode;
|
|
21
|
+
}
|
|
22
|
+
export declare function FoldRow({ title, facts, badges, detailsLabel, details, children }: FoldRowProps): import("react").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=FoldRow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FoldRow.d.ts","sourceRoot":"","sources":["../../src/notion/FoldRow.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,EAAe,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC,2CAA2C;IAC3C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;CAC/B;AAGD,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,KAAU,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,YAAY,+BA+CnG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronRight } from "lucide-react";
|
|
3
|
+
import { Badge } from "../ui/badge.js";
|
|
4
|
+
import { DetailTable } from "./DetailTable.js";
|
|
5
|
+
import { ICON_STROKE_WIDTH } from "./icon-stroke.js";
|
|
6
|
+
import { TONE_COLORS } from "./tones.js";
|
|
7
|
+
// An item as one folding list row: a native `<details>` that opens in place to its details, with no client state.
|
|
8
|
+
export function FoldRow({ title, facts = [], badges, detailsLabel, details, children }) {
|
|
9
|
+
return (_jsxs("details", { "data-slot": "fold-row", className: "group/fold-row border-b border-border", children: [_jsxs("summary", { "data-slot": "fold-row-summary", className: "flex min-h-row-height cursor-pointer list-none flex-wrap items-center gap-x-2 gap-y-1 rounded-md px-1 py-1 transition-colors duration-120 group-open/fold-row:bg-accent hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none [&::-webkit-details-marker]:hidden", children: [_jsxs("span", { "data-slot": "fold-row-heading", className: "flex min-w-0 items-center gap-2", children: [_jsx(ChevronRight, { "aria-hidden": "true", strokeWidth: ICON_STROKE_WIDTH, className: "size-4 shrink-0 text-muted-foreground transition-transform duration-150 group-open/fold-row:rotate-90" }), _jsx("span", { className: "min-w-0 text-ui-medium", children: title })] }), facts.map((fact, index) => (_jsx("span", { "data-slot": "fold-row-fact", className: "text-ui text-muted-foreground", children: fact }, index))), badges.length === 0 ? null : (_jsx("span", { "data-slot": "fold-row-badges", className: "ml-auto inline-flex flex-wrap gap-1", children: badges.map((badge) => {
|
|
10
|
+
const tone = badge.tone ?? "default";
|
|
11
|
+
return (_jsx(Badge, { variant: "tag", color: TONE_COLORS[tone] ?? "default", "data-badge": badge.key, "data-tone": tone, children: badge.text }, badge.key));
|
|
12
|
+
}) }))] }), _jsxs("div", { "data-slot": "fold-row-content", className: "flex flex-col gap-2 py-2 pr-1 pl-6 empty:hidden", children: [_jsx(DetailTable, { label: detailsLabel, rows: details }), children] })] }));
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=FoldRow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FoldRow.js","sourceRoot":"","sources":["../../src/notion/FoldRow.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,OAAO,EAAE,WAAW,EAAkB,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAa,MAAM,YAAY,CAAC;AAsBpD,kHAAkH;AAClH,MAAM,UAAU,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAgB;IAClG,OAAO,CACL,gCAAmB,UAAU,EAAC,SAAS,EAAC,uCAAuC,aAC7E,gCACY,kBAAkB,EAC5B,SAAS,EAAC,oSAAoS,aAG9S,6BAAgB,kBAAkB,EAAC,SAAS,EAAC,iCAAiC,aAC5E,KAAC,YAAY,mBACC,MAAM,EAClB,WAAW,EAAE,iBAAiB,EAC9B,SAAS,EAAC,uGAAuG,GACjH,EACF,eAAM,SAAS,EAAC,wBAAwB,YAAE,KAAK,GAAQ,IAClD,EACN,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAE1B,4BAA4B,eAAe,EAAC,SAAS,EAAC,+BAA+B,YAClF,IAAI,IADI,KAAK,CAET,CACR,CAAC,EACD,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC5B,4BAAgB,iBAAiB,EAAC,SAAS,EAAC,qCAAqC,YAC9E,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;4BACpB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;4BACrC,OAAO,CACL,KAAC,KAAK,IAEJ,OAAO,EAAC,KAAK,EACb,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,SAAS,gBACzB,KAAK,CAAC,GAAG,eACV,IAAI,YAEd,KAAK,CAAC,IAAI,IANN,KAAK,CAAC,GAAG,CAOR,CACT,CAAC;wBACJ,CAAC,CAAC,GACG,CACR,IACO,EACV,4BAAe,kBAAkB,EAAC,SAAS,EAAC,iDAAiD,aAC3F,KAAC,WAAW,IAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,GAAI,EAClD,QAAQ,IACL,IACE,CACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { LucideIcon } from "lucide-react";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
import type { PaletteColor } from "./palette.js";
|
|
4
|
+
export interface MarkPopoverProps {
|
|
5
|
+
/** The mark's colour: a palette colour that means the worst of what it lists. */
|
|
6
|
+
readonly color: PaletteColor;
|
|
7
|
+
readonly icon: LucideIcon;
|
|
8
|
+
readonly count: number;
|
|
9
|
+
/** The mark's accessible name: what it counts and that it opens a list. */
|
|
10
|
+
readonly label: string;
|
|
11
|
+
readonly heading: string;
|
|
12
|
+
readonly closeLabel: string;
|
|
13
|
+
/** Extra `data-*` attributes kept on the button. */
|
|
14
|
+
readonly buttonData?: Readonly<Record<`data-${string}`, string | undefined>>;
|
|
15
|
+
/** The entries, as phrasing elements with `role="listitem"`. */
|
|
16
|
+
readonly children: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
export declare function MarkPopover({ color, icon: Icon, count, label, heading, closeLabel, buttonData, children }: MarkPopoverProps): import("react").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=MarkPopover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkPopover.d.ts","sourceRoot":"","sources":["../../src/notion/MarkPopover.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAO/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,oDAAoD;IACpD,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC7E,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AAMD,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,gBAAgB,+BA8C3H"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { badgeVariants } from "../ui/badge.js";
|
|
5
|
+
import { buttonVariants } from "../ui/button.js";
|
|
6
|
+
import { cn } from "../lib/utils.js";
|
|
7
|
+
import { ICON_STROKE_WIDTH } from "./icon-stroke.js";
|
|
8
|
+
// A counted tag (open warnings, tickets to buy) that opens a list of what it counts. The browser's Popover API opens
|
|
9
|
+
// it on click or Enter and closes it on Escape or a click outside, with no client state; the panel sits in the top
|
|
10
|
+
// layer, so a card's overflow never clips it. Centred on a phone, under its mark where CSS anchor positioning works.
|
|
11
|
+
// Phrasing elements only, so the mark fits inside a `<summary>` or a paragraph.
|
|
12
|
+
export function MarkPopover({ color, icon: Icon, count, label, heading, closeLabel, buttonData, children }) {
|
|
13
|
+
const panelId = useId();
|
|
14
|
+
return (_jsxs("span", { "data-slot": "mark", className: "inline-flex [anchor-scope:--mark]", children: [_jsxs("button", { type: "button", className: cn(badgeVariants({ variant: "tag", color }), "cursor-pointer gap-1 font-medium tabular-nums [anchor-name:--mark] focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"), ...buttonData, popoverTarget: panelId, "aria-haspopup": "dialog", "aria-label": label, children: [_jsx(Icon, { "aria-hidden": "true", strokeWidth: ICON_STROKE_WIDTH }), _jsx("span", { "aria-hidden": "true", children: count })] }), _jsxs("span", { id: panelId, popover: "auto", role: "dialog", "aria-labelledby": `${panelId}-heading`, "data-slot": "mark-popover", className: "max-h-[min(24rem,calc(100vh-2rem))] w-[min(22rem,calc(100vw-2rem))] cursor-auto overflow-y-auto rounded-xl bg-popover p-3 text-left text-ui font-normal whitespace-normal text-popover-foreground shadow-menu backdrop:bg-transparent sm:supports-[position-anchor:--mark]:mt-1 sm:supports-[position-anchor:--mark]:mr-0 sm:supports-[position-anchor:--mark]:mb-0 sm:supports-[position-anchor:--mark]:ml-0 sm:supports-[position-anchor:--mark]:[position-anchor:--mark] sm:supports-[position-anchor:--mark]:[position-area:block-end_span-inline-start] sm:supports-[position-anchor:--mark]:[position-try-fallbacks:flip-block,flip-inline]", onClick: keepEnclosingDetailsFolded, children: [_jsxs("span", { className: "mb-2 flex items-center justify-between gap-2", children: [_jsx("span", { id: `${panelId}-heading`, className: "text-ui-medium", children: heading }), _jsx("button", { type: "button", className: buttonVariants({ variant: "ghost", size: "xs" }), popoverTarget: panelId, popoverTargetAction: "hide", children: closeLabel })] }), _jsx("span", { role: "list", className: "flex flex-col gap-2", children: children })] })] }));
|
|
15
|
+
}
|
|
16
|
+
// A click on the panel's text would toggle an enclosing `<details>` (the mark sits in its summary); links and
|
|
17
|
+
// buttons inside keep their default.
|
|
18
|
+
function keepEnclosingDetailsFolded(event) {
|
|
19
|
+
if (event.target instanceof Element && event.target.closest("a, button") === null)
|
|
20
|
+
event.preventDefault();
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=MarkPopover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkPopover.js","sourceRoot":"","sources":["../../src/notion/MarkPopover.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EAAE,KAAK,EAAmC,MAAM,OAAO,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAErC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAkBrD,qHAAqH;AACrH,mHAAmH;AACnH,qHAAqH;AACrH,gFAAgF;AAChF,MAAM,UAAU,WAAW,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAoB;IAC1H,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;IACxB,OAAO,CACL,6BAAgB,MAAM,EAAC,SAAS,EAAC,mCAAmC,aAClE,kBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,EAAE,CACX,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EACxC,4IAA4I,CAC7I,KACG,UAAU,EACd,aAAa,EAAE,OAAO,mBACR,QAAQ,gBACV,KAAK,aAEjB,KAAC,IAAI,mBAAa,MAAM,EAAC,WAAW,EAAE,iBAAiB,GAAI,EAC3D,8BAAkB,MAAM,YAAE,KAAK,GAAQ,IAChC,EACT,gBACE,EAAE,EAAE,OAAO,EACX,OAAO,EAAC,MAAM,EACd,IAAI,EAAC,QAAQ,qBACI,GAAG,OAAO,UAAU,eAC3B,cAAc,EACxB,SAAS,EAAC,mnBAAmnB,EAC7nB,OAAO,EAAE,0BAA0B,aAEnC,gBAAM,SAAS,EAAC,8CAA8C,aAC5D,eAAM,EAAE,EAAE,GAAG,OAAO,UAAU,EAAE,SAAS,EAAC,gBAAgB,YACvD,OAAO,GACH,EACP,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,cAAc,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAC3D,aAAa,EAAE,OAAO,EACtB,mBAAmB,EAAC,MAAM,YAEzB,UAAU,GACJ,IACJ,EACP,eAAM,IAAI,EAAC,MAAM,EAAC,SAAS,EAAC,qBAAqB,YAC9C,QAAQ,GACJ,IACF,IACF,CACR,CAAC;AACJ,CAAC;AAED,8GAA8G;AAC9G,qCAAqC;AACrC,SAAS,0BAA0B,CAAC,KAA8B;IAChE,IAAI,KAAK,CAAC,MAAM,YAAY,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI;QAAE,KAAK,CAAC,cAAc,EAAE,CAAC;AAC5G,CAAC"}
|
|
@@ -6,11 +6,12 @@ export interface PageCrumb {
|
|
|
6
6
|
export interface PageHeaderProps {
|
|
7
7
|
title: ReactNode;
|
|
8
8
|
crumbs?: PageCrumb[];
|
|
9
|
+
crumbsLabel?: string;
|
|
9
10
|
icon?: ReactNode;
|
|
10
11
|
description?: ReactNode;
|
|
11
12
|
actions?: ReactNode;
|
|
12
13
|
children?: ReactNode;
|
|
13
14
|
className?: string;
|
|
14
15
|
}
|
|
15
|
-
export declare function PageHeader({ title, crumbs, icon, description, actions, children, className }: PageHeaderProps): import("react").JSX.Element;
|
|
16
|
+
export declare function PageHeader({ title, crumbs, crumbsLabel, icon, description, actions, children, className }: PageHeaderProps): import("react").JSX.Element;
|
|
16
17
|
//# sourceMappingURL=PageHeader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageHeader.d.ts","sourceRoot":"","sources":["../../src/notion/PageHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAYjD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IAErB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAGD,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,eAAe,+
|
|
1
|
+
{"version":3,"file":"PageHeader.d.ts","sourceRoot":"","sources":["../../src/notion/PageHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAYjD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IAErB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAGD,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,eAAe,+BA8B1H"}
|
|
@@ -3,7 +3,7 @@ import { Fragment } from "react";
|
|
|
3
3
|
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "../ui/breadcrumb.js";
|
|
4
4
|
import { cn } from "../lib/utils.js";
|
|
5
5
|
// The page's header, once per screen: breadcrumb, page icon, the 40 px title, what follows it, a description and actions.
|
|
6
|
-
export function PageHeader({ title, crumbs, icon, description, actions, children, className }) {
|
|
7
|
-
return (_jsxs("header", { "data-slot": "page-header", className: cn("flex flex-col", className), children: [crumbs && crumbs.length > 0 ? (_jsx(Breadcrumb, { children: _jsx(BreadcrumbList, { children: crumbs.map((crumb, index) => (_jsxs(Fragment, { children: [index > 0 ? _jsx(BreadcrumbSeparator, {}) : null, _jsx(BreadcrumbItem, { children: crumb.href === undefined ? (_jsx(BreadcrumbPage, { children: crumb.label })) : (_jsx(BreadcrumbLink, { href: crumb.href, children: crumb.label })) })] }, `${index}-${crumb.label}`))) }) })) : null, icon ? (_jsx("div", { className: "mt-6 mb-2 flex size-14 items-center justify-center rounded-xl bg-secondary [&>svg]:size-8", children: icon })) : null, _jsx("h1", { className: "text-page-title text-balance", children: title }), children, description ? _jsx("p", { className: "mt-1 text-body text-muted-foreground", children: description }) : null, actions ? _jsx("div", { className: "mt-3 flex flex-wrap gap-1", children: actions }) : null] }));
|
|
6
|
+
export function PageHeader({ title, crumbs, crumbsLabel, icon, description, actions, children, className }) {
|
|
7
|
+
return (_jsxs("header", { "data-slot": "page-header", className: cn("flex flex-col", className), children: [crumbs && crumbs.length > 0 ? (_jsx(Breadcrumb, { ...(crumbsLabel === undefined ? {} : { "aria-label": crumbsLabel }), children: _jsx(BreadcrumbList, { children: crumbs.map((crumb, index) => (_jsxs(Fragment, { children: [index > 0 ? _jsx(BreadcrumbSeparator, {}) : null, _jsx(BreadcrumbItem, { children: crumb.href === undefined ? (_jsx(BreadcrumbPage, { children: crumb.label })) : (_jsx(BreadcrumbLink, { href: crumb.href, children: crumb.label })) })] }, `${index}-${crumb.label}`))) }) })) : null, icon ? (_jsx("div", { className: "mt-6 mb-2 flex size-14 items-center justify-center rounded-xl bg-secondary [&>svg]:size-8", children: icon })) : null, _jsx("h1", { className: "text-page-title text-balance", children: title }), children, description ? _jsx("p", { className: "mt-1 text-body text-muted-foreground", children: description }) : null, actions ? _jsx("div", { className: "mt-3 flex flex-wrap gap-1", children: actions }) : null] }));
|
|
8
8
|
}
|
|
9
9
|
//# sourceMappingURL=PageHeader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageHeader.js","sourceRoot":"","sources":["../../src/notion/PageHeader.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAEjD,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"PageHeader.js","sourceRoot":"","sources":["../../src/notion/PageHeader.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAEjD,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAsBrC,0HAA0H;AAC1H,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAmB;IACzH,OAAO,CACL,+BAAkB,aAAa,EAAC,SAAS,EAAE,EAAE,CAAC,eAAe,EAAE,SAAS,CAAC,aACtE,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAC7B,KAAC,UAAU,OAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,YAC9E,KAAC,cAAc,cACZ,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAC5B,MAAC,QAAQ,eACN,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAC,mBAAmB,KAAG,CAAC,CAAC,CAAC,IAAI,EAC3C,KAAC,cAAc,cACZ,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAC1B,KAAC,cAAc,cAAE,KAAK,CAAC,KAAK,GAAkB,CAC/C,CAAC,CAAC,CAAC,CACF,KAAC,cAAc,IAAC,IAAI,EAAE,KAAK,CAAC,IAAI,YAAG,KAAK,CAAC,KAAK,GAAkB,CACjE,GACc,KARJ,GAAG,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAS7B,CACZ,CAAC,GACa,GACN,CACd,CAAC,CAAC,CAAC,IAAI,EACP,IAAI,CAAC,CAAC,CAAC,CACN,cAAK,SAAS,EAAC,2FAA2F,YAAE,IAAI,GAAO,CACxH,CAAC,CAAC,CAAC,IAAI,EACR,aAAI,SAAS,EAAC,8BAA8B,YAAE,KAAK,GAAM,EACxD,QAAQ,EACR,WAAW,CAAC,CAAC,CAAC,YAAG,SAAS,EAAC,sCAAsC,YAAE,WAAW,GAAK,CAAC,CAAC,CAAC,IAAI,EAC1F,OAAO,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,2BAA2B,YAAE,OAAO,GAAO,CAAC,CAAC,CAAC,IAAI,IACrE,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export type SidePanelLayout = "over" | "beside" | "left" | "list";
|
|
3
|
+
export interface SidePanelProps {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly heading: string;
|
|
6
|
+
readonly layout: SidePanelLayout;
|
|
7
|
+
readonly isOpen: boolean;
|
|
8
|
+
readonly onClose: () => void;
|
|
9
|
+
readonly closeLabel?: string;
|
|
10
|
+
readonly children: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export declare function SidePanel({ id, heading, layout, isOpen, onClose, closeLabel, children }: SidePanelProps): import("react").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=SidePanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SidePanel.d.ts","sourceRoot":"","sources":["../../src/notion/SidePanel.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAyC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAS9E,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAElE,MAAM,WAAW,cAAc;IAE7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAE7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AAID,wBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAqC,EAAE,QAAQ,EAAE,EAAE,cAAc,+BA2ClI"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { X } from "lucide-react";
|
|
4
|
+
import { useEffect, useRef } from "react";
|
|
5
|
+
import { en as messages } from "../messages/en.js";
|
|
6
|
+
import { Button } from "../ui/button.js";
|
|
7
|
+
import { ICON_STROKE_WIDTH } from "./icon-stroke.js";
|
|
8
|
+
// A non-modal panel at a side of a canvas (a map) that leaves the canvas usable. Its parent is a `relative` flex row
|
|
9
|
+
// holding the canvas and the panel. Hidden while closed, so its content leaves the reading order.
|
|
10
|
+
export function SidePanel({ id, heading, layout, isOpen, onClose, closeLabel = messages.sidePanel.close, children }) {
|
|
11
|
+
const panelRef = useRef(null);
|
|
12
|
+
const wasOpenRef = useRef(isOpen);
|
|
13
|
+
const headingId = `${id}-heading`;
|
|
14
|
+
// Focus moves in when the panel opens, not when it is open on first render.
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (isOpen && !wasOpenRef.current)
|
|
17
|
+
panelRef.current?.focus();
|
|
18
|
+
wasOpenRef.current = isOpen;
|
|
19
|
+
}, [isOpen]);
|
|
20
|
+
function closeOnEscape(event) {
|
|
21
|
+
if (event.key !== "Escape")
|
|
22
|
+
return;
|
|
23
|
+
event.stopPropagation();
|
|
24
|
+
onClose();
|
|
25
|
+
}
|
|
26
|
+
return (_jsxs("aside", { ref: panelRef, id: id, tabIndex: -1, "data-slot": "side-panel", className: "absolute inset-y-0 right-0 z-3 flex w-[min(24rem,100%)] flex-col border-l border-border bg-background text-foreground shadow-menu outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset data-[layout=beside]:relative data-[layout=beside]:w-auto data-[layout=beside]:max-w-full data-[layout=beside]:flex-[0_0_max(50%,24rem)] data-[layout=left]:right-auto data-[layout=left]:left-0 data-[layout=left]:border-r data-[layout=left]:border-l-0 max-sm:data-[layout=beside]:absolute max-sm:data-[layout=beside]:inset-0 max-sm:data-[layout=beside]:w-full max-sm:data-[layout=beside]:border-l-0 data-[layout=list]:relative data-[layout=list]:flex-none data-[layout=list]:border-r data-[layout=list]:border-l-0 max-sm:data-[layout=list]:absolute max-sm:data-[layout=list]:inset-0 max-sm:data-[layout=list]:w-full max-sm:data-[layout=list]:border-r-0 [&[hidden]]:hidden", "data-layout": layout, hidden: !isOpen, "aria-labelledby": headingId, "data-testid": id, onKeyDown: closeOnEscape, children: [_jsxs("div", { className: "flex items-center justify-between gap-2 border-b border-border py-2 pr-2 pl-4", children: [_jsx("h2", { id: headingId, className: "text-heading-3", children: heading }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": closeLabel, onClick: onClose, children: _jsx(X, { "aria-hidden": "true", strokeWidth: ICON_STROKE_WIDTH }) })] }), _jsx("div", { "data-slot": "side-panel-content", className: "grid flex-1 content-start gap-3 overflow-y-auto p-3", children: children })] }));
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=SidePanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SidePanel.js","sourceRoot":"","sources":["../../src/notion/SidePanel.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAsC,MAAM,OAAO,CAAC;AAE9E,OAAO,EAAE,EAAE,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAmBrD,qHAAqH;AACrH,kGAAkG;AAClG,MAAM,UAAU,SAAS,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAkB;IACjI,MAAM,QAAQ,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,GAAG,EAAE,UAAU,CAAC;IAElC,4EAA4E;IAC5E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO;YAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QAC7D,UAAU,CAAC,OAAO,GAAG,MAAM,CAAC;IAC9B,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,SAAS,aAAa,CAAC,KAAiC;QACtD,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ;YAAE,OAAO;QACnC,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,CACL,iBACE,GAAG,EAAE,QAAQ,EACb,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,CAAC,CAAC,eACF,YAAY,EACtB,SAAS,EAAC,q3BAAq3B,iBACl3B,MAAM,EACnB,MAAM,EAAE,CAAC,MAAM,qBACE,SAAS,iBACb,EAAE,EACf,SAAS,EAAE,aAAa,aAExB,eAAK,SAAS,EAAC,+EAA+E,aAC5F,aAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAC,gBAAgB,YAC1C,OAAO,GACL,EACL,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,MAAM,gBAAa,UAAU,EAAE,OAAO,EAAE,OAAO,YACxF,KAAC,CAAC,mBAAa,MAAM,EAAC,WAAW,EAAE,iBAAiB,GAAI,GACjD,IACL,EACN,2BAAe,oBAAoB,EAAC,SAAS,EAAC,qDAAqD,YAChG,QAAQ,GACL,IACA,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { type Tone } from "./tones.js";
|
|
3
|
+
export interface StatsFoldProps {
|
|
4
|
+
/** The section's heading. */
|
|
5
|
+
readonly title: string;
|
|
6
|
+
readonly children: ReactNode;
|
|
7
|
+
readonly className?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function StatsFold({ title, children, className }: StatsFoldProps): import("react").JSX.Element;
|
|
10
|
+
export interface StatCardAside {
|
|
11
|
+
readonly text: string;
|
|
12
|
+
readonly tone?: Tone;
|
|
13
|
+
}
|
|
14
|
+
export interface StatCard {
|
|
15
|
+
/** Unique within the row; kept as `data-stat`. */
|
|
16
|
+
readonly key: string;
|
|
17
|
+
readonly label: string;
|
|
18
|
+
readonly value: string;
|
|
19
|
+
readonly hint?: string;
|
|
20
|
+
readonly tone?: Tone;
|
|
21
|
+
readonly aside?: StatCardAside;
|
|
22
|
+
}
|
|
23
|
+
export interface StatCardsProps {
|
|
24
|
+
/** The list's accessible name. */
|
|
25
|
+
readonly label: string;
|
|
26
|
+
readonly cards: readonly StatCard[];
|
|
27
|
+
/** The cards stretch across the column (min 14rem) instead of the narrow grid (min 10rem). */
|
|
28
|
+
readonly isFullWidth?: boolean;
|
|
29
|
+
/** Every card in one row from `sm` up, wrapping only on a phone. */
|
|
30
|
+
readonly isOneRow?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare function StatCards({ label, cards, isFullWidth, isOneRow }: StatCardsProps): import("react").JSX.Element;
|
|
33
|
+
export interface StatPill {
|
|
34
|
+
readonly key: string;
|
|
35
|
+
readonly label: string;
|
|
36
|
+
readonly value: string;
|
|
37
|
+
readonly tone?: Tone;
|
|
38
|
+
}
|
|
39
|
+
export interface StatPillsProps {
|
|
40
|
+
/** The list's accessible name. */
|
|
41
|
+
readonly label: string;
|
|
42
|
+
readonly pills: readonly StatPill[];
|
|
43
|
+
}
|
|
44
|
+
export declare function StatPills({ label, pills }: StatPillsProps): import("react").JSX.Element;
|
|
45
|
+
//# sourceMappingURL=Stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stats.d.ts","sourceRoot":"","sources":["../../src/notion/Stats.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,EAA0B,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,6BAA6B;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAID,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,cAAc,+BAmBvE;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,kDAAkD;IAClD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,8FAA8F;IAC9F,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AASD,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,WAAmB,EAAE,QAAgB,EAAE,EAAE,cAAc,+BA6ChG;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;CACrC;AAGD,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,cAAc,+BAYzD"}
|