@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
@@ -8,6 +8,9 @@ function assertRechartsPeer() {
8
8
  }
9
9
  }
10
10
  const {
11
+ Dot,
12
+ Rectangle,
13
+ Sector,
11
14
  Area,
12
15
  AreaChart,
13
16
  Bar,
@@ -31,13 +34,16 @@ export {
31
34
  BarChart,
32
35
  CartesianGrid,
33
36
  Cell,
37
+ Dot,
34
38
  Legend,
35
39
  Line,
36
40
  LineChart,
37
41
  Pie,
38
42
  PieChart,
39
43
  RECHARTS_PEER_MESSAGE,
44
+ Rectangle,
40
45
  ResponsiveContainer,
46
+ Sector,
41
47
  Tooltip,
42
48
  XAxis,
43
49
  YAxis,
@@ -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": "33.15.0",
3
+ "version": "33.16.0",
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,
@@ -797,6 +797,7 @@
797
797
  }
798
798
  },
799
799
  "chart": {
800
+ "datumLabel": "{label}, {series}: {value}",
800
801
  "empty": "No data to display",
801
802
  "summaryCartesian": "Chart with {series} series across {points} data points",
802
803
  "summaryPie": "Pie chart with {slices} slices",
@@ -868,5 +869,14 @@
868
869
  "error": "failed"
869
870
  }
870
871
  }
872
+ },
873
+ "dashboardGrid": {
874
+ "move": "Move {label}",
875
+ "resize": "Resize {label}",
876
+ "hint": "Enter or Space grabs and drops. Arrow keys move; Shift and arrows resize. Escape cancels.",
877
+ "grabbed": "Grabbed {label}. Column {x}, row {y}, width {w}, height {h}.",
878
+ "moved": "{label}. Column {x}, row {y}, width {w}, height {h}.",
879
+ "dropped": "Saved {label}. Column {x}, row {y}, width {w}, height {h}.",
880
+ "cancelled": "Cancelled changes to {label}."
871
881
  }
872
882
  }
@@ -771,6 +771,7 @@
771
771
  }
772
772
  },
773
773
  "chart": {
774
+ "datumLabel": "{label}, {series}: {value}",
774
775
  "empty": "データがありません",
775
776
  "summaryCartesian": "{series}系列・{points}データ点のグラフ",
776
777
  "summaryPie": "{slices}区分の円グラフ",
@@ -841,5 +842,14 @@
841
842
  "error": "失敗"
842
843
  }
843
844
  }
845
+ },
846
+ "dashboardGrid": {
847
+ "move": "{label}を移動",
848
+ "resize": "{label}のサイズ変更",
849
+ "hint": "Enter またはスペースでつかむ・確定。矢印キーで移動、Shift と矢印でサイズ変更。Escape で取り消します。",
850
+ "grabbed": "{label}をつかみました。列{x}、行{y}、幅{w}、高さ{h}。",
851
+ "moved": "{label}。列{x}、行{y}、幅{w}、高さ{h}。",
852
+ "dropped": "{label}を保存しました。列{x}、行{y}、幅{w}、高さ{h}。",
853
+ "cancelled": "{label}の変更を取り消しました。"
844
854
  }
845
855
  }
@@ -772,6 +772,7 @@
772
772
  }
773
773
  },
774
774
  "chart": {
775
+ "datumLabel": "{label}, {series}: {value}",
775
776
  "empty": "Không có dữ liệu",
776
777
  "summaryCartesian": "Biểu đồ gồm {series} chuỗi trên {points} điểm dữ liệu",
777
778
  "summaryPie": "Biểu đồ tròn gồm {slices} phần",
@@ -842,5 +843,14 @@
842
843
  "error": "thất bại"
843
844
  }
844
845
  }
846
+ },
847
+ "dashboardGrid": {
848
+ "move": "Di chuyển {label}",
849
+ "resize": "Đổi kích thước {label}",
850
+ "hint": "Enter hoặc Space để nắm và thả. Phím mũi tên để di chuyển; Shift và mũi tên để đổi kích thước. Escape để hủy.",
851
+ "grabbed": "Đã nắm {label}. Cột {x}, hàng {y}, rộng {w}, cao {h}.",
852
+ "moved": "{label}. Cột {x}, hàng {y}, rộng {w}, cao {h}.",
853
+ "dropped": "Đã lưu {label}. Cột {x}, hàng {y}, rộng {w}, cao {h}.",
854
+ "cancelled": "Đã hủy thay đổi {label}."
845
855
  }
846
856
  }
@@ -0,0 +1,4 @@
1
+ import type { DashboardGridItemProp } from "../props/components/dashboard-grid.prop.js";
2
+ export declare const gridColumns: (value: number) => number;
3
+ /** Active tile wins. Others push down in stable visual order, then compact upward without overlap. */
4
+ export declare function resolveDashboardLayout(layout: readonly DashboardGridItemProp[], columns: number, active?: string): DashboardGridItemProp[];
@@ -0,0 +1,36 @@
1
+ const integer = (value, fallback) => Number.isFinite(value) ? Math.trunc(value) : fallback;
2
+ const gridColumns = (value) => Math.max(1, integer(value, 1));
3
+ const overlaps = (a, b) => a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
4
+ function resolveDashboardLayout(layout, columns, active) {
5
+ const count = gridColumns(columns);
6
+ const normalized = layout.map((item) => {
7
+ const w = Math.min(count, Math.max(1, integer(item.w, 1)));
8
+ return {
9
+ ...item,
10
+ w,
11
+ h: Math.max(1, integer(item.h, 1)),
12
+ x: Math.max(0, Math.min(count - w, integer(item.x, 0))),
13
+ y: Math.max(0, integer(item.y, 0))
14
+ };
15
+ });
16
+ const sorted = normalized.slice().sort((a, b) => a.y - b.y || a.x - b.x);
17
+ const held = normalized.find((item) => item.id === active);
18
+ const placed = held ? [held] : [];
19
+ for (const item of sorted) {
20
+ if (item === held) continue;
21
+ let collision;
22
+ while (collision = placed.find((other) => overlaps(item, other)))
23
+ item.y = collision.y + collision.h;
24
+ while (item.y > 0 && !placed.some((other) => overlaps({ ...item, y: item.y - 1 }, other)))
25
+ item.y--;
26
+ placed.push(item);
27
+ }
28
+ if (held)
29
+ while (held.y > 0 && !placed.some((other) => other !== held && overlaps({ ...held, y: held.y - 1 }, other)))
30
+ held.y--;
31
+ return normalized;
32
+ }
33
+ export {
34
+ gridColumns,
35
+ resolveDashboardLayout
36
+ };
@@ -0,0 +1,5 @@
1
+ import * as React from "react";
2
+ import type { DashboardGridProp } from "../props/components/dashboard-grid.prop.js";
3
+ export type { DashboardGridItemProp, DashboardGridProp, DashboardGridProp as DashboardGridProps, } from "../props/components/dashboard-grid.prop.js";
4
+ /** Optional BI layout editor. DOM reading order remains items order; x starts at inline-start. */
5
+ export declare const DashboardGrid: React.ForwardRefExoticComponent<DashboardGridProp & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,258 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { GripVertical } from "lucide-react";
5
+ import { Card, CardHeader, CardTitle } from "../components/data-display/card.js";
6
+ import { Button } from "../components/general/button.js";
7
+ import { useTranslation } from "../i18n/use-translation.js";
8
+ import { useMediaQuery } from "../lib/hooks.js";
9
+ import { cn } from "../lib/utils.js";
10
+ import { gridColumns, resolveDashboardLayout } from "./dashboard-grid-layout.js";
11
+ const DashboardGrid = React.forwardRef(
12
+ function DashboardGrid2({
13
+ items,
14
+ layout,
15
+ defaultLayout,
16
+ onLayoutChange,
17
+ columns = 12,
18
+ rowHeight,
19
+ editable = false,
20
+ className,
21
+ ...props
22
+ }, ref) {
23
+ const { t, locale } = useTranslation();
24
+ const sm = useMediaQuery("(min-width: 40rem)");
25
+ const md = useMediaQuery("(min-width: 48rem)");
26
+ const lg = useMediaQuery("(min-width: 64rem)");
27
+ const xl = useMediaQuery("(min-width: 80rem)");
28
+ const count = gridColumns(
29
+ typeof columns === "number" ? columns : xl && columns.xl || lg && columns.lg || md && columns.md || sm && columns.sm || columns.base
30
+ );
31
+ const [inner, setInner] = React.useState(defaultLayout ?? []);
32
+ const source = layout ?? inner;
33
+ const committed = resolveDashboardLayout(
34
+ items.map(
35
+ (item, index) => source.find((entry) => entry.id === item.id) ?? {
36
+ id: item.id,
37
+ x: 0,
38
+ y: index,
39
+ w: 1,
40
+ h: 1
41
+ }
42
+ ),
43
+ count
44
+ );
45
+ const root = React.useRef(null);
46
+ const session = React.useRef(null);
47
+ const [preview, setPreview] = React.useState(null);
48
+ const [announcement, announce] = React.useState("");
49
+ const hint = React.useId();
50
+ const format = new Intl.NumberFormat(locale);
51
+ const speak = (action, entries, id) => {
52
+ const item = entries.find((entry) => entry.id === id);
53
+ if (!item) return;
54
+ announce(
55
+ t(`dashboardGrid.${action}`, {
56
+ label: items.find((entry) => entry.id === id)?.label ?? id,
57
+ x: format.format(item.x + 1),
58
+ y: format.format(item.y + 1),
59
+ w: format.format(item.w),
60
+ h: format.format(item.h)
61
+ })
62
+ );
63
+ };
64
+ const begin = (id) => {
65
+ const next = committed.map((item) => ({ ...item }));
66
+ session.current = { id, base: next, next };
67
+ setPreview(next);
68
+ speak("grabbed", next, id);
69
+ };
70
+ const finish = (cancel) => {
71
+ const current = session.current;
72
+ if (!current) return;
73
+ session.current = null;
74
+ setPreview(null);
75
+ speak(cancel ? "cancelled" : "dropped", cancel ? current.base : current.next, current.id);
76
+ if (!cancel && JSON.stringify(current.base) !== JSON.stringify(current.next)) {
77
+ if (layout === void 0) setInner(current.next);
78
+ onLayoutChange?.(current.next);
79
+ }
80
+ };
81
+ const update = (dx, dy, resize, fromBase = false) => {
82
+ const current = session.current;
83
+ if (!current) return;
84
+ current.next = resolveDashboardLayout(
85
+ (fromBase ? current.base : current.next).map(
86
+ (item) => item.id !== current.id ? item : resize ? { ...item, w: item.w + dx, h: item.h + dy } : { ...item, x: item.x + dx, y: item.y + dy }
87
+ ),
88
+ count,
89
+ current.id
90
+ );
91
+ setPreview(current.next);
92
+ speak("moved", current.next, current.id);
93
+ };
94
+ React.useEffect(() => {
95
+ session.current = null;
96
+ setPreview(null);
97
+ }, [layout, columns, count, editable, items]);
98
+ const latest = React.useRef({ finish, update });
99
+ latest.current = { finish, update };
100
+ React.useEffect(() => {
101
+ const move = (event) => {
102
+ const pointer = session.current?.pointer;
103
+ if (!pointer || event.pointerId !== pointer.id) return;
104
+ event.preventDefault();
105
+ latest.current.update(
106
+ Math.round((event.clientX - pointer.x) / pointer.stepX) * (pointer.rtl ? -1 : 1),
107
+ Math.round((event.clientY - pointer.y) / pointer.stepY),
108
+ pointer.resize,
109
+ true
110
+ );
111
+ };
112
+ const end = (event) => {
113
+ if (session.current?.pointer?.id === event.pointerId)
114
+ latest.current.finish(event.type === "pointercancel");
115
+ };
116
+ const escape = (event) => {
117
+ if (event.key === "Escape" && session.current) {
118
+ event.preventDefault();
119
+ latest.current.finish(true);
120
+ }
121
+ };
122
+ window.addEventListener("pointermove", move, { passive: false });
123
+ window.addEventListener("pointerup", end);
124
+ window.addEventListener("pointercancel", end);
125
+ window.addEventListener("keydown", escape);
126
+ return () => {
127
+ window.removeEventListener("pointermove", move);
128
+ window.removeEventListener("pointerup", end);
129
+ window.removeEventListener("pointercancel", end);
130
+ window.removeEventListener("keydown", escape);
131
+ };
132
+ }, []);
133
+ const pointerDown = (id, resize) => (event) => {
134
+ if (!editable || event.button !== 0 || session.current || !root.current) return;
135
+ event.preventDefault();
136
+ event.currentTarget.focus();
137
+ const css = getComputedStyle(root.current);
138
+ const gap = parseFloat(css.columnGap) || 0;
139
+ begin(id);
140
+ session.current.pointer = {
141
+ id: event.pointerId,
142
+ x: event.clientX,
143
+ y: event.clientY,
144
+ stepX: (root.current.clientWidth + gap) / count,
145
+ stepY: (parseFloat(css.gridAutoRows) || rowHeight || 80) + (parseFloat(css.rowGap) || 0),
146
+ rtl: css.direction === "rtl",
147
+ resize
148
+ };
149
+ };
150
+ const keyDown = (id) => (event) => {
151
+ if (event.key === "Enter" || event.key === " ") {
152
+ event.preventDefault();
153
+ if (!session.current) begin(id);
154
+ else if (session.current.id === id) finish(false);
155
+ return;
156
+ }
157
+ if (session.current?.id !== id || !event.key.startsWith("Arrow")) return;
158
+ event.preventDefault();
159
+ const rtl = root.current && getComputedStyle(root.current).direction === "rtl";
160
+ update(
161
+ (event.key === "ArrowRight" ? 1 : event.key === "ArrowLeft" ? -1 : 0) * (rtl ? -1 : 1),
162
+ event.key === "ArrowDown" ? 1 : event.key === "ArrowUp" ? -1 : 0,
163
+ event.shiftKey
164
+ );
165
+ };
166
+ const shown = preview ?? committed;
167
+ return /* @__PURE__ */ jsxs("div", { ...props, ref, className: cn("ui-dashboard-grid", className), children: [
168
+ /* @__PURE__ */ jsx(
169
+ "div",
170
+ {
171
+ ref: root,
172
+ className: "ui-dashboard-grid-items",
173
+ "data-stacked": count === 1 || void 0,
174
+ style: {
175
+ "--dashboard-grid-columns": count,
176
+ ...rowHeight && Number.isFinite(rowHeight) && rowHeight > 0 ? { "--dashboard-grid-row-height": `${rowHeight}px` } : {}
177
+ },
178
+ children: items.map((item) => {
179
+ const box = shown.find((entry) => entry.id === item.id) ?? committed.find((entry) => entry.id === item.id);
180
+ const held = session.current?.id === item.id;
181
+ return /* @__PURE__ */ jsx(
182
+ "section",
183
+ {
184
+ "aria-label": item.label,
185
+ className: "ui-dashboard-grid-item",
186
+ "data-dashboard-id": item.id,
187
+ "data-x": box.x,
188
+ "data-y": box.y,
189
+ "data-w": box.w,
190
+ "data-h": box.h,
191
+ "data-editable": editable || void 0,
192
+ "data-held": held || void 0,
193
+ style: {
194
+ gridColumn: `${box.x + 1} / span ${box.w}`,
195
+ gridRow: count === 1 ? "auto" : `${box.y + 1} / span ${box.h}`
196
+ },
197
+ children: /* @__PURE__ */ jsxs(Card, { className: "ui-dashboard-grid-surface", children: [
198
+ /* @__PURE__ */ jsx(CardHeader, { className: "ui-dashboard-grid-header", children: /* @__PURE__ */ jsx(CardTitle, { children: item.label }) }),
199
+ editable && /* @__PURE__ */ jsx(
200
+ Button,
201
+ {
202
+ variant: "ghost",
203
+ size: "icon-sm",
204
+ className: "ui-dashboard-grid-move",
205
+ "aria-label": t("dashboardGrid.move", { label: item.label }),
206
+ "aria-describedby": hint,
207
+ "aria-pressed": held,
208
+ onPointerDown: pointerDown(item.id, false),
209
+ onKeyDown: keyDown(item.id),
210
+ onBlur: () => {
211
+ if (!session.current?.pointer) finish(true);
212
+ },
213
+ children: /* @__PURE__ */ jsx(GripVertical, { "aria-hidden": "true" })
214
+ }
215
+ ),
216
+ /* @__PURE__ */ jsx("div", { className: "ui-dashboard-grid-content", children: item.content }),
217
+ editable && /* @__PURE__ */ jsx(
218
+ Button,
219
+ {
220
+ variant: "ghost",
221
+ size: "icon-sm",
222
+ className: "ui-dashboard-grid-resize",
223
+ "aria-label": t("dashboardGrid.resize", { label: item.label }),
224
+ "aria-describedby": hint,
225
+ "aria-pressed": held,
226
+ onPointerDown: pointerDown(item.id, true),
227
+ onKeyDown: keyDown(item.id),
228
+ onBlur: () => {
229
+ if (!session.current?.pointer) finish(true);
230
+ },
231
+ children: /* @__PURE__ */ jsx(
232
+ "svg",
233
+ {
234
+ viewBox: "0 0 24 24",
235
+ fill: "none",
236
+ stroke: "currentColor",
237
+ strokeWidth: "1.5",
238
+ "aria-hidden": "true",
239
+ children: /* @__PURE__ */ jsx("path", { d: "M8 20 20 8M14 20 20 14" })
240
+ }
241
+ )
242
+ }
243
+ )
244
+ ] })
245
+ },
246
+ item.id
247
+ );
248
+ })
249
+ }
250
+ ),
251
+ /* @__PURE__ */ jsx("span", { id: hint, className: "sr-only", children: t("dashboardGrid.hint") }),
252
+ /* @__PURE__ */ jsx("span", { role: "status", "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: announcement })
253
+ ] });
254
+ }
255
+ );
256
+ export {
257
+ DashboardGrid
258
+ };
@@ -37,3 +37,5 @@ export { MegaMenu } from "./mega-menu.js";
37
37
  export type { MegaMenuProp, MegaMenuProps, MegaMenuItemProp, MegaMenuItemProps, MegaMenuPanelProp, MegaMenuPanelProps, MegaMenuGroupProp, MegaMenuGroupProps, MegaMenuLinkProp, MegaMenuLinkProps, MegaMenuLinkComponentProp, MegaMenuLinkComponentProps, MegaMenuTriggerActionProp, MegaMenuTriggerActionProps, } from "./mega-menu.js";
38
38
  export { Anchor } from "./anchor.js";
39
39
  export type { AnchorContainerProp, AnchorDirectionProp, AnchorItemProp, AnchorProp, AnchorProps, } from "./anchor.js";
40
+ export { DashboardGrid } from "./dashboard-grid.js";
41
+ export type { DashboardGridProp, DashboardGridProps, DashboardGridItemProp } from "./dashboard-grid.js";
package/dist/lab/index.js CHANGED
@@ -21,6 +21,7 @@ import { EmojiPicker } from "./emoji-picker.js";
21
21
  import { SortableList } from "./sortable-list.js";
22
22
  import { MegaMenu } from "./mega-menu.js";
23
23
  import { Anchor } from "./anchor.js";
24
+ import { DashboardGrid } from "./dashboard-grid.js";
24
25
  export {
25
26
  Anchor,
26
27
  Carousel,
@@ -29,6 +30,7 @@ export {
29
30
  CarouselItem,
30
31
  CarouselNext,
31
32
  CarouselPrevious,
33
+ DashboardGrid,
32
34
  DraggablePanel,
33
35
  EmojiPicker,
34
36
  FloatButton,
@@ -21,6 +21,11 @@ export type ChartSeriesProp = {
21
21
  */
22
22
  fillColor?: string;
23
23
  };
24
+ /** Selection is an action: the dashboard owns filter state. Index refers to the original data array. */
25
+ export type ChartDatumSelect<T = ChartDatum> = (datum: T, context: {
26
+ seriesKey: string;
27
+ index: number;
28
+ }) => void;
24
29
  /** Shared base for the cartesian charts (Line / Bar / Area). */
25
30
  type ChartCartesianBase = {
26
31
  /** Row data. Each row is one category with a value per series. */
@@ -69,6 +74,8 @@ type ChartCartesianBase = {
69
74
  numberFormat?: Intl.NumberFormatOptions;
70
75
  /** Message shown when `data` is empty. Defaults to a localized "no data". */
71
76
  emptyMessage?: EmptyMessageProp;
77
+ /** Select a finite datum by pointer or Enter/Space. Arrows navigate categories and series. */
78
+ onDatumSelect?: ChartDatumSelect;
72
79
  /**
73
80
  * Called with the clicked category's datum and its index — drill-down, zoom-to-bucket. The whole
74
81
  * category column is the target, not only the mark, so a zero-height bar is still clickable.
@@ -161,6 +168,8 @@ export type HeatmapDatum = {
161
168
  * steps through the `--chart-heat-1..5` ramp; an empty cell is outlined, a zero cell is filled.
162
169
  */
163
170
  export type HeatmapChartProp = {
171
+ /** Select a present cell. seriesKey is String(column); index is the original data index. */
172
+ onDatumSelect?: ChartDatumSelect<HeatmapDatum>;
164
173
  /** Row categories, top to bottom (the y axis — weekdays). */
165
174
  rows: HeatmapCategory[];
166
175
  /** Column categories, start to end (the x axis — hours). */
@@ -207,6 +216,8 @@ export type AreaChartProp = ChartCartesianBase & {
207
216
  };
208
217
  /** @see PieChart */
209
218
  export type PieChartProp = {
219
+ /** Select a slice by pointer or Enter/Space; seriesKey is dataKey. Arrows navigate slices. */
220
+ onDatumSelect?: ChartDatumSelect;
210
221
  /** Row data — one slice per row. */
211
222
  data: ChartDatum[];
212
223
  /** Key into each datum holding the slice's numeric value. */
@@ -0,0 +1,27 @@
1
+ import type * as React from "react";
2
+ import type { BreakpointProp } from "../vocabulary/index.js";
3
+ /** Integer grid coordinates, zero-based from inline-start. Stable id owns persistence. */
4
+ export interface DashboardGridItemProp {
5
+ id: string;
6
+ x: number;
7
+ y: number;
8
+ w: number;
9
+ h: number;
10
+ }
11
+ export interface DashboardGridProp extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
12
+ /** Each tile owns its Card and visible label header; content is the body (e.g. CardContent). */
13
+ items: {
14
+ id: string;
15
+ label: string;
16
+ content: React.ReactNode;
17
+ }[];
18
+ layout?: DashboardGridItemProp[];
19
+ defaultLayout?: DashboardGridItemProp[];
20
+ onLayoutChange?: (layout: DashboardGridItemProp[]) => void;
21
+ columns?: number | ({
22
+ base: number;
23
+ } & Partial<Record<BreakpointProp, number>>);
24
+ /** Row track size in pixels; omitted reads --dashboard-grid-row-height. */
25
+ rowHeight?: number;
26
+ editable?: boolean;
27
+ }
File without changes
@@ -2,7 +2,7 @@ export type { AppLauncherApp, AppLauncherGroup, AppLauncherLabels, AppLauncherPr
2
2
  export type { ButtonProp } from "./general.prop.js";
3
3
  export type { CommandProp, CommandSeparatorProp, InputProp, TextareaProp, FormFieldProp, SearchInputProp, CheckboxProp, CheckboxGroupProp, ChoiceOptionProp, RadioProp, RadioGroupProp, SwitchProp, SliderProp, CalendarProp, DatePickerProp, TimePickerProp, ColorPickerProp, ColorPickerPresetProp, UploadProp, UploadFileItemProp, UploadVariantProp, TreeOptionProp, TreeFieldNamesProp, CascaderProp, TreeSelectProp, ShowCheckedStrategyProp, TransferProp, TransferItemProp, } from "./data-entry.prop.js";
4
4
  export type { AvatarProp, EmptyStateProp, DescriptionsProp, DescriptionsItemProp, BadgeProp, DataTableProp, QrCodeProp, } from "./data-display.prop.js";
5
- export type { ChartDatum, ChartSeriesProp, LineChartProp, BarChartProp, AreaChartProp, PieChartProp, } from "./charts.prop.js";
5
+ export type { ChartDatumSelect, ChartDatum, ChartSeriesProp, LineChartProp, BarChartProp, AreaChartProp, PieChartProp, } from "./charts.prop.js";
6
6
  export type { AlertQueryErrorProp, AuthExpiryProviderProp, AlertProp, DialogProp, DialogContentProp, AlertTitleProp, AlertContentProp, AlertDescriptionProp, AlertActionsProp, SheetResponsiveProp, SkeletonRowsProp, } from "./feedback.prop.js";
7
7
  export type { DataStateProp, InfiniteQueryStateProp, InfiniteQueryHelpers, PrefetchLinkProp, } from "./query.prop.js";
8
8
  export type { DropdownMenuPlacementProp, DropdownMenuTriggerActionProp, PaginationProp, PaginationSizeProp, PaginationAlignProp, StepsProp, StepItemProp, StepStatusProp, StepsTypeProp, TabsProp, TabItemProp, TabsVariantProp, TabsPlacementProp, TabsExtraProp, TabsOnEditProp, } from "./navigation.prop.js";
@@ -717,6 +717,64 @@ export declare const VOCABULARY_REGISTRY: {
717
717
  };
718
718
  export type VocabularyPropName = keyof typeof VOCABULARY_REGISTRY;
719
719
  export declare const COMPONENT_PROP_REGISTRY: {
720
+ readonly DashboardGridProp: {
721
+ readonly group: "layout";
722
+ readonly file: "components/dashboard-grid.prop.ts";
723
+ readonly vocabulary: readonly ["ClassNameProp", "IdProp", {
724
+ readonly field: "items";
725
+ readonly local: true;
726
+ readonly reason: "DashboardGrid cell-layout editing contract (#1397), owner-approved lab API.";
727
+ }, {
728
+ readonly field: "layout";
729
+ readonly local: true;
730
+ readonly reason: "DashboardGrid cell-layout editing contract (#1397), owner-approved lab API.";
731
+ }, {
732
+ readonly field: "defaultLayout";
733
+ readonly local: true;
734
+ readonly reason: "DashboardGrid cell-layout editing contract (#1397), owner-approved lab API.";
735
+ }, {
736
+ readonly field: "onLayoutChange";
737
+ readonly local: true;
738
+ readonly reason: "DashboardGrid cell-layout editing contract (#1397), owner-approved lab API.";
739
+ }, {
740
+ readonly field: "columns";
741
+ readonly local: true;
742
+ readonly reason: "DashboardGrid cell-layout editing contract (#1397), owner-approved lab API.";
743
+ }, {
744
+ readonly field: "rowHeight";
745
+ readonly local: true;
746
+ readonly reason: "DashboardGrid cell-layout editing contract (#1397), owner-approved lab API.";
747
+ }, {
748
+ readonly field: "editable";
749
+ readonly local: true;
750
+ readonly reason: "DashboardGrid cell-layout editing contract (#1397), owner-approved lab API.";
751
+ }];
752
+ };
753
+ readonly DashboardGridItemProp: {
754
+ readonly group: "layout";
755
+ readonly file: "components/dashboard-grid.prop.ts";
756
+ readonly vocabulary: readonly [{
757
+ readonly field: "id";
758
+ readonly local: true;
759
+ readonly reason: "Persisted grid cell coordinate or identity.";
760
+ }, {
761
+ readonly field: "x";
762
+ readonly local: true;
763
+ readonly reason: "Persisted grid cell coordinate or identity.";
764
+ }, {
765
+ readonly field: "y";
766
+ readonly local: true;
767
+ readonly reason: "Persisted grid cell coordinate or identity.";
768
+ }, {
769
+ readonly field: "w";
770
+ readonly local: true;
771
+ readonly reason: "Persisted grid cell coordinate or identity.";
772
+ }, {
773
+ readonly field: "h";
774
+ readonly local: true;
775
+ readonly reason: "Persisted grid cell coordinate or identity.";
776
+ }];
777
+ };
720
778
  readonly AppProviderProp: {
721
779
  readonly group: "app";
722
780
  readonly file: "components/app.prop.ts";
@@ -2319,7 +2377,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
2319
2377
  readonly LineChartProp: {
2320
2378
  readonly group: "data-display";
2321
2379
  readonly file: "components/charts.prop.ts";
2322
- readonly vocabulary: readonly ["LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "ClassNameProp", "IdProp", {
2380
+ readonly vocabulary: readonly [{
2381
+ readonly field: "onDatumSelect";
2382
+ readonly local: true;
2383
+ readonly reason: "Pointer and keyboard datum selection action, independent of dashboard state.";
2384
+ }, "LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "ClassNameProp", "IdProp", {
2323
2385
  readonly field: "data";
2324
2386
  readonly local: true;
2325
2387
  readonly reason: "Chart row data (category + value per series).";
@@ -2372,7 +2434,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
2372
2434
  readonly BarChartProp: {
2373
2435
  readonly group: "data-display";
2374
2436
  readonly file: "components/charts.prop.ts";
2375
- readonly vocabulary: readonly ["LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "ClassNameProp", "IdProp", {
2437
+ readonly vocabulary: readonly [{
2438
+ readonly field: "onDatumSelect";
2439
+ readonly local: true;
2440
+ readonly reason: "Pointer and keyboard datum selection action, independent of dashboard state.";
2441
+ }, "LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "ClassNameProp", "IdProp", {
2376
2442
  readonly field: "data";
2377
2443
  readonly local: true;
2378
2444
  readonly reason: "Chart row data (category + value per series).";
@@ -2462,7 +2528,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
2462
2528
  readonly HeatmapChartProp: {
2463
2529
  readonly group: "data-display";
2464
2530
  readonly file: "components/charts.prop.ts";
2465
- readonly vocabulary: readonly ["LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "ClassNameProp", "IdProp", {
2531
+ readonly vocabulary: readonly [{
2532
+ readonly field: "onDatumSelect";
2533
+ readonly local: true;
2534
+ readonly reason: "Pointer and keyboard datum selection action, independent of dashboard state.";
2535
+ }, "LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "ClassNameProp", "IdProp", {
2466
2536
  readonly field: "rows";
2467
2537
  readonly local: true;
2468
2538
  readonly reason: "Row categories (y axis) — key + translated label.";
@@ -2499,7 +2569,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
2499
2569
  readonly AreaChartProp: {
2500
2570
  readonly group: "data-display";
2501
2571
  readonly file: "components/charts.prop.ts";
2502
- readonly vocabulary: readonly ["LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "ClassNameProp", "IdProp", {
2572
+ readonly vocabulary: readonly [{
2573
+ readonly field: "onDatumSelect";
2574
+ readonly local: true;
2575
+ readonly reason: "Pointer and keyboard datum selection action, independent of dashboard state.";
2576
+ }, "LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "ClassNameProp", "IdProp", {
2503
2577
  readonly field: "data";
2504
2578
  readonly local: true;
2505
2579
  readonly reason: "Chart row data (category + value per series).";
@@ -2556,7 +2630,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
2556
2630
  readonly PieChartProp: {
2557
2631
  readonly group: "data-display";
2558
2632
  readonly file: "components/charts.prop.ts";
2559
- readonly vocabulary: readonly ["LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "ClassNameProp", "IdProp", {
2633
+ readonly vocabulary: readonly [{
2634
+ readonly field: "onDatumSelect";
2635
+ readonly local: true;
2636
+ readonly reason: "Pointer and keyboard datum selection action, independent of dashboard state.";
2637
+ }, "LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "ClassNameProp", "IdProp", {
2560
2638
  readonly field: "data";
2561
2639
  readonly local: true;
2562
2640
  readonly reason: "Chart row data (one slice per row).";