@godxjp/ui 32.2.0 → 32.2.2
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/README.md +1 -1
- package/agent/START-HERE.md +2 -2
- package/agent/components/DataTable.json +1 -1
- package/agent/components/DropdownMenu.json +1 -1
- package/agent/components/Toolbar.json +6 -0
- package/agent/components.json +8 -2
- package/agent/index.json +3 -3
- package/agent/llms.txt +4 -4
- package/dist/components/data-display/data-table.js +14 -4
- package/dist/components/data-entry/search-input.js +8 -2
- package/dist/components/navigation/dropdown-menu.js +8 -4
- package/dist/components/navigation/toolbar.d.ts +1 -1
- package/dist/components/navigation/toolbar.js +3 -1
- package/dist/contracts/measurement.json +1 -1
- package/dist/lib/shortcut.d.ts +8 -1
- package/dist/lib/shortcut.js +18 -1
- package/dist/props/components/navigation.prop.d.ts +8 -0
- package/dist/props/registry.d.ts +5 -0
- package/dist/props/registry.js +5 -0
- package/dist/styles/layers.json +1 -1
- package/dist/styles/table-layout.css +9 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ static files straight from this public repo — no hosting, no deploy step:
|
|
|
53
53
|
| [`agent/llms.txt`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/llms.txt) | 3 KB | the [llms.txt](https://llmstxt.org/) entry point |
|
|
54
54
|
| [`agent/index.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/index.json) | 3 KB | manifest: version, counts, every file's URL |
|
|
55
55
|
| [`agent/components-index.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json) | 47 KB | all 161 as name + group + tagline — **fetch this first** |
|
|
56
|
-
| [`agent/components/<Name>.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/Select.json) | 1 KB–
|
|
56
|
+
| [`agent/components/<Name>.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/Select.json) | 1 KB–37 KB | one file per component, each with its `importPath` — **this is the route to take** |
|
|
57
57
|
| [`agent/components.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components.json) | 1.2 MB | all 161 entries in one file — most URL fetchers truncate this silently; prefer the per-component files |
|
|
58
58
|
| [`agent/tokens.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/tokens.json) | 845 KB | all 2193 design tokens, their values and why they exist |
|
|
59
59
|
| [`agent/vocabulary.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/vocabulary.json) | 7 KB | the controlled prop vocabulary |
|
package/agent/START-HERE.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
You are about to write code against a design system you did not author. This file is the whole
|
|
4
4
|
contract. Read it before you write JSX.
|
|
5
5
|
|
|
6
|
-
**This catalog describes `@godxjp/ui` 32.2.
|
|
6
|
+
**This catalog describes `@godxjp/ui` 32.2.2.** If the project you are editing has a different
|
|
7
7
|
version in its `package.json`, read the pinned catalog for THAT version instead
|
|
8
8
|
(`…/v<their-version>/agent/…`). A catalog newer than the installed package describes props that do
|
|
9
9
|
not exist yet; older, and it hides props that do. Neither failure announces itself.
|
|
@@ -52,7 +52,7 @@ Then ask it: `search_components`, `get_component`, `get_tokens`, `get_rule`, `li
|
|
|
52
52
|
names that **do not exist** and map to it — `Combobox`, `Autocomplete`, `CountrySelect` and
|
|
53
53
|
`SearchSelect` are all `Select`. If you are about to hand-roll something, search this field
|
|
54
54
|
first; it exists because that is the mistake.
|
|
55
|
-
2. `components/<Name>.json` — one file per component (1 KB–
|
|
55
|
+
2. `components/<Name>.json` — one file per component (1 KB–37 KB, median 6 KB), carrying its props,
|
|
56
56
|
its `importPath`, and its examples. Fetch only the handful you picked in step 1.
|
|
57
57
|
3. `rules.json` — 43 cardinal rules. The ones about raw HTML and hardcoded colour are not
|
|
58
58
|
style advice.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"type": "T[]"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
|
-
"description": "Lean column definitions (adapted to TanStack internally — `meta.lean` is the declared home for every custom column option, so `priority` needs no second TanStack channel). Each column: { key: string; header: ReactNode; ariaLabel?: string; render?: (row: T) => ReactNode; sortable?: boolean; width?: string; align?: 'left'|'center'|'right'; hideBelow?: 'sm'|'md'|'lg'|'xl' (same contract as Flex hideBelow — stamped as data-hide-below on th/td); hiddenOnMobile?: boolean (alias for hideBelow:'md'); enableHiding?: boolean; pin?: 'end'; priority?: 'primary'|'secondary'|'meta'|'actions'; flush?: boolean }. flush (gh#1016 — the same word as TableCell flush / CardContent flush) drops the column's BODY cell padding so a self-padded row primitive owns the inset: a selectable list whose single column renders a `ListRow` writes `{ key: 'row', header: '', ariaLabel: …, flush: true, render: (m) => <ListRow asChild …><a/></ListRow> }` — the ListRow then sits 16px from the checkbox (not 32px) and the row is ListRow's own height; an unread ListRow in a flush cell paints `--list-row-unread-background` across the whole table row (checkbox cell included). The header keeps its padding, so the header label sits on the ListRow's inset. Never zero the cell with a className instead. priority is the column-priority contract read by preset=\"action-collection\" — DataTable stamps it as data-priority on the <th> AND every <td> of the column, so the preset can allocate the narrow-frame measure; leave the free-text column unmarked (it takes the remaining space), and prefer priority over width under the preset because an explicit width utility wins the cascade and defeats the measure. If render is omitted, the raw value at row[key] is rendered as a string. sortable opts the column into the sort cycle (client-side by default, or server-side via sort+onSortChange). enableHiding (default true) lists the column in DataTable.ViewOptions; set false to keep a key/actions column always visible. pin:'end' sticks the column (typically row actions) to the inline-end edge on horizontal scroll with a separating shadow — pin at most one column. ariaLabel gives a VISUALLY-EMPTY header (header='' — an action or selection column) a screen-reader name (e.g. 'Actions'/'Select'): it renders as an sr-only label inside the <th> so the column is never nameless (axe: empty-table-header). ANT DESIGN PARITY on the same column: fixed:'start'|'end' freezes the column against a scroll edge (logical, so it mirrors in RTL; the stacking offsets are MEASURED from the rendered header, so several adjacent frozen columns are correct at any width — pin:'end' is the older spelling of fixed:'end'). ellipsis holds the cell to one line (it also switches the table to table-layout: fixed, without which no ellipsis truncates anything); a cell that IS truncated — rendered cells too — gets a title from its text and a tab stop whose keyboard focus unfolds the text (PatternFly Truncate), and an ellipsis column's HEADER wraps instead of truncating (gh#1262). headerWrap lets any column's header wrap (default true with ellipsis, false otherwise). sorter is antd's richer `sortable`: true | (a, b) => number | { compare, multiple }, where multiple is the MULTI-column sort priority (highest sorts first). sortOrder / defaultSortOrder / sortDirections control and shape the cycle per column, and showSorterTooltip explains the next step. filters + onFilter + filteredValue / defaultFilteredValue / filterMultiple add a real filter menu to the header (filterMultiple: false makes it single-choice); omit onFilter for a server filter and drive it from the table's onFilterChange.",
|
|
17
|
+
"description": "Lean column definitions (adapted to TanStack internally — `meta.lean` is the declared home for every custom column option, so `priority` needs no second TanStack channel). Each column: { key: string; header: ReactNode; ariaLabel?: string; render?: (row: T) => ReactNode; sortable?: boolean; width?: string; align?: 'left'|'center'|'right'; hideBelow?: 'sm'|'md'|'lg'|'xl' (same contract as Flex hideBelow — stamped as data-hide-below on th/td); hiddenOnMobile?: boolean (alias for hideBelow:'md'); enableHiding?: boolean; pin?: 'end'; priority?: 'primary'|'secondary'|'meta'|'actions'; flush?: boolean }. flush (gh#1016 — the same word as TableCell flush / CardContent flush) drops the column's BODY cell padding so a self-padded row primitive owns the inset: a selectable list whose single column renders a `ListRow` writes `{ key: 'row', header: '', ariaLabel: …, flush: true, render: (m) => <ListRow asChild …><a/></ListRow> }` — the ListRow then sits 16px from the checkbox (not 32px) and the row is ListRow's own height; an unread ListRow in a flush cell paints `--list-row-unread-background` across the whole table row (checkbox cell included). The header keeps its padding, so the header label sits on the ListRow's inset. Never zero the cell with a className instead. priority is the column-priority contract read by preset=\"action-collection\" — DataTable stamps it as data-priority on the <th> AND every <td> of the column, so the preset can allocate the narrow-frame measure; leave the free-text column unmarked (it takes the remaining space), and prefer priority over width under the preset because an explicit width utility wins the cascade and defeats the measure. If render is omitted, the raw value at row[key] is rendered as a string. sortable opts the column into the sort cycle (client-side by default, or server-side via sort+onSortChange). enableHiding (default true) lists the column in DataTable.ViewOptions; set false to keep a key/actions column always visible. pin:'end' sticks the column (typically row actions) to the inline-end edge on horizontal scroll with a separating shadow — pin at most one column. ariaLabel gives a VISUALLY-EMPTY header (header='' — an action or selection column) a screen-reader name (e.g. 'Actions'/'Select'): it renders as an sr-only label inside the <th> so the column is never nameless (axe: empty-table-header). ANT DESIGN PARITY on the same column: fixed:'start'|'end' freezes the column against a scroll edge (logical, so it mirrors in RTL; the stacking offsets are MEASURED from the rendered header, so several adjacent frozen columns are correct at any width — pin:'end' is the older spelling of fixed:'end'). ellipsis holds the cell to one line (it also switches the table to table-layout: fixed, without which no ellipsis truncates anything); a cell that IS truncated — rendered cells too — gets a title from its text and a tab stop whose keyboard focus unfolds the text (PatternFly Truncate), and an ellipsis column's HEADER wraps instead of truncating (gh#1262). Truncation is detected on the cell OR on a descendant that ends in an ellipsis — a `Text truncate` link beside a badge or avatar — and the title then carries that descendant's text (gh#1269). headerWrap lets any column's header wrap (default true with ellipsis, false otherwise). sorter is antd's richer `sortable`: true | (a, b) => number | { compare, multiple }, where multiple is the MULTI-column sort priority (highest sorts first). sortOrder / defaultSortOrder / sortDirections control and shape the cycle per column, and showSorterTooltip explains the next step. filters + onFilter + filteredValue / defaultFilteredValue / filterMultiple add a real filter menu to the header (filterMultiple: false makes it single-choice); omit onFilter for a server filter and drive it from the table's onFilterChange.",
|
|
18
18
|
"name": "columns",
|
|
19
19
|
"required": true,
|
|
20
20
|
"type": "ColumnDef<T>[]"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"type": "number"
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
|
-
"description": "On the ROOT. A page-level key that OPENS the menu — `\"f\"` for a filter menu, `\"mod+shift+v\"` for a view menu (gh#1264). Same combo syntax and guard as SearchInput/CommandPalette: a bare key is ignored while focus is in an editable element or an IME is composing. Off by default; ignored while `disabled`.
|
|
41
|
+
"description": "On the ROOT. A page-level key that OPENS the menu — `\"f\"` for a filter menu, `\"mod+shift+v\"` for a view menu (gh#1264). Same combo syntax and guard as SearchInput/CommandPalette: a bare key is ignored while focus is in an editable element or an IME is composing. Off by default; ignored while `disabled`. The trigger gets `aria-keyshortcuts` automatically (an explicit consumer value wins); show the key visibly too (e.g. `DropdownMenuShortcut`). Never fires from inside a dialog, menu or listbox that does not contain the menu (gh#1267).",
|
|
42
42
|
"name": "shortcut",
|
|
43
43
|
"type": "string"
|
|
44
44
|
},
|
|
@@ -90,6 +90,12 @@
|
|
|
90
90
|
"name": "views",
|
|
91
91
|
"type": "ReactNode"
|
|
92
92
|
},
|
|
93
|
+
{
|
|
94
|
+
"defaultValue": "\"above\"",
|
|
95
|
+
"description": "Where `views` sits (gh#1267). `above` is its own row over the strip; `inline` puts it at the START of the strip's first row so an idle bar stays ONE row (with `above`, an idle bar measured 55 → 95px and one table row fewer above the fold at 1440×900).",
|
|
96
|
+
"name": "viewsPlacement",
|
|
97
|
+
"type": "\"above\" | \"inline\""
|
|
98
|
+
},
|
|
93
99
|
{
|
|
94
100
|
"description": "Extra classes on the root element.",
|
|
95
101
|
"name": "className",
|
package/agent/components.json
CHANGED
|
@@ -3326,7 +3326,7 @@
|
|
|
3326
3326
|
"type": "T[]"
|
|
3327
3327
|
},
|
|
3328
3328
|
{
|
|
3329
|
-
"description": "Lean column definitions (adapted to TanStack internally — `meta.lean` is the declared home for every custom column option, so `priority` needs no second TanStack channel). Each column: { key: string; header: ReactNode; ariaLabel?: string; render?: (row: T) => ReactNode; sortable?: boolean; width?: string; align?: 'left'|'center'|'right'; hideBelow?: 'sm'|'md'|'lg'|'xl' (same contract as Flex hideBelow — stamped as data-hide-below on th/td); hiddenOnMobile?: boolean (alias for hideBelow:'md'); enableHiding?: boolean; pin?: 'end'; priority?: 'primary'|'secondary'|'meta'|'actions'; flush?: boolean }. flush (gh#1016 — the same word as TableCell flush / CardContent flush) drops the column's BODY cell padding so a self-padded row primitive owns the inset: a selectable list whose single column renders a `ListRow` writes `{ key: 'row', header: '', ariaLabel: …, flush: true, render: (m) => <ListRow asChild …><a/></ListRow> }` — the ListRow then sits 16px from the checkbox (not 32px) and the row is ListRow's own height; an unread ListRow in a flush cell paints `--list-row-unread-background` across the whole table row (checkbox cell included). The header keeps its padding, so the header label sits on the ListRow's inset. Never zero the cell with a className instead. priority is the column-priority contract read by preset=\"action-collection\" — DataTable stamps it as data-priority on the <th> AND every <td> of the column, so the preset can allocate the narrow-frame measure; leave the free-text column unmarked (it takes the remaining space), and prefer priority over width under the preset because an explicit width utility wins the cascade and defeats the measure. If render is omitted, the raw value at row[key] is rendered as a string. sortable opts the column into the sort cycle (client-side by default, or server-side via sort+onSortChange). enableHiding (default true) lists the column in DataTable.ViewOptions; set false to keep a key/actions column always visible. pin:'end' sticks the column (typically row actions) to the inline-end edge on horizontal scroll with a separating shadow — pin at most one column. ariaLabel gives a VISUALLY-EMPTY header (header='' — an action or selection column) a screen-reader name (e.g. 'Actions'/'Select'): it renders as an sr-only label inside the <th> so the column is never nameless (axe: empty-table-header). ANT DESIGN PARITY on the same column: fixed:'start'|'end' freezes the column against a scroll edge (logical, so it mirrors in RTL; the stacking offsets are MEASURED from the rendered header, so several adjacent frozen columns are correct at any width — pin:'end' is the older spelling of fixed:'end'). ellipsis holds the cell to one line (it also switches the table to table-layout: fixed, without which no ellipsis truncates anything); a cell that IS truncated — rendered cells too — gets a title from its text and a tab stop whose keyboard focus unfolds the text (PatternFly Truncate), and an ellipsis column's HEADER wraps instead of truncating (gh#1262). headerWrap lets any column's header wrap (default true with ellipsis, false otherwise). sorter is antd's richer `sortable`: true | (a, b) => number | { compare, multiple }, where multiple is the MULTI-column sort priority (highest sorts first). sortOrder / defaultSortOrder / sortDirections control and shape the cycle per column, and showSorterTooltip explains the next step. filters + onFilter + filteredValue / defaultFilteredValue / filterMultiple add a real filter menu to the header (filterMultiple: false makes it single-choice); omit onFilter for a server filter and drive it from the table's onFilterChange.",
|
|
3329
|
+
"description": "Lean column definitions (adapted to TanStack internally — `meta.lean` is the declared home for every custom column option, so `priority` needs no second TanStack channel). Each column: { key: string; header: ReactNode; ariaLabel?: string; render?: (row: T) => ReactNode; sortable?: boolean; width?: string; align?: 'left'|'center'|'right'; hideBelow?: 'sm'|'md'|'lg'|'xl' (same contract as Flex hideBelow — stamped as data-hide-below on th/td); hiddenOnMobile?: boolean (alias for hideBelow:'md'); enableHiding?: boolean; pin?: 'end'; priority?: 'primary'|'secondary'|'meta'|'actions'; flush?: boolean }. flush (gh#1016 — the same word as TableCell flush / CardContent flush) drops the column's BODY cell padding so a self-padded row primitive owns the inset: a selectable list whose single column renders a `ListRow` writes `{ key: 'row', header: '', ariaLabel: …, flush: true, render: (m) => <ListRow asChild …><a/></ListRow> }` — the ListRow then sits 16px from the checkbox (not 32px) and the row is ListRow's own height; an unread ListRow in a flush cell paints `--list-row-unread-background` across the whole table row (checkbox cell included). The header keeps its padding, so the header label sits on the ListRow's inset. Never zero the cell with a className instead. priority is the column-priority contract read by preset=\"action-collection\" — DataTable stamps it as data-priority on the <th> AND every <td> of the column, so the preset can allocate the narrow-frame measure; leave the free-text column unmarked (it takes the remaining space), and prefer priority over width under the preset because an explicit width utility wins the cascade and defeats the measure. If render is omitted, the raw value at row[key] is rendered as a string. sortable opts the column into the sort cycle (client-side by default, or server-side via sort+onSortChange). enableHiding (default true) lists the column in DataTable.ViewOptions; set false to keep a key/actions column always visible. pin:'end' sticks the column (typically row actions) to the inline-end edge on horizontal scroll with a separating shadow — pin at most one column. ariaLabel gives a VISUALLY-EMPTY header (header='' — an action or selection column) a screen-reader name (e.g. 'Actions'/'Select'): it renders as an sr-only label inside the <th> so the column is never nameless (axe: empty-table-header). ANT DESIGN PARITY on the same column: fixed:'start'|'end' freezes the column against a scroll edge (logical, so it mirrors in RTL; the stacking offsets are MEASURED from the rendered header, so several adjacent frozen columns are correct at any width — pin:'end' is the older spelling of fixed:'end'). ellipsis holds the cell to one line (it also switches the table to table-layout: fixed, without which no ellipsis truncates anything); a cell that IS truncated — rendered cells too — gets a title from its text and a tab stop whose keyboard focus unfolds the text (PatternFly Truncate), and an ellipsis column's HEADER wraps instead of truncating (gh#1262). Truncation is detected on the cell OR on a descendant that ends in an ellipsis — a `Text truncate` link beside a badge or avatar — and the title then carries that descendant's text (gh#1269). headerWrap lets any column's header wrap (default true with ellipsis, false otherwise). sorter is antd's richer `sortable`: true | (a, b) => number | { compare, multiple }, where multiple is the MULTI-column sort priority (highest sorts first). sortOrder / defaultSortOrder / sortDirections control and shape the cycle per column, and showSorterTooltip explains the next step. filters + onFilter + filteredValue / defaultFilteredValue / filterMultiple add a real filter menu to the header (filterMultiple: false makes it single-choice); omit onFilter for a server filter and drive it from the table's onFilterChange.",
|
|
3330
3330
|
"name": "columns",
|
|
3331
3331
|
"required": true,
|
|
3332
3332
|
"type": "ColumnDef<T>[]"
|
|
@@ -8301,7 +8301,7 @@
|
|
|
8301
8301
|
"type": "number"
|
|
8302
8302
|
},
|
|
8303
8303
|
{
|
|
8304
|
-
"description": "On the ROOT. A page-level key that OPENS the menu — `\"f\"` for a filter menu, `\"mod+shift+v\"` for a view menu (gh#1264). Same combo syntax and guard as SearchInput/CommandPalette: a bare key is ignored while focus is in an editable element or an IME is composing. Off by default; ignored while `disabled`.
|
|
8304
|
+
"description": "On the ROOT. A page-level key that OPENS the menu — `\"f\"` for a filter menu, `\"mod+shift+v\"` for a view menu (gh#1264). Same combo syntax and guard as SearchInput/CommandPalette: a bare key is ignored while focus is in an editable element or an IME is composing. Off by default; ignored while `disabled`. The trigger gets `aria-keyshortcuts` automatically (an explicit consumer value wins); show the key visibly too (e.g. `DropdownMenuShortcut`). Never fires from inside a dialog, menu or listbox that does not contain the menu (gh#1267).",
|
|
8305
8305
|
"name": "shortcut",
|
|
8306
8306
|
"type": "string"
|
|
8307
8307
|
},
|
|
@@ -8560,6 +8560,12 @@
|
|
|
8560
8560
|
"name": "views",
|
|
8561
8561
|
"type": "ReactNode"
|
|
8562
8562
|
},
|
|
8563
|
+
{
|
|
8564
|
+
"defaultValue": "\"above\"",
|
|
8565
|
+
"description": "Where `views` sits (gh#1267). `above` is its own row over the strip; `inline` puts it at the START of the strip's first row so an idle bar stays ONE row (with `above`, an idle bar measured 55 → 95px and one table row fewer above the fold at 1440×900).",
|
|
8566
|
+
"name": "viewsPlacement",
|
|
8567
|
+
"type": "\"above\" | \"inline\""
|
|
8568
|
+
},
|
|
8563
8569
|
{
|
|
8564
8570
|
"description": "Extra classes on the root element.",
|
|
8565
8571
|
"name": "className",
|
package/agent/index.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
"file": "components/<Name>.json",
|
|
18
|
-
"note": "One file per component (1 KB–
|
|
18
|
+
"note": "One file per component (1 KB–37 KB, median 6 KB), each carrying its importPath. This is the selective route: read the index, then fetch only what you need instead of the 1.2 MB blob.",
|
|
19
19
|
"url": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/<Name>.json"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"note": "Pin to the tag that matches the @godxjp/ui version you installed. A catalog newer than your package describes props you do not have; older, and it hides props you do.",
|
|
49
49
|
"read": {
|
|
50
50
|
"live": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/index.json",
|
|
51
|
-
"pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v32.2.
|
|
51
|
+
"pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v32.2.2/agent/index.json"
|
|
52
52
|
},
|
|
53
53
|
"source": "mcp/src/data — the same data @godxjp/ui-mcp serves — plus the foundation and semantic token tiers, read from src/tokens/*.css",
|
|
54
54
|
"start": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/START-HERE.md",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"foundation": "the seeds a consumer is invited to set — --primary, --background, --radius",
|
|
63
63
|
"semantic": "named roles that follow the seeds — --ring, --text-link, --overlay-background"
|
|
64
64
|
},
|
|
65
|
-
"version": "32.2.
|
|
65
|
+
"version": "32.2.2"
|
|
66
66
|
}
|
package/agent/llms.txt
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @godxjp/ui
|
|
2
2
|
|
|
3
3
|
> A Japanese-enterprise React design system: 161 components, 2193 design tokens,
|
|
4
|
-
> 43 cardinal rules. This file is the entry point for AI agents. Catalog version 32.2.
|
|
4
|
+
> 43 cardinal rules. This file is the entry point for AI agents. Catalog version 32.2.2.
|
|
5
5
|
|
|
6
6
|
If your client can run a process, do not read these files — run the MCP server instead
|
|
7
|
-
(`npx @godxjp/ui-mcp@32.2.
|
|
7
|
+
(`npx @godxjp/ui-mcp@32.2.2`). It is searchable and version-locked. These files exist for agents
|
|
8
8
|
that can only fetch URLs.
|
|
9
9
|
|
|
10
10
|
## Start
|
|
@@ -16,7 +16,7 @@ that can only fetch URLs.
|
|
|
16
16
|
|
|
17
17
|
- [patterns-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/patterns-index.json): 24 whole-task patterns (name, tagline, tags). Start here when the task is a TASK — "build a settings page" — then fetch `patterns/<name>.json` for complete code.
|
|
18
18
|
- [components-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json): 47 KB — all 161 components as name, group, tagline, plus `absorbed`: the names that do NOT exist and map to it (`Combobox` → `Select`).
|
|
19
|
-
- [components/<Name>.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/Select.json): one file per component (1 KB–
|
|
19
|
+
- [components/<Name>.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/Select.json): one file per component (1 KB–37 KB, median 6 KB). Read the index, then fetch only the ones you chose — this is the selective route, and the reason you do not need the blob.
|
|
20
20
|
- [components.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components.json): 1.2 MB — every entry in one file. Most URL fetchers truncate a response this size without saying so; prefer the per-component files.
|
|
21
21
|
- [tokens.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/tokens.json): every design token with its value, the reason it exists, and its `tier` — 211 `foundation` seeds (`--primary`, `--background`, `--radius`: set these when you are handed a brand), 112 `semantic` roles, 1870 `component` knobs.
|
|
22
22
|
- [vocabulary.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/vocabulary.json): the controlled prop vocabulary — which prop name means what, across every component.
|
|
@@ -26,7 +26,7 @@ that can only fetch URLs.
|
|
|
26
26
|
## Pinning
|
|
27
27
|
|
|
28
28
|
Every URL above tracks `main`. To pin to the release a project actually installed, swap `main` for
|
|
29
|
-
the tag: `.../godx-jp/godxjp-ui/v32.2.
|
|
29
|
+
the tag: `.../godx-jp/godxjp-ui/v32.2.2/agent/...`. A catalog that does not match the installed
|
|
30
30
|
package describes props that are absent, or hides props that are present, and says nothing either way.
|
|
31
31
|
|
|
32
32
|
Pinned catalogs only exist for releases whose tag actually contains `agent/`. If `…/v<version>/agent/index.json` returns 404, that release predates this catalog: read `…/main/…` instead and compare `index.json` → `version` against the package you have, so you at least know which way it drifted.
|
|
@@ -729,6 +729,15 @@ function fixedEdge(col) {
|
|
|
729
729
|
return col.fixed ?? (col.pin === "end" ? "end" : void 0);
|
|
730
730
|
}
|
|
731
731
|
const TRUNCATED_CELL_FOCUSABLE = 'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"]), [contenteditable="true"]';
|
|
732
|
+
function truncatedPart(cell) {
|
|
733
|
+
if (cell.scrollWidth - cell.clientWidth > 1) return cell;
|
|
734
|
+
for (const el of cell.querySelectorAll("*")) {
|
|
735
|
+
if (el.scrollWidth - el.clientWidth > 1 && getComputedStyle(el).textOverflow === "ellipsis") {
|
|
736
|
+
return el;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return null;
|
|
740
|
+
}
|
|
732
741
|
function sameOffsets(a, b) {
|
|
733
742
|
const keys = Object.keys(a);
|
|
734
743
|
if (keys.length !== Object.keys(b).length) return false;
|
|
@@ -916,12 +925,13 @@ DataTable.Content = function DataTableContent() {
|
|
|
916
925
|
const el = scrollRef.current;
|
|
917
926
|
if (!el) return;
|
|
918
927
|
for (const cell of el.querySelectorAll("tbody td.ui-data-table-ellipsis")) {
|
|
919
|
-
if (cell
|
|
928
|
+
if (cell.contains(document.activeElement)) continue;
|
|
920
929
|
const ownTitle = cell.dataset.truncatedTitle !== void 0;
|
|
921
|
-
|
|
930
|
+
const part = truncatedPart(cell);
|
|
931
|
+
if (part) {
|
|
922
932
|
cell.dataset.truncated = "";
|
|
923
|
-
if (!cell.title || ownTitle) {
|
|
924
|
-
cell.title = (
|
|
933
|
+
if ((!cell.title || ownTitle) && (part === cell || !part.title)) {
|
|
934
|
+
cell.title = (part.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
925
935
|
cell.dataset.truncatedTitle = "";
|
|
926
936
|
}
|
|
927
937
|
if (!cell.querySelector(TRUNCATED_CELL_FOCUSABLE)) cell.tabIndex = 0;
|
|
@@ -8,7 +8,12 @@ import { Label } from "../data-entry/label.js";
|
|
|
8
8
|
import { cn } from "../../lib/utils.js";
|
|
9
9
|
import { resolveFieldA11y } from "../../lib/field-a11y.js";
|
|
10
10
|
import { useDebouncedValue } from "../../lib/hooks.js";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
ariaKeyShortcuts,
|
|
13
|
+
parseShortcut,
|
|
14
|
+
shortcutHint,
|
|
15
|
+
shouldHandleShortcut
|
|
16
|
+
} from "../../lib/shortcut.js";
|
|
12
17
|
function SearchInput({
|
|
13
18
|
value: controlledValue,
|
|
14
19
|
defaultValue = "",
|
|
@@ -55,7 +60,7 @@ function SearchInput({
|
|
|
55
60
|
React.useEffect(() => {
|
|
56
61
|
if (!shortcutSpec || disabled) return;
|
|
57
62
|
const handleKeyDown = (event) => {
|
|
58
|
-
if (!shouldHandleShortcut(shortcutSpec, event)) return;
|
|
63
|
+
if (!shouldHandleShortcut(shortcutSpec, event, inputRef.current)) return;
|
|
59
64
|
event.preventDefault();
|
|
60
65
|
inputRef.current?.focus();
|
|
61
66
|
};
|
|
@@ -78,6 +83,7 @@ function SearchInput({
|
|
|
78
83
|
id: inputId,
|
|
79
84
|
type: "text",
|
|
80
85
|
role: "searchbox",
|
|
86
|
+
"aria-keyshortcuts": shortcutSpec ? ariaKeyShortcuts(shortcutSpec) : void 0,
|
|
81
87
|
value,
|
|
82
88
|
onChange: (e) => {
|
|
83
89
|
setValue(e.target.value);
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
useLocale
|
|
21
21
|
} from "react-aria-components";
|
|
22
22
|
import { Check, ChevronRight } from "lucide-react";
|
|
23
|
-
import { parseShortcut, shouldHandleShortcut } from "../../lib/shortcut.js";
|
|
23
|
+
import { ariaKeyShortcuts, parseShortcut, shouldHandleShortcut } from "../../lib/shortcut.js";
|
|
24
24
|
import { cn } from "../../lib/utils.js";
|
|
25
25
|
import { Slot } from "../../lib/slot.js";
|
|
26
26
|
const DROPDOWN_MENU_PLACEMENT = {
|
|
@@ -189,9 +189,10 @@ function DropdownMenu({
|
|
|
189
189
|
disabled,
|
|
190
190
|
hover,
|
|
191
191
|
racOwnsContextMenu,
|
|
192
|
-
openedByHover
|
|
192
|
+
openedByHover,
|
|
193
|
+
keyShortcuts: shortcutSpec && !disabled ? ariaKeyShortcuts(shortcutSpec) : void 0
|
|
193
194
|
}),
|
|
194
|
-
[modal, wantsContextMenu, disabled, hover, racOwnsContextMenu, wantsHover]
|
|
195
|
+
[modal, wantsContextMenu, disabled, hover, racOwnsContextMenu, wantsHover, shortcutSpec]
|
|
195
196
|
);
|
|
196
197
|
return /* @__PURE__ */ jsx(DropdownMenuModalContext.Provider, { value: options, children: /* @__PURE__ */ jsx(
|
|
197
198
|
MenuTrigger,
|
|
@@ -208,7 +209,7 @@ function DropdownMenuTrigger({ asChild, children, ...props }) {
|
|
|
208
209
|
const menuState = React.useContext(
|
|
209
210
|
RootMenuTriggerStateContext
|
|
210
211
|
);
|
|
211
|
-
const { contextMenuGesture, disabled, hover, racOwnsContextMenu } = React.useContext(DropdownMenuModalContext);
|
|
212
|
+
const { contextMenuGesture, disabled, hover, racOwnsContextMenu, keyShortcuts } = React.useContext(DropdownMenuModalContext);
|
|
212
213
|
const dataState = state?.isOpen ? "open" : "closed";
|
|
213
214
|
const wantsContextMenu = contextMenuGesture;
|
|
214
215
|
const isDisabled = disabled || props.disabled;
|
|
@@ -251,6 +252,8 @@ function DropdownMenuTrigger({ asChild, children, ...props }) {
|
|
|
251
252
|
return /* @__PURE__ */ jsx(Pressable, { isDisabled, children: React.cloneElement(children, {
|
|
252
253
|
"data-slot": "dropdown-menu-trigger",
|
|
253
254
|
"data-state": dataState,
|
|
255
|
+
// The root's `shortcut`, announced (gh#1267); a consumer's own value wins.
|
|
256
|
+
...keyShortcuts && children.props["aria-keyshortcuts"] === void 0 ? { "aria-keyshortcuts": keyShortcuts } : {},
|
|
254
257
|
// A right click target is usually a region rather than a button, and Shift+F10 needs it
|
|
255
258
|
// focusable — so it is given a tab stop unless the consumer already placed one.
|
|
256
259
|
...wantsContextMenu && children.props.tabIndex === void 0 ? { tabIndex: 0 } : {},
|
|
@@ -270,6 +273,7 @@ function DropdownMenuTrigger({ asChild, children, ...props }) {
|
|
|
270
273
|
isDisabled,
|
|
271
274
|
"data-slot": "dropdown-menu-trigger",
|
|
272
275
|
"data-state": dataState,
|
|
276
|
+
"aria-keyshortcuts": props["aria-keyshortcuts"] ?? keyShortcuts,
|
|
273
277
|
children
|
|
274
278
|
}
|
|
275
279
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ToolbarGroupProp, ToolbarProp } from "../../props/components/navigation.prop.js";
|
|
2
2
|
export type { FilterBarChipProp, FilterBarChipProp as FilterBarChipProps, FilterBarFilterProp, FilterBarFilterProp as FilterBarFilterProps, FilterBarOverflowProp, FilterBarSearchProp, FilterBarSearchProp as FilterBarSearchProps, ToolbarGroupProp, ToolbarGroupProp as ToolbarGroupProps, ToolbarGroupProp as FilterBarGroupProp, ToolbarGroupProp as FilterBarGroupProps, ToolbarProp, ToolbarProp as ToolbarProps, ToolbarProp as FilterBarProp, ToolbarProp as FilterBarProps, } from "../../props/components/navigation.prop.js";
|
|
3
|
-
export declare function Toolbar({ onClear, hasActiveFilters, sticky, overflow, search, filters, chips, onChipRemove, actions, resultCount, loading, disabled, error, clearDisplay, views, className, children, }: ToolbarProp): import("react").JSX.Element;
|
|
3
|
+
export declare function Toolbar({ onClear, hasActiveFilters, sticky, overflow, search, filters, chips, onChipRemove, actions, resultCount, loading, disabled, error, clearDisplay, views, viewsPlacement, className, children, }: ToolbarProp): import("react").JSX.Element;
|
|
4
4
|
export declare function ToolbarGroup({ label, controlId, className, children }: ToolbarGroupProp): import("react").JSX.Element;
|
|
5
5
|
/** Canonical list-page filter strip. `Toolbar` remains available for backwards compatibility. */
|
|
6
6
|
export declare const FilterBar: typeof Toolbar;
|
|
@@ -25,6 +25,7 @@ function Toolbar({
|
|
|
25
25
|
error,
|
|
26
26
|
clearDisplay = "label",
|
|
27
27
|
views,
|
|
28
|
+
viewsPlacement = "above",
|
|
28
29
|
className,
|
|
29
30
|
children
|
|
30
31
|
}) {
|
|
@@ -90,7 +91,7 @@ function Toolbar({
|
|
|
90
91
|
className: cn("ui-filter-bar", sticky && "ui-toolbar-sticky", className),
|
|
91
92
|
"data-loading": loading || void 0,
|
|
92
93
|
children: [
|
|
93
|
-
views != null && /* @__PURE__ */ jsx("div", { className: "ui-filter-bar-views", children: views }),
|
|
94
|
+
views != null && viewsPlacement === "above" && /* @__PURE__ */ jsx("div", { className: "ui-filter-bar-views", children: views }),
|
|
94
95
|
/* @__PURE__ */ jsxs(
|
|
95
96
|
"div",
|
|
96
97
|
{
|
|
@@ -100,6 +101,7 @@ function Toolbar({
|
|
|
100
101
|
"data-overflow": overflow,
|
|
101
102
|
className: "ui-toolbar",
|
|
102
103
|
children: [
|
|
104
|
+
views != null && viewsPlacement === "inline" && /* @__PURE__ */ jsx("div", { className: "ui-filter-bar-views", "data-placement": "inline", children: views }),
|
|
103
105
|
search && /* @__PURE__ */ jsx(
|
|
104
106
|
SearchInput,
|
|
105
107
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
|
|
3
|
-
"version": "32.2.
|
|
3
|
+
"version": "32.2.2",
|
|
4
4
|
"targetSize": {
|
|
5
5
|
"standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
|
|
6
6
|
"min": 24,
|
package/dist/lib/shortcut.d.ts
CHANGED
|
@@ -25,9 +25,16 @@ export declare function isEditableTarget(target: EventTarget | null): boolean;
|
|
|
25
25
|
/**
|
|
26
26
|
* Should this keydown run the shortcut? The ONE gate every global shortcut goes through:
|
|
27
27
|
* - never during IME composition (the key belongs to the conversion, gh#1054);
|
|
28
|
+
* - never from inside a dialog/menu/listbox that does not contain `owner` (gh#1267);
|
|
28
29
|
* - the combo must match;
|
|
29
30
|
* - a shortcut with NO command modifier (`"/"`, `"f"`, `"shift+?"`) is ignored while focus is in
|
|
30
31
|
* an editable element, where that key is text. A modified one (`"mod+k"`) still fires there —
|
|
31
32
|
* no text field types ⌘K — which is how GitHub's and Linear's palettes behave.
|
|
32
33
|
*/
|
|
33
|
-
export declare function shouldHandleShortcut(spec: ShortcutSpec, event: KeyboardEvent): boolean;
|
|
34
|
+
export declare function shouldHandleShortcut(spec: ShortcutSpec, event: KeyboardEvent, owner?: Element | null): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* The `aria-keyshortcuts` value for a spec (WAI-ARIA 1.2: modifiers then key, `+`-joined, with
|
|
37
|
+
* `Control`/`Meta`/`Alt`/`Shift` spelled out and a letter upper-cased): `mod+k` → `Meta+K` on
|
|
38
|
+
* Apple platforms, `Control+K` elsewhere; `"/"` → `/` (gh#1267).
|
|
39
|
+
*/
|
|
40
|
+
export declare function ariaKeyShortcuts(spec: ShortcutSpec): string;
|
package/dist/lib/shortcut.js
CHANGED
|
@@ -51,12 +51,29 @@ function isEditableTarget(target) {
|
|
|
51
51
|
const role = target.getAttribute("role");
|
|
52
52
|
return role === "textbox" || role === "combobox" || role === "searchbox";
|
|
53
53
|
}
|
|
54
|
-
function shouldHandleShortcut(spec, event) {
|
|
54
|
+
function shouldHandleShortcut(spec, event, owner) {
|
|
55
55
|
if (isImeComposing(event) || !shortcutMatches(spec, event)) return false;
|
|
56
|
+
if (inForeignLayer(event.target, owner)) return false;
|
|
56
57
|
const commandModifier = spec.mod || spec.meta || spec.ctrl || spec.alt;
|
|
57
58
|
return commandModifier || !isEditableTarget(event.target);
|
|
58
59
|
}
|
|
60
|
+
const SHORTCUT_LAYER = '[role="dialog"], [role="alertdialog"], [aria-modal="true"], [role="menu"], [role="listbox"]';
|
|
61
|
+
function inForeignLayer(target, owner) {
|
|
62
|
+
if (!(target instanceof Element)) return false;
|
|
63
|
+
const layer = target.closest(SHORTCUT_LAYER);
|
|
64
|
+
return layer !== null && !(owner && layer.contains(owner));
|
|
65
|
+
}
|
|
66
|
+
function ariaKeyShortcuts(spec) {
|
|
67
|
+
return [
|
|
68
|
+
spec.ctrl || spec.mod && !isApplePlatform() ? "Control" : "",
|
|
69
|
+
spec.meta || spec.mod && isApplePlatform() ? "Meta" : "",
|
|
70
|
+
spec.alt ? "Alt" : "",
|
|
71
|
+
spec.shift ? "Shift" : "",
|
|
72
|
+
spec.key.length === 1 ? spec.key.toUpperCase() : spec.key
|
|
73
|
+
].filter(Boolean).join("+");
|
|
74
|
+
}
|
|
59
75
|
export {
|
|
76
|
+
ariaKeyShortcuts,
|
|
60
77
|
isEditableTarget,
|
|
61
78
|
parseShortcut,
|
|
62
79
|
shortcutHint,
|
|
@@ -112,9 +112,17 @@ export type ToolbarProp = {
|
|
|
112
112
|
* filter set, so it is not one more filter in the strip.
|
|
113
113
|
*/
|
|
114
114
|
views?: React.ReactNode;
|
|
115
|
+
/**
|
|
116
|
+
* Where `views` sits (gh#1267). `above` (default) is its own row over the strip; `inline` puts it
|
|
117
|
+
* at the START of the strip's first row, so an idle bar stays ONE row — measured with `above`: an
|
|
118
|
+
* idle bar 55 → 95px, one table row fewer above the fold at 1440×900.
|
|
119
|
+
*/
|
|
120
|
+
viewsPlacement?: FilterBarViewsPlacementProp;
|
|
115
121
|
className?: ClassNameProp;
|
|
116
122
|
children?: ChildrenProp;
|
|
117
123
|
};
|
|
124
|
+
/** @see ToolbarProp.viewsPlacement */
|
|
125
|
+
export type FilterBarViewsPlacementProp = "above" | "inline";
|
|
118
126
|
/** @see ToolbarProp.clearDisplay */
|
|
119
127
|
export type FilterBarClearDisplayProp = "label" | "icon";
|
|
120
128
|
/** @see ToolbarGroup */
|
package/dist/props/registry.d.ts
CHANGED
|
@@ -2596,6 +2596,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
|
|
|
2596
2596
|
readonly file: "components/navigation.prop.ts";
|
|
2597
2597
|
readonly vocabulary: readonly [];
|
|
2598
2598
|
};
|
|
2599
|
+
readonly FilterBarViewsPlacementProp: {
|
|
2600
|
+
readonly group: "navigation";
|
|
2601
|
+
readonly file: "components/navigation.prop.ts";
|
|
2602
|
+
readonly vocabulary: readonly [];
|
|
2603
|
+
};
|
|
2599
2604
|
readonly FilterBarOverflowProp: {
|
|
2600
2605
|
readonly group: "navigation";
|
|
2601
2606
|
readonly file: "components/navigation.prop.ts";
|
package/dist/props/registry.js
CHANGED
|
@@ -3028,6 +3028,11 @@ const COMPONENT_PROP_REGISTRY = {
|
|
|
3028
3028
|
file: "components/navigation.prop.ts",
|
|
3029
3029
|
vocabulary: []
|
|
3030
3030
|
},
|
|
3031
|
+
FilterBarViewsPlacementProp: {
|
|
3032
|
+
group: "navigation",
|
|
3033
|
+
file: "components/navigation.prop.ts",
|
|
3034
|
+
vocabulary: []
|
|
3035
|
+
},
|
|
3031
3036
|
FilterBarOverflowProp: {
|
|
3032
3037
|
group: "navigation",
|
|
3033
3038
|
file: "components/navigation.prop.ts",
|
package/dist/styles/layers.json
CHANGED
|
@@ -535,7 +535,15 @@
|
|
|
535
535
|
white-space: nowrap;
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
-
.ui-data-table-ellipsis[data-truncated]:focus-visible
|
|
538
|
+
.ui-data-table-ellipsis[data-truncated]:focus-visible,
|
|
539
|
+
.ui-data-table-ellipsis[data-truncated]:has(:focus-visible) {
|
|
540
|
+
white-space: normal;
|
|
541
|
+
overflow-wrap: anywhere;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
.ui-data-table-ellipsis[data-truncated]:focus-visible [data-truncate],
|
|
545
|
+
.ui-data-table-ellipsis[data-truncated]:has(:focus-visible) [data-truncate] {
|
|
546
|
+
overflow: visible;
|
|
539
547
|
white-space: normal;
|
|
540
548
|
overflow-wrap: anywhere;
|
|
541
549
|
}
|