@flanksource/clicky-ui 0.3.52 → 0.3.53

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 (57) hide show
  1. package/dist/components/clipboard.cjs +76 -11
  2. package/dist/components/clipboard.cjs.map +1 -1
  3. package/dist/components/clipboard.d.ts +37 -6
  4. package/dist/components/clipboard.d.ts.map +1 -1
  5. package/dist/components/clipboard.js +75 -12
  6. package/dist/components/clipboard.js.map +1 -1
  7. package/dist/components.cjs +2 -0
  8. package/dist/components.d.ts +1 -1
  9. package/dist/components.d.ts.map +1 -1
  10. package/dist/components.js +2 -2
  11. package/dist/data/MatrixTreeTable.cjs +94 -0
  12. package/dist/data/MatrixTreeTable.cjs.map +1 -0
  13. package/dist/data/MatrixTreeTable.d.ts +40 -0
  14. package/dist/data/MatrixTreeTable.d.ts.map +1 -0
  15. package/dist/data/MatrixTreeTable.js +92 -0
  16. package/dist/data/MatrixTreeTable.js.map +1 -0
  17. package/dist/data/TreeDataTable.cjs +52 -0
  18. package/dist/data/TreeDataTable.cjs.map +1 -0
  19. package/dist/data/TreeDataTable.d.ts +17 -0
  20. package/dist/data/TreeDataTable.d.ts.map +1 -0
  21. package/dist/data/TreeDataTable.js +52 -0
  22. package/dist/data/TreeDataTable.js.map +1 -0
  23. package/dist/data/test-runner/MatrixMarks.cjs +212 -0
  24. package/dist/data/test-runner/MatrixMarks.cjs.map +1 -0
  25. package/dist/data/test-runner/MatrixMarks.d.ts +76 -0
  26. package/dist/data/test-runner/MatrixMarks.d.ts.map +1 -0
  27. package/dist/data/test-runner/MatrixMarks.js +205 -0
  28. package/dist/data/test-runner/MatrixMarks.js.map +1 -0
  29. package/dist/data/test-runner/TestDetailPanel.cjs +3 -0
  30. package/dist/data/test-runner/TestDetailPanel.cjs.map +1 -1
  31. package/dist/data/test-runner/TestDetailPanel.d.ts.map +1 -1
  32. package/dist/data/test-runner/TestDetailPanel.js +3 -0
  33. package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
  34. package/dist/data/test-runner/index.d.ts +2 -0
  35. package/dist/data/test-runner/index.d.ts.map +1 -1
  36. package/dist/data/test-runner/matrix-marks.cjs +119 -0
  37. package/dist/data/test-runner/matrix-marks.cjs.map +1 -0
  38. package/dist/data/test-runner/matrix-marks.d.ts +154 -0
  39. package/dist/data/test-runner/matrix-marks.d.ts.map +1 -0
  40. package/dist/data/test-runner/matrix-marks.js +113 -0
  41. package/dist/data/test-runner/matrix-marks.js.map +1 -0
  42. package/dist/data/version-info.cjs +3 -3
  43. package/dist/data/version-info.js +3 -3
  44. package/dist/data.cjs +27 -0
  45. package/dist/data.d.ts +3 -0
  46. package/dist/data.d.ts.map +1 -1
  47. package/dist/data.js +6 -1
  48. package/dist/index.cjs +29 -0
  49. package/dist/index.js +7 -2
  50. package/dist/lib/tree-rows.cjs +63 -0
  51. package/dist/lib/tree-rows.cjs.map +1 -0
  52. package/dist/lib/tree-rows.d.ts +36 -0
  53. package/dist/lib/tree-rows.d.ts.map +1 -0
  54. package/dist/lib/tree-rows.js +60 -0
  55. package/dist/lib/tree-rows.js.map +1 -0
  56. package/dist/styles.css +1 -1
  57. package/package.json +1 -1
@@ -0,0 +1,92 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { UiChevronDown } from "../icons/components/UiChevronDown.js";
3
+ import { UiChevronRight } from "../icons/components/UiChevronRight.js";
4
+ import { MatrixTable } from "./MatrixTable.js";
5
+ import { useTreeRows } from "../lib/tree-rows.js";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ // src/data/MatrixTreeTable.tsx
8
+ /** The chevron that opens or closes a tree row; `label` names the row for assistive tech. */
9
+ function TreeRowToggle({ open, label, onToggle }) {
10
+ const Icon = open ? UiChevronDown : UiChevronRight;
11
+ return /* @__PURE__ */ jsx("button", {
12
+ type: "button",
13
+ "aria-expanded": open,
14
+ "aria-label": `${open ? "Collapse" : "Expand"} ${label}`,
15
+ className: "inline-flex size-4 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground",
16
+ onClick: (event) => {
17
+ event.stopPropagation();
18
+ onToggle();
19
+ },
20
+ children: /* @__PURE__ */ jsx(Icon, { className: "size-3.5" })
21
+ });
22
+ }
23
+ var TREE_STEP_REM = 1.25;
24
+ /**
25
+ * The indent and chevron that lead a tree row's label. Parents get a toggle
26
+ * (`onToggle` + `label`); leaves get a chevron-sized spacer so they line up.
27
+ */
28
+ function TreeRowLead({ depth, open = false, label, onToggle, children }) {
29
+ if (onToggle && label === void 0) throw new Error("TreeRowLead needs a label to name its toggle");
30
+ return /* @__PURE__ */ jsxs("span", {
31
+ "data-tree-depth": depth,
32
+ className: "inline-flex min-w-0 items-center gap-1",
33
+ style: { paddingLeft: `${depth * TREE_STEP_REM}rem` },
34
+ children: [onToggle ? /* @__PURE__ */ jsx(TreeRowToggle, {
35
+ open,
36
+ label,
37
+ onToggle
38
+ }) : /* @__PURE__ */ jsx("span", {
39
+ "aria-hidden": true,
40
+ className: "size-4 shrink-0"
41
+ }), children]
42
+ });
43
+ }
44
+ /**
45
+ * A MatrixTable whose rows form a tree: parent nodes are collapsible group
46
+ * bands that span every column, leaves are data rows, both indented by depth.
47
+ */
48
+ function MatrixTreeTable({ roots, getChildren, getKey, renderLabel, getAriaLabel, getCells, getGroupClassName, expanded, onExpandedChange, defaultExpanded, ...table }) {
49
+ const { rows, toggle } = useTreeRows(roots, {
50
+ getChildren,
51
+ getKey
52
+ }, {
53
+ ...expanded !== void 0 ? { expanded } : {},
54
+ ...onExpandedChange ? { onExpandedChange } : {},
55
+ ...defaultExpanded !== void 0 ? { defaultExpanded } : {}
56
+ });
57
+ const matrixRows = rows.map((row) => {
58
+ const label = renderLabel(row.node, {
59
+ depth: row.depth,
60
+ open: row.open,
61
+ hasChildren: row.hasChildren
62
+ });
63
+ if (!row.hasChildren) return {
64
+ key: row.key,
65
+ label: /* @__PURE__ */ jsx(TreeRowLead, {
66
+ depth: row.depth,
67
+ children: label
68
+ }),
69
+ cells: getCells(row.node)
70
+ };
71
+ const className = cn(row.depth > 0 && "bg-muted/30 font-medium", getGroupClassName?.(row.node, row.depth));
72
+ return {
73
+ type: "group",
74
+ key: row.key,
75
+ ...className ? { className } : {},
76
+ label: /* @__PURE__ */ jsx(TreeRowLead, {
77
+ depth: row.depth,
78
+ open: row.open,
79
+ label: getAriaLabel(row.node),
80
+ onToggle: () => toggle(row),
81
+ children: label
82
+ })
83
+ };
84
+ });
85
+ return /* @__PURE__ */ jsx(MatrixTable, {
86
+ ...table,
87
+ rows: matrixRows
88
+ });
89
+ }
90
+ export { MatrixTreeTable, TreeRowLead, TreeRowToggle };
91
+
92
+ //# sourceMappingURL=MatrixTreeTable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatrixTreeTable.js","names":[],"sources":["../../src/data/MatrixTreeTable.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { UiChevronDown, UiChevronRight } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { useTreeRows, type TreeExpansionProps, type TreeRowsAccessors } from \"../lib/tree-rows\";\nimport { MatrixTable, type MatrixTableGroupRow, type MatrixTableProps, type MatrixTableRow } from \"./MatrixTable\";\n\nexport type TreeLabelContext = { depth: number; open: boolean; hasChildren: boolean };\n\nexport type MatrixTreeTableProps<T> = Omit<MatrixTableProps, \"rows\"> &\n TreeRowsAccessors<T> &\n TreeExpansionProps<T> & {\n roots: T[];\n renderLabel: (node: T, context: TreeLabelContext) => ReactNode;\n /** Names a parent node in its expand/collapse button. */\n getAriaLabel: (node: T) => string;\n /** Cells of a leaf row, one per column. Parent nodes render as group bands. */\n getCells: (node: T) => ReactNode[];\n getGroupClassName?: (node: T, depth: number) => string | undefined;\n };\n\n/** The chevron that opens or closes a tree row; `label` names the row for assistive tech. */\nexport function TreeRowToggle({ open, label, onToggle }: { open: boolean; label: string; onToggle: () => void }) {\n const Icon = open ? UiChevronDown : UiChevronRight;\n return (\n <button\n type=\"button\"\n aria-expanded={open}\n aria-label={`${open ? \"Collapse\" : \"Expand\"} ${label}`}\n className=\"inline-flex size-4 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground\"\n onClick={(event) => { event.stopPropagation(); onToggle(); }}\n >\n <Icon className=\"size-3.5\" />\n </button>\n );\n}\n\n// One tree level: the chevron (1rem) plus its gap (0.25rem), so a child's text\n// starts one step right of its parent's text.\nconst TREE_STEP_REM = 1.25;\n\n/**\n * The indent and chevron that lead a tree row's label. Parents get a toggle\n * (`onToggle` + `label`); leaves get a chevron-sized spacer so they line up.\n */\nexport function TreeRowLead({ depth, open = false, label, onToggle, children }: { depth: number; open?: boolean; label?: string; onToggle?: () => void; children: ReactNode }) {\n if (onToggle && label === undefined) throw new Error(\"TreeRowLead needs a label to name its toggle\");\n return (\n <span data-tree-depth={depth} className=\"inline-flex min-w-0 items-center gap-1\" style={{ paddingLeft: `${depth * TREE_STEP_REM}rem` }}>\n {onToggle ? <TreeRowToggle open={open} label={label!} onToggle={onToggle} /> : <span aria-hidden className=\"size-4 shrink-0\" />}\n {children}\n </span>\n );\n}\n\n/**\n * A MatrixTable whose rows form a tree: parent nodes are collapsible group\n * bands that span every column, leaves are data rows, both indented by depth.\n */\nexport function MatrixTreeTable<T>({\n roots,\n getChildren,\n getKey,\n renderLabel,\n getAriaLabel,\n getCells,\n getGroupClassName,\n expanded,\n onExpandedChange,\n defaultExpanded,\n ...table\n}: MatrixTreeTableProps<T>) {\n const { rows, toggle } = useTreeRows(roots, { getChildren, getKey }, {\n ...(expanded !== undefined ? { expanded } : {}),\n ...(onExpandedChange ? { onExpandedChange } : {}),\n ...(defaultExpanded !== undefined ? { defaultExpanded } : {}),\n });\n const matrixRows = rows.map((row): MatrixTableRow | MatrixTableGroupRow => {\n const label = renderLabel(row.node, { depth: row.depth, open: row.open, hasChildren: row.hasChildren });\n if (!row.hasChildren) return { key: row.key, label: <TreeRowLead depth={row.depth}>{label}</TreeRowLead>, cells: getCells(row.node) };\n // MatrixTable's depth would indent a second time, so nested bands get its softer style here.\n const className = cn(row.depth > 0 && \"bg-muted/30 font-medium\", getGroupClassName?.(row.node, row.depth));\n return {\n type: \"group\",\n key: row.key,\n ...(className ? { className } : {}),\n label: <TreeRowLead depth={row.depth} open={row.open} label={getAriaLabel(row.node)} onToggle={() => toggle(row)}>{label}</TreeRowLead>,\n };\n });\n return <MatrixTable {...table} rows={matrixRows} />;\n}\n"],"mappings":";;;;;;;;AAqBA,SAAgB,cAAc,EAAE,MAAM,OAAO,YAAoE;CAC/G,MAAM,OAAO,OAAO,gBAAgB;CACpC,OACE,oBAAC,UAAD;EACE,MAAK;EACL,iBAAe;EACf,cAAY,GAAG,OAAO,aAAa,SAAS,GAAG;EAC/C,WAAU;EACV,UAAU,UAAU;GAAE,MAAM,gBAAgB;GAAG,SAAS;EAAG;EAE3D,UAAA,oBAAC,MAAD,EAAM,WAAU,WAAY,CAAA;CACtB,CAAA;AAEZ;AAIA,IAAM,gBAAgB;;;;;AAMtB,SAAgB,YAAY,EAAE,OAAO,OAAO,OAAO,OAAO,UAAU,YAA2G;CAC7K,IAAI,YAAY,UAAU,KAAA,GAAW,MAAM,IAAI,MAAM,8CAA8C;CACnG,OACE,qBAAC,QAAD;EAAM,mBAAiB;EAAO,WAAU;EAAyC,OAAO,EAAE,aAAa,GAAG,QAAQ,cAAc,KAAK;EAArI,UAAA,CACG,WAAW,oBAAC,eAAD;GAAqB;GAAa;GAAkB;EAAW,CAAA,IAAI,oBAAC,QAAD;GAAM,eAAA;GAAY,WAAU;EAAmB,CAAA,GAC7H,QACG;;AAEV;;;;;AAMA,SAAgB,gBAAmB,EACjC,OACA,aACA,QACA,aACA,cACA,UACA,mBACA,UACA,kBACA,iBACA,GAAG,SACuB;CAC1B,MAAM,EAAE,MAAM,WAAW,YAAY,OAAO;EAAE;EAAa;CAAO,GAAG;EACnE,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;EAC7C,GAAI,mBAAmB,EAAE,iBAAiB,IAAI,CAAC;EAC/C,GAAI,oBAAoB,KAAA,IAAY,EAAE,gBAAgB,IAAI,CAAC;CAC7D,CAAC;CACD,MAAM,aAAa,KAAK,KAAK,QAA8C;EACzE,MAAM,QAAQ,YAAY,IAAI,MAAM;GAAE,OAAO,IAAI;GAAO,MAAM,IAAI;GAAM,aAAa,IAAI;EAAY,CAAC;EACtG,IAAI,CAAC,IAAI,aAAa,OAAO;GAAE,KAAK,IAAI;GAAK,OAAO,oBAAC,aAAD;IAAa,OAAO,IAAI;IAAQ,UAAA;GAAmB,CAAA;GAAG,OAAO,SAAS,IAAI,IAAI;EAAE;EAEpI,MAAM,YAAY,GAAG,IAAI,QAAQ,KAAK,2BAA2B,oBAAoB,IAAI,MAAM,IAAI,KAAK,CAAC;EACzG,OAAO;GACL,MAAM;GACN,KAAK,IAAI;GACT,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;GACjC,OAAO,oBAAC,aAAD;IAAa,OAAO,IAAI;IAAO,MAAM,IAAI;IAAM,OAAO,aAAa,IAAI,IAAI;IAAG,gBAAgB,OAAO,GAAG;IAAI,UAAA;GAAmB,CAAA;EACxI;CACF,CAAC;CACD,OAAO,oBAAC,aAAD;EAAa,GAAI;EAAO,MAAM;CAAa,CAAA;AACpD"}
@@ -0,0 +1,52 @@
1
+ const require_DataTable = require("./DataTable.cjs");
2
+ const require_tree_rows = require("../lib/tree-rows.cjs");
3
+ const require_MatrixTreeTable = require("./MatrixTreeTable.cjs");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+ // src/data/TreeDataTable.tsx
6
+ /**
7
+ * A DataTable whose rows form a tree. Parent and leaf nodes share the columns;
8
+ * the tree column indents each row by depth and gives parents a chevron. Tree
9
+ * order is the row order, so sorting and grouping are not offered.
10
+ */
11
+ function TreeDataTable({ roots, getChildren, getKey, getAriaLabel, treeColumn, columns, expanded, onExpandedChange, defaultExpanded, ...table }) {
12
+ if (!columns.some((column) => column.key === treeColumn)) throw new Error(`TreeDataTable treeColumn "${treeColumn}" is not one of its columns`);
13
+ const { rows, toggle } = require_tree_rows.useTreeRows(roots, {
14
+ getChildren,
15
+ getKey
16
+ }, {
17
+ ...expanded !== void 0 ? { expanded } : {},
18
+ ...onExpandedChange ? { onExpandedChange } : {},
19
+ ...defaultExpanded !== void 0 ? { defaultExpanded } : {}
20
+ });
21
+ const byNode = new Map(rows.map((row) => [row.node, row]));
22
+ const treeColumns = columns.map((column) => {
23
+ const { sortable: _sortable, ...rest } = column;
24
+ if (column.key !== treeColumn) return rest;
25
+ return {
26
+ ...rest,
27
+ render: (value, node) => {
28
+ const row = byNode.get(node);
29
+ const content = column.render ? column.render(value, node) : String(value ?? "");
30
+ return row.hasChildren ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MatrixTreeTable.TreeRowLead, {
31
+ depth: row.depth,
32
+ open: row.open,
33
+ label: getAriaLabel(node),
34
+ onToggle: () => toggle(row),
35
+ children: content
36
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MatrixTreeTable.TreeRowLead, {
37
+ depth: row.depth,
38
+ children: content
39
+ });
40
+ }
41
+ };
42
+ });
43
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_DataTable.DataTable, {
44
+ ...table,
45
+ columns: treeColumns,
46
+ data: rows.map((row) => row.node),
47
+ getRowId: (node) => byNode.get(node).key
48
+ });
49
+ }
50
+ exports.TreeDataTable = TreeDataTable;
51
+
52
+ //# sourceMappingURL=TreeDataTable.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeDataTable.cjs","names":["useTreeRows","TreeRowLead","DataTable"],"sources":["../../src/data/TreeDataTable.tsx"],"sourcesContent":["import { useTreeRows, type TreeExpansionProps, type TreeRow, type TreeRowsAccessors } from \"../lib/tree-rows\";\nimport { DataTable, type DataTableColumn, type DataTableProps } from \"./DataTable\";\nimport { TreeRowLead } from \"./MatrixTreeTable\";\n\nexport type TreeDataTableProps<T extends Record<string, unknown>> = Omit<\n DataTableProps<T>,\n \"data\" | \"columns\" | \"getRowId\" | \"grouping\" | \"groupingModes\" | \"groupingMode\" | \"defaultGroupingMode\" | \"onGroupingModeChange\" | \"defaultSort\" | \"sort\" | \"onSortChange\"\n> &\n TreeRowsAccessors<T> &\n TreeExpansionProps<T> & {\n roots: T[];\n columns: DataTableColumn<T>[];\n /** Key of the column that carries the indent and the expand/collapse chevron. */\n treeColumn: string;\n /** Names a parent node in its expand/collapse button. */\n getAriaLabel: (node: T) => string;\n };\n\n/**\n * A DataTable whose rows form a tree. Parent and leaf nodes share the columns;\n * the tree column indents each row by depth and gives parents a chevron. Tree\n * order is the row order, so sorting and grouping are not offered.\n */\nexport function TreeDataTable<T extends Record<string, unknown>>({\n roots,\n getChildren,\n getKey,\n getAriaLabel,\n treeColumn,\n columns,\n expanded,\n onExpandedChange,\n defaultExpanded,\n ...table\n}: TreeDataTableProps<T>) {\n if (!columns.some((column) => column.key === treeColumn)) {\n throw new Error(`TreeDataTable treeColumn \"${treeColumn}\" is not one of its columns`);\n }\n const { rows, toggle } = useTreeRows(roots, { getChildren, getKey }, {\n ...(expanded !== undefined ? { expanded } : {}),\n ...(onExpandedChange ? { onExpandedChange } : {}),\n ...(defaultExpanded !== undefined ? { defaultExpanded } : {}),\n });\n const byNode = new Map<T, TreeRow<T>>(rows.map((row) => [row.node, row]));\n const treeColumns = columns.map((column): DataTableColumn<T> => {\n const { sortable: _sortable, ...rest } = column;\n if (column.key !== treeColumn) return rest;\n return {\n ...rest,\n render: (value, node) => {\n const row = byNode.get(node)!;\n const content = column.render ? column.render(value, node) : String(value ?? \"\");\n return row.hasChildren\n ? <TreeRowLead depth={row.depth} open={row.open} label={getAriaLabel(node)} onToggle={() => toggle(row)}>{content}</TreeRowLead>\n : <TreeRowLead depth={row.depth}>{content}</TreeRowLead>;\n },\n };\n });\n return <DataTable<T> {...table} columns={treeColumns} data={rows.map((row) => row.node)} getRowId={(node) => byNode.get(node)!.key} />;\n}\n"],"mappings":";;;;;;;;;;AAuBA,SAAgB,cAAiD,EAC/D,OACA,aACA,QACA,cACA,YACA,SACA,UACA,kBACA,iBACA,GAAG,SACqB;CACxB,IAAI,CAAC,QAAQ,MAAM,WAAW,OAAO,QAAQ,UAAU,GACrD,MAAM,IAAI,MAAM,6BAA6B,WAAW,4BAA4B;CAEtF,MAAM,EAAE,MAAM,WAAWA,kBAAAA,YAAY,OAAO;EAAE;EAAa;CAAO,GAAG;EACnE,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;EAC7C,GAAI,mBAAmB,EAAE,iBAAiB,IAAI,CAAC;EAC/C,GAAI,oBAAoB,KAAA,IAAY,EAAE,gBAAgB,IAAI,CAAC;CAC7D,CAAC;CACD,MAAM,SAAS,IAAI,IAAmB,KAAK,KAAK,QAAQ,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;CACxE,MAAM,cAAc,QAAQ,KAAK,WAA+B;EAC9D,MAAM,EAAE,UAAU,WAAW,GAAG,SAAS;EACzC,IAAI,OAAO,QAAQ,YAAY,OAAO;EACtC,OAAO;GACL,GAAG;GACH,SAAS,OAAO,SAAS;IACvB,MAAM,MAAM,OAAO,IAAI,IAAI;IAC3B,MAAM,UAAU,OAAO,SAAS,OAAO,OAAO,OAAO,IAAI,IAAI,OAAO,SAAS,EAAE;IAC/E,OAAO,IAAI,cACP,iBAAA,GAAA,kBAAA,IAAA,CAACC,wBAAAA,aAAD;KAAa,OAAO,IAAI;KAAO,MAAM,IAAI;KAAM,OAAO,aAAa,IAAI;KAAG,gBAAgB,OAAO,GAAG;KAAI,UAAA;IAAqB,CAAA,IAC7H,iBAAA,GAAA,kBAAA,IAAA,CAACA,wBAAAA,aAAD;KAAa,OAAO,IAAI;KAAQ,UAAA;IAAqB,CAAA;GAC3D;EACF;CACF,CAAC;CACD,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAACC,kBAAAA,WAAD;EAAc,GAAI;EAAO,SAAS;EAAa,MAAM,KAAK,KAAK,QAAQ,IAAI,IAAI;EAAG,WAAW,SAAS,OAAO,IAAI,IAAI,CAAC,CAAE;CAAM,CAAA;AACvI"}
@@ -0,0 +1,17 @@
1
+ import { TreeExpansionProps, TreeRowsAccessors } from '../lib/tree-rows.js';
2
+ import { DataTableColumn, DataTableProps } from './DataTable.js';
3
+ export type TreeDataTableProps<T extends Record<string, unknown>> = Omit<DataTableProps<T>, "data" | "columns" | "getRowId" | "grouping" | "groupingModes" | "groupingMode" | "defaultGroupingMode" | "onGroupingModeChange" | "defaultSort" | "sort" | "onSortChange"> & TreeRowsAccessors<T> & TreeExpansionProps<T> & {
4
+ roots: T[];
5
+ columns: DataTableColumn<T>[];
6
+ /** Key of the column that carries the indent and the expand/collapse chevron. */
7
+ treeColumn: string;
8
+ /** Names a parent node in its expand/collapse button. */
9
+ getAriaLabel: (node: T) => string;
10
+ };
11
+ /**
12
+ * A DataTable whose rows form a tree. Parent and leaf nodes share the columns;
13
+ * the tree column indents each row by depth and gives parents a chevron. Tree
14
+ * order is the row order, so sorting and grouping are not offered.
15
+ */
16
+ export declare function TreeDataTable<T extends Record<string, unknown>>({ roots, getChildren, getKey, getAriaLabel, treeColumn, columns, expanded, onExpandedChange, defaultExpanded, ...table }: TreeDataTableProps<T>): import("react").JSX.Element;
17
+ //# sourceMappingURL=TreeDataTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeDataTable.d.ts","sourceRoot":"","sources":["../../src/data/TreeDataTable.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,kBAAkB,EAAgB,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC9G,OAAO,EAAa,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAGnF,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,IAAI,CACtE,cAAc,CAAC,CAAC,CAAC,EACjB,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,eAAe,GAAG,cAAc,GAAG,qBAAqB,GAAG,sBAAsB,GAAG,aAAa,GAAG,MAAM,GAAG,cAAc,CAC3K,GACC,iBAAiB,CAAC,CAAC,CAAC,GACpB,kBAAkB,CAAC,CAAC,CAAC,GAAG;IACtB,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,YAAY,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;CACnC,CAAC;AAEJ;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/D,KAAK,EACL,WAAW,EACX,MAAM,EACN,YAAY,EACZ,UAAU,EACV,OAAO,EACP,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,CAAC,CAAC,+BAyBvB"}
@@ -0,0 +1,52 @@
1
+ import { DataTable } from "./DataTable.js";
2
+ import { useTreeRows } from "../lib/tree-rows.js";
3
+ import { TreeRowLead } from "./MatrixTreeTable.js";
4
+ import { jsx } from "react/jsx-runtime";
5
+ // src/data/TreeDataTable.tsx
6
+ /**
7
+ * A DataTable whose rows form a tree. Parent and leaf nodes share the columns;
8
+ * the tree column indents each row by depth and gives parents a chevron. Tree
9
+ * order is the row order, so sorting and grouping are not offered.
10
+ */
11
+ function TreeDataTable({ roots, getChildren, getKey, getAriaLabel, treeColumn, columns, expanded, onExpandedChange, defaultExpanded, ...table }) {
12
+ if (!columns.some((column) => column.key === treeColumn)) throw new Error(`TreeDataTable treeColumn "${treeColumn}" is not one of its columns`);
13
+ const { rows, toggle } = useTreeRows(roots, {
14
+ getChildren,
15
+ getKey
16
+ }, {
17
+ ...expanded !== void 0 ? { expanded } : {},
18
+ ...onExpandedChange ? { onExpandedChange } : {},
19
+ ...defaultExpanded !== void 0 ? { defaultExpanded } : {}
20
+ });
21
+ const byNode = new Map(rows.map((row) => [row.node, row]));
22
+ const treeColumns = columns.map((column) => {
23
+ const { sortable: _sortable, ...rest } = column;
24
+ if (column.key !== treeColumn) return rest;
25
+ return {
26
+ ...rest,
27
+ render: (value, node) => {
28
+ const row = byNode.get(node);
29
+ const content = column.render ? column.render(value, node) : String(value ?? "");
30
+ return row.hasChildren ? /* @__PURE__ */ jsx(TreeRowLead, {
31
+ depth: row.depth,
32
+ open: row.open,
33
+ label: getAriaLabel(node),
34
+ onToggle: () => toggle(row),
35
+ children: content
36
+ }) : /* @__PURE__ */ jsx(TreeRowLead, {
37
+ depth: row.depth,
38
+ children: content
39
+ });
40
+ }
41
+ };
42
+ });
43
+ return /* @__PURE__ */ jsx(DataTable, {
44
+ ...table,
45
+ columns: treeColumns,
46
+ data: rows.map((row) => row.node),
47
+ getRowId: (node) => byNode.get(node).key
48
+ });
49
+ }
50
+ export { TreeDataTable };
51
+
52
+ //# sourceMappingURL=TreeDataTable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeDataTable.js","names":[],"sources":["../../src/data/TreeDataTable.tsx"],"sourcesContent":["import { useTreeRows, type TreeExpansionProps, type TreeRow, type TreeRowsAccessors } from \"../lib/tree-rows\";\nimport { DataTable, type DataTableColumn, type DataTableProps } from \"./DataTable\";\nimport { TreeRowLead } from \"./MatrixTreeTable\";\n\nexport type TreeDataTableProps<T extends Record<string, unknown>> = Omit<\n DataTableProps<T>,\n \"data\" | \"columns\" | \"getRowId\" | \"grouping\" | \"groupingModes\" | \"groupingMode\" | \"defaultGroupingMode\" | \"onGroupingModeChange\" | \"defaultSort\" | \"sort\" | \"onSortChange\"\n> &\n TreeRowsAccessors<T> &\n TreeExpansionProps<T> & {\n roots: T[];\n columns: DataTableColumn<T>[];\n /** Key of the column that carries the indent and the expand/collapse chevron. */\n treeColumn: string;\n /** Names a parent node in its expand/collapse button. */\n getAriaLabel: (node: T) => string;\n };\n\n/**\n * A DataTable whose rows form a tree. Parent and leaf nodes share the columns;\n * the tree column indents each row by depth and gives parents a chevron. Tree\n * order is the row order, so sorting and grouping are not offered.\n */\nexport function TreeDataTable<T extends Record<string, unknown>>({\n roots,\n getChildren,\n getKey,\n getAriaLabel,\n treeColumn,\n columns,\n expanded,\n onExpandedChange,\n defaultExpanded,\n ...table\n}: TreeDataTableProps<T>) {\n if (!columns.some((column) => column.key === treeColumn)) {\n throw new Error(`TreeDataTable treeColumn \"${treeColumn}\" is not one of its columns`);\n }\n const { rows, toggle } = useTreeRows(roots, { getChildren, getKey }, {\n ...(expanded !== undefined ? { expanded } : {}),\n ...(onExpandedChange ? { onExpandedChange } : {}),\n ...(defaultExpanded !== undefined ? { defaultExpanded } : {}),\n });\n const byNode = new Map<T, TreeRow<T>>(rows.map((row) => [row.node, row]));\n const treeColumns = columns.map((column): DataTableColumn<T> => {\n const { sortable: _sortable, ...rest } = column;\n if (column.key !== treeColumn) return rest;\n return {\n ...rest,\n render: (value, node) => {\n const row = byNode.get(node)!;\n const content = column.render ? column.render(value, node) : String(value ?? \"\");\n return row.hasChildren\n ? <TreeRowLead depth={row.depth} open={row.open} label={getAriaLabel(node)} onToggle={() => toggle(row)}>{content}</TreeRowLead>\n : <TreeRowLead depth={row.depth}>{content}</TreeRowLead>;\n },\n };\n });\n return <DataTable<T> {...table} columns={treeColumns} data={rows.map((row) => row.node)} getRowId={(node) => byNode.get(node)!.key} />;\n}\n"],"mappings":";;;;;;;;;;AAuBA,SAAgB,cAAiD,EAC/D,OACA,aACA,QACA,cACA,YACA,SACA,UACA,kBACA,iBACA,GAAG,SACqB;CACxB,IAAI,CAAC,QAAQ,MAAM,WAAW,OAAO,QAAQ,UAAU,GACrD,MAAM,IAAI,MAAM,6BAA6B,WAAW,4BAA4B;CAEtF,MAAM,EAAE,MAAM,WAAW,YAAY,OAAO;EAAE;EAAa;CAAO,GAAG;EACnE,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;EAC7C,GAAI,mBAAmB,EAAE,iBAAiB,IAAI,CAAC;EAC/C,GAAI,oBAAoB,KAAA,IAAY,EAAE,gBAAgB,IAAI,CAAC;CAC7D,CAAC;CACD,MAAM,SAAS,IAAI,IAAmB,KAAK,KAAK,QAAQ,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;CACxE,MAAM,cAAc,QAAQ,KAAK,WAA+B;EAC9D,MAAM,EAAE,UAAU,WAAW,GAAG,SAAS;EACzC,IAAI,OAAO,QAAQ,YAAY,OAAO;EACtC,OAAO;GACL,GAAG;GACH,SAAS,OAAO,SAAS;IACvB,MAAM,MAAM,OAAO,IAAI,IAAI;IAC3B,MAAM,UAAU,OAAO,SAAS,OAAO,OAAO,OAAO,IAAI,IAAI,OAAO,SAAS,EAAE;IAC/E,OAAO,IAAI,cACP,oBAAC,aAAD;KAAa,OAAO,IAAI;KAAO,MAAM,IAAI;KAAM,OAAO,aAAa,IAAI;KAAG,gBAAgB,OAAO,GAAG;KAAI,UAAA;IAAqB,CAAA,IAC7H,oBAAC,aAAD;KAAa,OAAO,IAAI;KAAQ,UAAA;IAAqB,CAAA;GAC3D;EACF;CACF,CAAC;CACD,OAAO,oBAAC,WAAD;EAAc,GAAI;EAAO,SAAS;EAAa,MAAM,KAAK,KAAK,QAAQ,IAAI,IAAI;EAAG,WAAW,SAAS,OAAO,IAAI,IAAI,CAAC,CAAE;CAAM,CAAA;AACvI"}
@@ -0,0 +1,212 @@
1
+ const require_utils = require("../../lib/utils.cjs");
2
+ const require_UiServer = require("../../icons/components/UiServer.cjs");
3
+ const require_UiClock = require("../../icons/components/UiClock.cjs");
4
+ const require_ProgressBar = require("../ProgressBar.cjs");
5
+ const require_matrix_marks = require("./matrix-marks.cjs");
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ // src/data/test-runner/MatrixMarks.tsx
8
+ function MatrixMark({ mark, label, className, static: isStatic = false }) {
9
+ const token = require_matrix_marks.MATRIX_MARKS[mark];
10
+ const Glyph = token.icon;
11
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Glyph, {
12
+ ...label === "" ? {} : { title: label ?? token.label },
13
+ className: require_utils.cn("size-3.5 shrink-0", token.tone, token.spin && !isStatic && "animate-spin", className),
14
+ "data-mark": mark
15
+ });
16
+ }
17
+ /** Outcome counts as glyph + number, in matrix order. */
18
+ function MatrixMix({ counts, unit, always = [], static: isStatic = false }) {
19
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
20
+ role: "group",
21
+ "aria-label": `${unit} by outcome`,
22
+ className: "flex shrink-0 items-center gap-2 text-xs tabular-nums",
23
+ "data-mix": unit,
24
+ children: require_matrix_marks.MATRIX_ORDER.filter((key) => (counts[key] ?? 0) > 0 || always.includes(key)).map((key) => {
25
+ const text = `${counts[key] ?? 0} ${require_matrix_marks.MATRIX_MARKS[key].label} ${unit}`;
26
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
27
+ role: "img",
28
+ "aria-label": text,
29
+ title: text,
30
+ className: require_utils.cn("inline-flex items-center gap-0.5", require_matrix_marks.MATRIX_MARKS[key].tone),
31
+ "data-mix-outcome": key,
32
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MatrixMark, {
33
+ mark: key,
34
+ label: "",
35
+ static: isStatic
36
+ }), counts[key] ?? 0]
37
+ }, key);
38
+ })
39
+ });
40
+ }
41
+ function MatrixElapsed({ ms, running, clock = false }) {
42
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
43
+ className: require_utils.cn("inline-flex shrink-0 items-center gap-1 whitespace-nowrap text-[11px] tabular-nums", running ? "text-blue-700 dark:text-blue-300" : "text-muted-foreground"),
44
+ title: running ? "elapsed so far" : "total duration",
45
+ "data-duration": "",
46
+ children: [clock && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_UiClock.UiClock, {
47
+ className: "size-3",
48
+ "aria-hidden": "true"
49
+ }), require_matrix_marks.formatMatrixDuration(ms)]
50
+ });
51
+ }
52
+ /**
53
+ * A plan with no run in an environment: pending while queued, error when it
54
+ * never started, hollow when not part of that run.
55
+ */
56
+ function EmptyMatrixCell({ outcome, detail, title, bare = false }) {
57
+ const neverStarted = detail === "never started";
58
+ if (!neverStarted && outcome !== "queued" && outcome !== "absent") throw new Error(`unexpected empty matrix cell ${outcome}: ${title}`);
59
+ const mark = neverStarted ? "error" : outcome === "queued" ? "pending" : "absent";
60
+ const label = neverStarted ? "never started" : require_matrix_marks.MATRIX_MARKS[mark].label;
61
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
62
+ title,
63
+ className: "flex h-5 min-w-0 items-center gap-1.5 text-xs",
64
+ "data-empty-cell": mark,
65
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MatrixMark, {
66
+ mark,
67
+ label
68
+ }), !bare && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
69
+ className: require_matrix_marks.MATRIX_MARKS[mark].tone,
70
+ children: label
71
+ })]
72
+ });
73
+ }
74
+ function MatrixLegend({ static: isStatic = false }) {
75
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
76
+ className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground",
77
+ "data-batch-legend": "",
78
+ children: [require_matrix_marks.MATRIX_ORDER.map((key) => {
79
+ const token = require_matrix_marks.MATRIX_MARKS[key];
80
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
81
+ className: "inline-flex items-center gap-1",
82
+ "data-legend-mark": key,
83
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MatrixMark, {
84
+ mark: key,
85
+ label: "",
86
+ static: isStatic
87
+ }), token.legend ?? token.label]
88
+ }, key);
89
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
90
+ className: "inline-flex items-center gap-1",
91
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_UiClock.UiClock, {
92
+ className: "size-3",
93
+ "aria-hidden": "true"
94
+ }), "elapsed · total duration"]
95
+ })]
96
+ });
97
+ }
98
+ /** A context name, always in the same chip, so an environment never reads as a plan or a status. */
99
+ function EnvChip({ context, className }) {
100
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
101
+ className: require_utils.cn("inline-flex items-center gap-1 rounded border border-border bg-muted/50 px-1.5 py-0.5 font-mono text-[11px] text-foreground", className),
102
+ "data-env-chip": context,
103
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_UiServer.UiServer, {
104
+ className: "size-3 text-muted-foreground",
105
+ "aria-hidden": "true"
106
+ }), context]
107
+ });
108
+ }
109
+ var HEADER_GRID = "grid min-w-48 grid-rows-[auto_auto_auto] gap-1.5";
110
+ var HEADER_ROW = "flex h-5 min-w-0 items-center gap-2";
111
+ /**
112
+ * One environment's column head in three fixed rows: its chip, the plans'
113
+ * progress with the elapsed time, and the plan verdict naming its units.
114
+ */
115
+ function MatrixEnvHeader({ context, counts, durationMs, running, renderChip, aside, static: isStatic = false }) {
116
+ const done = counts.passed + counts.warned + counts.failed + counts.error;
117
+ const chip = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EnvChip, { context });
118
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
119
+ className: HEADER_GRID,
120
+ "data-env-header": context,
121
+ children: [
122
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
123
+ className: HEADER_ROW,
124
+ children: [renderChip && !isStatic ? renderChip(chip) : chip, aside]
125
+ }),
126
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
127
+ className: HEADER_ROW,
128
+ title: `${done} of ${counts.total} plans finished`,
129
+ "data-env-progress": "",
130
+ children: [
131
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
132
+ className: "min-w-0 flex-1",
133
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ProgressBar.ProgressBar, {
134
+ total: counts.total,
135
+ height: "h-1.5",
136
+ segments: require_matrix_marks.MATRIX_PLAN_BAR.map((key) => ({
137
+ count: counts[key],
138
+ color: require_matrix_marks.matrixBarClass(key, isStatic),
139
+ label: `${require_matrix_marks.MATRIX_MARKS[key].label} plans`
140
+ }))
141
+ })
142
+ }),
143
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
144
+ className: "shrink-0 whitespace-nowrap text-[11px] tabular-nums text-foreground",
145
+ children: [
146
+ done,
147
+ "/",
148
+ counts.total,
149
+ " plans"
150
+ ]
151
+ }),
152
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MatrixElapsed, {
153
+ ms: durationMs,
154
+ running,
155
+ clock: true
156
+ })
157
+ ]
158
+ }),
159
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
160
+ className: HEADER_ROW,
161
+ "data-env-verdict": "",
162
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MatrixMix, {
163
+ counts: {
164
+ passed: counts.passed,
165
+ warned: counts.warned,
166
+ running: counts.running,
167
+ pending: counts.queued,
168
+ failed: counts.failed,
169
+ error: counts.error
170
+ },
171
+ unit: "plans",
172
+ always: ["failed"],
173
+ static: isStatic
174
+ })
175
+ })
176
+ ]
177
+ });
178
+ }
179
+ /** An environment whose member run did not load, in the same three rows as MatrixEnvHeader. */
180
+ function MatrixUnavailableEnvHeader({ context }) {
181
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
182
+ className: HEADER_GRID,
183
+ "data-env-header": context,
184
+ children: [
185
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
186
+ className: HEADER_ROW,
187
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EnvChip, { context })
188
+ }),
189
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
190
+ className: `${HEADER_ROW} text-[11px] font-medium ${require_matrix_marks.MATRIX_MARKS.error.tone}`,
191
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MatrixMark, {
192
+ mark: "error",
193
+ label: ""
194
+ }), "did not load"]
195
+ }),
196
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
197
+ className: HEADER_ROW,
198
+ "aria-hidden": "true"
199
+ })
200
+ ]
201
+ });
202
+ }
203
+ exports.EmptyMatrixCell = EmptyMatrixCell;
204
+ exports.EnvChip = EnvChip;
205
+ exports.MatrixElapsed = MatrixElapsed;
206
+ exports.MatrixEnvHeader = MatrixEnvHeader;
207
+ exports.MatrixLegend = MatrixLegend;
208
+ exports.MatrixMark = MatrixMark;
209
+ exports.MatrixMix = MatrixMix;
210
+ exports.MatrixUnavailableEnvHeader = MatrixUnavailableEnvHeader;
211
+
212
+ //# sourceMappingURL=MatrixMarks.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatrixMarks.cjs","names":["MATRIX_MARKS","cn","MATRIX_ORDER","UiClock","formatMatrixDuration","UiServer","ProgressBar","MATRIX_PLAN_BAR","matrixBarClass"],"sources":["../../../src/data/test-runner/MatrixMarks.tsx"],"sourcesContent":["// Renders the matrix-marks.ts vocabulary: one outcome's glyph, outcome mixes,\n// durations, empty cells, the legend, environment chips and the environment\n// column header. Props-only, so a live web matrix and a static print template\n// draw the same marks; `static` drops animation and links for print.\n\nimport type { ReactNode } from \"react\";\nimport { UiClock, UiServer } from \"../../icons\";\nimport { cn } from \"../../lib/utils\";\nimport { ProgressBar } from \"../ProgressBar\";\nimport {\n MATRIX_MARKS,\n MATRIX_ORDER,\n MATRIX_PLAN_BAR,\n formatMatrixDuration,\n matrixBarClass,\n type MatrixCounts,\n type MatrixEnvCounts,\n type MatrixMarkKey,\n type MatrixMarkToken,\n} from \"./matrix-marks\";\n\nexport type MatrixMarkProps = {\n mark: MatrixMarkKey;\n /** Hover title; \"\" leaves the glyph untitled where the surrounding element already names it. */\n label?: string;\n className?: string;\n /** Print: never spins. */\n static?: boolean;\n};\n\nexport function MatrixMark({ mark, label, className, static: isStatic = false }: MatrixMarkProps) {\n const token: MatrixMarkToken = MATRIX_MARKS[mark];\n const Glyph = token.icon;\n return (\n <Glyph\n {...(label === \"\" ? {} : { title: label ?? token.label })}\n className={cn(\"size-3.5 shrink-0\", token.tone, token.spin && !isStatic && \"animate-spin\", className)}\n data-mark={mark}\n />\n );\n}\n\nexport type MatrixMixProps = {\n counts: MatrixCounts;\n unit: \"steps\" | \"plans\";\n /** Outcomes drawn even at zero; every other zero count is dropped. */\n always?: readonly MatrixMarkKey[];\n static?: boolean;\n};\n\n/** Outcome counts as glyph + number, in matrix order. */\nexport function MatrixMix({ counts, unit, always = [], static: isStatic = false }: MatrixMixProps) {\n return (\n <span role=\"group\" aria-label={`${unit} by outcome`} className=\"flex shrink-0 items-center gap-2 text-xs tabular-nums\" data-mix={unit}>\n {MATRIX_ORDER.filter((key) => (counts[key] ?? 0) > 0 || always.includes(key)).map((key) => {\n const text = `${counts[key] ?? 0} ${MATRIX_MARKS[key].label} ${unit}`;\n return (\n <span key={key} role=\"img\" aria-label={text} title={text} className={cn(\"inline-flex items-center gap-0.5\", MATRIX_MARKS[key].tone)} data-mix-outcome={key}>\n <MatrixMark mark={key} label=\"\" static={isStatic} />\n {counts[key] ?? 0}\n </span>\n );\n })}\n </span>\n );\n}\n\nexport type MatrixElapsedProps = {\n ms: number;\n /** Still counting: drawn blue and titled \"elapsed so far\". */\n running: boolean;\n /** Prefix a clock glyph. */\n clock?: boolean;\n};\n\nexport function MatrixElapsed({ ms, running, clock = false }: MatrixElapsedProps) {\n return (\n <span\n className={cn(\"inline-flex shrink-0 items-center gap-1 whitespace-nowrap text-[11px] tabular-nums\", running ? \"text-blue-700 dark:text-blue-300\" : \"text-muted-foreground\")}\n title={running ? \"elapsed so far\" : \"total duration\"}\n data-duration=\"\"\n >\n {clock && <UiClock className=\"size-3\" aria-hidden=\"true\" />}\n {formatMatrixDuration(ms)}\n </span>\n );\n}\n\nexport type EmptyMatrixCellProps = {\n /** The cell outcome: \"queued\", \"absent\", or \"error\" with detail \"never started\". Anything else throws. */\n outcome: string;\n /** Why a cell has no run: \"never started\". */\n detail?: string;\n /** Hover title of the cell. */\n title: string;\n /** The glyph alone (sub-step rows), its meaning on hover. */\n bare?: boolean;\n};\n\n/**\n * A plan with no run in an environment: pending while queued, error when it\n * never started, hollow when not part of that run.\n */\nexport function EmptyMatrixCell({ outcome, detail, title, bare = false }: EmptyMatrixCellProps) {\n const neverStarted = detail === \"never started\";\n if (!neverStarted && outcome !== \"queued\" && outcome !== \"absent\") throw new Error(`unexpected empty matrix cell ${outcome}: ${title}`);\n const mark: MatrixMarkKey = neverStarted ? \"error\" : outcome === \"queued\" ? \"pending\" : \"absent\";\n const label = neverStarted ? \"never started\" : MATRIX_MARKS[mark].label;\n return (\n <span title={title} className=\"flex h-5 min-w-0 items-center gap-1.5 text-xs\" data-empty-cell={mark}>\n <MatrixMark mark={mark} label={label} />\n {!bare && <span className={MATRIX_MARKS[mark].tone}>{label}</span>}\n </span>\n );\n}\n\nexport type MatrixLegendProps = { static?: boolean };\n\nexport function MatrixLegend({ static: isStatic = false }: MatrixLegendProps) {\n return (\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground\" data-batch-legend=\"\">\n {MATRIX_ORDER.map((key) => {\n const token: MatrixMarkToken = MATRIX_MARKS[key];\n return (\n <span key={key} className=\"inline-flex items-center gap-1\" data-legend-mark={key}>\n <MatrixMark mark={key} label=\"\" static={isStatic} />\n {token.legend ?? token.label}\n </span>\n );\n })}\n <span className=\"inline-flex items-center gap-1\">\n <UiClock className=\"size-3\" aria-hidden=\"true\" />\n elapsed · total duration\n </span>\n </div>\n );\n}\n\nexport type EnvChipProps = { context: string; className?: string };\n\n/** A context name, always in the same chip, so an environment never reads as a plan or a status. */\nexport function EnvChip({ context, className }: EnvChipProps) {\n return (\n <span\n className={cn(\"inline-flex items-center gap-1 rounded border border-border bg-muted/50 px-1.5 py-0.5 font-mono text-[11px] text-foreground\", className)}\n data-env-chip={context}\n >\n <UiServer className=\"size-3 text-muted-foreground\" aria-hidden=\"true\" />\n {context}\n </span>\n );\n}\n\nconst HEADER_GRID = \"grid min-w-48 grid-rows-[auto_auto_auto] gap-1.5\";\nconst HEADER_ROW = \"flex h-5 min-w-0 items-center gap-2\";\n\nexport type MatrixEnvHeaderProps = {\n context: string;\n counts: MatrixEnvCounts;\n durationMs: number;\n /** The environment's run is still running: its elapsed time is still counting. */\n running: boolean;\n /** Wraps the chip, e.g. in the host router's link to the member run. Never called when static. */\n renderChip?: (chip: ReactNode) => ReactNode;\n /** Drawn beside the chip, e.g. how often the member was retried. */\n aside?: ReactNode;\n static?: boolean;\n};\n\n/**\n * One environment's column head in three fixed rows: its chip, the plans'\n * progress with the elapsed time, and the plan verdict naming its units.\n */\nexport function MatrixEnvHeader({ context, counts, durationMs, running, renderChip, aside, static: isStatic = false }: MatrixEnvHeaderProps) {\n const done = counts.passed + counts.warned + counts.failed + counts.error;\n const chip = <EnvChip context={context} />;\n return (\n <div className={HEADER_GRID} data-env-header={context}>\n <div className={HEADER_ROW}>\n {renderChip && !isStatic ? renderChip(chip) : chip}\n {aside}\n </div>\n <div className={HEADER_ROW} title={`${done} of ${counts.total} plans finished`} data-env-progress=\"\">\n <span className=\"min-w-0 flex-1\">\n <ProgressBar\n total={counts.total}\n height=\"h-1.5\"\n segments={MATRIX_PLAN_BAR.map((key) => ({ count: counts[key], color: matrixBarClass(key, isStatic), label: `${MATRIX_MARKS[key].label} plans` }))}\n />\n </span>\n <span className=\"shrink-0 whitespace-nowrap text-[11px] tabular-nums text-foreground\">\n {done}/{counts.total} plans\n </span>\n <MatrixElapsed ms={durationMs} running={running} clock />\n </div>\n <div className={HEADER_ROW} data-env-verdict=\"\">\n <MatrixMix\n counts={{ passed: counts.passed, warned: counts.warned, running: counts.running, pending: counts.queued, failed: counts.failed, error: counts.error }}\n unit=\"plans\"\n always={[\"failed\"]}\n static={isStatic}\n />\n </div>\n </div>\n );\n}\n\nexport type MatrixUnavailableEnvHeaderProps = { context: string };\n\n/** An environment whose member run did not load, in the same three rows as MatrixEnvHeader. */\nexport function MatrixUnavailableEnvHeader({ context }: MatrixUnavailableEnvHeaderProps) {\n return (\n <div className={HEADER_GRID} data-env-header={context}>\n <div className={HEADER_ROW}>\n <EnvChip context={context} />\n </div>\n <div className={`${HEADER_ROW} text-[11px] font-medium ${MATRIX_MARKS.error.tone}`}>\n <MatrixMark mark=\"error\" label=\"\" />\n did not load\n </div>\n <div className={HEADER_ROW} aria-hidden=\"true\" />\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import { ReactNode } from 'react';
2
+ import { MatrixCounts, MatrixEnvCounts, MatrixMarkKey } from './matrix-marks.js';
3
+ export type MatrixMarkProps = {
4
+ mark: MatrixMarkKey;
5
+ /** Hover title; "" leaves the glyph untitled where the surrounding element already names it. */
6
+ label?: string;
7
+ className?: string;
8
+ /** Print: never spins. */
9
+ static?: boolean;
10
+ };
11
+ export declare function MatrixMark({ mark, label, className, static: isStatic }: MatrixMarkProps): import("react").JSX.Element;
12
+ export type MatrixMixProps = {
13
+ counts: MatrixCounts;
14
+ unit: "steps" | "plans";
15
+ /** Outcomes drawn even at zero; every other zero count is dropped. */
16
+ always?: readonly MatrixMarkKey[];
17
+ static?: boolean;
18
+ };
19
+ /** Outcome counts as glyph + number, in matrix order. */
20
+ export declare function MatrixMix({ counts, unit, always, static: isStatic }: MatrixMixProps): import("react").JSX.Element;
21
+ export type MatrixElapsedProps = {
22
+ ms: number;
23
+ /** Still counting: drawn blue and titled "elapsed so far". */
24
+ running: boolean;
25
+ /** Prefix a clock glyph. */
26
+ clock?: boolean;
27
+ };
28
+ export declare function MatrixElapsed({ ms, running, clock }: MatrixElapsedProps): import("react").JSX.Element;
29
+ export type EmptyMatrixCellProps = {
30
+ /** The cell outcome: "queued", "absent", or "error" with detail "never started". Anything else throws. */
31
+ outcome: string;
32
+ /** Why a cell has no run: "never started". */
33
+ detail?: string;
34
+ /** Hover title of the cell. */
35
+ title: string;
36
+ /** The glyph alone (sub-step rows), its meaning on hover. */
37
+ bare?: boolean;
38
+ };
39
+ /**
40
+ * A plan with no run in an environment: pending while queued, error when it
41
+ * never started, hollow when not part of that run.
42
+ */
43
+ export declare function EmptyMatrixCell({ outcome, detail, title, bare }: EmptyMatrixCellProps): import("react").JSX.Element;
44
+ export type MatrixLegendProps = {
45
+ static?: boolean;
46
+ };
47
+ export declare function MatrixLegend({ static: isStatic }: MatrixLegendProps): import("react").JSX.Element;
48
+ export type EnvChipProps = {
49
+ context: string;
50
+ className?: string;
51
+ };
52
+ /** A context name, always in the same chip, so an environment never reads as a plan or a status. */
53
+ export declare function EnvChip({ context, className }: EnvChipProps): import("react").JSX.Element;
54
+ export type MatrixEnvHeaderProps = {
55
+ context: string;
56
+ counts: MatrixEnvCounts;
57
+ durationMs: number;
58
+ /** The environment's run is still running: its elapsed time is still counting. */
59
+ running: boolean;
60
+ /** Wraps the chip, e.g. in the host router's link to the member run. Never called when static. */
61
+ renderChip?: (chip: ReactNode) => ReactNode;
62
+ /** Drawn beside the chip, e.g. how often the member was retried. */
63
+ aside?: ReactNode;
64
+ static?: boolean;
65
+ };
66
+ /**
67
+ * One environment's column head in three fixed rows: its chip, the plans'
68
+ * progress with the elapsed time, and the plan verdict naming its units.
69
+ */
70
+ export declare function MatrixEnvHeader({ context, counts, durationMs, running, renderChip, aside, static: isStatic }: MatrixEnvHeaderProps): import("react").JSX.Element;
71
+ export type MatrixUnavailableEnvHeaderProps = {
72
+ context: string;
73
+ };
74
+ /** An environment whose member run did not load, in the same three rows as MatrixEnvHeader. */
75
+ export declare function MatrixUnavailableEnvHeader({ context }: MatrixUnavailableEnvHeaderProps): import("react").JSX.Element;
76
+ //# sourceMappingURL=MatrixMarks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatrixMarks.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/MatrixMarks.tsx"],"names":[],"mappings":"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"}