@ai-matrx/design-system 0.31.0 → 0.34.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.
- package/CHANGELOG.md +59 -0
- package/dist/data-table/index.cjs +56 -12
- package/dist/data-table/index.cjs.map +1 -1
- package/dist/data-table/index.js +56 -12
- package/dist/data-table/index.js.map +1 -1
- package/dist/index.cjs +189 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +194 -96
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.34.0 — 2026-09-21
|
|
4
|
+
|
|
5
|
+
**The release gate was red on main, and the red was a stale expectation.**
|
|
6
|
+
|
|
7
|
+
0.33.0's tag could not publish: `default-copy-regressions.test.tsx` required a
|
|
8
|
+
JSON-`null` cell to copy as the literal word `null` in HTML and CSV, and
|
|
9
|
+
`@ai-matrx/kit` 0.16.1 had just stopped doing that on purpose — a host
|
|
10
|
+
normalises a missing cell to `null` so the row keeps its shape, and a row
|
|
11
|
+
copied out of this very table arrived in Sheets carrying `null` as TEXT in its
|
|
12
|
+
empty columns (observed live 2026-09-15). The same test's workbook leg had
|
|
13
|
+
always expected an empty cell, so it was asserting two answers for one value.
|
|
14
|
+
Both clauses now expect empty, with a clause that no copied cell may contain
|
|
15
|
+
the word again. No product code changed in this release beyond 0.33.0's
|
|
16
|
+
contents.
|
|
17
|
+
|
|
18
|
+
## 0.33.0 — 2026-09-21
|
|
19
|
+
|
|
20
|
+
**The organization picker stops negating the matches one click below it, and a
|
|
21
|
+
frozen column stops showing the rows sliding under it.**
|
|
22
|
+
|
|
23
|
+
- `OrganizationPicker` — when every match for a search is a test organization,
|
|
24
|
+
the picker used to say *"Nothing matches “X” outside the test organizations
|
|
25
|
+
below."* `isTestFixture` rows are query-filtered, so those rows below **are**
|
|
26
|
+
matches for X: the sentence opened by denying the thing sitting one click
|
|
27
|
+
away, and a person who reads "nothing matches" retypes their search instead
|
|
28
|
+
of clicking. It now says what is true and carries the click that reveals
|
|
29
|
+
them — *"1 match for “vis” is in your test organizations — show them"* — and
|
|
30
|
+
reads "listed below" once open. Two clauses in
|
|
31
|
+
`src/organization-picker.test.tsx` hold the wording.
|
|
32
|
+
- `MatrxDataTable` frozen columns are painted **opaque**, with the paint taken
|
|
33
|
+
from the semantic surface tokens rather than a literal colour, so a frozen
|
|
34
|
+
column matches its theme instead of being a hardcoded swatch and the
|
|
35
|
+
scrolled rows no longer show through it.
|
|
36
|
+
|
|
37
|
+
Additive: no API changed.
|
|
38
|
+
|
|
39
|
+
## 0.32.0 — 2026-09-21
|
|
40
|
+
|
|
41
|
+
**The organization picker stopped being a filing cabinet.**
|
|
42
|
+
|
|
43
|
+
On the account that ships the data product's demo ground, `OrganizationPicker`
|
|
44
|
+
drew 116 rows nine at a time, with no way to type a name, and 59 of them were
|
|
45
|
+
lane scratch organizations. VERIFIER-8 (MEDIUM-3) met it as the FIRST screen of
|
|
46
|
+
`/data-v2`. Three additions, all host-classified — the component still decides
|
|
47
|
+
nothing from a name:
|
|
48
|
+
|
|
49
|
+
- **Search**, appearing once the list passes eight rows: case-insensitive
|
|
50
|
+
substring over `name` and `abbreviation`. An empty box is exactly the list
|
|
51
|
+
that was there before, and a query that matches nothing says so instead of
|
|
52
|
+
rendering an empty list.
|
|
53
|
+
- **`isTestFixture`** rows are hidden by default behind `ArchivedDisclosure` —
|
|
54
|
+
the platform's ONE archive-style disclosure, not a second pattern — with the
|
|
55
|
+
hidden count always on screen. Hidden, never dropped. When every row is a
|
|
56
|
+
fixture the list says so rather than claiming to be empty.
|
|
57
|
+
- **`isOwn`** rows are drawn first, under the starred one.
|
|
58
|
+
|
|
59
|
+
Additive: a host that passes neither flag gets its previous list, in its
|
|
60
|
+
previous order, and under nine rows gets no search box.
|
|
61
|
+
|
|
3
62
|
## 0.31.0 — 2026-09-21
|
|
4
63
|
|
|
5
64
|
**A paste refusal now carries the value it refused.**
|
|
@@ -10084,8 +10084,26 @@ function pixelWidth(width) {
|
|
|
10084
10084
|
}
|
|
10085
10085
|
return void 0;
|
|
10086
10086
|
}
|
|
10087
|
-
var FROZEN_CELL_CLASS = "sm:sticky sm:left-[var(--matrx-frozen-left)] sm:z-20 sm:bg-
|
|
10088
|
-
var FROZEN_HEADER_CLASS = "sm:sticky sm:left-[var(--matrx-frozen-left)] sm:z-30";
|
|
10087
|
+
var FROZEN_CELL_CLASS = "sm:sticky sm:left-[var(--matrx-frozen-left)] sm:z-20 sm:bg-card";
|
|
10088
|
+
var FROZEN_HEADER_CLASS = "sm:sticky sm:left-[var(--matrx-frozen-left)] sm:z-30 sm:bg-muted";
|
|
10089
|
+
var FROZEN_ROW_TINT_CLASS = {
|
|
10090
|
+
slate: "sm:bg-[color-mix(in_oklab,var(--color-slate-100)_70%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-slate-800)_40%,var(--color-card))]",
|
|
10091
|
+
green: "sm:bg-[color-mix(in_oklab,var(--color-green-50)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-green-950)_40%,var(--color-card))]",
|
|
10092
|
+
amber: "sm:bg-[color-mix(in_oklab,var(--color-amber-50)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-amber-950)_40%,var(--color-card))]",
|
|
10093
|
+
red: "sm:bg-[color-mix(in_oklab,var(--color-red-50)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-red-950)_40%,var(--color-card))]",
|
|
10094
|
+
blue: "sm:bg-[color-mix(in_oklab,var(--color-blue-50)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-blue-950)_40%,var(--color-card))]",
|
|
10095
|
+
violet: "sm:bg-[color-mix(in_oklab,var(--color-violet-50)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-violet-950)_40%,var(--color-card))]",
|
|
10096
|
+
teal: "sm:bg-[color-mix(in_oklab,var(--color-teal-50)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-teal-950)_40%,var(--color-card))]"
|
|
10097
|
+
};
|
|
10098
|
+
var FROZEN_CELL_TINT_CLASS = {
|
|
10099
|
+
slate: "sm:bg-[color-mix(in_oklab,var(--color-slate-200)_70%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-slate-700)_50%,var(--color-card))]",
|
|
10100
|
+
green: "sm:bg-[color-mix(in_oklab,var(--color-green-100)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-green-900)_50%,var(--color-card))]",
|
|
10101
|
+
amber: "sm:bg-[color-mix(in_oklab,var(--color-amber-100)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-amber-900)_50%,var(--color-card))]",
|
|
10102
|
+
red: "sm:bg-[color-mix(in_oklab,var(--color-red-100)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-red-900)_50%,var(--color-card))]",
|
|
10103
|
+
blue: "sm:bg-[color-mix(in_oklab,var(--color-blue-100)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-blue-900)_50%,var(--color-card))]",
|
|
10104
|
+
violet: "sm:bg-[color-mix(in_oklab,var(--color-violet-100)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-violet-900)_50%,var(--color-card))]",
|
|
10105
|
+
teal: "sm:bg-[color-mix(in_oklab,var(--color-teal-100)_100%,var(--color-card))] dark:sm:bg-[color-mix(in_oklab,var(--color-teal-900)_50%,var(--color-card))]"
|
|
10106
|
+
};
|
|
10089
10107
|
var FROZEN_EDGE_CLASS = "sm:shadow-[inset_-1px_0_0_var(--border)]";
|
|
10090
10108
|
|
|
10091
10109
|
// src/field-formats/registry.ts
|
|
@@ -12749,23 +12767,29 @@ function MatrxDataTableCore({
|
|
|
12749
12767
|
const styleFieldOf = tableStyle?.fieldOf ?? ((id) => id);
|
|
12750
12768
|
const styleDocumentOf = tableStyle?.documentOf ?? ((row) => row);
|
|
12751
12769
|
const noChoiceColor = () => void 0;
|
|
12752
|
-
const
|
|
12753
|
-
if (!tableStyle) return
|
|
12754
|
-
|
|
12770
|
+
const rowTintColor = (row, id) => {
|
|
12771
|
+
if (!tableStyle) return null;
|
|
12772
|
+
return resolveRowColor(
|
|
12755
12773
|
tableStyle.style,
|
|
12756
12774
|
{ id, data: styleDocumentOf(row) },
|
|
12757
12775
|
tableStyle.choiceColorFor ?? noChoiceColor
|
|
12758
12776
|
);
|
|
12777
|
+
};
|
|
12778
|
+
const rowTintClass = (row, id) => {
|
|
12779
|
+
const color = rowTintColor(row, id);
|
|
12759
12780
|
return color ? ROW_TINT_CLASS[color] : void 0;
|
|
12760
12781
|
};
|
|
12761
|
-
const
|
|
12762
|
-
if (!tableStyle) return
|
|
12763
|
-
|
|
12782
|
+
const cellTintColor = (row, id, colId) => {
|
|
12783
|
+
if (!tableStyle) return null;
|
|
12784
|
+
return resolveCellColor(
|
|
12764
12785
|
tableStyle.style,
|
|
12765
12786
|
{ id, data: styleDocumentOf(row) },
|
|
12766
12787
|
styleFieldOf(colId),
|
|
12767
12788
|
tableStyle.choiceColorFor ?? noChoiceColor
|
|
12768
12789
|
);
|
|
12790
|
+
};
|
|
12791
|
+
const cellTintClass = (row, id, colId) => {
|
|
12792
|
+
const color = cellTintColor(row, id, colId);
|
|
12769
12793
|
return color ? CELL_TINT_CLASS[color] : void 0;
|
|
12770
12794
|
};
|
|
12771
12795
|
const declaredVisibleCopyColumns = (0, import_react21.useMemo)(
|
|
@@ -14611,7 +14635,10 @@ function MatrxDataTableCore({
|
|
|
14611
14635
|
"th",
|
|
14612
14636
|
{
|
|
14613
14637
|
"data-matrx-table-selection-column": true,
|
|
14614
|
-
className:
|
|
14638
|
+
className: cn(
|
|
14639
|
+
"h-9 w-9 px-2 text-left align-middle",
|
|
14640
|
+
frozenColumns.selectionOffset !== null && "sm:sticky sm:left-0 sm:z-30 sm:bg-muted"
|
|
14641
|
+
),
|
|
14615
14642
|
style: fixedUtilityWidth(fixedTableGeometry?.selectionWidth),
|
|
14616
14643
|
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14617
14644
|
"div",
|
|
@@ -14873,6 +14900,9 @@ function MatrxDataTableCore({
|
|
|
14873
14900
|
const displayRow = applyRowEdits(row, rowEdits);
|
|
14874
14901
|
const controls = buildRecordControls(displayRow);
|
|
14875
14902
|
const isChecked = selectedIdSet.has(id);
|
|
14903
|
+
const rowTint = rowTintColor(row, id);
|
|
14904
|
+
const canHoverFrozenCell = !rowTint && (detailEnabled || Boolean(onRowOpen) || canExpandRow(row));
|
|
14905
|
+
const frozenRowBackgroundClass = rowTint ? FROZEN_ROW_TINT_CLASS[rowTint] : highlightedIndex === index || isSelected ? "sm:bg-muted" : isChecked ? "sm:bg-[color-mix(in_oklab,var(--color-primary)_5%,var(--color-card))]" : zebra && index % 2 === 1 ? "sm:bg-[color-mix(in_oklab,var(--color-muted)_20%,var(--color-card))]" : "sm:bg-card";
|
|
14876
14906
|
const rowNode = /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
14877
14907
|
"tr",
|
|
14878
14908
|
{
|
|
@@ -14900,7 +14930,7 @@ function MatrxDataTableCore({
|
|
|
14900
14930
|
// Keep the mobile row opaque while the complete row scrolls
|
|
14901
14931
|
// horizontally. The translucent zebra/hover tints remain
|
|
14902
14932
|
// desktop-only so densely layered mobile content stays crisp.
|
|
14903
|
-
"border-b border-border/60 bg-card transition-colors",
|
|
14933
|
+
"group/matrx-row border-b border-border/60 bg-card transition-colors",
|
|
14904
14934
|
(detailEnabled || Boolean(onRowOpen) || canExpandRow(row)) && "cursor-pointer sm:hover:bg-muted/50",
|
|
14905
14935
|
isSelected && "bg-muted",
|
|
14906
14936
|
isChecked && "bg-primary/5",
|
|
@@ -14924,7 +14954,11 @@ function MatrxDataTableCore({
|
|
|
14924
14954
|
// When a data column is frozen the checkbox
|
|
14925
14955
|
// column has to freeze with it, or the first
|
|
14926
14956
|
// frozen column slides over the checkboxes.
|
|
14927
|
-
frozenColumns.selectionOffset !== null &&
|
|
14957
|
+
frozenColumns.selectionOffset !== null && cn(
|
|
14958
|
+
"sm:sticky sm:left-0 sm:z-20",
|
|
14959
|
+
frozenRowBackgroundClass,
|
|
14960
|
+
canHoverFrozenCell && "sm:group-hover/matrx-row:bg-[color-mix(in_oklab,var(--color-muted)_50%,var(--color-card))]"
|
|
14961
|
+
)
|
|
14928
14962
|
),
|
|
14929
14963
|
style: fixedUtilityWidth(fixedTableGeometry?.selectionWidth),
|
|
14930
14964
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -14964,6 +14998,12 @@ function MatrxDataTableCore({
|
|
|
14964
14998
|
const isColumnDragShadow = columnDragPreview?.draggedId === columnId(col) && columnDragPreview.targetId !== null;
|
|
14965
14999
|
const sheetCell = spreadsheetEnabled ? sheet.cellProps(id, columnId(col)) : null;
|
|
14966
15000
|
const carriesFillHandle = sheetCell !== null && sheet.isFillHandleCell(id, columnId(col));
|
|
15001
|
+
const frozen = frozenColumns.offsets[columnId(col)] !== void 0;
|
|
15002
|
+
const frozenCellTint = cellTintColor(
|
|
15003
|
+
row,
|
|
15004
|
+
id,
|
|
15005
|
+
columnId(col)
|
|
15006
|
+
);
|
|
14967
15007
|
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
14968
15008
|
"td",
|
|
14969
15009
|
{
|
|
@@ -14994,12 +15034,16 @@ function MatrxDataTableCore({
|
|
|
14994
15034
|
isColumnDragShadow && "bg-primary/10 shadow-[inset_2px_0_0_var(--primary),inset_-2px_0_0_var(--primary)]",
|
|
14995
15035
|
alignForFormat(col) === "center" && "text-center",
|
|
14996
15036
|
alignForFormat(col) === "right" && "text-right",
|
|
14997
|
-
|
|
15037
|
+
frozen && FROZEN_CELL_CLASS,
|
|
15038
|
+
frozen && frozenRowBackgroundClass,
|
|
15039
|
+
frozen && sheetCell?.["data-matrx-cell-selected"] && "sm:bg-[color-mix(in_oklab,var(--color-primary)_10%,var(--color-card))]",
|
|
15040
|
+
frozen && canHoverFrozenCell && "sm:group-hover/matrx-row:bg-[color-mix(in_oklab,var(--color-muted)_50%,var(--color-card))]",
|
|
14998
15041
|
frozenEdgeId === columnId(col) && FROZEN_EDGE_CLASS,
|
|
14999
15042
|
// A cell tint paints OVER the row tint beneath
|
|
15000
15043
|
// it, and the consumer's own hook comes last so
|
|
15001
15044
|
// it can always win.
|
|
15002
15045
|
cellTintClass(row, id, columnId(col)),
|
|
15046
|
+
frozen && frozenCellTint && FROZEN_CELL_TINT_CLASS[frozenCellTint],
|
|
15003
15047
|
cellClassName?.(row, columnId(col), index)
|
|
15004
15048
|
),
|
|
15005
15049
|
style: {
|