@godxjp/ui 33.15.0 → 33.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +4 -4
  2. package/agent/START-HERE.md +5 -5
  3. package/agent/components/AreaChart.json +6 -0
  4. package/agent/components/BarChart.json +6 -0
  5. package/agent/components/DashboardGrid.json +76 -0
  6. package/agent/components/DataTable.json +1 -1
  7. package/agent/components/HeatmapChart.json +6 -0
  8. package/agent/components/LineChart.json +6 -0
  9. package/agent/components/Pagination.json +1 -1
  10. package/agent/components/PieChart.json +6 -0
  11. package/agent/components/Table.json +1 -1
  12. package/agent/components-index.json +7 -1
  13. package/agent/components.json +109 -3
  14. package/agent/index.json +6 -6
  15. package/agent/llms.txt +6 -6
  16. package/agent/tokens.json +38 -2
  17. package/dist/components/charts/chart-cartesian.d.ts +3 -2
  18. package/dist/components/charts/chart-cartesian.js +146 -46
  19. package/dist/components/charts/chart-datum-selection.d.ts +15 -0
  20. package/dist/components/charts/chart-datum-selection.js +97 -0
  21. package/dist/components/charts/chart-frame.d.ts +2 -1
  22. package/dist/components/charts/chart-frame.js +2 -1
  23. package/dist/components/charts/heatmap-chart.d.ts +1 -1
  24. package/dist/components/charts/heatmap-chart.js +20 -0
  25. package/dist/components/charts/index.d.ts +1 -1
  26. package/dist/components/charts/pie-chart.d.ts +2 -1
  27. package/dist/components/charts/pie-chart.js +36 -1
  28. package/dist/components/charts/recharts-peer.d.ts +1 -1
  29. package/dist/components/charts/recharts-peer.js +6 -0
  30. package/dist/contracts/measurement.json +1 -1
  31. package/dist/i18n/messages/en.json +10 -0
  32. package/dist/i18n/messages/ja.json +10 -0
  33. package/dist/i18n/messages/vi.json +10 -0
  34. package/dist/lab/dashboard-grid-layout.d.ts +4 -0
  35. package/dist/lab/dashboard-grid-layout.js +36 -0
  36. package/dist/lab/dashboard-grid.d.ts +5 -0
  37. package/dist/lab/dashboard-grid.js +258 -0
  38. package/dist/lab/index.d.ts +2 -0
  39. package/dist/lab/index.js +2 -0
  40. package/dist/props/components/charts.prop.d.ts +11 -0
  41. package/dist/props/components/dashboard-grid.prop.d.ts +27 -0
  42. package/dist/props/components/dashboard-grid.prop.js +0 -0
  43. package/dist/props/components/index.d.ts +1 -1
  44. package/dist/props/registry.d.ts +83 -5
  45. package/dist/props/registry.js +79 -0
  46. package/dist/styles/chart-layout.css +28 -0
  47. package/dist/styles/control.css +82 -0
  48. package/dist/styles/layers.json +10 -1
  49. package/dist/styles/navigation-layout.css +2 -0
  50. package/dist/styles.css +1 -1
  51. package/dist/tokens/base.css +2 -0
  52. package/dist/tokens/components/dashboard-grid.css +14 -0
  53. package/dist/tokens/components/table.css +1 -1
  54. package/docs/COMPOSITION-VS-COMPONENT.md +15 -14
  55. package/package.json +2 -2
package/README.md CHANGED
@@ -18,7 +18,7 @@ npm i @godxjp/ui
18
18
 
19
19
  <!-- agent-catalog-counts:start -->
20
20
 
21
- The catalog — 170 components, 2251 tokens, 44 cardinal rules — is published in two forms from one
21
+ The catalog — 171 components, 2257 tokens, 44 cardinal rules — is published in two forms from one
22
22
  source. **Entry point for either: [`AGENTS.md`](AGENTS.md).**
23
23
  <!-- agent-catalog-counts:end -->
24
24
 
@@ -53,10 +53,10 @@ 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/DESIGN.md`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/DESIGN.md) | 18 KB | the visual spec: tokens, colour scarcity, admin screen anatomy, do/don't |
55
55
  | [`agent/index.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/index.json) | 3 KB | manifest: version, counts, every file's URL |
56
- | [`agent/components-index.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json) | 53 KB | all 170 as name + group + tagline — **fetch this first** |
56
+ | [`agent/components-index.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json) | 54 KB | all 171 as name + group + tagline — **fetch this first** |
57
57
  | [`agent/components/<Name>.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/Select.json) | 1 KB–38 KB | one file per component, each with its `importPath` — **this is the route to take** |
58
- | [`agent/components.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components.json) | 1.3 MB | all 170 entries in one file — most URL fetchers truncate this silently; prefer the per-component files |
59
- | [`agent/tokens.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/tokens.json) | 860 KB | all 2251 design tokens, their values and why they exist |
58
+ | [`agent/components.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components.json) | 1.3 MB | all 171 entries in one file — most URL fetchers truncate this silently; prefer the per-component files |
59
+ | [`agent/tokens.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/tokens.json) | 861 KB | all 2257 design tokens, their values and why they exist |
60
60
  | [`agent/vocabulary.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/vocabulary.json) | 7 KB | the controlled prop vocabulary |
61
61
  | [`agent/rules.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/rules.json) | 23 KB | the 44 cardinal rules |
62
62
  <!-- prettier-ignore-end -->
@@ -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` 33.15.0.** If the project you are editing has a different
6
+ **This catalog describes `@godxjp/ui` 33.16.0.** 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 @@ screen anatomy, the visual target the rules below do not give you. Then fetch in
52
52
  task is a task** — "build a settings page", "confirm a destructive delete", "a list page with
53
53
  filters" — start HERE, not at the components. Then fetch `patterns/<name>.json` for complete,
54
54
  copy-paste-ready code. A component index answers "does X exist"; it cannot answer "build Y".
55
- 1. `components-index.json` — 53 KB, all 170 components as name + group +
55
+ 1. `components-index.json` — 54 KB, all 171 components as name + group +
56
56
  tagline. Read this when you already know the SHAPE you need. Each entry may carry `absorbed`:
57
57
  names that **do not exist** and map to it — `Combobox`, `Autocomplete`, `CountrySelect` and
58
58
  `SearchSelect` are all `Select`. If you are about to hand-roll something, search this field
@@ -61,10 +61,10 @@ screen anatomy, the visual target the rules below do not give you. Then fetch in
61
61
  its `importPath`, and its examples. Fetch only the handful you picked in step 1.
62
62
  3. `rules.json` — 44 cardinal rules. The ones about raw HTML and hardcoded colour are not
63
63
  style advice.
64
- 4. `tokens.json` — 2251 design tokens, each tagged with its `tier`. **If you were handed a
64
+ 4. `tokens.json` — 2257 design tokens, each tagged with its `tier`. **If you were handed a
65
65
  brand, read the 218 `foundation` entries first** — `--primary`, `--background`,
66
66
  `--radius`, `--font-size-base` are the handful everything else derives from. The
67
- 1920 `component` entries are per-part knobs; reach for one only when a role is
67
+ 1926 `component` entries are per-part knobs; reach for one only when a role is
68
68
  right everywhere except one component.
69
69
  5. `anti-ai-tells.json` — 35 shapes that make generated UI look generated, each with the
70
70
  fix. Read before you reach for a gradient hero or a wall of coloured chips.
@@ -150,7 +150,7 @@ has stopped following the brand.
150
150
  |---|---|---|---|
151
151
  | `foundation` | 218 | the seeds — `--primary`, `--background`, `--foreground`, `--radius`, `--font-size-base`, `--shadow-color`. Everything below is derived from these | **yes — this is the main road.** The default `--primary` is a neutral placeholder: set it (`:root { --primary: <H> <S>% <L>%; }`, HSL components, no `hsl()` wrapper) or import a theme preset such as `@godxjp/ui/themes/godx.css` |
152
152
  | `semantic` | 113 | named roles that follow the seeds — `--ring`, `--text-link`, `--primary-hover`, `--overlay-background` | only when the seed is right and ONE role must differ. That role then stops following a later brand change |
153
- | `component` | 1920 | per-part knobs, `--{component}-{part}-{property}` | rarely. Most are declared `initial` with the real default at the call site — deliberate, so a scoped override re-resolves instead of freezing at `:root` |
153
+ | `component` | 1926 | per-part knobs, `--{component}-{part}-{property}` | rarely. Most are declared `initial` with the real default at the call site — deliberate, so a scoped override re-resolves instead of freezing at `:root` |
154
154
 
155
155
  A token whose `value` is `initial` is not empty and not broken: `initial` is the guaranteed-invalid
156
156
  value, so the real default is computed where the element paints it. Set it and yours wins.
@@ -4,6 +4,11 @@
4
4
  "importPath": "@godxjp/ui/charts",
5
5
  "name": "AreaChart",
6
6
  "props": [
7
+ {
8
+ "description": "Opt-in pointer and Enter/Space selection. seriesKey is the series dataKey; index is the original data index. Arrows navigate; Home/End move to ends. Finite data only (pie: positive slices). No handler preserves the non-selectable chart. Dashboard owns filter state.",
9
+ "name": "onDatumSelect",
10
+ "type": "(datum: ChartDatum, context: { seriesKey: string; index: number }) => void"
11
+ },
7
12
  {
8
13
  "description": "Row data: one category per row with a numeric value per series.",
9
14
  "name": "data",
@@ -108,6 +113,7 @@
108
113
  "rules": [],
109
114
  "tagline": "Magnitude over an ordered category axis — overlay or `stacked` areas, optional `curved` smoothing, localized formatting + text alternative. Data-visualization graph / plot.",
110
115
  "usage": [
116
+ "DO use onDatumSelect for accessible drill-through; keep filter state in the screen. Marks have localized names, roving focus and the brand ring. Line/area display points while interactive. RTL mirrors horizontal arrow navigation.",
111
117
  "DO import from the charts entry: `import { AreaChart } from \"@godxjp/ui/charts\";` (recharts optional peer required).",
112
118
  "DO import only the chart a screen uses — `import { AreaChart } from \"@godxjp/ui/charts/area-chart\";` — when the `./charts` barrel should not link the whole chart family. Without the `recharts` peer the build then fails ONCE, naming the package and the fix.",
113
119
  "DO use `stacked` to show how parts accumulate into a total over time.",
@@ -4,6 +4,11 @@
4
4
  "importPath": "@godxjp/ui/charts",
5
5
  "name": "BarChart",
6
6
  "props": [
7
+ {
8
+ "description": "Opt-in pointer and Enter/Space selection. seriesKey is the series dataKey; index is the original data index. Arrows navigate; Home/End move to ends. Finite data only (pie: positive slices). No handler preserves the non-selectable chart. Dashboard owns filter state.",
9
+ "name": "onDatumSelect",
10
+ "type": "(datum: ChartDatum, context: { seriesKey: string; index: number }) => void"
11
+ },
7
12
  {
8
13
  "description": "Row data: one category per row with a numeric value per series.",
9
14
  "name": "data",
@@ -103,6 +108,7 @@
103
108
  "rules": [],
104
109
  "tagline": "Compare a value across categories — grouped or `stacked`, vertical or `horizontal`, with localized ticks/tooltips and a built-in text alternative. Data-visualization graph / plot / diagram.",
105
110
  "usage": [
111
+ "DO use onDatumSelect for accessible drill-through; keep filter state in the screen. Marks have localized names, roving focus and the brand ring. Line/area display points while interactive. RTL mirrors horizontal arrow navigation.",
106
112
  "DO import from the charts entry: `import { BarChart } from \"@godxjp/ui/charts\";` (recharts optional peer required).",
107
113
  "DO import only the chart a screen uses — `import { BarChart } from \"@godxjp/ui/charts/bar-chart\";` — when the `./charts` barrel should not link the whole chart family. Without the `recharts` peer the build then fails ONCE, naming the package and the fix.",
108
114
  "DO use `horizontal` when category labels are long (they read better on the y-axis).",
@@ -0,0 +1,76 @@
1
+ {
2
+ "docPath": "docs/lab/dashboard-grid.tsx",
3
+ "example": "import { DashboardGrid } from \"@godxjp/ui/lab\";\n\n<DashboardGrid items={[{ id: \"revenue\", label: \"Revenue\", content: \"Revenue\" }]} defaultLayout={[{ id: \"revenue\", x: 0, y: 0, w: 2, h: 3 }]} columns={{ base: 1, lg: 4 }} editable />",
4
+ "group": "layout",
5
+ "importPath": "@godxjp/ui/lab",
6
+ "name": "DashboardGrid",
7
+ "props": [
8
+ {
9
+ "description": "Stable ids, visible header labels (also accessible region names) and widget body content. Wrap padded bodies in CardContent, tables in CardContent flush; DashboardGrid owns the Card and header. DOM reading order remains items order.",
10
+ "name": "items",
11
+ "required": true,
12
+ "type": "{ id: string; label: string; content: ReactNode }[]"
13
+ },
14
+ {
15
+ "description": "Controlled layout: {id,x,y,w,h}, integer cells, zero-based x from inline-start.",
16
+ "name": "layout",
17
+ "type": "DashboardGridItemProp[]"
18
+ },
19
+ {
20
+ "description": "Uncontrolled initial layout.",
21
+ "name": "defaultLayout",
22
+ "type": "DashboardGridItemProp[]"
23
+ },
24
+ {
25
+ "description": "One callback per changed drop; Escape restores without saving.",
26
+ "name": "onLayoutChange",
27
+ "type": "(layout: DashboardGridItemProp[]) => void"
28
+ },
29
+ {
30
+ "description": "Default 12. Responsive viewport breakpoints; a single column stacks at natural content heights. Narrow projection never overwrites saved layout.",
31
+ "name": "columns",
32
+ "type": "number | { base: number; sm?: number; md?: number; lg?: number; xl?: number }"
33
+ },
34
+ {
35
+ "description": "Positive pixel row track size. Omitted uses --dashboard-grid-row-height.",
36
+ "name": "rowHeight",
37
+ "type": "number"
38
+ },
39
+ {
40
+ "description": "Default false. Inset header grip and bottom-end resize corner (on hover/focus); header space is reserved in view mode to prevent content shift. Enter/Space grab/drop, arrows move, Shift+arrows resize, Escape cancels.",
41
+ "name": "editable",
42
+ "type": "boolean"
43
+ },
44
+ {
45
+ "description": "Root class.",
46
+ "name": "className",
47
+ "type": "string"
48
+ },
49
+ {
50
+ "description": "Root id.",
51
+ "name": "id",
52
+ "type": "string"
53
+ }
54
+ ],
55
+ "related": [
56
+ "ResponsiveGrid — static flow layout.",
57
+ "SortableList — ordering without cell geometry."
58
+ ],
59
+ "rules": [
60
+ 44,
61
+ 45
62
+ ],
63
+ "storyPath": "lab/dashboard-grid.tsx",
64
+ "tagline": "BI widget layout editor with deterministic push-down collisions and vertical compaction. Static CSS grid in view mode; temporary pointer/touch/keyboard previews commit once on drop.",
65
+ "tier": "lab",
66
+ "usage": [
67
+ "C7 exception approved by the owner, BI precedents (Tableau/Power BI/Grafana/react-grid-layout). Approved 2026-10-23. Lab §2.1: same gates as core; promotion only once ≥2 repos import it.",
68
+ "Use stable unique ids and order items by reading priority. Persist only onLayoutChange.",
69
+ "Coordinates are normalized and compacted. View mode exposes content semantics, not an ARIA data grid.",
70
+ "RTL mirrors x and horizontal keyboard/pointer deltas. Touch-action none is confined to handles.",
71
+ "Theme --dashboard-grid-gap, row-height, handle-size, handle-inset, item-radius and preview-ring-color."
72
+ ],
73
+ "useCases": [
74
+ "BI dashboards with rearrangeable and resizable widgets."
75
+ ]
76
+ }
@@ -86,7 +86,7 @@
86
86
  },
87
87
  {
88
88
  "defaultValue": "'default'",
89
- "description": "Named collection contract — the SAME preset the Table primitive owns, forwarded to the table DataTable renders. 'default' emits NO attribute and matches no selector, so an existing DataTable is byte-identical. 'action-collection' is the canonical dense approval/action queue: at EVERY width the desktop INTRINSIC column widths give way to the token-owned column-PRIORITY measures (--table-action-collection-*: primary 18% · secondary 22% · meta 12% · actions a 3.5rem floor, the unmarked column takes the rest) under table-layout: fixed, and below collapseBelow they switch to the compact tier (24% · 22% · 20% · 2.75rem) — collapseBelow picks the TIER, it does not turn the measures on (gh#1408). Cells wrap, and the bordered surface drops its --table-surface-min-inline-size floor — so requester · target · reason · requested date · row actions all stay inside a 390px frame with no horizontal scroll. Mark each column with `priority` on its ColumnDef. Semantics are untouched (no display change, no role rewriting, no card swap), so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. Measured: table 1182 / 766 / 388px at 1440 / 1024 / 390, document scrollWidth === clientWidth at every width, LTR and RTL. 'stacked-record-collection' is the other direction, for a WIDE, HETEROGENEOUS record set that has no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a key-value record with a single separator between records (--table-stacked-collection-*). Each cell then carries its column's header inline above the value, DERIVED from the same ColumnDef.header the <th> uses — so the card cannot drift from the table, and a column with a deliberately empty header names itself with ariaLabel (gh#864). In card mode the row inset defaults to the live --card-space-inset, sharing the CardTitle keyline at every density and in RTL (override --table-stacked-collection-card-padding-x independently). The CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). The labels are aria-hidden: the real <th> is still in the DOM and remains the accessible-name source, so screen-reader table navigation is unchanged at every width. Reach for this instead of building a parallel Card tree beside the table; two trees for one dataset means two sets of labels to keep in sync.",
89
+ "description": "Named collection contract — the SAME preset the Table primitive owns, forwarded to the table DataTable renders. 'default' emits NO attribute and matches no selector, so an existing DataTable is byte-identical. 'action-collection' is the canonical dense approval/action queue: at EVERY width the desktop INTRINSIC column widths give way to the token-owned column-PRIORITY measures (--table-action-collection-*: primary 18% · secondary 22% · meta 12% · actions a 3.5rem floor, the unmarked column takes the rest) under table-layout: fixed, and below collapseBelow they switch to the compact tier (24% · 22% · 20% · 2.75rem) — collapseBelow picks the TIER, it does not turn the measures on (gh#1408). Cells wrap, and the bordered surface drops its --table-surface-min-inline-size floor — so requester · target · reason · requested date · row actions all stay inside a 390px frame with no horizontal scroll. Mark each column with `priority` on its ColumnDef. Semantics are untouched (no display change, no role rewriting, no card swap), so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. Measured: table 1182 / 766 / 388px at 1440 / 1024 / 390, document scrollWidth === clientWidth at every width, LTR and RTL. 'stacked-record-collection' is the other direction, for a WIDE, HETEROGENEOUS record set that has no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a key-value record with zero gap and a single separator between records (--table-stacked-collection-*; --table-stacked-collection-card-gap defaults to 0 and remains themeable). Each cell then carries its column's header inline above the value, DERIVED from the same ColumnDef.header the <th> uses — so the card cannot drift from the table, and a column with a deliberately empty header names itself with ariaLabel (gh#864). In card mode the row inset defaults to the live --card-space-inset, sharing the CardTitle keyline at every density and in RTL (override --table-stacked-collection-card-padding-x independently). The CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). The labels are aria-hidden: the real <th> is still in the DOM and remains the accessible-name source, so screen-reader table navigation is unchanged at every width. Reach for this instead of building a parallel Card tree beside the table; two trees for one dataset means two sets of labels to keep in sync.",
90
90
  "name": "preset",
91
91
  "type": "'default' | 'action-collection' | 'stacked-record-collection'"
92
92
  },
@@ -4,6 +4,11 @@
4
4
  "importPath": "@godxjp/ui/charts/heatmap-chart",
5
5
  "name": "HeatmapChart",
6
6
  "props": [
7
+ {
8
+ "description": "Opt-in pointer and Enter/Space selection. seriesKey is String(column key); index is the original data index. Arrows navigate; Home/End move to ends. Finite data only (pie: positive slices). No handler preserves the non-selectable chart. Dashboard owns filter state.",
9
+ "name": "onDatumSelect",
10
+ "type": "(datum: HeatmapDatum, context: { seriesKey: string; index: number }) => void"
11
+ },
7
12
  {
8
13
  "description": "Row categories, top to bottom (the y axis — weekdays). `label` is already translated.",
9
14
  "name": "rows",
@@ -81,6 +86,7 @@
81
86
  "storyPath": "charts/heatmap-chart.tsx",
82
87
  "tagline": "DEPENDENCY-FREE rows × columns heatmap — weekday × hour revenue / order counts, cell intensity from the sequential CVD-safe --chart-heat-1..5 ramp. Empty ≠ zero (dashed outline + 'no data' text), optional top-N ring, per-cell tooltip, APG grid keyboard, the table itself is the text alternative. Needs NO recharts. Matrix / punch card / activity heatmap / busy-hours chart.",
83
88
  "usage": [
89
+ "DO use onDatumSelect for accessible drill-through; keep filter state in the screen. Marks have localized names, roving focus and the brand ring. Line/area display points while interactive. RTL mirrors horizontal arrow navigation.",
84
90
  "DO import from the isolated entry: `import { HeatmapChart } from \"@godxjp/ui/charts/heatmap-chart\";` — it never links the optional `recharts` peer.",
85
91
  "DO derive axis labels with Intl in the active locale — weekdays via `Intl.DateTimeFormat(locale, { weekday: 'short' })`, hours via `Intl.NumberFormat(locale)` — and pass money through `numberFormat`, never a hand-built '¥' string.",
86
92
  "DO leave a slot OUT of `data` (or pass `value: null`) when there is no measurement — a closed hour, a day before the store opened. Pass `0` only for a real zero. The two render differently (dashed outline vs filled) and read differently ('No data' vs '¥0').",
@@ -4,6 +4,11 @@
4
4
  "importPath": "@godxjp/ui/charts",
5
5
  "name": "LineChart",
6
6
  "props": [
7
+ {
8
+ "description": "Opt-in pointer and Enter/Space selection. seriesKey is the series dataKey; index is the original data index. Arrows navigate; Home/End move to ends. Finite data only (pie: positive slices). No handler preserves the non-selectable chart. Dashboard owns filter state.",
9
+ "name": "onDatumSelect",
10
+ "type": "(datum: ChartDatum, context: { seriesKey: string; index: number }) => void"
11
+ },
7
12
  {
8
13
  "description": "Row data: one category per row with a numeric value per series.",
9
14
  "name": "data",
@@ -103,6 +108,7 @@
103
108
  "rules": [],
104
109
  "tagline": "Trends over an ordered category axis — one or more series, locale-formatted ticks/tooltips, screen-reader text alternative built in. Data-visualization graph / plot.",
105
110
  "usage": [
111
+ "DO use onDatumSelect for accessible drill-through; keep filter state in the screen. Marks have localized names, roving focus and the brand ring. Line/area display points while interactive. RTL mirrors horizontal arrow navigation.",
106
112
  "DO import from the tree-shaken charts entry: `import { LineChart } from \"@godxjp/ui/charts\";`. Importing any other subpath never pulls in recharts.",
107
113
  "DO import only the chart a screen uses — `import { LineChart } from \"@godxjp/ui/charts/line-chart\";` — when the `./charts` barrel should not link the whole chart family. Without the `recharts` peer the build then fails ONCE, naming the package and the fix.",
108
114
  "DO install the `recharts` optional peer dependency in the consuming app — charts are the only part of @godxjp/ui that needs it, so apps without charts never pay for it.",
@@ -109,7 +109,7 @@
109
109
  "PaginationNext",
110
110
  "PaginationPrevious"
111
111
  ],
112
- "tagline": "Offset/page-based pagination bar. Sits below a table card. Keyboard focus uses the shared inset ring in clipping surfaces; scrollports reveal partially clipped keyboard targets without changing their layout.",
112
+ "tagline": "Offset/page-based pagination bar. Its container owns the inset: no outer inline padding, including inside CardContent, CardFooter or PageContainer footer. Keyboard focus uses the shared inset ring in clipping surfaces; scrollports reveal partially clipped keyboard targets without changing their layout.",
113
113
  "usage": [
114
114
  "DO always control Pagination externally: store `value` (page) and `pageSize` in React state (or URL params), and update both in the `onValueChange(page, pageSize)` callback. Pagination is fully controlled — it has no internal state and will not move unless `value` changes.",
115
115
  "DO let Pagination hide itself for zero items and single pages (`hideOnSinglePage`, default true) — it is navigation between multiple result pages. Render it inside a table footer only in the DATA state: never during loading, empty, error, or an unmet prerequisite. Pass `hideOnSinglePage={false}` only when you still want the bar on one page to keep `showTotal` visible.",
@@ -4,6 +4,11 @@
4
4
  "importPath": "@godxjp/ui/charts",
5
5
  "name": "PieChart",
6
6
  "props": [
7
+ {
8
+ "description": "Opt-in pointer and Enter/Space selection. seriesKey is dataKey; index is the original data index. Arrows navigate; Home/End move to ends. Finite data only (pie: positive slices). No handler preserves the non-selectable chart. Dashboard owns filter state.",
9
+ "name": "onDatumSelect",
10
+ "type": "(datum: ChartDatum, context: { seriesKey: string; index: number }) => void"
11
+ },
7
12
  {
8
13
  "description": "Row data: one slice per row.",
9
14
  "name": "data",
@@ -85,6 +90,7 @@
85
90
  "rules": [],
86
91
  "tagline": "Part-to-whole composition across a small set of slices — `donut` option, localized tooltips, and a screen-reader breakdown of every slice. Data-visualization graph / diagram.",
87
92
  "usage": [
93
+ "DO use onDatumSelect for accessible drill-through; keep filter state in the screen. Marks have localized names, roving focus and the brand ring. Line/area display points while interactive. RTL mirrors horizontal arrow navigation.",
88
94
  "DO import from the charts entry: `import { PieChart } from \"@godxjp/ui/charts\";` (recharts optional peer required).",
89
95
  "DO import only the chart a screen uses — `import { PieChart } from \"@godxjp/ui/charts/pie-chart\";` — when the `./charts` barrel should not link the whole chart family. Without the `recharts` peer the build then fails ONCE, naming the package and the fix.",
90
96
  "DO keep slices few (≈2–6) — pies are unreadable past a handful; use BarChart for many categories.",
@@ -69,7 +69,7 @@
69
69
  },
70
70
  {
71
71
  "defaultValue": "\"default\"",
72
- "description": "Named collection contract. \"default\" emits no attribute and keeps the plain table. \"action-collection\" is the canonical dense approval/action queue: the desktop INTRINSIC column widths (which make a five-column queue wider than its card and force a horizontal scroll at 390) are replaced by table-layout: fixed plus the token-owned column PRIORITY measures (--table-action-collection-*), and cells wrap. Mark each column with `priority` on its TableHead AND its TableCell. Semantics are untouched — no display change, no role rewriting, no card transformation — so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. \"stacked-record-collection\" is the other direction, for a WIDE, HETEROGENEOUS record set with no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a key-value record with a single separator between records (--table-stacked-collection-*). Give each TableCell a `label` — its column header — because the <th> association it normally reads from is the thing that just went away; DataTable derives that label from ColumnDef.header for you (gh#864). In card mode the row inset defaults to the live --card-space-inset, sharing the CardTitle keyline at every density and in RTL (override --table-stacked-collection-card-padding-x independently). The CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). The label is aria-hidden and the real <th> stays in the DOM, so the accessible name and table navigation are unchanged.",
72
+ "description": "Named collection contract. \"default\" emits no attribute and keeps the plain table. \"action-collection\" is the canonical dense approval/action queue: the desktop INTRINSIC column widths (which make a five-column queue wider than its card and force a horizontal scroll at 390) are replaced by table-layout: fixed plus the token-owned column PRIORITY measures (--table-action-collection-*), and cells wrap. Mark each column with `priority` on its TableHead AND its TableCell. Semantics are untouched — no display change, no role rewriting, no card transformation — so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. \"stacked-record-collection\" is the other direction, for a WIDE, HETEROGENEOUS record set with no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a key-value record with zero gap and a single separator between records (--table-stacked-collection-*; --table-stacked-collection-card-gap defaults to 0 and remains themeable). Give each TableCell a `label` — its column header — because the <th> association it normally reads from is the thing that just went away; DataTable derives that label from ColumnDef.header for you (gh#864). In card mode the row inset defaults to the live --card-space-inset, sharing the CardTitle keyline at every density and in RTL (override --table-stacked-collection-card-padding-x independently). The CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). The label is aria-hidden and the real <th> stays in the DOM, so the accessible name and table navigation are unchanged.",
73
73
  "name": "preset",
74
74
  "type": "\"default\" | \"action-collection\" | \"stacked-record-collection\""
75
75
  },
@@ -498,7 +498,7 @@
498
498
  {
499
499
  "group": "navigation",
500
500
  "name": "Pagination",
501
- "tagline": "Offset/page-based pagination bar. Sits below a table card. Keyboard focus uses the shared inset ring in clipping surfaces; scrollports reveal partially clipped keyboard targets without changing their layout."
501
+ "tagline": "Offset/page-based pagination bar. Its container owns the inset: no outer inline padding, including inside CardContent, CardFooter or PageContainer footer. Keyboard focus uses the shared inset ring in clipping surfaces; scrollports reveal partially clipped keyboard targets without changing their layout."
502
502
  },
503
503
  {
504
504
  "group": "navigation",
@@ -777,6 +777,12 @@
777
777
  "tagline": "Page icon / reaction picker in a Popover (gh#1164): search by the active language's CLDR keywords (ja / en / vi — emojibase-data, loaded lazily for that locale only), categories, per-user recents, a WAI-ARIA grid (one tab stop, arrows, Home / End, Enter), and \"remove icon\". No skin tones.",
778
778
  "tier": "lab"
779
779
  },
780
+ {
781
+ "group": "layout",
782
+ "name": "DashboardGrid",
783
+ "tagline": "BI widget layout editor with deterministic push-down collisions and vertical compaction. Static CSS grid in view mode; temporary pointer/touch/keyboard previews commit once on drop.",
784
+ "tier": "lab"
785
+ },
780
786
  {
781
787
  "group": "data-entry",
782
788
  "name": "SortableList",
@@ -3489,7 +3489,7 @@
3489
3489
  },
3490
3490
  {
3491
3491
  "defaultValue": "'default'",
3492
- "description": "Named collection contract — the SAME preset the Table primitive owns, forwarded to the table DataTable renders. 'default' emits NO attribute and matches no selector, so an existing DataTable is byte-identical. 'action-collection' is the canonical dense approval/action queue: at EVERY width the desktop INTRINSIC column widths give way to the token-owned column-PRIORITY measures (--table-action-collection-*: primary 18% · secondary 22% · meta 12% · actions a 3.5rem floor, the unmarked column takes the rest) under table-layout: fixed, and below collapseBelow they switch to the compact tier (24% · 22% · 20% · 2.75rem) — collapseBelow picks the TIER, it does not turn the measures on (gh#1408). Cells wrap, and the bordered surface drops its --table-surface-min-inline-size floor — so requester · target · reason · requested date · row actions all stay inside a 390px frame with no horizontal scroll. Mark each column with `priority` on its ColumnDef. Semantics are untouched (no display change, no role rewriting, no card swap), so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. Measured: table 1182 / 766 / 388px at 1440 / 1024 / 390, document scrollWidth === clientWidth at every width, LTR and RTL. 'stacked-record-collection' is the other direction, for a WIDE, HETEROGENEOUS record set that has no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a key-value record with a single separator between records (--table-stacked-collection-*). Each cell then carries its column's header inline above the value, DERIVED from the same ColumnDef.header the <th> uses — so the card cannot drift from the table, and a column with a deliberately empty header names itself with ariaLabel (gh#864). In card mode the row inset defaults to the live --card-space-inset, sharing the CardTitle keyline at every density and in RTL (override --table-stacked-collection-card-padding-x independently). The CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). The labels are aria-hidden: the real <th> is still in the DOM and remains the accessible-name source, so screen-reader table navigation is unchanged at every width. Reach for this instead of building a parallel Card tree beside the table; two trees for one dataset means two sets of labels to keep in sync.",
3492
+ "description": "Named collection contract — the SAME preset the Table primitive owns, forwarded to the table DataTable renders. 'default' emits NO attribute and matches no selector, so an existing DataTable is byte-identical. 'action-collection' is the canonical dense approval/action queue: at EVERY width the desktop INTRINSIC column widths give way to the token-owned column-PRIORITY measures (--table-action-collection-*: primary 18% · secondary 22% · meta 12% · actions a 3.5rem floor, the unmarked column takes the rest) under table-layout: fixed, and below collapseBelow they switch to the compact tier (24% · 22% · 20% · 2.75rem) — collapseBelow picks the TIER, it does not turn the measures on (gh#1408). Cells wrap, and the bordered surface drops its --table-surface-min-inline-size floor — so requester · target · reason · requested date · row actions all stay inside a 390px frame with no horizontal scroll. Mark each column with `priority` on its ColumnDef. Semantics are untouched (no display change, no role rewriting, no card swap), so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. Measured: table 1182 / 766 / 388px at 1440 / 1024 / 390, document scrollWidth === clientWidth at every width, LTR and RTL. 'stacked-record-collection' is the other direction, for a WIDE, HETEROGENEOUS record set that has no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a key-value record with zero gap and a single separator between records (--table-stacked-collection-*; --table-stacked-collection-card-gap defaults to 0 and remains themeable). Each cell then carries its column's header inline above the value, DERIVED from the same ColumnDef.header the <th> uses — so the card cannot drift from the table, and a column with a deliberately empty header names itself with ariaLabel (gh#864). In card mode the row inset defaults to the live --card-space-inset, sharing the CardTitle keyline at every density and in RTL (override --table-stacked-collection-card-padding-x independently). The CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). The labels are aria-hidden: the real <th> is still in the DOM and remains the accessible-name source, so screen-reader table navigation is unchanged at every width. Reach for this instead of building a parallel Card tree beside the table; two trees for one dataset means two sets of labels to keep in sync.",
3493
3493
  "name": "preset",
3494
3494
  "type": "'default' | 'action-collection' | 'stacked-record-collection'"
3495
3495
  },
@@ -5696,7 +5696,7 @@
5696
5696
  },
5697
5697
  {
5698
5698
  "defaultValue": "\"default\"",
5699
- "description": "Named collection contract. \"default\" emits no attribute and keeps the plain table. \"action-collection\" is the canonical dense approval/action queue: the desktop INTRINSIC column widths (which make a five-column queue wider than its card and force a horizontal scroll at 390) are replaced by table-layout: fixed plus the token-owned column PRIORITY measures (--table-action-collection-*), and cells wrap. Mark each column with `priority` on its TableHead AND its TableCell. Semantics are untouched — no display change, no role rewriting, no card transformation — so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. \"stacked-record-collection\" is the other direction, for a WIDE, HETEROGENEOUS record set with no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a key-value record with a single separator between records (--table-stacked-collection-*). Give each TableCell a `label` — its column header — because the <th> association it normally reads from is the thing that just went away; DataTable derives that label from ColumnDef.header for you (gh#864). In card mode the row inset defaults to the live --card-space-inset, sharing the CardTitle keyline at every density and in RTL (override --table-stacked-collection-card-padding-x independently). The CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). The label is aria-hidden and the real <th> stays in the DOM, so the accessible name and table navigation are unchanged.",
5699
+ "description": "Named collection contract. \"default\" emits no attribute and keeps the plain table. \"action-collection\" is the canonical dense approval/action queue: the desktop INTRINSIC column widths (which make a five-column queue wider than its card and force a horizontal scroll at 390) are replaced by table-layout: fixed plus the token-owned column PRIORITY measures (--table-action-collection-*), and cells wrap. Mark each column with `priority` on its TableHead AND its TableCell. Semantics are untouched — no display change, no role rewriting, no card transformation — so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. \"stacked-record-collection\" is the other direction, for a WIDE, HETEROGENEOUS record set with no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a key-value record with zero gap and a single separator between records (--table-stacked-collection-*; --table-stacked-collection-card-gap defaults to 0 and remains themeable). Give each TableCell a `label` — its column header — because the <th> association it normally reads from is the thing that just went away; DataTable derives that label from ColumnDef.header for you (gh#864). In card mode the row inset defaults to the live --card-space-inset, sharing the CardTitle keyline at every density and in RTL (override --table-stacked-collection-card-padding-x independently). The CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). The label is aria-hidden and the real <th> stays in the DOM, so the accessible name and table navigation are unchanged.",
5700
5700
  "name": "preset",
5701
5701
  "type": "\"default\" | \"action-collection\" | \"stacked-record-collection\""
5702
5702
  },
@@ -8834,7 +8834,7 @@
8834
8834
  "PaginationNext",
8835
8835
  "PaginationPrevious"
8836
8836
  ],
8837
- "tagline": "Offset/page-based pagination bar. Sits below a table card. Keyboard focus uses the shared inset ring in clipping surfaces; scrollports reveal partially clipped keyboard targets without changing their layout.",
8837
+ "tagline": "Offset/page-based pagination bar. Its container owns the inset: no outer inline padding, including inside CardContent, CardFooter or PageContainer footer. Keyboard focus uses the shared inset ring in clipping surfaces; scrollports reveal partially clipped keyboard targets without changing their layout.",
8838
8838
  "usage": [
8839
8839
  "DO always control Pagination externally: store `value` (page) and `pageSize` in React state (or URL params), and update both in the `onValueChange(page, pageSize)` callback. Pagination is fully controlled — it has no internal state and will not move unless `value` changes.",
8840
8840
  "DO let Pagination hide itself for zero items and single pages (`hideOnSinglePage`, default true) — it is navigation between multiple result pages. Render it inside a table footer only in the DATA state: never during loading, empty, error, or an unmet prerequisite. Pass `hideOnSinglePage={false}` only when you still want the bar on one page to keep `showTotal` visible.",
@@ -13557,6 +13557,11 @@
13557
13557
  "importPath": "@godxjp/ui/charts",
13558
13558
  "name": "LineChart",
13559
13559
  "props": [
13560
+ {
13561
+ "description": "Opt-in pointer and Enter/Space selection. seriesKey is the series dataKey; index is the original data index. Arrows navigate; Home/End move to ends. Finite data only (pie: positive slices). No handler preserves the non-selectable chart. Dashboard owns filter state.",
13562
+ "name": "onDatumSelect",
13563
+ "type": "(datum: ChartDatum, context: { seriesKey: string; index: number }) => void"
13564
+ },
13560
13565
  {
13561
13566
  "description": "Row data: one category per row with a numeric value per series.",
13562
13567
  "name": "data",
@@ -13656,6 +13661,7 @@
13656
13661
  "rules": [],
13657
13662
  "tagline": "Trends over an ordered category axis — one or more series, locale-formatted ticks/tooltips, screen-reader text alternative built in. Data-visualization graph / plot.",
13658
13663
  "usage": [
13664
+ "DO use onDatumSelect for accessible drill-through; keep filter state in the screen. Marks have localized names, roving focus and the brand ring. Line/area display points while interactive. RTL mirrors horizontal arrow navigation.",
13659
13665
  "DO import from the tree-shaken charts entry: `import { LineChart } from \"@godxjp/ui/charts\";`. Importing any other subpath never pulls in recharts.",
13660
13666
  "DO import only the chart a screen uses — `import { LineChart } from \"@godxjp/ui/charts/line-chart\";` — when the `./charts` barrel should not link the whole chart family. Without the `recharts` peer the build then fails ONCE, naming the package and the fix.",
13661
13667
  "DO install the `recharts` optional peer dependency in the consuming app — charts are the only part of @godxjp/ui that needs it, so apps without charts never pay for it.",
@@ -13677,6 +13683,11 @@
13677
13683
  "importPath": "@godxjp/ui/charts",
13678
13684
  "name": "BarChart",
13679
13685
  "props": [
13686
+ {
13687
+ "description": "Opt-in pointer and Enter/Space selection. seriesKey is the series dataKey; index is the original data index. Arrows navigate; Home/End move to ends. Finite data only (pie: positive slices). No handler preserves the non-selectable chart. Dashboard owns filter state.",
13688
+ "name": "onDatumSelect",
13689
+ "type": "(datum: ChartDatum, context: { seriesKey: string; index: number }) => void"
13690
+ },
13680
13691
  {
13681
13692
  "description": "Row data: one category per row with a numeric value per series.",
13682
13693
  "name": "data",
@@ -13776,6 +13787,7 @@
13776
13787
  "rules": [],
13777
13788
  "tagline": "Compare a value across categories — grouped or `stacked`, vertical or `horizontal`, with localized ticks/tooltips and a built-in text alternative. Data-visualization graph / plot / diagram.",
13778
13789
  "usage": [
13790
+ "DO use onDatumSelect for accessible drill-through; keep filter state in the screen. Marks have localized names, roving focus and the brand ring. Line/area display points while interactive. RTL mirrors horizontal arrow navigation.",
13779
13791
  "DO import from the charts entry: `import { BarChart } from \"@godxjp/ui/charts\";` (recharts optional peer required).",
13780
13792
  "DO import only the chart a screen uses — `import { BarChart } from \"@godxjp/ui/charts/bar-chart\";` — when the `./charts` barrel should not link the whole chart family. Without the `recharts` peer the build then fails ONCE, naming the package and the fix.",
13781
13793
  "DO use `horizontal` when category labels are long (they read better on the y-axis).",
@@ -13895,6 +13907,11 @@
13895
13907
  "importPath": "@godxjp/ui/charts/heatmap-chart",
13896
13908
  "name": "HeatmapChart",
13897
13909
  "props": [
13910
+ {
13911
+ "description": "Opt-in pointer and Enter/Space selection. seriesKey is String(column key); index is the original data index. Arrows navigate; Home/End move to ends. Finite data only (pie: positive slices). No handler preserves the non-selectable chart. Dashboard owns filter state.",
13912
+ "name": "onDatumSelect",
13913
+ "type": "(datum: HeatmapDatum, context: { seriesKey: string; index: number }) => void"
13914
+ },
13898
13915
  {
13899
13916
  "description": "Row categories, top to bottom (the y axis — weekdays). `label` is already translated.",
13900
13917
  "name": "rows",
@@ -13972,6 +13989,7 @@
13972
13989
  "storyPath": "charts/heatmap-chart.tsx",
13973
13990
  "tagline": "DEPENDENCY-FREE rows × columns heatmap — weekday × hour revenue / order counts, cell intensity from the sequential CVD-safe --chart-heat-1..5 ramp. Empty ≠ zero (dashed outline + 'no data' text), optional top-N ring, per-cell tooltip, APG grid keyboard, the table itself is the text alternative. Needs NO recharts. Matrix / punch card / activity heatmap / busy-hours chart.",
13974
13991
  "usage": [
13992
+ "DO use onDatumSelect for accessible drill-through; keep filter state in the screen. Marks have localized names, roving focus and the brand ring. Line/area display points while interactive. RTL mirrors horizontal arrow navigation.",
13975
13993
  "DO import from the isolated entry: `import { HeatmapChart } from \"@godxjp/ui/charts/heatmap-chart\";` — it never links the optional `recharts` peer.",
13976
13994
  "DO derive axis labels with Intl in the active locale — weekdays via `Intl.DateTimeFormat(locale, { weekday: 'short' })`, hours via `Intl.NumberFormat(locale)` — and pass money through `numberFormat`, never a hand-built '¥' string.",
13977
13995
  "DO leave a slot OUT of `data` (or pass `value: null`) when there is no measurement — a closed hour, a day before the store opened. Pass `0` only for a real zero. The two render differently (dashed outline vs filled) and read differently ('No data' vs '¥0').",
@@ -13992,6 +14010,11 @@
13992
14010
  "importPath": "@godxjp/ui/charts",
13993
14011
  "name": "AreaChart",
13994
14012
  "props": [
14013
+ {
14014
+ "description": "Opt-in pointer and Enter/Space selection. seriesKey is the series dataKey; index is the original data index. Arrows navigate; Home/End move to ends. Finite data only (pie: positive slices). No handler preserves the non-selectable chart. Dashboard owns filter state.",
14015
+ "name": "onDatumSelect",
14016
+ "type": "(datum: ChartDatum, context: { seriesKey: string; index: number }) => void"
14017
+ },
13995
14018
  {
13996
14019
  "description": "Row data: one category per row with a numeric value per series.",
13997
14020
  "name": "data",
@@ -14096,6 +14119,7 @@
14096
14119
  "rules": [],
14097
14120
  "tagline": "Magnitude over an ordered category axis — overlay or `stacked` areas, optional `curved` smoothing, localized formatting + text alternative. Data-visualization graph / plot.",
14098
14121
  "usage": [
14122
+ "DO use onDatumSelect for accessible drill-through; keep filter state in the screen. Marks have localized names, roving focus and the brand ring. Line/area display points while interactive. RTL mirrors horizontal arrow navigation.",
14099
14123
  "DO import from the charts entry: `import { AreaChart } from \"@godxjp/ui/charts\";` (recharts optional peer required).",
14100
14124
  "DO import only the chart a screen uses — `import { AreaChart } from \"@godxjp/ui/charts/area-chart\";` — when the `./charts` barrel should not link the whole chart family. Without the `recharts` peer the build then fails ONCE, naming the package and the fix.",
14101
14125
  "DO use `stacked` to show how parts accumulate into a total over time.",
@@ -14114,6 +14138,11 @@
14114
14138
  "importPath": "@godxjp/ui/charts",
14115
14139
  "name": "PieChart",
14116
14140
  "props": [
14141
+ {
14142
+ "description": "Opt-in pointer and Enter/Space selection. seriesKey is dataKey; index is the original data index. Arrows navigate; Home/End move to ends. Finite data only (pie: positive slices). No handler preserves the non-selectable chart. Dashboard owns filter state.",
14143
+ "name": "onDatumSelect",
14144
+ "type": "(datum: ChartDatum, context: { seriesKey: string; index: number }) => void"
14145
+ },
14117
14146
  {
14118
14147
  "description": "Row data: one slice per row.",
14119
14148
  "name": "data",
@@ -14195,6 +14224,7 @@
14195
14224
  "rules": [],
14196
14225
  "tagline": "Part-to-whole composition across a small set of slices — `donut` option, localized tooltips, and a screen-reader breakdown of every slice. Data-visualization graph / diagram.",
14197
14226
  "usage": [
14227
+ "DO use onDatumSelect for accessible drill-through; keep filter state in the screen. Marks have localized names, roving focus and the brand ring. Line/area display points while interactive. RTL mirrors horizontal arrow navigation.",
14198
14228
  "DO import from the charts entry: `import { PieChart } from \"@godxjp/ui/charts\";` (recharts optional peer required).",
14199
14229
  "DO import only the chart a screen uses — `import { PieChart } from \"@godxjp/ui/charts/pie-chart\";` — when the `./charts` barrel should not link the whole chart family. Without the `recharts` peer the build then fails ONCE, naming the package and the fix.",
14200
14230
  "DO keep slices few (≈2–6) — pies are unreadable past a handful; use BarChart for many categories.",
@@ -14386,6 +14416,82 @@
14386
14416
  "The data loads on first open (one locale, ~100 KB gzip); nothing ships in your main bundle."
14387
14417
  ]
14388
14418
  },
14419
+ {
14420
+ "docPath": "docs/lab/dashboard-grid.tsx",
14421
+ "example": "import { DashboardGrid } from \"@godxjp/ui/lab\";\n\n<DashboardGrid items={[{ id: \"revenue\", label: \"Revenue\", content: \"Revenue\" }]} defaultLayout={[{ id: \"revenue\", x: 0, y: 0, w: 2, h: 3 }]} columns={{ base: 1, lg: 4 }} editable />",
14422
+ "group": "layout",
14423
+ "importPath": "@godxjp/ui/lab",
14424
+ "name": "DashboardGrid",
14425
+ "props": [
14426
+ {
14427
+ "description": "Stable ids, visible header labels (also accessible region names) and widget body content. Wrap padded bodies in CardContent, tables in CardContent flush; DashboardGrid owns the Card and header. DOM reading order remains items order.",
14428
+ "name": "items",
14429
+ "required": true,
14430
+ "type": "{ id: string; label: string; content: ReactNode }[]"
14431
+ },
14432
+ {
14433
+ "description": "Controlled layout: {id,x,y,w,h}, integer cells, zero-based x from inline-start.",
14434
+ "name": "layout",
14435
+ "type": "DashboardGridItemProp[]"
14436
+ },
14437
+ {
14438
+ "description": "Uncontrolled initial layout.",
14439
+ "name": "defaultLayout",
14440
+ "type": "DashboardGridItemProp[]"
14441
+ },
14442
+ {
14443
+ "description": "One callback per changed drop; Escape restores without saving.",
14444
+ "name": "onLayoutChange",
14445
+ "type": "(layout: DashboardGridItemProp[]) => void"
14446
+ },
14447
+ {
14448
+ "description": "Default 12. Responsive viewport breakpoints; a single column stacks at natural content heights. Narrow projection never overwrites saved layout.",
14449
+ "name": "columns",
14450
+ "type": "number | { base: number; sm?: number; md?: number; lg?: number; xl?: number }"
14451
+ },
14452
+ {
14453
+ "description": "Positive pixel row track size. Omitted uses --dashboard-grid-row-height.",
14454
+ "name": "rowHeight",
14455
+ "type": "number"
14456
+ },
14457
+ {
14458
+ "description": "Default false. Inset header grip and bottom-end resize corner (on hover/focus); header space is reserved in view mode to prevent content shift. Enter/Space grab/drop, arrows move, Shift+arrows resize, Escape cancels.",
14459
+ "name": "editable",
14460
+ "type": "boolean"
14461
+ },
14462
+ {
14463
+ "description": "Root class.",
14464
+ "name": "className",
14465
+ "type": "string"
14466
+ },
14467
+ {
14468
+ "description": "Root id.",
14469
+ "name": "id",
14470
+ "type": "string"
14471
+ }
14472
+ ],
14473
+ "related": [
14474
+ "ResponsiveGrid — static flow layout.",
14475
+ "SortableList — ordering without cell geometry."
14476
+ ],
14477
+ "rules": [
14478
+ 44,
14479
+ 45
14480
+ ],
14481
+ "storyPath": "lab/dashboard-grid.tsx",
14482
+ "tagline": "BI widget layout editor with deterministic push-down collisions and vertical compaction. Static CSS grid in view mode; temporary pointer/touch/keyboard previews commit once on drop.",
14483
+ "tier": "lab",
14484
+ "usage": [
14485
+ "C7 exception approved by the owner, BI precedents (Tableau/Power BI/Grafana/react-grid-layout). Approved 2026-10-23. Lab §2.1: same gates as core; promotion only once ≥2 repos import it.",
14486
+ "Use stable unique ids and order items by reading priority. Persist only onLayoutChange.",
14487
+ "Coordinates are normalized and compacted. View mode exposes content semantics, not an ARIA data grid.",
14488
+ "RTL mirrors x and horizontal keyboard/pointer deltas. Touch-action none is confined to handles.",
14489
+ "Theme --dashboard-grid-gap, row-height, handle-size, handle-inset, item-radius and preview-ring-color."
14490
+ ],
14491
+ "useCases": [
14492
+ "BI dashboards with rearrangeable and resizable widgets."
14493
+ ]
14494
+ },
14389
14495
  {
14390
14496
  "docPath": "docs/data-entry/sortable-list.tsx",
14391
14497
  "example": "import { SortableList } from \"@godxjp/ui/lab\";\n\n<SortableList\n aria-label=\"Widgets\"\n items={[{ value: \"cal\", label: \"Calendar\" }, { value: \"mail\", label: \"Mail\" }]}\n value={order}\n onValueChange={setOrder}\n/>",
package/agent/index.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "counts": {
3
3
  "anti-ai-tells": 35,
4
- "components": 170,
4
+ "components": 171,
5
5
  "patterns": 28,
6
6
  "rules": 44,
7
- "tokens": 2251,
7
+ "tokens": 2257,
8
8
  "vocabulary": 15
9
9
  },
10
10
  "design": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/DESIGN.md",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  {
18
18
  "file": "components-index.json",
19
- "note": "53 KB — name + group + tagline for all 170. FETCH THIS FIRST, then fetch only the components you chose.",
19
+ "note": "54 KB — name + group + tagline for all 171. FETCH THIS FIRST, then fetch only the components you chose.",
20
20
  "url": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json"
21
21
  },
22
22
  {
@@ -54,19 +54,19 @@
54
54
  "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.",
55
55
  "read": {
56
56
  "live": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/index.json",
57
- "pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v33.15.0/agent/index.json"
57
+ "pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v33.16.0/agent/index.json"
58
58
  },
59
59
  "source": "mcp/src/data — the same data @godxjp/ui-mcp serves — plus the foundation and semantic token tiers, read from src/tokens/*.css",
60
60
  "start": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/START-HERE.md",
61
61
  "tokenTiers": {
62
62
  "component": "per-part knobs, --{component}-{part}-{property}; usually leave these alone",
63
63
  "counts": {
64
- "component": 1920,
64
+ "component": 1926,
65
65
  "foundation": 218,
66
66
  "semantic": 113
67
67
  },
68
68
  "foundation": "the seeds a consumer is invited to set — --primary, --background, --radius",
69
69
  "semantic": "named roles that follow the seeds — --ring, --text-link, --overlay-background"
70
70
  },
71
- "version": "33.15.0"
71
+ "version": "33.16.0"
72
72
  }