@ai-matrx/design-system 0.39.2 → 0.39.4

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 CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.39.4
4
+
5
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
6
+ `git diff npm/design-system/v0.39.3..npm/design-system/v0.39.4 -- apps/shared/design-system`).
7
+ No source changes intended and no consumer action required.
8
+
9
+ ## 0.39.3
10
+
11
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
12
+ `git diff npm/design-system/v0.39.2..npm/design-system/v0.39.3 -- apps/shared/design-system`).
13
+ No source changes intended and no consumer action required.
14
+
15
+ ## Unreleased
16
+
17
+ ### Lane UI-FIX-19 (2026-09-24)
18
+
19
+ * **A row's colour wins at every width.** `MatrxDataTable` decides a row's background once, in
20
+ `row-background.ts` (`rowBackground`), for the row and its frozen cells alike: colour tint, then
21
+ keyboard highlight / open row / ticked row, then the zebra stripe, then the card. The stripe was
22
+ `sm:bg-muted/20` and the tint a bare `bg-*`; tailwind-merge keeps both, and at ≥640px the stripe
23
+ won the cascade, so every other coloured row went plain on a desktop (VERIFIER-19 #5). Under a
24
+ tint no stripe, selection wash or hover wash is emitted; the keyboard's ring stays. Suite
25
+ `MatrxDataTable.tint-beats-zebra.test.tsx`: RED on the prior bytes ("row 2 (Quoting) stripe:
26
+ sm:bg-muted/20"), GREEN 3/3. No consumer action.
27
+
3
28
  ## 0.39.2
4
29
 
5
30
  Automatic changed-only republish (docs/metadata drift since the last tag — see
@@ -1,5 +1,5 @@
1
1
  import { AgentPayloadInput } from './copy-types.cjs';
2
- import { g as MatrxDataTableCopyConfig, M as MatrxColumnDef } from '../types-Bq-K6JWF.cjs';
2
+ import { g as MatrxDataTableCopyConfig, M as MatrxColumnDef } from '../types-D7O3uOIs.cjs';
3
3
  import '../content-transfer.cjs';
4
4
  import 'react';
5
5
  import '@ai-matrx/kit/content-transfer';
@@ -1,5 +1,5 @@
1
1
  import { AgentPayloadInput } from './copy-types.js';
2
- import { g as MatrxDataTableCopyConfig, M as MatrxColumnDef } from '../types-CM9oqzia.js';
2
+ import { g as MatrxDataTableCopyConfig, M as MatrxColumnDef } from '../types-p13OrDj-.js';
3
3
  import '../content-transfer.js';
4
4
  import 'react';
5
5
  import '@ai-matrx/kit/content-transfer';
@@ -1,4 +1,4 @@
1
- import { M as MatrxColumnDef, C as ColumnFiltersState, S as SortState, L as LayeredFilterRule, T as TableSearchMatchMode, a as ColumnFilterValue } from '../types-Bq-K6JWF.cjs';
1
+ import { M as MatrxColumnDef, C as ColumnFiltersState, S as SortState, L as LayeredFilterRule, T as TableSearchMatchMode, a as ColumnFilterValue } from '../types-D7O3uOIs.cjs';
2
2
  import '../content-transfer.cjs';
3
3
  import 'react';
4
4
  import '@ai-matrx/kit/content-transfer';
@@ -1,4 +1,4 @@
1
- import { M as MatrxColumnDef, C as ColumnFiltersState, S as SortState, L as LayeredFilterRule, T as TableSearchMatchMode, a as ColumnFilterValue } from '../types-CM9oqzia.js';
1
+ import { M as MatrxColumnDef, C as ColumnFiltersState, S as SortState, L as LayeredFilterRule, T as TableSearchMatchMode, a as ColumnFilterValue } from '../types-p13OrDj-.js';
2
2
  import '../content-transfer.js';
3
3
  import 'react';
4
4
  import '@ai-matrx/kit/content-transfer';
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { ComponentType, ReactNode, MouseEventHandler } from 'react';
3
3
  import { CopyControlProps } from './copy-types.cjs';
4
4
  export { AgentPayloadInput, AiCustomSource, AiVariant, CopyExportConfig } from './copy-types.cjs';
5
- import { b as TableSavedViewsProps, c as MatrxDataTableDensity, d as MatrxDataTableRecordControls } from '../types-Bq-K6JWF.cjs';
5
+ import { b as TableSavedViewsProps, c as MatrxDataTableDensity, d as MatrxDataTableRecordControls } from '../types-D7O3uOIs.cjs';
6
6
  import { MatrxTableMenuTarget, MatrxTableMenuPayload } from './menu-targets.cjs';
7
7
  import '../content-transfer.cjs';
8
8
  import '@ai-matrx/kit/content-transfer';
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { ComponentType, ReactNode, MouseEventHandler } from 'react';
3
3
  import { CopyControlProps } from './copy-types.js';
4
4
  export { AgentPayloadInput, AiCustomSource, AiVariant, CopyExportConfig } from './copy-types.js';
5
- import { b as TableSavedViewsProps, c as MatrxDataTableDensity, d as MatrxDataTableRecordControls } from '../types-CM9oqzia.js';
5
+ import { b as TableSavedViewsProps, c as MatrxDataTableDensity, d as MatrxDataTableRecordControls } from '../types-p13OrDj-.js';
6
6
  import { MatrxTableMenuTarget, MatrxTableMenuPayload } from './menu-targets.js';
7
7
  import '../content-transfer.js';
8
8
  import '@ai-matrx/kit/content-transfer';
@@ -10194,6 +10194,40 @@ var FROZEN_CELL_TINT_CLASS = {
10194
10194
  };
10195
10195
  var FROZEN_EDGE_CLASS = "sm:shadow-[inset_-1px_0_0_var(--border)]";
10196
10196
 
10197
+ // src/data-table/row-background.ts
10198
+ function rowBackground(state) {
10199
+ const ring = state.highlighted ? " ring-1 ring-inset ring-primary/60" : "";
10200
+ if (state.tint) {
10201
+ return {
10202
+ row: ROW_TINT_CLASS[state.tint] + ring,
10203
+ frozen: FROZEN_ROW_TINT_CLASS[state.tint],
10204
+ frozenHover: false
10205
+ };
10206
+ }
10207
+ const hover = state.hoverable ? "sm:hover:bg-muted/50" : "";
10208
+ if (state.highlighted) {
10209
+ return { row: `bg-muted${ring} ${hover}`.trim(), frozen: "sm:bg-muted", frozenHover: state.hoverable };
10210
+ }
10211
+ if (state.selected) {
10212
+ return { row: `bg-muted ${hover}`.trim(), frozen: "sm:bg-muted", frozenHover: state.hoverable };
10213
+ }
10214
+ if (state.checked) {
10215
+ return {
10216
+ row: `bg-primary/5 ${hover}`.trim(),
10217
+ frozen: "sm:bg-[color-mix(in_oklab,var(--color-primary)_5%,var(--color-card))]",
10218
+ frozenHover: state.hoverable
10219
+ };
10220
+ }
10221
+ if (state.zebraOdd) {
10222
+ return {
10223
+ row: `sm:bg-muted/20 ${hover}`.trim(),
10224
+ frozen: "sm:bg-[color-mix(in_oklab,var(--color-muted)_20%,var(--color-card))]",
10225
+ frozenHover: state.hoverable
10226
+ };
10227
+ }
10228
+ return { row: hover, frozen: "sm:bg-card", frozenHover: state.hoverable };
10229
+ }
10230
+
10197
10231
  // src/field-formats/registry.ts
10198
10232
  var import_format3 = require("@ai-matrx/kit/format");
10199
10233
  function formatSignedDuration(totalSeconds) {
@@ -12306,7 +12340,9 @@ function MatrxDataTableCore({
12306
12340
  const remoteQuery = query?.mode === "controlled" || query?.mode === "controlled-append" ? query : null;
12307
12341
  const sourceProcessing = query?.mode === "controlled" || query?.mode === "controlled-local" ? query.sourceProcessing : appendQuery?.sourceProcessing;
12308
12342
  const appendUsesLocalProcessing = appendQuery !== null && sourceProcessing !== void 0;
12309
- const sourceOwnsColumnFilters = appendQuery !== null && sourceProcessing === void 0 ? true : sourceProcessing?.columnFilters === "source";
12343
+ const appendDefaultsToSourceProcessing = appendQuery !== null && sourceProcessing === void 0;
12344
+ const sourceColumnFilterOwnership = sourceProcessing?.columnFilters;
12345
+ const sourceOwnsColumnFilters = appendDefaultsToSourceProcessing ? true : sourceColumnFilterOwnership === "source" || typeof sourceColumnFilterOwnership === "object" && sourceColumnFilterOwnership.source.length > 0;
12310
12346
  const sourceOwnsSort = appendQuery !== null && sourceProcessing === void 0 ? true : sourceProcessing?.sort === "source";
12311
12347
  const sourceOwnsIntelligentSearch = sourceProcessing?.intelligentSearch === "source";
12312
12348
  const sourceOwnsSearch = remoteQuery?.mode === "controlled" || appendQuery !== null && sourceProcessing === void 0 || sourceProcessing?.search === "source" || sourceOwnsIntelligentSearch;
@@ -12379,6 +12415,17 @@ function MatrxDataTableCore({
12379
12415
  };
12380
12416
  const [internalColumnFilters, setInternalColumnFilters] = (0, import_react21.useState)({});
12381
12417
  const columnFilters = controlledQuery ? controlledQuery.state.columnFilters : internalColumnFilters;
12418
+ const localColumnFilters = (0, import_react21.useMemo)(() => {
12419
+ if (appendDefaultsToSourceProcessing) return {};
12420
+ if (sourceColumnFilterOwnership === "source") return {};
12421
+ if (sourceColumnFilterOwnership === void 0 || sourceColumnFilterOwnership === "local") {
12422
+ return columnFilters;
12423
+ }
12424
+ const sourceColumnIds = new Set(sourceColumnFilterOwnership.source);
12425
+ return Object.fromEntries(
12426
+ Object.entries(columnFilters).filter(([columnId2]) => !sourceColumnIds.has(columnId2))
12427
+ );
12428
+ }, [appendDefaultsToSourceProcessing, columnFilters, sourceColumnFilterOwnership]);
12382
12429
  const setColumnFilter = (id, next) => {
12383
12430
  const nextFilters = { ...columnFilters, [id]: next };
12384
12431
  if (controlledQuery) {
@@ -12892,10 +12939,6 @@ function MatrxDataTableCore({
12892
12939
  tableStyle.choiceColorFor ?? noChoiceColor
12893
12940
  );
12894
12941
  };
12895
- const rowTintClass = (row, id) => {
12896
- const color = rowTintColor(row, id);
12897
- return color ? ROW_TINT_CLASS[color] : void 0;
12898
- };
12899
12942
  const cellTintColor = (row, id, colId) => {
12900
12943
  if (!tableStyle) return null;
12901
12944
  return resolveCellColor(
@@ -12978,14 +13021,14 @@ function MatrxDataTableCore({
12978
13021
  ...intelligentSearchEnabled ? { searchScope } : {},
12979
13022
  anyOf: anyOfValue,
12980
13023
  layeredFilters,
12981
- columnFilters,
13024
+ columnFilters: localColumnFilters,
12982
13025
  sort
12983
13026
  });
12984
13027
  }
12985
13028
  const locallyFiltered = filterAndSortRows(
12986
13029
  data,
12987
13030
  intelligentSearchEnabled ? columns : visibleColumns,
12988
- sourceOwnsColumnFilters ? {} : columnFilters,
13031
+ localColumnFilters,
12989
13032
  sourceOwnsSort ? null : sort,
12990
13033
  "",
12991
13034
  // Global matching and identity ranking run once across all loaded fields below.
@@ -13010,7 +13053,7 @@ function MatrxDataTableCore({
13010
13053
  }, [
13011
13054
  data,
13012
13055
  visibleColumns,
13013
- columnFilters,
13056
+ localColumnFilters,
13014
13057
  sort,
13015
13058
  searchValue,
13016
13059
  toolbar,
@@ -13966,6 +14009,7 @@ function MatrxDataTableCore({
13966
14009
  );
13967
14010
  }, [host.rowContextRegistry, tableContextMenuInstanceId]);
13968
14011
  const showActionsCol = windowEnabled || Boolean(rowActions) || showInlineRowCopy;
14012
+ const getSelectionId = selection?.getSelectionId ?? getRowId;
13969
14013
  const selectedIdSet = (0, import_react21.useMemo)(
13970
14014
  () => new Set(selection?.selectedIds ?? []),
13971
14015
  [selection?.selectedIds]
@@ -13974,14 +14018,19 @@ function MatrxDataTableCore({
13974
14018
  (row) => selection?.isRowSelectable?.(row) ?? true
13975
14019
  );
13976
14020
  const selectedOnPage = selectableRows.filter(
13977
- (row) => selectedIdSet.has(getRowId(row))
14021
+ (row) => selectedIdSet.has(getSelectionId(row))
13978
14022
  );
13979
14023
  const allOnPageSelected = selectableRows.length > 0 && selectedOnPage.length === selectableRows.length;
13980
14024
  const someOnPageSelected = selectedOnPage.length > 0 && !allOnPageSelected;
13981
- const selectedRows = (0, import_react21.useMemo)(
13982
- () => data.filter((row) => selectedIdSet.has(getRowId(row))),
13983
- [data, selectedIdSet, getRowId]
13984
- );
14025
+ const selectedRows = (0, import_react21.useMemo)(() => {
14026
+ const resolved = /* @__PURE__ */ new Set();
14027
+ return data.filter((row) => {
14028
+ const id = getSelectionId(row);
14029
+ if (!selectedIdSet.has(id) || resolved.has(id)) return false;
14030
+ resolved.add(id);
14031
+ return true;
14032
+ });
14033
+ }, [data, getSelectionId, selectedIdSet]);
13985
14034
  const lastToggledIndex = (0, import_react21.useRef)(null);
13986
14035
  const setSelectedIds = (next) => selection?.onSelectedIdsChange([...next]);
13987
14036
  const toggleRowSelected = (index, shiftKey) => {
@@ -13989,7 +14038,7 @@ function MatrxDataTableCore({
13989
14038
  if (!paginated[index]) return;
13990
14039
  const { next, anchor } = toggleSelection({
13991
14040
  order: paginated,
13992
- idOf: getRowId,
14041
+ idOf: getSelectionId,
13993
14042
  selected: selectedIdSet,
13994
14043
  index,
13995
14044
  anchor: lastToggledIndex.current,
@@ -14003,7 +14052,7 @@ function MatrxDataTableCore({
14003
14052
  if (!selection) return;
14004
14053
  const next = new Set(selectedIdSet);
14005
14054
  for (const row of selectableRows) {
14006
- const id = getRowId(row);
14055
+ const id = getSelectionId(row);
14007
14056
  if (allOnPageSelected) next.delete(id);
14008
14057
  else next.add(id);
14009
14058
  }
@@ -14011,7 +14060,7 @@ function MatrxDataTableCore({
14011
14060
  setSelectedIds(next);
14012
14061
  };
14013
14062
  const selectionNoun = selection?.noun ?? "row";
14014
- const selectionCount = selection?.selectedIds.length ?? 0;
14063
+ const selectionCount = selectedIdSet.size;
14015
14064
  const leadingCols = selection ? 1 : 0;
14016
14065
  const renderedColSpan = renderedColumns.length + leadingCols + (showActionsCol ? 1 : 0) + (columnSpacers ? (columnSpacers.start > 0 ? 1 : 0) + (columnSpacers.end > 0 ? 1 : 0) : 0);
14017
14066
  const renderedFacets = controlledQuery ? toolbar?.facets?.map(
@@ -14613,15 +14662,16 @@ function MatrxDataTableCore({
14613
14662
  const column = columns.find((candidate) => columnId(candidate) === columnKey);
14614
14663
  return column ? renderRecordCell(row, column, index) : null;
14615
14664
  },
14616
- selected: selectedIdSet.has(id),
14665
+ selected: selectedIdSet.has(getSelectionId(row)),
14617
14666
  selectable,
14618
14667
  onSelectedChange: (nextSelected) => {
14619
- if (!selection || !selectable || nextSelected === selectedIdSet.has(id)) {
14668
+ if (!selection || !selectable || nextSelected === selectedIdSet.has(getSelectionId(row))) {
14620
14669
  return;
14621
14670
  }
14622
14671
  const next = new Set(selectedIdSet);
14623
- if (nextSelected) next.add(id);
14624
- else next.delete(id);
14672
+ const selectionId = getSelectionId(row);
14673
+ if (nextSelected) next.add(selectionId);
14674
+ else next.delete(selectionId);
14625
14675
  setSelectedIds(next);
14626
14676
  },
14627
14677
  actions: showInlineRowCopy || rowActions ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
@@ -15025,10 +15075,17 @@ function MatrxDataTableCore({
15025
15075
  const rowEdits = edits[id];
15026
15076
  const displayRow = applyRowEdits(row, rowEdits);
15027
15077
  const controls = buildRecordControls(displayRow);
15028
- const isChecked = selectedIdSet.has(id);
15029
- const rowTint = rowTintColor(row, id);
15030
- const canHoverFrozenCell = !rowTint && (detailEnabled || Boolean(onRowOpen) || canExpandRow(row));
15031
- 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";
15078
+ const isChecked = selectedIdSet.has(getSelectionId(row));
15079
+ const background = rowBackground({
15080
+ tint: rowTintColor(row, id),
15081
+ highlighted: highlightedIndex === index,
15082
+ selected: isSelected,
15083
+ checked: isChecked,
15084
+ zebraOdd: zebra && index % 2 === 1,
15085
+ hoverable: detailEnabled || Boolean(onRowOpen) || canExpandRow(row)
15086
+ });
15087
+ const canHoverFrozenCell = background.frozenHover;
15088
+ const frozenRowBackgroundClass = background.frozen;
15032
15089
  const rowNode = /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
15033
15090
  "tr",
15034
15091
  {
@@ -15057,19 +15114,13 @@ function MatrxDataTableCore({
15057
15114
  // horizontally. The translucent zebra/hover tints remain
15058
15115
  // desktop-only so densely layered mobile content stays crisp.
15059
15116
  "group/matrx-row border-b border-border/60 bg-card transition-colors",
15060
- (detailEnabled || Boolean(onRowOpen) || canExpandRow(row)) && "cursor-pointer sm:hover:bg-muted/50",
15061
- isSelected && "bg-muted",
15062
- isChecked && "bg-primary/5",
15063
- highlightedIndex === index && "bg-muted ring-1 ring-inset ring-primary/60",
15117
+ (detailEnabled || Boolean(onRowOpen) || canExpandRow(row)) && "cursor-pointer",
15064
15118
  rowClassName?.(row, index),
15065
15119
  draggedRowId === id && "opacity-40",
15066
- zebra && index % 2 === 1 && !isSelected && !isChecked && "sm:bg-muted/20",
15067
- // LAST so a colored row STAYS colored while selected
15068
- // and on an odd zebra stripe — `cn` is tailwind-merge
15069
- // and keeps the last background of a group. The
15070
- // checkbox already says the row is selected; the tint
15071
- // is the only thing saying WHY the row matters.
15072
- rowTintClass(row, id)
15120
+ // LAST, and decided once: tint, then highlight / open / ticked, then
15121
+ // the zebra stripe (./row-background.ts). Under a tint no stripe is
15122
+ // emitted at all, so no `sm:` class can win the cascade over it.
15123
+ background.row
15073
15124
  ),
15074
15125
  children: [
15075
15126
  selection ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
@@ -15494,7 +15545,7 @@ function MatrxDataTableCore({
15494
15545
  new Date(appendQuery.pagination.sourceUntil).toLocaleString(),
15495
15546
  "."
15496
15547
  ] }) : null,
15497
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { children: !isLoading && !isFetching && !appendQuery.pagination.loadAll?.isLoading && !scrollPagination.error && !appendQuery.pagination.hasNextPage && appendQuery.pagination.totalItems !== void 0 && data.length === appendQuery.pagination.totalItems ? "All source rows are loaded." : appendUsesLocalProcessing ? "Local search and filters cover loaded rows." : "Source paging is active." })
15548
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { children: !isLoading && !isFetching && !appendQuery.pagination.loadAll?.isLoading && !scrollPagination.error && !appendQuery.pagination.hasNextPage && appendQuery.pagination.totalItems !== void 0 && data.length === appendQuery.pagination.totalItems ? "All source rows are loaded." : appendUsesLocalProcessing ? sourceOwnsColumnFilters ? "Local processing covers loaded rows; source-owned column filters are applied by the source." : "Local search and filters cover loaded rows." : "Source paging is active." })
15498
15549
  ] })
15499
15550
  ] }) : null,
15500
15551
  scrollPagination.error ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { role: "alert", className: "text-destructive", children: scrollPagination.error.message }) : null,
@@ -15656,7 +15707,7 @@ function MatrxDataTableCore({
15656
15707
  }
15657
15708
  }
15658
15709
  ) : null,
15659
- selection.actions?.(selectedRows, selection.selectedIds)
15710
+ selection.actions?.(selectedRows, [...selectedIdSet])
15660
15711
  ] })
15661
15712
  ]
15662
15713
  }