@ai-matrx/design-system 0.21.9 → 0.21.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/data-table/copy-helpers.cjs.map +1 -1
  3. package/dist/data-table/copy-helpers.d.cts +1 -1
  4. package/dist/data-table/copy-helpers.d.ts +1 -1
  5. package/dist/data-table/copy-helpers.js.map +1 -1
  6. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  7. package/dist/data-table/data-row-inspector.js.map +1 -1
  8. package/dist/data-table/data-row-window.cjs.map +1 -1
  9. package/dist/data-table/data-row-window.js.map +1 -1
  10. package/dist/data-table/filter-engine.cjs +1 -1
  11. package/dist/data-table/filter-engine.cjs.map +1 -1
  12. package/dist/data-table/filter-engine.d.cts +1 -1
  13. package/dist/data-table/filter-engine.d.ts +1 -1
  14. package/dist/data-table/filter-engine.js +1 -1
  15. package/dist/data-table/filter-engine.js.map +1 -1
  16. package/dist/data-table/host.d.cts +1 -1
  17. package/dist/data-table/host.d.ts +1 -1
  18. package/dist/data-table/index.cjs +86 -26
  19. package/dist/data-table/index.cjs.map +1 -1
  20. package/dist/data-table/index.d.cts +2 -2
  21. package/dist/data-table/index.d.ts +2 -2
  22. package/dist/data-table/index.js +86 -26
  23. package/dist/data-table/index.js.map +1 -1
  24. package/dist/data-table/infer-filter.cjs +16 -6
  25. package/dist/data-table/infer-filter.cjs.map +1 -1
  26. package/dist/data-table/infer-filter.d.cts +1 -1
  27. package/dist/data-table/infer-filter.d.ts +1 -1
  28. package/dist/data-table/infer-filter.js +16 -6
  29. package/dist/data-table/infer-filter.js.map +1 -1
  30. package/dist/data-table/layered-filters.d.cts +1 -1
  31. package/dist/data-table/layered-filters.d.ts +1 -1
  32. package/dist/data-table/pagination.cjs +28 -14
  33. package/dist/data-table/pagination.cjs.map +1 -1
  34. package/dist/data-table/pagination.d.cts +7 -1
  35. package/dist/data-table/pagination.d.ts +7 -1
  36. package/dist/data-table/pagination.js +28 -14
  37. package/dist/data-table/pagination.js.map +1 -1
  38. package/dist/data-table/query-control.cjs +16 -6
  39. package/dist/data-table/query-control.cjs.map +1 -1
  40. package/dist/data-table/query-control.d.cts +1 -1
  41. package/dist/data-table/query-control.d.ts +1 -1
  42. package/dist/data-table/query-control.js +16 -6
  43. package/dist/data-table/query-control.js.map +1 -1
  44. package/dist/data-table/types.cjs.map +1 -1
  45. package/dist/data-table/types.d.cts +1 -1
  46. package/dist/data-table/types.d.ts +1 -1
  47. package/dist/data-table/url-state.d.cts +1 -1
  48. package/dist/data-table/url-state.d.ts +1 -1
  49. package/dist/data-table/xlsx.cjs.map +1 -1
  50. package/dist/data-table/xlsx.d.cts +1 -1
  51. package/dist/data-table/xlsx.d.ts +1 -1
  52. package/dist/data-table/xlsx.js.map +1 -1
  53. package/dist/{types-CqA8mpjE.d.cts → types-BAJiOaQL.d.cts} +7 -0
  54. package/dist/{types-CuTdr8mW.d.ts → types-Da781-Wq.d.ts} +7 -0
  55. package/package.json +1 -1
@@ -1991,6 +1991,7 @@ function PageNavigationControl({
1991
1991
  }
1992
1992
  function PaginationAction({
1993
1993
  HostAction,
1994
+ compact = false,
1994
1995
  active = false,
1995
1996
  disabledHint,
1996
1997
  visibilityClassName = "inline-flex",
@@ -2019,6 +2020,7 @@ function PaginationAction({
2019
2020
  onClick: props.onClick,
2020
2021
  className: cn(
2021
2022
  PAGINATION_ACTION_CLASS,
2023
+ compact && "h-8 w-8 min-h-8 min-w-8",
2022
2024
  active && PAGINATION_ACTIVE_CLASS,
2023
2025
  fallbackClassName
2024
2026
  ),
@@ -2032,6 +2034,8 @@ var PAGINATION_ACTION_CLASS = "h-11 w-11 min-h-11 min-w-11 rounded-md border bor
2032
2034
  var PAGINATION_ACTIVE_CLASS = "border-primary bg-primary text-primary-foreground hover:bg-primary/90";
2033
2035
  function GenericTablePagination({
2034
2036
  totalItems,
2037
+ unknownTotal,
2038
+ isFetching = false,
2035
2039
  itemsPerPage,
2036
2040
  currentPage,
2037
2041
  onPageChange,
@@ -2072,11 +2076,12 @@ function GenericTablePagination({
2072
2076
  (_, i) => startPage + i
2073
2077
  );
2074
2078
  };
2075
- const isFirstPageDisabled = currentPage <= 1;
2076
- const isLastPageDisabled = currentPage >= totalPages;
2079
+ const isFirstPageDisabled = isFetching || currentPage <= 1;
2080
+ const isLastPageDisabled = isFetching || (unknownTotal ? !unknownTotal.hasNextPage : currentPage >= totalPages);
2077
2081
  const startItem = totalItems === 0 ? 0 : progressive ? 1 : (currentPage - 1) * effectiveItemsPerPage + 1;
2078
2082
  const endItem = Math.min(progressive?.shownCount ?? currentPage * effectiveItemsPerPage, totalItems);
2079
2083
  const defaultLabelFormat = (start, end, total) => {
2084
+ if (unknownTotal) return `${unknownTotal.pageRowCount.toLocaleString()} on page ${currentPage.toLocaleString()}`;
2080
2085
  if (progressive) return progressive.loadedCount !== void 0 && progressive.loadedCount !== total ? `${end} shown / ${total} matching \xB7 ${progressive.loadedCount} loaded` : `${end} shown / ${total} loaded`;
2081
2086
  return compact ? `${start}-${end} of ${total}` : `Showing ${start} to ${end} of ${total} entries`;
2082
2087
  };
@@ -2101,6 +2106,7 @@ function GenericTablePagination({
2101
2106
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2102
2107
  Select,
2103
2108
  {
2109
+ disabled: isFetching,
2104
2110
  value: itemsPerPage.toString(),
2105
2111
  onValueChange: (value) => onItemsPerPageChange(parseInt(value)),
2106
2112
  children: [
@@ -2117,7 +2123,7 @@ function GenericTablePagination({
2117
2123
  ),
2118
2124
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(SelectContent, { children: [
2119
2125
  availablePageSizes.map((size) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SelectItem, { value: size.toString(), children: size }, size)),
2120
- showAllOption ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SelectItem, { value: allValue.toString(), children: allOptionLabel }) : null
2126
+ showAllOption && !unknownTotal ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SelectItem, { value: allValue.toString(), children: allOptionLabel }) : null
2121
2127
  ] })
2122
2128
  ]
2123
2129
  }
@@ -2129,7 +2135,7 @@ function GenericTablePagination({
2129
2135
  {
2130
2136
  className: cn("flex min-w-0 justify-center", infoContainerClassName),
2131
2137
  children: showPageInfo && !hideEntriesInfo && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
2132
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "truncate text-xs tabular-nums text-muted-foreground sm:hidden", children: progressive ? `${endItem}/${totalItems} ${progressive.loadedCount !== void 0 && progressive.loadedCount !== totalItems ? "matching" : "loaded"}` : `${startItem}-${endItem} / ${totalItems}` }),
2138
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "truncate text-xs tabular-nums text-muted-foreground sm:hidden", children: labelFormat ? formatLabel(startItem, endItem, totalItems) : unknownTotal ? defaultLabelFormat(startItem, endItem, totalItems) : progressive ? `${endItem}/${totalItems} ${progressive.loadedCount !== void 0 && progressive.loadedCount !== totalItems ? "matching" : "loaded"}` : `${startItem}-${endItem} / ${totalItems}` }),
2133
2139
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2134
2140
  "span",
2135
2141
  {
@@ -2154,7 +2160,7 @@ function GenericTablePagination({
2154
2160
  }
2155
2161
  ) }),
2156
2162
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { children: "Show more already-loaded rows" })
2157
- ] }) : null : showPageControls && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2163
+ ] }) : null : showPageControls && (unknownTotal ? currentPage > 1 || unknownTotal.hasNextPage : totalPages > 1) && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2158
2164
  "div",
2159
2165
  {
2160
2166
  className: cn(
@@ -2167,8 +2173,9 @@ function GenericTablePagination({
2167
2173
  PaginationAction,
2168
2174
  {
2169
2175
  HostAction: host.ToolbarAction,
2176
+ compact,
2170
2177
  ariaLabel: "First page",
2171
- disabledHint: "Already on the first page",
2178
+ disabledHint: isFetching ? "Loading source page" : "Already on the first page",
2172
2179
  visibilityClassName: "hidden sm:inline-flex",
2173
2180
  fallbackClassName: navButtonClassName,
2174
2181
  onClick: () => onPageChange(1),
@@ -2180,41 +2187,46 @@ function GenericTablePagination({
2180
2187
  PaginationAction,
2181
2188
  {
2182
2189
  HostAction: host.ToolbarAction,
2190
+ compact,
2183
2191
  ariaLabel: "Previous page",
2184
- disabledHint: "Already on the first page",
2192
+ disabledHint: isFetching ? "Loading source page" : "Already on the first page",
2185
2193
  fallbackClassName: navButtonClassName,
2186
2194
  onClick: () => onPageChange(currentPage - 1),
2187
2195
  disabled: isFirstPageDisabled,
2188
2196
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ChevronLeft, { className: "h-5 w-5" })
2189
2197
  }
2190
2198
  ),
2191
- getPageNumbers(3).map((page) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2199
+ !unknownTotal && getPageNumbers(3).map((page) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2192
2200
  PaginationAction,
2193
2201
  {
2194
2202
  HostAction: host.ToolbarAction,
2203
+ compact,
2195
2204
  ariaLabel: `Page ${page}`,
2196
2205
  active: currentPage === page,
2197
- disabledHint: `Already on page ${page}`,
2206
+ disabledHint: isFetching ? "Loading source page" : `Already on page ${page}`,
2198
2207
  visibilityClassName: cn(
2199
2208
  "sm:hidden",
2200
2209
  page === currentPage ? "inline-flex" : "hidden min-[360px]:inline-flex"
2201
2210
  ),
2202
2211
  fallbackClassName: page === currentPage ? pageActiveButtonClassName : pageButtonClassName,
2203
2212
  onClick: () => onPageChange(page),
2213
+ disabled: isFetching,
2204
2214
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: page })
2205
2215
  },
2206
2216
  `mobile-${page}`
2207
2217
  )),
2208
- getPageNumbers().map((page) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2218
+ !unknownTotal && getPageNumbers().map((page) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2209
2219
  PaginationAction,
2210
2220
  {
2211
2221
  HostAction: host.ToolbarAction,
2222
+ compact,
2212
2223
  ariaLabel: `Page ${page}`,
2213
2224
  active: currentPage === page,
2214
- disabledHint: `Already on page ${page}`,
2225
+ disabledHint: isFetching ? "Loading source page" : `Already on page ${page}`,
2215
2226
  visibilityClassName: "hidden sm:inline-flex",
2216
2227
  fallbackClassName: currentPage === page ? pageActiveButtonClassName : pageButtonClassName,
2217
2228
  onClick: () => onPageChange(page),
2229
+ disabled: isFetching,
2218
2230
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: page })
2219
2231
  },
2220
2232
  `desktop-${page}`
@@ -2223,20 +2235,22 @@ function GenericTablePagination({
2223
2235
  PaginationAction,
2224
2236
  {
2225
2237
  HostAction: host.ToolbarAction,
2238
+ compact,
2226
2239
  ariaLabel: "Next page",
2227
- disabledHint: "Already on the last page",
2240
+ disabledHint: isFetching ? "Loading source page" : "Already on the last page",
2228
2241
  fallbackClassName: navButtonClassName,
2229
2242
  onClick: () => onPageChange(currentPage + 1),
2230
2243
  disabled: isLastPageDisabled,
2231
2244
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ChevronRight, { className: "h-5 w-5" })
2232
2245
  }
2233
2246
  ),
2234
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2247
+ !unknownTotal && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2235
2248
  PaginationAction,
2236
2249
  {
2237
2250
  HostAction: host.ToolbarAction,
2251
+ compact,
2238
2252
  ariaLabel: "Last page",
2239
- disabledHint: "Already on the last page",
2253
+ disabledHint: isFetching ? "Loading source page" : "Already on the last page",
2240
2254
  visibilityClassName: "hidden sm:inline-flex",
2241
2255
  fallbackClassName: navButtonClassName,
2242
2256
  onClick: () => onPageChange(totalPages),
@@ -5117,7 +5131,7 @@ function passesColumnFilter(value, filter) {
5117
5131
  if (selected.length === 0) return true;
5118
5132
  const values = selectCellValues(value);
5119
5133
  return selected.some(
5120
- (v) => v === SELECT_NULL_VALUE ? value == null : v === SELECT_EMPTY_VALUE ? values.length === 0 : v === SELECT_NOT_EMPTY_VALUE ? values.length > 0 : values.includes(v)
5134
+ (v) => v === SELECT_NULL_VALUE ? value == null : v === SELECT_EMPTY_VALUE ? values.length === 0 : v === SELECT_NOT_EMPTY_VALUE ? values.length > 0 : v === "" ? value === "" || Array.isArray(value) && value.includes("") : values.includes(v)
5121
5135
  );
5122
5136
  }
5123
5137
  case "boolean": {
@@ -6354,7 +6368,7 @@ function SearchableSelectFilter({
6354
6368
  const toggle = (v) => {
6355
6369
  if (single) {
6356
6370
  onChange(
6357
- selected.length === 1 && selected[0] === v ? void 0 : { kind: "select", value: v }
6371
+ selected.length === 1 && selected[0] === v ? void 0 : { kind: "select", value: v, ...v === "" ? { values: [v] } : {} }
6358
6372
  );
6359
6373
  return;
6360
6374
  }
@@ -8457,10 +8471,13 @@ function collectSelectOptions(col, rows) {
8457
8471
  const seen = /* @__PURE__ */ new Set();
8458
8472
  const options = [];
8459
8473
  let hasEmpty = false;
8474
+ let hasEmptyCollection = false;
8460
8475
  for (const row of rows) {
8461
- const values = selectCellValues(getCellValue(row, col));
8476
+ const cell = getCellValue(row, col);
8477
+ const values = selectCellValues(cell);
8462
8478
  if (values.length === 0) {
8463
8479
  hasEmpty = true;
8480
+ if (Array.isArray(cell)) hasEmptyCollection = true;
8464
8481
  continue;
8465
8482
  }
8466
8483
  for (const value of values) {
@@ -8469,12 +8486,18 @@ function collectSelectOptions(col, rows) {
8469
8486
  options.push({ value, label: value });
8470
8487
  }
8471
8488
  }
8472
- const base = col.filterOptions?.length ? [...col.filterOptions] : options.sort((a, b) => a.label.localeCompare(b.label));
8489
+ const base = col.filterOptions?.length ? col.filterOptions.map((option) => ({
8490
+ ...option,
8491
+ label: option.label.trim() ? option.label : option.value === "" ? "(empty string)" : option.value.trim() ? option.value : "(whitespace)"
8492
+ })) : options.sort((a, b) => a.label.localeCompare(b.label));
8473
8493
  if (hasEmpty) {
8474
- base.unshift(
8475
- { value: SELECT_EMPTY_VALUE, label: "(empty)" },
8476
- { value: SELECT_NOT_EMPTY_VALUE, label: "(not empty)" }
8477
- );
8494
+ const emptyOption = !hasEmptyCollection && base.some((option) => option.value === "") ? { value: SELECT_NULL_VALUE, label: "(null)" } : { value: SELECT_EMPTY_VALUE, label: "(empty)" };
8495
+ const additions = [];
8496
+ if (!base.some((option) => option.value === emptyOption.value)) additions.push(emptyOption);
8497
+ if (!base.some((option) => option.value === SELECT_NOT_EMPTY_VALUE)) {
8498
+ additions.push({ value: SELECT_NOT_EMPTY_VALUE, label: "(not empty)" });
8499
+ }
8500
+ base.unshift(...additions);
8478
8501
  }
8479
8502
  return base;
8480
8503
  }
@@ -8685,6 +8708,24 @@ function MatrxDataTableWithUrlState({
8685
8708
  );
8686
8709
  }
8687
8710
  var COLUMN_REORDER_ACTIVATION_DISTANCE = 6;
8711
+ var ROW_INTERACTIVE_DESCENDANT_SELECTOR = [
8712
+ "a",
8713
+ "button",
8714
+ "input",
8715
+ "select",
8716
+ "textarea",
8717
+ '[role="button"]',
8718
+ '[role="combobox"]',
8719
+ '[contenteditable="true"]',
8720
+ "[data-matrx-cell-control]"
8721
+ ].join(", ");
8722
+ function rowEventTargetsInteractiveDescendant(target) {
8723
+ const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
8724
+ return element?.closest(ROW_INTERACTIVE_DESCENDANT_SELECTOR) !== null;
8725
+ }
8726
+ function opensRowHref(event) {
8727
+ return event.metaKey || event.ctrlKey || event.shiftKey || event.button === 1;
8728
+ }
8688
8729
  function TableContextPassthrough({ children }) {
8689
8730
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_jsx_runtime41.Fragment, { children });
8690
8731
  }
@@ -8739,6 +8780,7 @@ function MatrxDataTableCore({
8739
8780
  tableClassName,
8740
8781
  mobileCards,
8741
8782
  mobileCardsBreakpoint = "sm",
8783
+ getRowHref,
8742
8784
  onRowOpen,
8743
8785
  density
8744
8786
  }) {
@@ -9217,7 +9259,12 @@ function MatrxDataTableCore({
9217
9259
  0,
9218
9260
  ...visibleActionStrips.map((element) => Math.ceil(element.scrollWidth))
9219
9261
  );
9220
- const actionsWidth = actionContentWidth || headerActionsWidth;
9262
+ const actionsHeader = table?.querySelector("th[data-matrx-table-actions-column]");
9263
+ const actionsLabel = actionsHeader?.querySelector("[data-matrx-table-actions-label]");
9264
+ const headerPadding = actionsHeader ? getComputedStyle(actionsHeader) : void 0;
9265
+ const measuredLabelWidth = actionsLabel?.getBoundingClientRect().width ?? 0;
9266
+ const labelWidth = measuredLabelWidth > 0 ? Math.ceil(measuredLabelWidth + (Number.parseFloat(headerPadding?.paddingLeft ?? "0") || 0) + (Number.parseFloat(headerPadding?.paddingRight ?? "0") || 0)) : 0;
9267
+ const actionsWidth = Math.max(actionContentWidth, labelWidth) || headerActionsWidth;
9221
9268
  return {
9222
9269
  ...headerTotal > 0 ? { tableWidth: Math.ceil(headerTotal) } : {},
9223
9270
  ...selectionWidth === void 0 ? {} : { selectionWidth },
@@ -10846,9 +10893,9 @@ function MatrxDataTableCore({
10846
10893
  "th",
10847
10894
  {
10848
10895
  "data-matrx-table-actions-column": true,
10849
- className: "h-9 w-px px-2 text-right align-middle text-xs font-semibold uppercase tracking-wide text-muted-foreground",
10896
+ className: "h-9 w-px whitespace-nowrap px-2 text-right align-middle text-xs font-semibold uppercase tracking-wide text-muted-foreground",
10850
10897
  style: fixedUtilityWidth(fixedTableGeometry?.actionsWidth),
10851
- children: "Actions"
10898
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { "data-matrx-table-actions-label": true, className: "inline-block whitespace-nowrap", children: "Actions" })
10852
10899
  }
10853
10900
  )
10854
10901
  ] })
@@ -10894,9 +10941,22 @@ function MatrxDataTableCore({
10894
10941
  "data-row-id": id,
10895
10942
  "data-state": isSelected ? "selected" : void 0,
10896
10943
  onClick: (e) => {
10897
- if (e.target.closest('a, button, input, select, textarea, [role="button"], [role="combobox"], [contenteditable="true"]')) return;
10944
+ if (rowEventTargetsInteractiveDescendant(e.target)) return;
10945
+ if (opensRowHref(e)) {
10946
+ const href = getRowHref?.(row);
10947
+ if (href) window.open(href, "_blank", "noopener");
10948
+ return;
10949
+ }
10898
10950
  openRow(row);
10899
10951
  },
10952
+ onAuxClick: (e) => {
10953
+ if (e.button !== 1 || rowEventTargetsInteractiveDescendant(e.target)) return;
10954
+ const href = getRowHref?.(row);
10955
+ if (href) {
10956
+ e.preventDefault();
10957
+ window.open(href, "_blank", "noopener");
10958
+ }
10959
+ },
10900
10960
  className: cn(
10901
10961
  // Keep the mobile row opaque while the complete row scrolls
10902
10962
  // horizontally. The translucent zebra/hover tints remain