@ai-matrx/design-system 0.21.10 → 0.21.11

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,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.21.11
4
+
5
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
6
+ `git diff npm/design-system/v0.21.10..npm/design-system/v0.21.11 -- apps/shared/design-system`).
7
+ No source changes intended and no consumer action required.
8
+
3
9
  ## 0.21.10
4
10
 
5
11
  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-BAJiOaQL.cjs';
2
+ import { g as MatrxDataTableCopyConfig, M as MatrxColumnDef } from '../types-9Ii-b9EJ.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-Da781-Wq.js';
2
+ import { g as MatrxDataTableCopyConfig, M as MatrxColumnDef } from '../types-wy1EEaeG.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-BAJiOaQL.cjs';
1
+ import { M as MatrxColumnDef, C as ColumnFiltersState, S as SortState, L as LayeredFilterRule, T as TableSearchMatchMode, a as ColumnFilterValue } from '../types-9Ii-b9EJ.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-Da781-Wq.js';
1
+ import { M as MatrxColumnDef, C as ColumnFiltersState, S as SortState, L as LayeredFilterRule, T as TableSearchMatchMode, a as ColumnFilterValue } from '../types-wy1EEaeG.js';
2
2
  import '../content-transfer.js';
3
3
  import 'react';
4
4
  import '@ai-matrx/kit/content-transfer';
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentType, ReactNode, MouseEventHandler } from 'react';
3
- import { b as TableSavedViewsProps, c as MatrxDataTableRecordControls, d as MatrxDataTableDensity } from '../types-BAJiOaQL.cjs';
3
+ import { b as TableSavedViewsProps, c as MatrxDataTableRecordControls, d as MatrxDataTableDensity } from '../types-9Ii-b9EJ.cjs';
4
4
  import { CopyControlProps } from './copy-types.cjs';
5
5
  export { AgentPayloadInput, AiCustomSource, AiVariant, CopyExportConfig } from './copy-types.cjs';
6
6
  import '../content-transfer.cjs';
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentType, ReactNode, MouseEventHandler } from 'react';
3
- import { b as TableSavedViewsProps, c as MatrxDataTableRecordControls, d as MatrxDataTableDensity } from '../types-Da781-Wq.js';
3
+ import { b as TableSavedViewsProps, c as MatrxDataTableRecordControls, d as MatrxDataTableDensity } from '../types-wy1EEaeG.js';
4
4
  import { CopyControlProps } from './copy-types.js';
5
5
  export { AgentPayloadInput, AiCustomSource, AiVariant, CopyExportConfig } from './copy-types.js';
6
6
  import '../content-transfer.js';
@@ -5899,6 +5899,7 @@ function ColumnHeaderCell({
5899
5899
  onFilterChange,
5900
5900
  selectOptions = [],
5901
5901
  selectSingle = false,
5902
+ selectAllowCustom = false,
5902
5903
  align = "left",
5903
5904
  className,
5904
5905
  compact = false,
@@ -5934,9 +5935,13 @@ function ColumnHeaderCell({
5934
5935
  const filterActive = isColumnFilterActive(filterValue);
5935
5936
  const deferredFilter = filterApplyLabel !== void 0 || filterShowCancel || filterFooterHint !== void 0;
5936
5937
  const [filterOpen, setFilterOpen] = (0, import_react13.useState)(false);
5938
+ const [pendingNegation, setPendingNegation] = (0, import_react13.useState)(false);
5937
5939
  const [draftFilter, setDraftFilter] = (0, import_react13.useState)(filterValue);
5938
5940
  (0, import_react13.useEffect)(() => {
5939
- if (!filterOpen) setDraftFilter(filterValue);
5941
+ if (!filterOpen) {
5942
+ setDraftFilter(filterValue);
5943
+ setPendingNegation(filterValue?.negated ?? false);
5944
+ }
5940
5945
  }, [filterOpen, filterValue]);
5941
5946
  const applyFilter = () => {
5942
5947
  onFilterChange(draftFilter);
@@ -5948,6 +5953,7 @@ function ColumnHeaderCell({
5948
5953
  };
5949
5954
  const visibleFilter = deferredFilter ? draftFilter : filterValue;
5950
5955
  const setNegated = (negated) => {
5956
+ setPendingNegation(negated);
5951
5957
  if (!visibleFilter) return;
5952
5958
  const next = { ...visibleFilter, ...negated ? { negated: true } : {} };
5953
5959
  if (!negated) delete next.negated;
@@ -6024,12 +6030,13 @@ function ColumnHeaderCell({
6024
6030
  kind: filterKind,
6025
6031
  value: visibleFilter,
6026
6032
  onChange: (next) => {
6027
- const preservingNegation = next && visibleFilter?.negated ? { ...next, negated: true } : next;
6033
+ const preservingNegation = next && (visibleFilter?.negated ?? pendingNegation) ? { ...next, negated: true } : next;
6028
6034
  if (deferredFilter) setDraftFilter(preservingNegation);
6029
6035
  else onFilterChange(preservingNegation);
6030
6036
  },
6031
6037
  selectOptions,
6032
6038
  selectSingle,
6039
+ selectAllowCustom,
6033
6040
  ...markerLabels ? {
6034
6041
  booleanLabels: {
6035
6042
  all: "All",
@@ -6040,18 +6047,18 @@ function ColumnHeaderCell({
6040
6047
  allowNullModes
6041
6048
  }
6042
6049
  ) : null,
6043
- filterKind && visibleFilter && allowNegation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "mt-2 border-t border-border pt-2", children: [
6050
+ filterKind && allowNegation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "mt-2 border-t border-border pt-2", children: [
6044
6051
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "mb-1 text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: "Match mode" }),
6045
6052
  /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "grid grid-cols-2 gap-1 rounded-md border p-0.5", children: [
6046
6053
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6047
6054
  "button",
6048
6055
  {
6049
6056
  type: "button",
6050
- "aria-pressed": !visibleFilter.negated,
6057
+ "aria-pressed": !(visibleFilter?.negated ?? pendingNegation),
6051
6058
  onClick: () => setNegated(false),
6052
6059
  className: cn(
6053
6060
  "rounded px-2 py-1.5 text-xs transition-colors",
6054
- !visibleFilter.negated ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"
6061
+ !(visibleFilter?.negated ?? pendingNegation) ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"
6055
6062
  ),
6056
6063
  children: "Include"
6057
6064
  }
@@ -6060,11 +6067,11 @@ function ColumnHeaderCell({
6060
6067
  "button",
6061
6068
  {
6062
6069
  type: "button",
6063
- "aria-pressed": visibleFilter.negated === true,
6070
+ "aria-pressed": visibleFilter?.negated ?? pendingNegation,
6064
6071
  onClick: () => setNegated(true),
6065
6072
  className: cn(
6066
6073
  "rounded px-2 py-1.5 text-xs transition-colors",
6067
- visibleFilter.negated ? "bg-destructive text-destructive-foreground" : "text-muted-foreground hover:bg-muted"
6074
+ visibleFilter?.negated ?? pendingNegation ? "bg-destructive text-destructive-foreground" : "text-muted-foreground hover:bg-muted"
6068
6075
  ),
6069
6076
  children: "Exclude"
6070
6077
  }
@@ -6252,6 +6259,7 @@ function FilterBody({
6252
6259
  onChange,
6253
6260
  selectOptions,
6254
6261
  selectSingle = false,
6262
+ selectAllowCustom = false,
6255
6263
  allowNullModes = false,
6256
6264
  booleanLabels
6257
6265
  }) {
@@ -6315,15 +6323,29 @@ function FilterBody({
6315
6323
  }
6316
6324
  if (kind === "select") {
6317
6325
  const selected = value?.kind === "select" ? value.values ?? (value.value && value.value !== "__all__" ? [value.value] : []) : [];
6318
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6319
- SearchableSelectFilter,
6320
- {
6321
- selected,
6322
- options: selectOptions,
6323
- onChange,
6324
- single: selectSingle
6325
- }
6326
- );
6326
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "space-y-2", children: [
6327
+ allowNullModes && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex flex-wrap gap-1", "aria-label": "Blank checks", children: [["empty", "(empty)"], ["not_empty", "(not empty)"], ["null", "(null)"], ["not_null", "(not null)"]].map(([mode, label]) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6328
+ "button",
6329
+ {
6330
+ type: "button",
6331
+ "aria-pressed": value?.kind === "text" && value.mode === mode,
6332
+ className: "rounded border px-1.5 py-0.5 text-[10px] hover:bg-muted",
6333
+ onClick: () => onChange({ kind: "text", value: "", mode }),
6334
+ children: label
6335
+ },
6336
+ mode
6337
+ )) }),
6338
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6339
+ SearchableSelectFilter,
6340
+ {
6341
+ selected,
6342
+ options: selectOptions,
6343
+ onChange,
6344
+ single: selectSingle,
6345
+ allowCustom: selectAllowCustom
6346
+ }
6347
+ )
6348
+ ] });
6327
6349
  }
6328
6350
  if (kind === "boolean") {
6329
6351
  const current = value?.kind === "boolean" ? value.value : "__all__";
@@ -6355,7 +6377,8 @@ function SearchableSelectFilter({
6355
6377
  selected,
6356
6378
  options,
6357
6379
  onChange,
6358
- single = false
6380
+ single = false,
6381
+ allowCustom = false
6359
6382
  }) {
6360
6383
  const [query, setQuery] = (0, import_react13.useState)("");
6361
6384
  const filtered = (0, import_react13.useMemo)(() => {
@@ -6405,6 +6428,11 @@ function SearchableSelectFilter({
6405
6428
  /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(CommandList, { className: "max-h-48", children: [
6406
6429
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(CommandEmpty, { className: "py-3 text-xs text-muted-foreground", children: "No matches" }),
6407
6430
  /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(CommandGroup, { children: [
6431
+ allowCustom && query.trim() && !options.some((option) => option.value === query.trim()) && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(CommandItem, { value: `custom:${query.trim()}`, onSelect: () => toggle(query.trim()), className: "text-xs", children: [
6432
+ "Use \u201C",
6433
+ query.trim(),
6434
+ "\u201D"
6435
+ ] }),
6408
6436
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6409
6437
  CommandItem,
6410
6438
  {
@@ -8753,6 +8781,7 @@ function MatrxDataTableCore({
8753
8781
  hidePagination = false,
8754
8782
  filterUi,
8755
8783
  detail,
8784
+ expandedDetail,
8756
8785
  window: windowConfig,
8757
8786
  copy,
8758
8787
  contextMenu,
@@ -9620,7 +9649,20 @@ function MatrxDataTableCore({
9620
9649
  setWindowRowId(null);
9621
9650
  setWindowRowSnapshot(null);
9622
9651
  };
9652
+ const canExpandRow = (row) => Boolean(expandedDetail && (expandedDetail.canExpand?.(row) ?? true));
9653
+ const isRowExpanded = (row) => canExpandRow(row) && expandedDetail?.expandedId === getRowId(row);
9654
+ const toggleExpanded = (row) => {
9655
+ if (!expandedDetail || !canExpandRow(row)) return;
9656
+ const id = getRowId(row);
9657
+ expandedDetail.onExpandedIdChange(
9658
+ expandedDetail.expandedId === id ? null : id
9659
+ );
9660
+ };
9623
9661
  const openRow = (row) => {
9662
+ if (canExpandRow(row)) {
9663
+ toggleExpanded(row);
9664
+ return;
9665
+ }
9624
9666
  if (opensWindowOnRowClick) {
9625
9667
  openWindow(row);
9626
9668
  return;
@@ -9724,7 +9766,11 @@ function MatrxDataTableCore({
9724
9766
  } : {},
9725
9767
  ...editEnabled && visibleColumns.some(
9726
9768
  (column) => column.editable && (column.editableIf?.(row) ?? true)
9727
- ) ? { beginEdit: () => beginRowEdit(row) } : {}
9769
+ ) ? { beginEdit: () => beginRowEdit(row) } : {},
9770
+ ...canExpandRow(row) ? {
9771
+ isExpanded: isRowExpanded(row),
9772
+ toggleExpanded: () => toggleExpanded(row)
9773
+ } : {}
9728
9774
  };
9729
9775
  };
9730
9776
  const hierarchyRows = hierarchy?.rows ?? data;
@@ -10630,6 +10676,7 @@ function MatrxDataTableCore({
10630
10676
  ] }) }) : paginated.map((row, index) => {
10631
10677
  const id = getRowId(row);
10632
10678
  const displayRow = applyRowEdits(row, edits[id]);
10679
+ const controls = buildRecordControls(displayRow);
10633
10680
  const selectable = selection?.isRowSelectable?.(row) ?? Boolean(selection);
10634
10681
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { "data-row-id": id, className: "contents", children: mobileCards(displayRow, index, {
10635
10682
  renderCell: (columnKey) => {
@@ -10664,10 +10711,15 @@ function MatrxDataTableCore({
10664
10711
  ...copy === void 0 ? { defaultColumns: declaredVisibleCopyColumns } : {}
10665
10712
  }
10666
10713
  ) : null,
10667
- renderRowActions(displayRow, buildRecordControls(displayRow))
10714
+ renderRowActions(displayRow, controls)
10668
10715
  ]
10669
10716
  }
10670
- ) : null
10717
+ ) : null,
10718
+ ...canExpandRow(row) ? {
10719
+ isExpanded: isRowExpanded(row),
10720
+ toggleExpanded: () => toggleExpanded(row)
10721
+ } : {},
10722
+ expandedDetail: expandedDetail && isRowExpanded(row) ? expandedDetail.render(displayRow, controls) : null
10671
10723
  }) }, id);
10672
10724
  }),
10673
10725
  appendQuery !== null && isFetching && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
@@ -10857,6 +10909,7 @@ function MatrxDataTableCore({
10857
10909
  onFilterChange: (next) => setColumnFilter(id, next),
10858
10910
  selectOptions: meta?.options,
10859
10911
  selectSingle: col.filterSingle,
10912
+ selectAllowCustom: col.filterAllowCustom,
10860
10913
  filterApplyLabel: filterUi?.applyLabel,
10861
10914
  filterShowCancel: filterUi?.showCancel,
10862
10915
  filterFooterHint: filterUi?.footerHint,
@@ -10934,6 +10987,7 @@ function MatrxDataTableCore({
10934
10987
  const isSelected = selectedId === id;
10935
10988
  const rowEdits = edits[id];
10936
10989
  const displayRow = applyRowEdits(row, rowEdits);
10990
+ const controls = buildRecordControls(displayRow);
10937
10991
  const isChecked = selectedIdSet.has(id);
10938
10992
  const rowNode = /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
10939
10993
  "tr",
@@ -10962,7 +11016,7 @@ function MatrxDataTableCore({
10962
11016
  // horizontally. The translucent zebra/hover tints remain
10963
11017
  // desktop-only so densely layered mobile content stays crisp.
10964
11018
  "border-b border-border/60 bg-card transition-colors",
10965
- (detailEnabled || Boolean(onRowOpen)) && "cursor-pointer sm:hover:bg-muted/50",
11019
+ (detailEnabled || Boolean(onRowOpen) || canExpandRow(row)) && "cursor-pointer sm:hover:bg-muted/50",
10966
11020
  isSelected && "bg-muted",
10967
11021
  isChecked && "bg-primary/5",
10968
11022
  highlightedIndex === index && "bg-muted ring-1 ring-inset ring-primary/60",
@@ -11078,7 +11132,7 @@ function MatrxDataTableCore({
11078
11132
  ...copy === void 0 ? { defaultColumns: declaredVisibleCopyColumns } : {}
11079
11133
  }
11080
11134
  ) : null,
11081
- renderRowActions(displayRow, buildRecordControls(displayRow)),
11135
+ renderRowActions(displayRow, controls),
11082
11136
  windowEnabled ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(Tooltip, { children: [
11083
11137
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11084
11138
  Button,
@@ -11109,15 +11163,36 @@ function MatrxDataTableCore({
11109
11163
  id
11110
11164
  );
11111
11165
  const wrappedRow = rowWrapper ? rowWrapper(row, rowNode) : rowNode;
11112
- return hierarchy ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11113
- HierarchyDroppableRow,
11166
+ const inlineDetail = expandedDetail && isRowExpanded(row) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11167
+ "tr",
11114
11168
  {
11115
- id,
11116
- disabled: !canDropOn(row),
11117
- children: wrappedRow
11169
+ "data-matrx-table-expanded-detail": id,
11170
+ className: cn("bg-muted/20", expandedDetail.className),
11171
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11172
+ "td",
11173
+ {
11174
+ colSpan: visibleColumns.length + leadingCols + (showActionsCol ? 1 : 0),
11175
+ className: "p-4",
11176
+ children: expandedDetail.render(displayRow, controls)
11177
+ }
11178
+ )
11118
11179
  },
11119
- id
11120
- ) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react20.Fragment, { children: wrappedRow }, id);
11180
+ `${id}:expanded-detail`
11181
+ ) : null;
11182
+ return hierarchy ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_react20.Fragment, { children: [
11183
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11184
+ HierarchyDroppableRow,
11185
+ {
11186
+ id,
11187
+ disabled: !canDropOn(row),
11188
+ children: wrappedRow
11189
+ }
11190
+ ),
11191
+ inlineDetail
11192
+ ] }, id) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_react20.Fragment, { children: [
11193
+ wrappedRow,
11194
+ inlineDetail
11195
+ ] }, id);
11121
11196
  }),
11122
11197
  appendQuery !== null && isFetching && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("tr", { "data-matrx-table-append-loading-row": true, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11123
11198
  "td",