@slotted/react 0.1.0-beta.3 → 0.1.0-beta.4
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/{accordion-D-YuMJzk.js → accordion-lCqrmQ3w.js} +43 -43
- package/dist/accordion.js +1 -1
- package/dist/calendar-BZ6PP7Ke.js +436 -0
- package/dist/calendar.js +1 -1
- package/dist/{collapsible-CGo49NNW.js → collapsible-F-K36XbF.js} +17 -17
- package/dist/collapsible.js +1 -1
- package/dist/{data-grid-BKaGMqIm.js → data-grid-Eb-a4jg3.js} +6 -6
- package/dist/data-grid.js +1 -1
- package/dist/date-field-Hr-OCU-H.js +290 -0
- package/dist/date-field.js +1 -1
- package/dist/date-picker-D3-y2Jxw.js +295 -0
- package/dist/date-picker.js +1 -1
- package/dist/{date-range-picker-CNOAtHwU.js → date-range-picker-y3b82Wmf.js} +2 -2
- package/dist/date-range-picker.js +1 -1
- package/dist/{datetime-picker-HDVlUhzy.js → datetime-picker-CIRHVLQp.js} +1 -1
- package/dist/datetime-picker.js +1 -1
- package/dist/{datetime-range-picker-IqOFJtdW.js → datetime-range-picker-DM-1m98z.js} +1 -1
- package/dist/datetime-range-picker.js +1 -1
- package/dist/{detail-panel-qOJiNuzr.js → detail-panel-CW53lUjp.js} +3 -3
- package/dist/detail-panel.js +1 -1
- package/dist/docs/calendar.json +7 -0
- package/dist/docs/calendar.md +1 -0
- package/dist/docs/collapsible.json +1 -1
- package/dist/docs/collapsible.md +1 -1
- package/dist/docs/date-field.json +8 -1
- package/dist/docs/date-field.md +2 -1
- package/dist/docs/date-picker.examples.md +29 -0
- package/dist/docs/date-picker.json +16 -1
- package/dist/docs/date-picker.md +2 -1
- package/dist/docs/guidelines/composition.md +10 -0
- package/dist/docs/guidelines/index.md +2 -0
- package/dist/docs/guidelines/list-pages.md +12 -1
- package/dist/docs/page.json +1 -0
- package/dist/docs/page.md +1 -0
- package/dist/docs/select.json +1 -1
- package/dist/docs/select.md +1 -1
- package/dist/docs/skills/compose-screen/SKILL.md +7 -0
- package/dist/docs/table.json +13 -0
- package/dist/docs/table.md +3 -1
- package/dist/docs/tabs.json +9 -1
- package/dist/docs/tabs.md +3 -1
- package/dist/docs/text-field.json +1 -1
- package/dist/docs/text-field.md +1 -1
- package/dist/{entity-picker-CPDd73JR.js → entity-picker-Dn1T7JCq.js} +1 -1
- package/dist/entity-picker.js +1 -1
- package/dist/{filter-bar-D_xDcAp2.js → filter-bar-CHyy1o--.js} +3 -3
- package/dist/filter-bar.js +1 -1
- package/dist/{import-export-center-DpY2DGBZ.js → import-export-center-jF37b909.js} +2 -2
- package/dist/import-export-center.js +1 -1
- package/dist/index.js +19 -19
- package/dist/{notification-center-Sz54IziY.js → notification-center-C1iWWl5Y.js} +1 -1
- package/dist/notification-center.js +1 -1
- package/dist/{page-kQgLctsA.js → page-IiYXk1sz.js} +32 -32
- package/dist/{page-header-CWEBfMGq.js → page-header-Bn4nIGfF.js} +1 -1
- package/dist/page-header.js +1 -1
- package/dist/page.js +1 -1
- package/dist/{select-DOFqPy26.js → select-M7Io4UL9.js} +273 -260
- package/dist/select.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/{table-Cipi2c5X.js → table-U9eJYCuB.js} +167 -165
- package/dist/table.js +1 -1
- package/dist/tabs-BtHmjlnM.js +348 -0
- package/dist/tabs.js +1 -1
- package/dist/types/accordion/accordion.d.ts.map +1 -1
- package/dist/types/calendar/calendar.d.ts +1 -1
- package/dist/types/calendar/calendar.d.ts.map +1 -1
- package/dist/types/calendar/calendar.types.d.ts +9 -0
- package/dist/types/calendar/calendar.types.d.ts.map +1 -1
- package/dist/types/calendar/index.d.ts +1 -1
- package/dist/types/calendar/index.d.ts.map +1 -1
- package/dist/types/collapsible/collapsible-parts.d.ts.map +1 -1
- package/dist/types/date-field/date-field.d.ts +1 -1
- package/dist/types/date-field/date-field.d.ts.map +1 -1
- package/dist/types/date-field/date-field.types.d.ts +7 -0
- package/dist/types/date-field/date-field.types.d.ts.map +1 -1
- package/dist/types/date-picker/date-picker.d.ts +5 -1
- package/dist/types/date-picker/date-picker.d.ts.map +1 -1
- package/dist/types/date-picker/date-picker.types.d.ts +20 -2
- package/dist/types/date-picker/date-picker.types.d.ts.map +1 -1
- package/dist/types/date-picker/index.d.ts +1 -1
- package/dist/types/date-picker/index.d.ts.map +1 -1
- package/dist/types/page/page.d.ts.map +1 -1
- package/dist/types/select/select-items.d.ts.map +1 -1
- package/dist/types/select/select-parts.d.ts.map +1 -1
- package/dist/types/select/select.d.ts.map +1 -1
- package/dist/types/table/index.d.ts +1 -1
- package/dist/types/table/index.d.ts.map +1 -1
- package/dist/types/table/table-defaults.d.ts.map +1 -1
- package/dist/types/table/table.d.ts +1 -1
- package/dist/types/table/table.d.ts.map +1 -1
- package/dist/types/table/table.types.d.ts +15 -0
- package/dist/types/table/table.types.d.ts.map +1 -1
- package/dist/types/tabs/tabs-parts.d.ts.map +1 -1
- package/dist/types/tabs/tabs.d.ts +1 -1
- package/dist/types/tabs/tabs.d.ts.map +1 -1
- package/dist/types/tabs/tabs.types.d.ts +18 -0
- package/dist/types/tabs/tabs.types.d.ts.map +1 -1
- package/package.json +6 -6
- package/dist/calendar-B3mio8iQ.js +0 -387
- package/dist/date-field-CYcN6diW.js +0 -279
- package/dist/date-picker-4X-_2ltN.js +0 -264
- package/dist/tabs-DQ36APY-.js +0 -343
|
@@ -2,10 +2,10 @@ import { r as e } from "./i18n-DpW8lqJ1.js";
|
|
|
2
2
|
import { n as t } from "./badge-C6rbwVpu.js";
|
|
3
3
|
import { t as n } from "./skeleton-2LSpg84Z.js";
|
|
4
4
|
import { n as r } from "./container-CjxY6rYv.js";
|
|
5
|
-
import { a as i } from "./page-
|
|
6
|
-
import { w as a } from "./page-header-
|
|
5
|
+
import { a as i } from "./page-IiYXk1sz.js";
|
|
6
|
+
import { w as a } from "./page-header-Bn4nIGfF.js";
|
|
7
7
|
import { a as o, l as s, n as c, o as l, s as u, t as d } from "./section-Be7dX9MC.js";
|
|
8
|
-
import { a as f, n as p, o as m, r as h, t as g } from "./tabs-
|
|
8
|
+
import { a as f, n as p, o as m, r as h, t as g } from "./tabs-BtHmjlnM.js";
|
|
9
9
|
import { createControllable as _ } from "@slotted/core/state";
|
|
10
10
|
import { createContext as v, useCallback as y, useContext as b, useEffect as x, useImperativeHandle as S, useMemo as C, useRef as w, useState as T } from "react";
|
|
11
11
|
import { Fragment as E, jsx as D, jsxs as O } from "react/jsx-runtime";
|
package/dist/detail-panel.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./detail-panel-
|
|
1
|
+
import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./detail-panel-CW53lUjp.js";
|
|
2
2
|
export { t as DetailPanel, o as DetailPanelBody, r as DetailPanelDefaultsProvider, n as DetailPanelSection, i as DetailPanelTabs, e as useDetailPanel, a as useDetailPanelDefaults };
|
package/dist/docs/calendar.json
CHANGED
|
@@ -258,6 +258,13 @@
|
|
|
258
258
|
"appliesTo": "Calendar",
|
|
259
259
|
"description": "The view it opens on."
|
|
260
260
|
},
|
|
261
|
+
{
|
|
262
|
+
"name": "granularity",
|
|
263
|
+
"type": "'day' | 'month'",
|
|
264
|
+
"defaultValue": "day",
|
|
265
|
+
"appliesTo": "Calendar",
|
|
266
|
+
"description": "What a choice is. month opens on the months of a year and never shows the day grid: a month cell is the value, written as the first day of that month, the arrow keys move one month or one row of four, Home and End reach January and December, Page Up and Page Down move a year, and Enter or Space chooses. A month the bounds leave no day of carries aria-disabled."
|
|
267
|
+
},
|
|
261
268
|
{
|
|
262
269
|
"name": "min",
|
|
263
270
|
"type": "PlainDate",
|
package/dist/docs/calendar.md
CHANGED
|
@@ -51,6 +51,7 @@ Excerpt — not a complete module
|
|
|
51
51
|
| `months` | `number` | 1 | Calendar | How many months are drawn side by side. They wrap when they do not fit; nothing is withdrawn. |
|
|
52
52
|
| `view` | `'day' \| 'month' \| 'year'` | day | Calendar | Which grid is showing. Present means the consumer owns it; defaultView sets the starting one. |
|
|
53
53
|
| `defaultView` | `'day' \| 'month' \| 'year'` | day | Calendar | The view it opens on. |
|
|
54
|
+
| `granularity` | `'day' \| 'month'` | day | Calendar | What a choice is. month opens on the months of a year and never shows the day grid: a month cell is the value, written as the first day of that month, the arrow keys move one month or one row of four, Home and End reach January and December, Page Up and Page Down move a year, and Enter or Space chooses. A month the bounds leave no day of carries aria-disabled. |
|
|
54
55
|
| `min` | `PlainDate` | — | Calendar | The earliest date the reader may reach. An arrow that would leave the range stops at the edge. |
|
|
55
56
|
| `max` | `PlainDate` | — | Calendar | The latest date the reader may reach. |
|
|
56
57
|
| `isDateUnavailable` | `(date: PlainDate) => boolean` | — | Calendar | Refuses particular dates. A refused date stays focusable and cannot be chosen. |
|
|
@@ -416,7 +416,7 @@
|
|
|
416
416
|
{
|
|
417
417
|
"id": "mount",
|
|
418
418
|
"title": "When the content exists",
|
|
419
|
-
"note": "eager builds it up front so the panel can transition closed, lazy builds it on the first open, active drops it each time, and until-found lets the browser’s own page search open the panel.",
|
|
419
|
+
"note": "eager builds it up front so the panel can transition closed, lazy builds it on the first open, active drops it each time, and until-found lets the browser’s own page search open the panel. A closed item under active commits once and reads no layout and no computed style; it creates no observer and no portal. Fifty closed items inside an Accordion, measured in Chrome: 7 ms of script and 23 ms to layout with a production build of React, 46 ms of script and 83 ms to layout with its development build.",
|
|
420
420
|
"language": "tsx",
|
|
421
421
|
"source": "<Collapsible mount=\"until-found\">\n <CollapsibleHeader>\n <CollapsibleTrigger>Histórico de entregas</CollapsibleTrigger>\n </CollapsibleHeader>\n <CollapsiblePanel>Entregue em 2 de setembro por Ana Ribeiro.</CollapsiblePanel>\n</Collapsible>;\n",
|
|
422
422
|
"verdict": "excerpt"
|
package/dist/docs/collapsible.md
CHANGED
|
@@ -187,7 +187,7 @@ Excerpt — not a complete module
|
|
|
187
187
|
|
|
188
188
|
### When the content exists
|
|
189
189
|
|
|
190
|
-
eager builds it up front so the panel can transition closed, lazy builds it on the first open, active drops it each time, and until-found lets the browser’s own page search open the panel.
|
|
190
|
+
eager builds it up front so the panel can transition closed, lazy builds it on the first open, active drops it each time, and until-found lets the browser’s own page search open the panel. A closed item under active commits once and reads no layout and no computed style; it creates no observer and no portal. Fifty closed items inside an Accordion, measured in Chrome: 7 ms of script and 23 ms to layout with a production build of React, 46 ms of script and 83 ms to layout with its development build.
|
|
191
191
|
|
|
192
192
|
Excerpt — not a complete module
|
|
193
193
|
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
"type": "PlainDate | null",
|
|
126
126
|
"defaultValue": "—",
|
|
127
127
|
"appliesTo": "DateField",
|
|
128
|
-
"description": "The date the control shows. Present means the consumer owns it: the control asks and waits rather than moving it."
|
|
128
|
+
"description": "The date the control shows. Present means the consumer owns it: the control asks and waits rather than moving it. PlainDate is exported by @slotted/core/date. parseISODate(text) returns a PlainDate or null, and toISODate(date) returns 'YYYY-MM-DD': value={parseISODate(iso)} onValueChange={(v) => setIso(v === null ? '' : toISODate(v))}."
|
|
129
129
|
},
|
|
130
130
|
{
|
|
131
131
|
"name": "defaultValue",
|
|
@@ -134,6 +134,13 @@
|
|
|
134
134
|
"appliesTo": "DateField",
|
|
135
135
|
"description": "The date the control starts from when nobody else writes one. Read once; a later change to it is not new state."
|
|
136
136
|
},
|
|
137
|
+
{
|
|
138
|
+
"name": "granularity",
|
|
139
|
+
"type": "'day' | 'month'",
|
|
140
|
+
"defaultValue": "day",
|
|
141
|
+
"appliesTo": "DateField",
|
|
142
|
+
"description": "What the control holds. month shows the month and the year segments in the locale’s order, takes the first day of the month as its value, and submits YYYY-MM through name."
|
|
143
|
+
},
|
|
137
144
|
{
|
|
138
145
|
"name": "min",
|
|
139
146
|
"type": "PlainDate",
|
package/dist/docs/date-field.md
CHANGED
|
@@ -38,8 +38,9 @@ Excerpt — not a complete module
|
|
|
38
38
|
|
|
39
39
|
| Name | Type | Default | Applies to | Description |
|
|
40
40
|
| --- | --- | --- | --- | --- |
|
|
41
|
-
| `value` | `PlainDate \| null` | — | DateField | The date the control shows. Present means the consumer owns it: the control asks and waits rather than moving it. |
|
|
41
|
+
| `value` | `PlainDate \| null` | — | DateField | The date the control shows. Present means the consumer owns it: the control asks and waits rather than moving it. PlainDate is exported by @slotted/core/date. parseISODate(text) returns a PlainDate or null, and toISODate(date) returns 'YYYY-MM-DD': value={parseISODate(iso)} onValueChange={(v) => setIso(v === null ? '' : toISODate(v))}. |
|
|
42
42
|
| `defaultValue` | `PlainDate \| null` | — | DateField | The date the control starts from when nobody else writes one. Read once; a later change to it is not new state. |
|
|
43
|
+
| `granularity` | `'day' \| 'month'` | day | DateField | What the control holds. month shows the month and the year segments in the locale’s order, takes the first day of the month as its value, and submits YYYY-MM through name. |
|
|
43
44
|
| `min` | `PlainDate` | — | DateField | The earliest date the control accepts. Reported through each segment’s aria-valuemin, and a value below it makes the control invalid. |
|
|
44
45
|
| `max` | `PlainDate` | — | DateField | The latest date the control accepts, on the same terms as min. |
|
|
45
46
|
| `isDateUnavailable` | `(date: PlainDate) => boolean` | — | DateField | Refuses particular dates — a weekend, a holiday, a day already booked. A refused date makes the control invalid. |
|
|
@@ -740,6 +740,35 @@ export default function DatePickerInvoiceDue() {
|
|
|
740
740
|
}
|
|
741
741
|
```
|
|
742
742
|
|
|
743
|
+
### iso-date.tsx
|
|
744
|
+
|
|
745
|
+
Example
|
|
746
|
+
|
|
747
|
+
```tsx
|
|
748
|
+
import { useState } from 'react';
|
|
749
|
+
import { DatePicker } from '@slotted/react/date-picker';
|
|
750
|
+
import { Field, FieldDescription, FieldLabel } from '@slotted/react/field';
|
|
751
|
+
import { isPlainDate, parseISODate, toISODate } from '@slotted/core/date';
|
|
752
|
+
|
|
753
|
+
export default function DatePickerIsoDate() {
|
|
754
|
+
/* The API carries the date as text; the picker holds a PlainDate. */
|
|
755
|
+
const [iso, setIso] = useState('2026-10-19');
|
|
756
|
+
|
|
757
|
+
return (
|
|
758
|
+
<Field>
|
|
759
|
+
<FieldLabel>Statement date</FieldLabel>
|
|
760
|
+
<DatePicker
|
|
761
|
+
onValueChange={(value) => setIso(isPlainDate(value) ? toISODate(value) : '')}
|
|
762
|
+
value={parseISODate(iso)}
|
|
763
|
+
/>
|
|
764
|
+
<FieldDescription>
|
|
765
|
+
{iso === '' ? 'No date sent.' : `The API receives ${iso}.`}
|
|
766
|
+
</FieldDescription>
|
|
767
|
+
</Field>
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
```
|
|
771
|
+
|
|
743
772
|
### locale.tsx
|
|
744
773
|
|
|
745
774
|
Example
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
"type": "PlainDate | DateRange | PlainDate[] | null",
|
|
136
136
|
"defaultValue": "—",
|
|
137
137
|
"appliesTo": "DatePicker",
|
|
138
|
-
"description": "The selected value, whose shape follows selectionMode. Setting it makes the value controlled."
|
|
138
|
+
"description": "The selected value, whose shape follows selectionMode. Setting it makes the value controlled. PlainDate is exported by @slotted/core/date. parseISODate(text) returns a PlainDate or null, toISODate(date) returns 'YYYY-MM-DD', and isPlainDate(value) narrows the CalendarValue onValueChange reports: value={parseISODate(iso)} onValueChange={(v) => setIso(isPlainDate(v) ? toISODate(v) : '')}."
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
141
|
"name": "defaultValue",
|
|
@@ -179,6 +179,13 @@
|
|
|
179
179
|
"appliesTo": "DatePicker",
|
|
180
180
|
"description": "Returns true for a date the reader cannot choose. The calendar disables it, and a typed unavailable date marks the date picker invalid."
|
|
181
181
|
},
|
|
182
|
+
{
|
|
183
|
+
"name": "granularity",
|
|
184
|
+
"type": "'day' | 'month'",
|
|
185
|
+
"defaultValue": "day",
|
|
186
|
+
"appliesTo": "DatePicker",
|
|
187
|
+
"description": "What a choice is. month opens the calendar on the months of a year and chooses a month cell; the field shows the month and the year segments; value, defaultValue, min and max are PlainYearMonth from @slotted/core/date ({ year, month }), onValueChange reports one, and name submits YYYY-MM. parseISOYearMonth and toISOYearMonth convert to and from that text. selectionMode, months, isDateUnavailable and the week props do not apply."
|
|
188
|
+
},
|
|
182
189
|
{
|
|
183
190
|
"name": "selectionMode",
|
|
184
191
|
"type": "'single' | 'range' | 'multiple'",
|
|
@@ -627,6 +634,14 @@
|
|
|
627
634
|
"source": "import { useState } from 'react';\nimport { DatePicker } from '@slotted/react/date-picker';\nimport { Field, FieldDescription, FieldLabel } from '@slotted/react/field';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@slotted/react/select';\nimport { Stack } from '@slotted/react/stack';\nimport {\n addDays,\n createDateFormat,\n isPlainDate,\n plainDate,\n type PlainDate,\n} from '@slotted/core/date';\n\nconst TERMS = [\n { value: 'receipt', label: 'Due on receipt', days: 0 },\n { value: 'net-15', label: 'Net 15', days: 15 },\n { value: 'net-30', label: 'Net 30', days: 30 },\n { value: 'net-60', label: 'Net 60', days: 60 },\n];\nconst words = createDateFormat({ locale: 'en-US' });\n\nexport default function DatePickerInvoiceDue() {\n const [issued, setIssued] = useState<PlainDate | null>(plainDate(2026, 9, 30));\n const [terms, setTerms] = useState('net-30');\n const days = TERMS.find((option) => option.value === terms)?.days ?? 0;\n const due = issued === null ? null : addDays(issued, days);\n\n return (\n <Stack gap={5}>\n <Field required>\n <FieldLabel>Invoice date</FieldLabel>\n <DatePicker\n onValueChange={(value) => setIssued(isPlainDate(value) ? value : null)}\n value={issued}\n />\n </Field>\n <Field>\n <FieldLabel>Payment terms</FieldLabel>\n <Select\n items={TERMS}\n onValueChange={(next) => {\n if (typeof next === 'string') setTerms(next);\n }}\n value={terms}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TERMS.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </Field>\n <Field readOnly>\n <FieldLabel>Due date</FieldLabel>\n <DatePicker value={due} />\n <FieldDescription>\n {due === null ? 'Set the invoice date first.' : `Payment is due ${words.describe(due)}.`}\n </FieldDescription>\n </Field>\n </Stack>\n );\n}\n",
|
|
628
635
|
"verdict": "example"
|
|
629
636
|
},
|
|
637
|
+
{
|
|
638
|
+
"id": "iso-date",
|
|
639
|
+
"title": "iso-date.tsx",
|
|
640
|
+
"note": null,
|
|
641
|
+
"language": "tsx",
|
|
642
|
+
"source": "import { useState } from 'react';\nimport { DatePicker } from '@slotted/react/date-picker';\nimport { Field, FieldDescription, FieldLabel } from '@slotted/react/field';\nimport { isPlainDate, parseISODate, toISODate } from '@slotted/core/date';\n\nexport default function DatePickerIsoDate() {\n /* The API carries the date as text; the picker holds a PlainDate. */\n const [iso, setIso] = useState('2026-10-19');\n\n return (\n <Field>\n <FieldLabel>Statement date</FieldLabel>\n <DatePicker\n onValueChange={(value) => setIso(isPlainDate(value) ? toISODate(value) : '')}\n value={parseISODate(iso)}\n />\n <FieldDescription>\n {iso === '' ? 'No date sent.' : `The API receives ${iso}.`}\n </FieldDescription>\n </Field>\n );\n}\n",
|
|
643
|
+
"verdict": "example"
|
|
644
|
+
},
|
|
630
645
|
{
|
|
631
646
|
"id": "locale",
|
|
632
647
|
"title": "locale.tsx",
|
package/dist/docs/date-picker.md
CHANGED
|
@@ -44,13 +44,14 @@ export default function DatePickerBasic() {
|
|
|
44
44
|
|
|
45
45
|
| Name | Type | Default | Applies to | Description |
|
|
46
46
|
| --- | --- | --- | --- | --- |
|
|
47
|
-
| `value` | `PlainDate \| DateRange \| PlainDate[] \| null` | — | DatePicker | The selected value, whose shape follows selectionMode. Setting it makes the value controlled. |
|
|
47
|
+
| `value` | `PlainDate \| DateRange \| PlainDate[] \| null` | — | DatePicker | The selected value, whose shape follows selectionMode. Setting it makes the value controlled. PlainDate is exported by @slotted/core/date. parseISODate(text) returns a PlainDate or null, toISODate(date) returns 'YYYY-MM-DD', and isPlainDate(value) narrows the CalendarValue onValueChange reports: value={parseISODate(iso)} onValueChange={(v) => setIso(isPlainDate(v) ? toISODate(v) : '')}. |
|
|
48
48
|
| `defaultValue` | `PlainDate \| DateRange \| PlainDate[] \| null` | — | DatePicker | The starting value of an uncontrolled date picker. Read once, on the first render. |
|
|
49
49
|
| `open` | `boolean` | — | DatePicker | Whether the calendar is showing. Setting it makes the open state controlled. |
|
|
50
50
|
| `defaultOpen` | `boolean` | false | DatePicker | Whether the calendar shows on the first render. Focus does not move into it. |
|
|
51
51
|
| `min` | `PlainDate` | — | DatePicker | The earliest date the field and the calendar accept. Earlier days are disabled in the calendar, and an earlier typed date marks the date picker invalid. |
|
|
52
52
|
| `max` | `PlainDate` | — | DatePicker | The latest date the field and the calendar accept. Later days are disabled in the calendar, and a later typed date marks the date picker invalid. |
|
|
53
53
|
| `isDateUnavailable` | `(date: PlainDate) => boolean` | — | DatePicker | Returns true for a date the reader cannot choose. The calendar disables it, and a typed unavailable date marks the date picker invalid. |
|
|
54
|
+
| `granularity` | `'day' \| 'month'` | day | DatePicker | What a choice is. month opens the calendar on the months of a year and chooses a month cell; the field shows the month and the year segments; value, defaultValue, min and max are PlainYearMonth from @slotted/core/date ({ year, month }), onValueChange reports one, and name submits YYYY-MM. parseISOYearMonth and toISOYearMonth convert to and from that text. selectionMode, months, isDateUnavailable and the week props do not apply. |
|
|
54
55
|
| `selectionMode` | `'single' \| 'range' \| 'multiple'` | single | DatePicker | How many dates the calendar selects, and so the shape of the value. The field shows a single date only; for a start and an end, use DateRangePicker. |
|
|
55
56
|
| `months` | `number` | 1 | DatePicker | How many months the calendar draws side by side. |
|
|
56
57
|
| `defaultView` | `'day' \| 'month' \| 'year'` | day | DatePicker | The grid the calendar opens on. |
|
|
@@ -127,3 +127,13 @@ Why: The line beside Reply and Internal note was longer in one mode and wrapped
|
|
|
127
127
|
Do: Give the varying text `flex: 1 1 0`, `min-inline-size: 0` and a one-line cut, write the two texts to similar lengths, and keep a control's label set fixed across modes.
|
|
128
128
|
Don't: Let a mode add or remove a line, a hint or a control that changes the region's height, or let a row wrap differently in one mode than in the other.
|
|
129
129
|
Check: At 1280, 570 and 390 pixels, switch the mode and read the bounding box of each box in the region: every top and height is the same in both modes.
|
|
130
|
+
|
|
131
|
+
### CP-09 · A control that switches a region does not render the region in its own frame
|
|
132
|
+
|
|
133
|
+
Level: MUST
|
|
134
|
+
Applies to: tabs, a segmented control, a route link or a filter whose change mounts a region holding tables, grids, charts or forms
|
|
135
|
+
Rule: The control's own state — the selected tab, the pressed segment — updates in the interaction's frame; the region renders from a deferred value (in React, useDeferredValue or startTransition) and states aria-busy while the shown value lags the selected one.
|
|
136
|
+
Why: Mounting a region of families in the click's task blocks the next paint, and Interaction to Next Paint above 200 ms is "needs improvement" and above 500 ms "poor": a table of a hundred rows of twenty cells measured 160 ms in one task in a development build, and a 4× CPU throttle takes its 93 ms in a production build past the first threshold.
|
|
137
|
+
Do: Keep the selection state urgent and hand the region the deferred value; mount only the selected panel, with mount active.
|
|
138
|
+
Don't: Set the selection and the region from one state update inside the click handler, or mount every panel to make switching look instant.
|
|
139
|
+
Check: Switch the control with the CPU throttled 4× in Chrome: the selection marker moves in the next frame, and the Performance panel shows no long task between the click and that paint.
|
|
@@ -29,6 +29,7 @@ Every active rule, one line each. Load this first; load a topic file when the ta
|
|
|
29
29
|
| CP-06 | SHOULD | A screen states a state once. Where the family has a state for it, the screen sets that state and adds nothing louder beside it. | `composition.md` |
|
|
30
30
|
| CP-07 | SHOULD | A list page is `bleed` with `fill`; a record, a dashboard and an overview keep the default `wide`; a create or edit form is `content`; a page of preferences read as prose is `measure`. | `composition.md` |
|
|
31
31
|
| CP-08 | MUST | Switching the mode changes the words and the values in the region, never the size, the line count or the position of any box in it or around it; text whose length differs between modes stands on one line, cut with an ellipsis and read whole from its title. | `composition.md` |
|
|
32
|
+
| CP-09 | MUST | The control's own state — the selected tab, the pressed segment — updates in the interaction's frame; the region renders from a deferred value (in React, useDeferredValue or startTransition) and states aria-busy while the shown value lags the selected one. | `composition.md` |
|
|
32
33
|
| CV-01 | MUST | From 600 pixels the conversation fills its region and scrolls on its own with the composer under it, and the record's context scrolls on its own beside it or behind a tab of the header; below 600 pixels the page scrolls, the composer is stuck to the bottom of the screen, and the record opens on its last message. | `conversations.md` |
|
|
33
34
|
| CV-02 | SHOULD | A running clock says the business time left and the hour it falls due in the organization's zone, a passed one by how much and when it was due, a paused one that it is stopped and why; a queue's row says the span alone, and no clock is ever said in raw minutes. | `conversations.md` |
|
|
34
35
|
| CV-03 | SHOULD | Each queue is a view of the list's `filter-bar`, a tree of the bar's own fields, labelled with the count of the rows it opens on; choosing it writes its pills, and editing a pill leaves a view the bar marks as changed. | `conversations.md` |
|
|
@@ -72,6 +73,7 @@ Every active rule, one line each. Load this first; load a topic file when the ta
|
|
|
72
73
|
| LP-11 | SHOULD | Where the primary input is a touch screen, the list tools leave out the row density: the theme raises every density's rows to the touch target, and the tools keep the sort, the views and the columns on one line. | `list-pages.md` |
|
|
73
74
|
| LP-12 | MUST | From 600 pixels of the page's width the listing takes the height the bar and the messages leave and scrolls its own rows while the page does not scroll; below 600 the page's `fill` does not apply, the listing is as tall as its rows and the page scrolls. | `list-pages.md` |
|
|
74
75
|
| LP-13 | SHOULD | The mark takes the `sm` `size`; the default `md` belongs to a record's header and to a region with room around it. | `list-pages.md` |
|
|
76
|
+
| LP-14 | MUST | A list that can hold more than a hundred rows, or more than twenty columns, is a `data-grid`, which windows rows and middle columns under its default `virtualize` of `auto`; `table` is for sets the page bounds, such as a statement's lines or a record's related rows. | `list-pages.md` |
|
|
75
77
|
| OV-01 | SHOULD | The figure leads to the list page of the records it counts, and that list opens with the figure's condition applied as the bar's own pills, which the reader removes like any other. | `overviews.md` |
|
|
76
78
|
| OV-02 | SHOULD | Below 600 pixels the figures are one `list` of rows that are destinations — label, comparison, number — followed by the records to act on, the work in flight, the charts, and the history last. | `overviews.md` |
|
|
77
79
|
| OV-03 | SHOULD | Where the reader's scope holds one category, the chart is not drawn and one sentence states the numbers it would have compared. | `overviews.md` |
|
|
@@ -27,7 +27,8 @@ triggers:
|
|
|
27
27
|
badge,
|
|
28
28
|
tag,
|
|
29
29
|
]
|
|
30
|
-
families:
|
|
30
|
+
families:
|
|
31
|
+
[data-grid, table, filter-bar, action-bar, pagination, page, page-header, link, badge, tag]
|
|
31
32
|
---
|
|
32
33
|
|
|
33
34
|
# List pages
|
|
@@ -163,3 +164,13 @@ Why: A row sets its text at the small type step, 13 pixels in a 34-pixel row; an
|
|
|
163
164
|
Do: Give every mark a cell holds — a state, a flag, a warning — the `sm` `size`: 12-pixel words in a 19-pixel box.
|
|
164
165
|
Don't: Leave a cell's mark at the family's default, or size it up to make a state stand out; a tone says that.
|
|
165
166
|
Check: On every list, every `badge` and `tag` inside a cell of a `data-grid` or a `table` carries the `sm` `size`.
|
|
167
|
+
|
|
168
|
+
### LP-14 · A list that can pass a hundred rows is a data-grid
|
|
169
|
+
|
|
170
|
+
Level: MUST
|
|
171
|
+
Applies to: a list of records whose count the reader does not bound — transactions, postings, imports
|
|
172
|
+
Rule: A list that can hold more than a hundred rows, or more than twenty columns, is a `data-grid`, which windows rows and middle columns under its default `virtualize` of `auto`; `table` is for sets the page bounds, such as a statement's lines or a record's related rows.
|
|
173
|
+
Why: `table` mounts every cell: a hundred rows of twenty columns measured 93 ms in one task with a production build of React in Chrome and 160 ms with a development build, and the count of rows the store returns sets that cost.
|
|
174
|
+
Do: Give the store's list a `data-grid` with its query, and keep `table` for the bounded sets inside a record or a document.
|
|
175
|
+
Don't: Render an unbounded store into a `table`, or page a `table` to keep it under a hundred rows where the grid's window would have kept the whole set reachable.
|
|
176
|
+
Check: Every list over an unbounded store is a `data-grid`; every `table` on a page renders a set the page bounds.
|
package/dist/docs/page.json
CHANGED
|
@@ -219,6 +219,7 @@
|
|
|
219
219
|
"accessibility": [
|
|
220
220
|
"The practice is the WAI-ARIA APG’s Landmark Regions (w3.org/WAI/ARIA/apg/practices/landmark-regions/): each page should have one main landmark, and the page is it. landmark=\"none\" is for the page that is not the document’s — inside a drawer, a dialog or the detail pane of a master–detail layout — and it renders a div so the document keeps one main.",
|
|
221
221
|
"The footer is a footer element inside main, which is not a contentinfo landmark, so it is named: the catalog’s footer message by default, an aria-label the consumer writes otherwise. A reader walking the page’s controls finds “Page actions” before the buttons in it.",
|
|
222
|
+
"Content outside PageBody receives no inset: the inset lives on the body, so content written straight into Page is drawn against the viewport edges. In development, Page warns once when it holds content and no PageBody.",
|
|
222
223
|
"The outline is typography’s. The body is one HeadingLevel deeper than the header, so a Section written directly in it takes h2 under the header’s h1, and a section inside that takes h3 — without either family reading the other, and without a skip the HTML Standard forbids.",
|
|
223
224
|
"The body carries aria-busy while loading, which is what tells a screen reader the region is not ready. The page draws no placeholder: the header stands skeleton text of the title’s own width, and each family inside stands its own.",
|
|
224
225
|
"Scrolling is the platform’s. The page never writes a scroll position, and under scroll=\"self\" the scroll part is an ordinary scrolling box a keyboard reaches with the arrow keys once something inside it has focus."
|
package/dist/docs/page.md
CHANGED
|
@@ -64,6 +64,7 @@ Excerpt — not a complete module
|
|
|
64
64
|
|
|
65
65
|
- The practice is the WAI-ARIA APG’s Landmark Regions (w3.org/WAI/ARIA/apg/practices/landmark-regions/): each page should have one main landmark, and the page is it. landmark="none" is for the page that is not the document’s — inside a drawer, a dialog or the detail pane of a master–detail layout — and it renders a div so the document keeps one main.
|
|
66
66
|
- The footer is a footer element inside main, which is not a contentinfo landmark, so it is named: the catalog’s footer message by default, an aria-label the consumer writes otherwise. A reader walking the page’s controls finds “Page actions” before the buttons in it.
|
|
67
|
+
- Content outside PageBody receives no inset: the inset lives on the body, so content written straight into Page is drawn against the viewport edges. In development, Page warns once when it holds content and no PageBody.
|
|
67
68
|
- The outline is typography’s. The body is one HeadingLevel deeper than the header, so a Section written directly in it takes h2 under the header’s h1, and a section inside that takes h3 — without either family reading the other, and without a skip the HTML Standard forbids.
|
|
68
69
|
- The body carries aria-busy while loading, which is what tells a screen reader the region is not ready. The page draws no placeholder: the header stands skeleton text of the title’s own width, and each family inside stands its own.
|
|
69
70
|
- Scrolling is the platform’s. The page never writes a scroll position, and under scroll="self" the scroll part is an ordinary scrolling box a keyboard reaches with the arrow keys once something inside it has focus.
|
package/dist/docs/select.json
CHANGED
|
@@ -483,7 +483,7 @@
|
|
|
483
483
|
"type": "SelectItems",
|
|
484
484
|
"defaultValue": "—",
|
|
485
485
|
"appliesTo": "Select",
|
|
486
|
-
"description": "Values with their labels,
|
|
486
|
+
"description": "Values with their labels, read before any option renders. Without it, a held value takes its label from its SelectItem: while the list is closed and a held value has no label, the options render once outside the document and register theirs. Pass items when the options are not rendered until the list opens, such as options fetched on open."
|
|
487
487
|
},
|
|
488
488
|
{
|
|
489
489
|
"name": "name",
|
package/dist/docs/select.md
CHANGED
|
@@ -100,7 +100,7 @@ export default function SelectBasic() {
|
|
|
100
100
|
| `defaultOpen` | `boolean` | false | Select | Whether an uncontrolled select starts open. |
|
|
101
101
|
| `highlightedValue` | `string \| null` | — | Select | The highlighted option. Passing it makes the highlight controlled. The highlight is where the keyboard is, not what is chosen. |
|
|
102
102
|
| `defaultHighlightedValue` | `string \| null` | — | Select | The option an uncontrolled highlight starts on. |
|
|
103
|
-
| `items` | `SelectItems` | — | Select | Values with their labels,
|
|
103
|
+
| `items` | `SelectItems` | — | Select | Values with their labels, read before any option renders. Without it, a held value takes its label from its SelectItem: while the list is closed and a held value has no label, the options render once outside the document and register theirs. Pass items when the options are not rendered until the list opens, such as options fetched on open. |
|
|
104
104
|
| `name` | `string` | — | Select | The name the value is submitted under. It renders a hidden native select, which FormData reads and a form reset restores. |
|
|
105
105
|
| `form` | `string` | — | Select | The id of the form the control belongs to, when it is not the enclosing form. |
|
|
106
106
|
| `total` | `number` | — | Select | The size of the whole collection when only part of it is rendered. Options with position then carry aria-setsize and aria-posinset. |
|
|
@@ -59,6 +59,10 @@ element stands in that slot.
|
|
|
59
59
|
nothing louder beside it (CP-06).
|
|
60
60
|
- A control that switches what a region holds changes words and values, never
|
|
61
61
|
the size or the position of a box (CP-08).
|
|
62
|
+
- A control that switches a region — tabs, a route, a filter — updates its
|
|
63
|
+
own state at once and renders the region from a deferred value (in React,
|
|
64
|
+
useDeferredValue or startTransition) (CP-09). A list longer than a hundred
|
|
65
|
+
rows is a `data-grid`, which windows its rows (LP-14).
|
|
62
66
|
- Where no anatomy answers the problem, the screen writes an element of its
|
|
63
67
|
own instead of bending a family into a shape it does not have (CP-04). That
|
|
64
68
|
element is built with `node_modules/@slotted/react/dist/docs/skills/build-own-element/SKILL.md`.
|
|
@@ -74,3 +78,6 @@ Every region filled by a request and every control that starts one follow
|
|
|
74
78
|
2. Each `SHOULD` rule not followed is listed with its reason.
|
|
75
79
|
3. No CSS of the screen's own targets a family's parts; a family's appearance
|
|
76
80
|
changes through its axes.
|
|
81
|
+
4. In a browser with the CPU throttled 4×, each control that switches a region
|
|
82
|
+
paints its new state in the next frame, with no long task between the input
|
|
83
|
+
and that paint.
|
package/dist/docs/table.json
CHANGED
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
"ruled",
|
|
13
13
|
"framed"
|
|
14
14
|
],
|
|
15
|
+
"edges": [
|
|
16
|
+
"inset",
|
|
17
|
+
"flush"
|
|
18
|
+
],
|
|
15
19
|
"striped": [
|
|
16
20
|
true,
|
|
17
21
|
false
|
|
@@ -71,6 +75,7 @@
|
|
|
71
75
|
"nativeElement": "div",
|
|
72
76
|
"defaults": {
|
|
73
77
|
"variant": "ruled",
|
|
78
|
+
"edges": "inset",
|
|
74
79
|
"striped": false,
|
|
75
80
|
"stickyHeader": false,
|
|
76
81
|
"stickyTo": "scroll",
|
|
@@ -418,6 +423,13 @@
|
|
|
418
423
|
"appliesTo": "Table",
|
|
419
424
|
"description": "How much of a frame the set is given"
|
|
420
425
|
},
|
|
426
|
+
{
|
|
427
|
+
"name": "edges",
|
|
428
|
+
"type": "'inset' | 'flush'",
|
|
429
|
+
"defaultValue": "inset",
|
|
430
|
+
"appliesTo": "Table",
|
|
431
|
+
"description": "Whether the first and the last column keep the cell inset on their outer side. flush lines a plain or ruled table up with the heading around it, leaving the theme’s --slotted-table-edge-inset (0 unless set); a framed table ignores it. Sticky and selection columns keep their own offsets"
|
|
432
|
+
},
|
|
421
433
|
{
|
|
422
434
|
"name": "striped",
|
|
423
435
|
"type": "boolean",
|
|
@@ -799,6 +811,7 @@
|
|
|
799
811
|
"--slotted-table-color-muted",
|
|
800
812
|
"--slotted-table-column-actions-size",
|
|
801
813
|
"--slotted-table-control-radius",
|
|
814
|
+
"--slotted-table-edge-inset",
|
|
802
815
|
"--slotted-table-font-family",
|
|
803
816
|
"--slotted-table-font-size",
|
|
804
817
|
"--slotted-table-gap",
|
package/dist/docs/table.md
CHANGED
|
@@ -180,6 +180,7 @@ export default function TableBasic() {
|
|
|
180
180
|
| `expanded` | `readonly string[]` | — | Table | The rows whose detail is open. Present means you own it. |
|
|
181
181
|
| `defaultExpanded` | `readonly string[]` | [] | Table | The details an uncontrolled table starts with |
|
|
182
182
|
| `variant` | `'plain' \| 'ruled' \| 'framed'` | ruled | Table | How much of a frame the set is given |
|
|
183
|
+
| `edges` | `'inset' \| 'flush'` | inset | Table | Whether the first and the last column keep the cell inset on their outer side. flush lines a plain or ruled table up with the heading around it, leaving the theme’s --slotted-table-edge-inset (0 unless set); a framed table ignores it. Sticky and selection columns keep their own offsets |
|
|
183
184
|
| `striped` | `boolean` | false | Table | A tinted ground on every second record |
|
|
184
185
|
| `stickyHeader` | `boolean` | false | Table | Whether the header stays while the body scrolls |
|
|
185
186
|
| `stickyFooter` | `boolean` | false | Table | Whether the summary rows stay while the body scrolls. It pins the tfoot and not the footer bar, which never scrolls. |
|
|
@@ -238,6 +239,7 @@ export default function TableBasic() {
|
|
|
238
239
|
| Axis | Values | Default |
|
|
239
240
|
| --- | --- | --- |
|
|
240
241
|
| `variant` | `plain`, `ruled`, `framed` | `ruled` |
|
|
242
|
+
| `edges` | `inset`, `flush` | `inset` |
|
|
241
243
|
| `striped` | `true`, `false` | `false` |
|
|
242
244
|
| `stickyHeader` | `true`, `false` | `false` |
|
|
243
245
|
| `stickyFooter` | `true`, `false` | `false` |
|
|
@@ -265,7 +267,7 @@ export default function TableBasic() {
|
|
|
265
267
|
|
|
266
268
|
## Tokens
|
|
267
269
|
|
|
268
|
-
`--slotted-border-strong`, `--slotted-border-subtle`, `--slotted-border-width-thin`, `--slotted-control-font-family`, `--slotted-control-font-size-md`, `--slotted-control-gap-md`, `--slotted-control-height-md`, `--slotted-control-icon-size-md`, `--slotted-control-padding-inline-md`, `--slotted-control-transition-duration`, `--slotted-control-transition-easing`, `--slotted-disabled-foreground`, `--slotted-duration-short`, `--slotted-easing-standard`, `--slotted-focus-ring-color`, `--slotted-focus-ring-offset`, `--slotted-focus-ring-width`, `--slotted-font-size-xs`, `--slotted-font-weight-medium`, `--slotted-font-weight-regular`, `--slotted-font-weight-semibold`, `--slotted-ground`, `--slotted-line-height-md`, `--slotted-radius-md`, `--slotted-radius-sm`, `--slotted-shadow-xs`, `--slotted-space-2`, `--slotted-space-5`, `--slotted-space-9`, `--slotted-surface`, `--slotted-table-border-color`, `--slotted-table-border-color-strong`, `--slotted-table-border-width`, `--slotted-table-cell-padding-block`, `--slotted-table-cell-padding-inline`, `--slotted-table-color`, `--slotted-table-color-muted`, `--slotted-table-column-actions-size`, `--slotted-table-control-radius`, `--slotted-table-font-family`, `--slotted-table-font-size`, `--slotted-table-gap`, `--slotted-table-group-color`, `--slotted-table-group-sticky-offset`, `--slotted-table-group-surface`, `--slotted-table-header-surface`, `--slotted-table-header-surface-hover`, `--slotted-table-icon-size`, `--slotted-table-radius`, `--slotted-table-row-color-selected`, `--slotted-table-row-min-block-size`, `--slotted-table-row-surface-current`, `--slotted-table-row-surface-hover`, `--slotted-table-row-surface-selected`, `--slotted-table-row-surface-selected-hover`, `--slotted-table-row-surface-stripe`, `--slotted-table-selection-size`, `--slotted-table-shadow`, `--slotted-table-sticky-inset`, `--slotted-table-sticky-offset`, `--slotted-table-sticky-offset-end`, `--slotted-table-surface`, `--slotted-target-comfortable`, `--slotted-target-min`, `--slotted-text`, `--slotted-text-muted`, `--slotted-tone-accent-subtle-hover`, `--slotted-tone-accent-surface`, `--slotted-tone-accent-text`, `--slotted-tone-secondary-subtle-active`, `--slotted-tone-secondary-subtle-hover`, `--slotted-z-index-sticky`
|
|
270
|
+
`--slotted-border-strong`, `--slotted-border-subtle`, `--slotted-border-width-thin`, `--slotted-control-font-family`, `--slotted-control-font-size-md`, `--slotted-control-gap-md`, `--slotted-control-height-md`, `--slotted-control-icon-size-md`, `--slotted-control-padding-inline-md`, `--slotted-control-transition-duration`, `--slotted-control-transition-easing`, `--slotted-disabled-foreground`, `--slotted-duration-short`, `--slotted-easing-standard`, `--slotted-focus-ring-color`, `--slotted-focus-ring-offset`, `--slotted-focus-ring-width`, `--slotted-font-size-xs`, `--slotted-font-weight-medium`, `--slotted-font-weight-regular`, `--slotted-font-weight-semibold`, `--slotted-ground`, `--slotted-line-height-md`, `--slotted-radius-md`, `--slotted-radius-sm`, `--slotted-shadow-xs`, `--slotted-space-2`, `--slotted-space-5`, `--slotted-space-9`, `--slotted-surface`, `--slotted-table-border-color`, `--slotted-table-border-color-strong`, `--slotted-table-border-width`, `--slotted-table-cell-padding-block`, `--slotted-table-cell-padding-inline`, `--slotted-table-color`, `--slotted-table-color-muted`, `--slotted-table-column-actions-size`, `--slotted-table-control-radius`, `--slotted-table-edge-inset`, `--slotted-table-font-family`, `--slotted-table-font-size`, `--slotted-table-gap`, `--slotted-table-group-color`, `--slotted-table-group-sticky-offset`, `--slotted-table-group-surface`, `--slotted-table-header-surface`, `--slotted-table-header-surface-hover`, `--slotted-table-icon-size`, `--slotted-table-radius`, `--slotted-table-row-color-selected`, `--slotted-table-row-min-block-size`, `--slotted-table-row-surface-current`, `--slotted-table-row-surface-hover`, `--slotted-table-row-surface-selected`, `--slotted-table-row-surface-selected-hover`, `--slotted-table-row-surface-stripe`, `--slotted-table-selection-size`, `--slotted-table-shadow`, `--slotted-table-sticky-inset`, `--slotted-table-sticky-offset`, `--slotted-table-sticky-offset-end`, `--slotted-table-surface`, `--slotted-target-comfortable`, `--slotted-target-min`, `--slotted-text`, `--slotted-text-muted`, `--slotted-tone-accent-subtle-hover`, `--slotted-tone-accent-surface`, `--slotted-tone-accent-text`, `--slotted-tone-secondary-subtle-active`, `--slotted-tone-secondary-subtle-hover`, `--slotted-z-index-sticky`
|
|
269
271
|
|
|
270
272
|
## Examples
|
|
271
273
|
|
package/dist/docs/tabs.json
CHANGED
|
@@ -221,6 +221,13 @@
|
|
|
221
221
|
"appliesTo": "Tabs, TabsDefaultsProvider",
|
|
222
222
|
"description": "When a panel’s content exists: only while its tab is selected (active), from its first selection on (lazy), or from the start (eager). A panel that is not selected carries the hidden attribute."
|
|
223
223
|
},
|
|
224
|
+
{
|
|
225
|
+
"name": "deferPanels",
|
|
226
|
+
"type": "boolean",
|
|
227
|
+
"defaultValue": "true under mount=\"active\", false otherwise",
|
|
228
|
+
"appliesTo": "Tabs",
|
|
229
|
+
"description": "Whether the panels render from useDeferredValue(value). The selected tab paints in the click’s frame and its panel renders after it; until it is ready the panel on screen stays, with aria-busy and data-pending. A panel that suspends keeps the shown one when its Suspense boundary is outside Tabs; a boundary inside the new panel shows its own fallback."
|
|
230
|
+
},
|
|
224
231
|
{
|
|
225
232
|
"name": "loop",
|
|
226
233
|
"type": "boolean",
|
|
@@ -319,7 +326,7 @@
|
|
|
319
326
|
"type": "() => TabsContextValue",
|
|
320
327
|
"defaultValue": "—",
|
|
321
328
|
"appliesTo": "inside Tabs",
|
|
322
|
-
"description": "What a tab and a panel read: the value, the mount strategy, the ids, and select(value, reason, source) for a view the page changes on its own. It throws outside Tabs instead of rendering a control that looks right and does nothing."
|
|
329
|
+
"description": "What a tab and a panel read: the value, shownValue (the value the panels render, deferred under deferPanels), the mount strategy, the ids, and select(value, reason, source) for a view the page changes on its own. A region rendered outside the panels — a page header’s tab with controls= — renders from shownValue. It throws outside Tabs instead of rendering a control that looks right and does nothing."
|
|
323
330
|
},
|
|
324
331
|
{
|
|
325
332
|
"name": "TabsDefaultsProvider",
|
|
@@ -354,6 +361,7 @@
|
|
|
354
361
|
}
|
|
355
362
|
],
|
|
356
363
|
"accessibility": [
|
|
364
|
+
"Selecting a tab never waits for its panel: keep value urgent and render the region from useDeferredValue(value), which deferPanels does for the panels and useTabs().shownValue hands a region outside them. Wrapping the setter in startTransition delays the marker too.",
|
|
357
365
|
"Tabs implements the WAI-ARIA APG Tabs pattern (w3.org/WAI/ARIA/apg/patterns/tabs/) and its whole keyboard table: Tab enters the list on the selected tab and leaves to the panel, the arrow keys of the list’s direction move focus and wrap at both ends, Home and End reach the first and last enabled tab, Enter and Space select under manual activation, and Delete closes a dismissible tab. A horizontal list does not listen for Up and Down, so those keys keep scrolling the page while focus is in the list.",
|
|
358
366
|
"After a dismissal, focus follows the pattern: the next tab, the previous one when the closed tab was last, or the list itself when no tab is left, which is why the list carries tabindex=\"-1\". The selection follows the same rule, with the reason remove.",
|
|
359
367
|
"The close button is outside the arrow-key sequence and inside the accessibility tree. A screen reader reaches and presses it; from the keyboard, Delete closes the focused tab, and the tab announces the key with aria-keyshortcuts. In the arrow-key sequence, close buttons would double the presses it takes to cross the list.",
|
package/dist/docs/tabs.md
CHANGED
|
@@ -127,6 +127,7 @@ export default function TabsBasic() {
|
|
|
127
127
|
| `track` | `'line' \| 'none'` | line | Tabs, TabsDefaultsProvider | Whether the list draws the line its tabs stand on. none is for a list placed on a line the page already draws, such as a card header’s edge or a table’s rule, where two hairlines a pixel apart read as one smudge. The marker then sits on the item’s own edge, on the line that is there. |
|
|
128
128
|
| `fit` | `'auto' \| 'equal'` | auto | Tabs, TabsDefaultsProvider | Whether each tab is as wide as its label or takes an equal share of the line. equal cuts a label longer than its share with an ellipsis; auto never cuts a label and scrolls the list instead. |
|
|
129
129
|
| `mount` | `'active' \| 'lazy' \| 'eager'` | active | Tabs, TabsDefaultsProvider | When a panel’s content exists: only while its tab is selected (active), from its first selection on (lazy), or from the start (eager). A panel that is not selected carries the hidden attribute. |
|
|
130
|
+
| `deferPanels` | `boolean` | true under mount="active", false otherwise | Tabs | Whether the panels render from useDeferredValue(value). The selected tab paints in the click’s frame and its panel renders after it; until it is ready the panel on screen stays, with aria-busy and data-pending. A panel that suspends keeps the shown one when its Suspense boundary is outside Tabs; a boundary inside the new panel shows its own fallback. |
|
|
130
131
|
| `loop` | `boolean` | true | Tabs, TabsDefaultsProvider | Whether the arrow keys wrap past the ends of the list. |
|
|
131
132
|
| `disabled` | `boolean` | false | Tabs | Disables every tab with the native attribute, which also makes the arrow keys skip them, and dims the track. |
|
|
132
133
|
| `value, on Tab` | `string` | — | Tab | What this tab selects, and what the value of Tabs holds. It reaches the DOM as data-value, which the keyboard reads. |
|
|
@@ -140,7 +141,7 @@ export default function TabsBasic() {
|
|
|
140
141
|
| `value, on TabPanel` | `string` | — | TabPanel | The tab this panel belongs to. Tabs wires the pair with ids generated from the value. |
|
|
141
142
|
| `render` | `(props) => ReactNode` | — | Tabs, TabList, Tab, TabPanel, TabActions | Replaces the root element of any of the five and passes it every attribute, so a list can be a nav and Tabs a section. The tab control itself cannot be replaced: it holds the role, the value and the keyboard, and href covers the substitution that matters. |
|
|
142
143
|
| `ref` | `Ref<HTMLElement>` | — | Tab, TabPanel, Tabs | On Tab, reaches the tab’s own control, so focus() and click() are the element’s own methods and no imperative handle stands in for them. |
|
|
143
|
-
| `useTabs()` | `() => TabsContextValue` | — | inside Tabs | What a tab and a panel read: the value, the mount strategy, the ids, and select(value, reason, source) for a view the page changes on its own. It throws outside Tabs instead of rendering a control that looks right and does nothing. |
|
|
144
|
+
| `useTabs()` | `() => TabsContextValue` | — | inside Tabs | What a tab and a panel read: the value, shownValue (the value the panels render, deferred under deferPanels), the mount strategy, the ids, and select(value, reason, source) for a view the page changes on its own. A region rendered outside the panels — a page header’s tab with controls= — renders from shownValue. It throws outside Tabs instead of rendering a control that looks right and does nothing. |
|
|
144
145
|
| `TabsDefaultsProvider` | `{ activation, orientation, size, variant, track, fit, mount, loop }` | — | a subtree | The eight settings an application decides once. A value set on one Tabs still wins. |
|
|
145
146
|
| `aria-label, on TabList` | `string` | — | TabList | The name of the set of views. Tabs writes no name of its own; aria-labelledby works the same way. |
|
|
146
147
|
|
|
@@ -166,6 +167,7 @@ export default function TabsBasic() {
|
|
|
166
167
|
|
|
167
168
|
## Rules
|
|
168
169
|
|
|
170
|
+
- Selecting a tab never waits for its panel: keep value urgent and render the region from useDeferredValue(value), which deferPanels does for the panels and useTabs().shownValue hands a region outside them. Wrapping the setter in startTransition delays the marker too.
|
|
169
171
|
- Tabs implements the WAI-ARIA APG Tabs pattern (w3.org/WAI/ARIA/apg/patterns/tabs/) and its whole keyboard table: Tab enters the list on the selected tab and leaves to the panel, the arrow keys of the list’s direction move focus and wrap at both ends, Home and End reach the first and last enabled tab, Enter and Space select under manual activation, and Delete closes a dismissible tab. A horizontal list does not listen for Up and Down, so those keys keep scrolling the page while focus is in the list.
|
|
170
172
|
- After a dismissal, focus follows the pattern: the next tab, the previous one when the closed tab was last, or the list itself when no tab is left, which is why the list carries tabindex="-1". The selection follows the same rule, with the reason remove.
|
|
171
173
|
- The close button is outside the arrow-key sequence and inside the accessibility tree. A screen reader reaches and presses it; from the keyboard, Delete closes the focused tab, and the tab announces the key with aria-keyshortcuts. In the arrow-key sequence, close buttons would double the presses it takes to cross the list.
|
|
@@ -268,7 +268,7 @@
|
|
|
268
268
|
"type": "'text' | 'search' | 'email' | 'url' | 'tel' | 'password'",
|
|
269
269
|
"defaultValue": "text",
|
|
270
270
|
"appliesTo": "TextField",
|
|
271
|
-
"description": "The input’s own type.
|
|
271
|
+
"description": "The input’s own type, one of the six listed. A date, a time, a month or a number is not a TextField: use date-picker (forms.md FM-16), time-picker or number-field. Other strings still reach the element for compatibility and are not supported."
|
|
272
272
|
},
|
|
273
273
|
{
|
|
274
274
|
"name": "messages",
|
package/dist/docs/text-field.md
CHANGED
|
@@ -65,7 +65,7 @@ export default function TextFieldBasic() {
|
|
|
65
65
|
| `readOnly` | `boolean` | from the field, or false | TextField | Unset by default, so the text field takes the state of the field around it. It is the native readonly: the input stays focusable and selectable, and its value is submitted. |
|
|
66
66
|
| `invalid` | `boolean` | from the field, or false | TextField | Unset by default, so the text field takes the state of the field around it. It sets aria-invalid on the input and data-invalid on the frame. |
|
|
67
67
|
| `required` | `boolean` | — | TextField | The input’s own attribute, passed through unchanged; TextField never writes it. A field marks a required value with aria-required instead, because the native attribute turns on browser constraint validation. |
|
|
68
|
-
| `type` | `'text' \| 'search' \| 'email' \| 'url' \| 'tel' \| 'password'` | text | TextField | The input’s own type.
|
|
68
|
+
| `type` | `'text' \| 'search' \| 'email' \| 'url' \| 'tel' \| 'password'` | text | TextField | The input’s own type, one of the six listed. A date, a time, a month or a number is not a TextField: use date-picker (forms.md FM-16), time-picker or number-field. Other strings still reach the element for compatibility and are not supported. |
|
|
69
69
|
| `messages` | `Partial<TextFieldMessages>` | — | TextField | Replaces words of the active language, key by key. clear, reveal and copy name the buttons; reveal does not change with the state, because aria-pressed carries it. copied and copyFailed announce the outcome of a copy. capsLock is announced once when Caps Lock turns on in a focused password field. |
|
|
70
70
|
| `render` | `(props: TextFieldRootProps) => ReactNode` | — | TextField | Renders the frame into another element and passes it every attribute. The props are typed against HTMLAttributes<HTMLElement>, so they can be spread onto a label or a fieldset. The input cannot be replaced, because it holds the value, the identifier and the wiring. |
|
|
71
71
|
| `TextFieldAction` | `ComponentPropsWithRef<"button"> & { render? }` | type="button" | start, end | A button you place inside the frame. Every native prop reaches the button, and render replaces it. MenuTrigger, PopoverTrigger and TooltipTrigger pass their wiring to it through their own render. |
|
|
@@ -6,7 +6,7 @@ import { t as i } from "./avatar-BnlE5jjr.js";
|
|
|
6
6
|
import { b as a } from "./field-NJaCxl2h.js";
|
|
7
7
|
/* empty css */
|
|
8
8
|
import { t as o } from "./highlight-0Qw23QPp.js";
|
|
9
|
-
import { c as s, i as c, n as l, o as ee, s as te } from "./select-
|
|
9
|
+
import { c as s, i as c, n as l, o as ee, s as te } from "./select-M7Io4UL9.js";
|
|
10
10
|
import { createArrowNavigation as ne, createRemovalFocus as re } from "@slotted/core/focus";
|
|
11
11
|
import { createControllable as u } from "@slotted/core/state";
|
|
12
12
|
import { createContext as ie, useCallback as d, useContext as f, useEffect as p, useId as ae, useImperativeHandle as oe, useLayoutEffect as se, useMemo as m, useRef as h, useState as g } from "react";
|
package/dist/entity-picker.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, c as t, i as n, n as r, o as i, r as a, s as o, t as s } from "./entity-picker-
|
|
1
|
+
import { a as e, c as t, i as n, n as r, o as i, r as a, s as o, t as s } from "./entity-picker-Dn1T7JCq.js";
|
|
2
2
|
export { s as CREATE_OPTION, i as ENTITY_PICKER_FALLBACK, e as EntityPicker, o as EntityPickerDefaultsProvider, r as RETRY_OPTION, a as localEntitySource, n as rememberRecent, t as useEntityPickerDefaults };
|
|
@@ -6,12 +6,12 @@ import { n as _, t as v } from "./icon-button-CCWkCDMs.js";
|
|
|
6
6
|
import { t as ne } from "./text-field-DLfIZ0fk.js";
|
|
7
7
|
import { a as re, d as ie, f as ae, l as oe, p as se, r as ce } from "./popover-Be7JWbGJ.js";
|
|
8
8
|
import { n as le } from "./kbd-eFSWTKxN.js";
|
|
9
|
-
import { t as ue } from "./date-picker-
|
|
10
|
-
import { t as de } from "./datetime-picker-
|
|
9
|
+
import { t as ue } from "./date-picker-D3-y2Jxw.js";
|
|
10
|
+
import { t as de } from "./datetime-picker-CIRHVLQp.js";
|
|
11
11
|
import { a as fe, i as pe, n as me, s as he } from "./multi-select-DQ5ds0fX.js";
|
|
12
12
|
import { t as ge } from "./number-field-BFIAmv-z.js";
|
|
13
13
|
import { a as _e, t as y } from "./segmented-control-DmuOGiu6.js";
|
|
14
|
-
import { c as ve, i as ye, n as be, o as xe, s as Se } from "./select-
|
|
14
|
+
import { c as ve, i as ye, n as be, o as xe, s as Se } from "./select-M7Io4UL9.js";
|
|
15
15
|
import { t as b } from "./time-picker-CRQsMJbQ.js";
|
|
16
16
|
import { createRemovalFocus as Ce, createRovingTabindex as we } from "@slotted/core/focus";
|
|
17
17
|
import { createControllable as Te } from "@slotted/core/state";
|
package/dist/filter-bar.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as e, n as t, r as n, t as r } from "./filter-bar-
|
|
1
|
+
import { i as e, n as t, r as n, t as r } from "./filter-bar-CHyy1o--.js";
|
|
2
2
|
export { r as FILTER_BAR_FALLBACK, t as FilterBar, n as FilterBarDefaultsProvider, e as useFilterBarDefaults };
|
|
@@ -6,8 +6,8 @@ import { n as o } from "./button-Db9f3Bxn.js";
|
|
|
6
6
|
import { a as s, i as c, n as l, r as u } from "./tooltip-DbKTPe_i.js";
|
|
7
7
|
import { i as d, t as f } from "./skeleton-2LSpg84Z.js";
|
|
8
8
|
import { i as p, n as m, o as h, r as g, t as _ } from "./result-state-CZsQfdN4.js";
|
|
9
|
-
import { a as ee, r as te, t as v } from "./tabs-
|
|
10
|
-
import { A as y, O as ne, b, c as x, f as S, l as C, u as w, v as re } from "./table-
|
|
9
|
+
import { a as ee, r as te, t as v } from "./tabs-BtHmjlnM.js";
|
|
10
|
+
import { A as y, O as ne, b, c as x, f as S, l as C, u as w, v as re } from "./table-U9eJYCuB.js";
|
|
11
11
|
import { v as T } from "./toast-Bf3e0AgC.js";
|
|
12
12
|
import { createControllable as ie } from "@slotted/core/state";
|
|
13
13
|
import { createContext as ae, useCallback as E, useContext as oe, useEffect as D, useId as se, useImperativeHandle as ce, useLayoutEffect as le, useMemo as ue, useRef as O, useState as k } from "react";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as e, n as t, r as n, t as r } from "./import-export-center-
|
|
1
|
+
import { i as e, n as t, r as n, t as r } from "./import-export-center-jF37b909.js";
|
|
2
2
|
export { t as ImportExportCenter, n as ImportExportCenterDefaultsProvider, e as useImportExportCenterDefaults, r as useJobToasts };
|