@ai-matrx/design-system 0.20.5 → 0.20.8

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 (37) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/content-transfer.cjs +35 -15
  3. package/dist/content-transfer.cjs.map +1 -1
  4. package/dist/content-transfer.css +10 -2
  5. package/dist/content-transfer.js +35 -15
  6. package/dist/content-transfer.js.map +1 -1
  7. package/dist/data-table/copy-helpers.cjs.map +1 -1
  8. package/dist/data-table/copy-helpers.js.map +1 -1
  9. package/dist/data-table/data-row-inspector.cjs +33 -13
  10. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  11. package/dist/data-table/data-row-inspector.js +33 -13
  12. package/dist/data-table/data-row-inspector.js.map +1 -1
  13. package/dist/data-table/data-row-window.cjs +33 -13
  14. package/dist/data-table/data-row-window.cjs.map +1 -1
  15. package/dist/data-table/data-row-window.js +33 -13
  16. package/dist/data-table/data-row-window.js.map +1 -1
  17. package/dist/data-table/filter-engine.cjs +6 -2
  18. package/dist/data-table/filter-engine.cjs.map +1 -1
  19. package/dist/data-table/filter-engine.d.cts +3 -1
  20. package/dist/data-table/filter-engine.d.ts +3 -1
  21. package/dist/data-table/filter-engine.js +6 -2
  22. package/dist/data-table/filter-engine.js.map +1 -1
  23. package/dist/data-table/index.cjs +294 -228
  24. package/dist/data-table/index.cjs.map +1 -1
  25. package/dist/data-table/index.js +136 -70
  26. package/dist/data-table/index.js.map +1 -1
  27. package/dist/data-table/infer-filter.cjs +11 -7
  28. package/dist/data-table/infer-filter.cjs.map +1 -1
  29. package/dist/data-table/infer-filter.js +11 -7
  30. package/dist/data-table/infer-filter.js.map +1 -1
  31. package/dist/data-table/query-control.cjs +11 -7
  32. package/dist/data-table/query-control.cjs.map +1 -1
  33. package/dist/data-table/query-control.js +11 -7
  34. package/dist/data-table/query-control.js.map +1 -1
  35. package/dist/data-table/xlsx.cjs.map +1 -1
  36. package/dist/data-table/xlsx.js.map +1 -1
  37. package/package.json +1 -1
@@ -8,9 +8,9 @@ import {
8
8
  useCallback as useCallback6,
9
9
  useEffect as useEffect13,
10
10
  useId as useId2,
11
- useLayoutEffect,
11
+ useLayoutEffect as useLayoutEffect2,
12
12
  useMemo as useMemo7,
13
- useRef as useRef10,
13
+ useRef as useRef11,
14
14
  useState as useState19
15
15
  } from "react";
16
16
  import {
@@ -183,6 +183,46 @@ var Button = React.forwardRef(
183
183
  );
184
184
  Button.displayName = "Button";
185
185
 
186
+ // src/data-table/use-column-reorder-animation.ts
187
+ import { useLayoutEffect, useRef } from "react";
188
+ function useColumnReorderAnimation(tableRef, order, dragging) {
189
+ const previous = useRef({ positions: /* @__PURE__ */ new Map(), dragging: false });
190
+ const animations = useRef([]);
191
+ useLayoutEffect(() => {
192
+ const table = tableRef.current;
193
+ if (!table) return;
194
+ const headers = Array.from(table.querySelectorAll("th[data-matrx-table-column-id]"));
195
+ const positions = new Map(headers.map((header) => [header.dataset.matrxTableColumnId, header.offsetLeft]));
196
+ const prefersReducedMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
197
+ const shouldAnimate = (dragging || previous.current.dragging) && !prefersReducedMotion;
198
+ const offsets = /* @__PURE__ */ new Map();
199
+ for (const header of headers) {
200
+ const id = header.dataset.matrxTableColumnId;
201
+ const oldLeft = previous.current.positions.get(id);
202
+ if (oldLeft === void 0) continue;
203
+ const transform = getComputedStyle(header).transform;
204
+ const remaining = transform && transform !== "none" ? new DOMMatrixReadOnly(transform).m41 : 0;
205
+ offsets.set(id, oldLeft - header.offsetLeft + remaining);
206
+ }
207
+ animations.current.forEach((animation) => animation.cancel());
208
+ animations.current = [];
209
+ if (shouldAnimate) {
210
+ for (const cell of Array.from(table.querySelectorAll("[data-matrx-table-column-id]"))) {
211
+ const offset = offsets.get(cell.dataset.matrxTableColumnId);
212
+ if (!offset || typeof cell.animate !== "function") continue;
213
+ animations.current.push(cell.animate(
214
+ [{ transform: `translateX(${offset}px)` }, { transform: "translateX(0)" }],
215
+ { duration: 180, easing: "cubic-bezier(0.2, 0.8, 0.2, 1)" }
216
+ ));
217
+ }
218
+ }
219
+ previous.current = { positions, dragging };
220
+ }, [tableRef, order, dragging]);
221
+ useLayoutEffect(() => () => {
222
+ animations.current.forEach((animation) => animation.cancel());
223
+ }, []);
224
+ }
225
+
186
226
  // src/data-table/MatrxDataTable.tsx
187
227
  import { formatCount as formatCount3 } from "@ai-matrx/kit/format";
188
228
 
@@ -928,7 +968,7 @@ function TableTitleRow({
928
968
  }
929
969
 
930
970
  // src/data-table/TableSearch.tsx
931
- import { useRef, useState } from "react";
971
+ import { useRef as useRef2, useState } from "react";
932
972
 
933
973
  // src/tooltip.tsx
934
974
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
@@ -960,7 +1000,7 @@ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
960
1000
  import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
961
1001
  function TableSearch({ value, onChange, scope, onScopeChange, scopes, placeholder = "Search\u2026" }) {
962
1002
  const [expanded, setExpanded] = useState(false);
963
- const inputRef = useRef(null);
1003
+ const inputRef = useRef2(null);
964
1004
  return /* @__PURE__ */ jsx13("div", { "data-matrx-table-search": true, className: "h-11 min-w-0 w-full sm:max-w-xs", children: /* @__PURE__ */ jsxs8(
965
1005
  "div",
966
1006
  {
@@ -1006,7 +1046,7 @@ function TableSearch({ value, onChange, scope, onScopeChange, scopes, placeholde
1006
1046
  }
1007
1047
 
1008
1048
  // src/data-table/useScrollPagination.ts
1009
- import { useEffect, useRef as useRef2, useState as useState2 } from "react";
1049
+ import { useEffect, useRef as useRef3, useState as useState2 } from "react";
1010
1050
  var DEFAULT_THRESHOLD_PX = 96;
1011
1051
  var DEFAULT_INTENT_TIMEOUT_MS = 1200;
1012
1052
  function resolveContainer(container) {
@@ -1078,7 +1118,7 @@ function useScrollPagination({
1078
1118
  enabled = true
1079
1119
  }) {
1080
1120
  const [requestError, setRequestError] = useState2(null);
1081
- const latestRef = useRef2({
1121
+ const latestRef = useRef3({
1082
1122
  queryKey,
1083
1123
  hasNextPage,
1084
1124
  isFetchingNextPage,
@@ -1100,14 +1140,14 @@ function useScrollPagination({
1100
1140
  thresholdPx,
1101
1141
  enabled
1102
1142
  };
1103
- const intentRef = useRef2(null);
1104
- const inputSequenceRef = useRef2(0);
1105
- const consumedSequenceRef = useRef2(0);
1106
- const requestGenerationRef = useRef2(0);
1107
- const inFlightGenerationRef = useRef2(null);
1108
- const requestErrorRef = useRef2(null);
1109
- const mountedRef = useRef2(false);
1110
- const observedTopRef = useRef2(/* @__PURE__ */ new WeakMap());
1143
+ const intentRef = useRef3(null);
1144
+ const inputSequenceRef = useRef3(0);
1145
+ const consumedSequenceRef = useRef3(0);
1146
+ const requestGenerationRef = useRef3(0);
1147
+ const inFlightGenerationRef = useRef3(null);
1148
+ const requestErrorRef = useRef3(null);
1149
+ const mountedRef = useRef3(false);
1150
+ const observedTopRef = useRef3(/* @__PURE__ */ new WeakMap());
1111
1151
  const effectiveError = error ?? requestError;
1112
1152
  useEffect(() => {
1113
1153
  mountedRef.current = true;
@@ -1244,7 +1284,7 @@ function useScrollPagination({
1244
1284
  }
1245
1285
 
1246
1286
  // src/data-table/useProgressiveTableRows.ts
1247
- import { useEffect as useEffect2, useMemo, useRef as useRef3, useState as useState3 } from "react";
1287
+ import { useEffect as useEffect2, useMemo, useRef as useRef4, useState as useState3 } from "react";
1248
1288
  function safePageSize(pageSize) {
1249
1289
  return Number.isFinite(pageSize) && pageSize > 0 ? Math.floor(pageSize) : 0;
1250
1290
  }
@@ -1267,9 +1307,9 @@ function useProgressiveTableRows({
1267
1307
  const pageSize = safePageSize(rawPageSize);
1268
1308
  const hasExplicitRequestedPage = rawRequestedPage !== void 0;
1269
1309
  const requestedPage = safeRequestedPage(rawRequestedPage);
1270
- const initialRequestedPageRef = useRef3(requestedPage);
1271
- const latestRequestedPageRef = useRef3(requestedPage);
1272
- const optimisticAdvancePageRef = useRef3(null);
1310
+ const initialRequestedPageRef = useRef4(requestedPage);
1311
+ const latestRequestedPageRef = useRef4(requestedPage);
1312
+ const optimisticAdvancePageRef = useRef4(null);
1273
1313
  latestRequestedPageRef.current = requestedPage;
1274
1314
  const progressionKey = `${queryKey}\0${pageSize}`;
1275
1315
  const initialShownCount = startCount(pageSize, initialRequestedPageRef.current);
@@ -2825,7 +2865,7 @@ var useContentTransferCapabilities = () => React14.useContext(CapabilityContext)
2825
2865
  var SurfaceContext = React14.createContext(null);
2826
2866
  function MenuPresentation({ label, hint, icon: Icon3 }) {
2827
2867
  return /* @__PURE__ */ jsxs16(Fragment2, { children: [
2828
- Icon3 ? /* @__PURE__ */ jsx24(Icon3, { className: "matrx-alchemy-menu-icon" }) : null,
2868
+ Icon3 ? /* @__PURE__ */ jsx24(Icon3, { className: "matrx-alchemy-menu-icon" }) : /* @__PURE__ */ jsx24(PaletteGlyph, { file: true }),
2829
2869
  /* @__PURE__ */ jsxs16("span", { children: [
2830
2870
  label,
2831
2871
  hint ? /* @__PURE__ */ jsx24("small", { className: "matrx-alchemy-menu-hint", children: hint }) : null
@@ -2847,8 +2887,11 @@ function DestinationPresentation({ action }) {
2847
2887
  };
2848
2888
  const path2 = paths[action.id.replace(/^matrx:/, "")];
2849
2889
  return /* @__PURE__ */ jsxs16(Fragment2, { children: [
2850
- !action.icon ? path2 ? /* @__PURE__ */ jsx24("svg", { className: "matrx-alchemy-palette-glyph", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx24("path", { d: path2 }) }) : /* @__PURE__ */ jsx24(PaletteGlyph, { file: true }) : null,
2851
- /* @__PURE__ */ jsx24(MenuPresentation, { ...action })
2890
+ action.icon ? /* @__PURE__ */ jsx24(action.icon, { className: "matrx-alchemy-menu-icon" }) : path2 ? /* @__PURE__ */ jsx24("svg", { className: "matrx-alchemy-palette-glyph", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx24("path", { d: path2 }) }) : /* @__PURE__ */ jsx24(PaletteGlyph, { file: true }),
2891
+ /* @__PURE__ */ jsxs16("span", { children: [
2892
+ action.label,
2893
+ action.hint ? /* @__PURE__ */ jsx24("small", { className: "matrx-alchemy-menu-hint", children: action.hint }) : null
2894
+ ] })
2852
2895
  ] });
2853
2896
  }
2854
2897
  function ReceiptLink({ target }) {
@@ -2858,6 +2901,11 @@ function ReceiptLink({ target }) {
2858
2901
  ] }) : null;
2859
2902
  }
2860
2903
  function PaletteGlyph({ format, ai = false, file = false, kind }) {
2904
+ if (kind === "link") return /* @__PURE__ */ jsx24("svg", { className: "matrx-alchemy-palette-glyph", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx24("path", { d: "M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-2 2M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l2-2" }) });
2905
+ if (kind === "surface") return /* @__PURE__ */ jsxs16("svg", { className: "matrx-alchemy-palette-glyph", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
2906
+ /* @__PURE__ */ jsx24("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
2907
+ /* @__PURE__ */ jsx24("path", { d: "M3 9h18M9 9v12" })
2908
+ ] });
2861
2909
  if (kind === "ai-copy") return /* @__PURE__ */ jsxs16("svg", { className: "matrx-alchemy-palette-glyph", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
2862
2910
  /* @__PURE__ */ jsx24("rect", { x: "5", y: "5", width: "11", height: "14", rx: "2" }),
2863
2911
  /* @__PURE__ */ jsx24("path", { d: "M9 3h6a2 2 0 0 1 2 2v10" }),
@@ -3338,7 +3386,7 @@ function ContentTransferMenuSession({ references = [], referenceActions = [], so
3338
3386
  const presentation = options.action;
3339
3387
  const Icon3 = presentation?.icon;
3340
3388
  const fallbackLabel = options.file && !/^download\b/i.test(label2) ? `Download ${label2}` : label2;
3341
- return /* @__PURE__ */ jsxs16("button", { type: "button", className: "matrx-alchemy-palette-tile", "aria-label": presentation?.ariaLabel ?? (presentation ? fallbackLabel : options.ariaLabel ?? `${resolvedMode === "copy" ? "Copy" : "Download"} ${label2}`), onClick: () => {
3389
+ return /* @__PURE__ */ jsxs16("button", { type: "button", className: "matrx-alchemy-palette-tile", title: id === "table-data" ? "JSON using column display names" : id === "table-schema" ? "Table schema and rows" : label2, "aria-label": presentation?.ariaLabel ?? (presentation ? fallbackLabel : options.ariaLabel ?? `${resolvedMode === "copy" ? "Copy" : "Download"} ${label2}`), onClick: () => {
3342
3390
  closePalette();
3343
3391
  onClick();
3344
3392
  }, children: [
@@ -3400,7 +3448,7 @@ function ContentTransferMenuSession({ references = [], referenceActions = [], so
3400
3448
  /* @__PURE__ */ jsx24(PaletteGlyph, { kind: "ai-copy" }),
3401
3449
  /* @__PURE__ */ jsxs16("span", { children: [
3402
3450
  "Copy with AI context",
3403
- /* @__PURE__ */ jsx24("small", { className: "matrx-alchemy-menu-hint", children: "Content, source and capture details" })
3451
+ /* @__PURE__ */ jsx24("small", { className: "matrx-alchemy-menu-hint", children: "Include source context" })
3404
3452
  ] })
3405
3453
  ] }) : null, items: quickVariants("ai"), onRun: (variant) => {
3406
3454
  closePalette();
@@ -3413,32 +3461,44 @@ function ContentTransferMenuSession({ references = [], referenceActions = [], so
3413
3461
  /* @__PURE__ */ jsx24(PaletteGlyph, { kind: "sliders" }),
3414
3462
  /* @__PURE__ */ jsxs16("span", { children: [
3415
3463
  "Prepare for AI",
3416
- /* @__PURE__ */ jsx24("small", { className: "matrx-alchemy-menu-hint", children: "Review and edit before copying" })
3464
+ /* @__PURE__ */ jsx24("small", { className: "matrx-alchemy-menu-hint", children: "Trim, edit or summarize" })
3417
3465
  ] })
3418
3466
  ] }) })
3419
3467
  ] }) : null,
3420
3468
  prepareAvailable && (nearestWorkspaceKey || variants.length) ? /* @__PURE__ */ jsx24(PaletteRows, { title: "Other sources", items: [], extra: /* @__PURE__ */ jsxs16(Fragment2, { children: [
3421
- nearestWorkspaceKey && nearestSurface ? /* @__PURE__ */ jsx24("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => {
3469
+ nearestWorkspaceKey && nearestSurface ? /* @__PURE__ */ jsxs16("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => {
3422
3470
  closePalette();
3423
3471
  void openWorkspace(nearestWorkspaceKey, { source: nearestSurface, label: nearestSurface.surfaceName });
3424
- }, children: /* @__PURE__ */ jsx24("span", { children: "Prepare this surface" }) }) : null,
3472
+ }, children: [
3473
+ /* @__PURE__ */ jsx24(PaletteGlyph, { kind: "surface" }),
3474
+ /* @__PURE__ */ jsx24("span", { children: "Prepare this page" })
3475
+ ] }) : null,
3425
3476
  variants.map((variant) => /* @__PURE__ */ jsx24("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": variant.ariaLabel, onClick: () => {
3426
3477
  closePalette();
3427
3478
  void openWorkspace(variantWorkspaceKeys.get(variant.id), variant);
3428
3479
  }, children: /* @__PURE__ */ jsx24(MenuPresentation, { ...variant, label: `Prepare ${variant.label}` }) }, variant.id))
3429
3480
  ] }) }) : null,
3430
3481
  references.length || referenceActions.length ? /* @__PURE__ */ jsxs16("section", { className: "matrx-alchemy-palette-section", children: [
3431
- /* @__PURE__ */ jsx24("h3", { children: "Live references" }),
3432
- /* @__PURE__ */ jsx24("p", { className: "matrx-alchemy-menu-hint", children: "Pointers to saved data, independent of filters and edits." }),
3433
- references.map((reference) => /* @__PURE__ */ jsx24("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => void copyReference(reference), children: /* @__PURE__ */ jsx24("span", { children: reference.label }) }, reference.id)),
3434
- referenceActions.map((action) => /* @__PURE__ */ jsx24("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => void openReference(action), children: /* @__PURE__ */ jsx24("span", { children: action.label }) }, action.id))
3482
+ /* @__PURE__ */ jsx24("h3", { children: "References" }),
3483
+ referenceActions.map((action) => /* @__PURE__ */ jsxs16("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => void openReference(action), children: [
3484
+ /* @__PURE__ */ jsx24(PaletteGlyph, { kind: "link" }),
3485
+ /* @__PURE__ */ jsx24("span", { children: action.label }),
3486
+ /* @__PURE__ */ jsx24("svg", { className: "matrx-alchemy-disclosure", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: /* @__PURE__ */ jsx24("path", { d: "m6 4 4 4-4 4" }) })
3487
+ ] }, action.id)),
3488
+ references.map((reference) => /* @__PURE__ */ jsxs16("button", { type: "button", className: "matrx-alchemy-palette-row", title: "Copies a reference to saved data", onClick: () => void copyReference(reference), children: [
3489
+ /* @__PURE__ */ jsx24(PaletteGlyph, { kind: "link" }),
3490
+ /* @__PURE__ */ jsx24("span", { children: reference.label })
3491
+ ] }, reference.id))
3435
3492
  ] }) : null,
3436
3493
  ["save", "chat", "email", "other"].map((group) => {
3437
3494
  const entries = ordinaryActions.filter((action) => (action.group ?? "other") === group);
3438
3495
  return entries.length ? /* @__PURE__ */ jsxs16("details", { className: "matrx-alchemy-palette-destinations", children: [
3439
3496
  /* @__PURE__ */ jsxs16("summary", { children: [
3440
3497
  group === "save" ? "Save to Matrx" : group === "chat" ? "Continue with AI" : group === "email" ? "Email to me" : "Actions",
3441
- /* @__PURE__ */ jsx24("span", { children: entries.length })
3498
+ /* @__PURE__ */ jsxs16("span", { className: "matrx-alchemy-disclosure-meta", children: [
3499
+ /* @__PURE__ */ jsx24("span", { children: entries.length }),
3500
+ /* @__PURE__ */ jsx24("svg", { className: "matrx-alchemy-disclosure", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: /* @__PURE__ */ jsx24("path", { d: "m6 4 4 4-4 4" }) })
3501
+ ] })
3442
3502
  ] }),
3443
3503
  /* @__PURE__ */ jsx24("div", { children: entries.map((action) => /* @__PURE__ */ jsx24("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": action.ariaLabel, onClick: () => {
3444
3504
  closePalette();
@@ -4799,6 +4859,9 @@ function compareValues(a, b) {
4799
4859
  sensitivity: "base"
4800
4860
  });
4801
4861
  }
4862
+ function selectCellValues(value) {
4863
+ return (Array.isArray(value) ? value : [value]).map(stringifyCellValue).filter((item) => item !== "");
4864
+ }
4802
4865
  function passesColumnFilter(value, filter) {
4803
4866
  const matches = (() => {
4804
4867
  switch (filter.kind) {
@@ -4815,9 +4878,9 @@ function passesColumnFilter(value, filter) {
4815
4878
  case "select": {
4816
4879
  const selected = filter.values ?? (filter.value && filter.value !== "__all__" ? [filter.value] : []);
4817
4880
  if (selected.length === 0) return true;
4818
- const s = stringifyCellValue(value);
4881
+ const values = selectCellValues(value);
4819
4882
  return selected.some(
4820
- (v) => v === SELECT_EMPTY_VALUE ? s === "" : v === SELECT_NOT_EMPTY_VALUE ? s !== "" : s === v
4883
+ (v) => v === SELECT_EMPTY_VALUE ? values.length === 0 : v === SELECT_NOT_EMPTY_VALUE ? values.length > 0 : values.includes(v)
4821
4884
  );
4822
4885
  }
4823
4886
  case "boolean": {
@@ -5157,7 +5220,7 @@ function useClippedContentGuard(ref, options) {
5157
5220
  }
5158
5221
 
5159
5222
  // src/data-table/url-state.ts
5160
- import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo4, useRef as useRef7, useState as useState11 } from "react";
5223
+ import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo4, useRef as useRef8, useState as useState11 } from "react";
5161
5224
  import {
5162
5225
  commitUrlParams,
5163
5226
  useUrlSearchParams
@@ -5237,7 +5300,7 @@ function useTableUrlState(options) {
5237
5300
  [defaultPageSize, defaultSortDirection, defaultSortId, key]
5238
5301
  );
5239
5302
  const state = readState(searchParams);
5240
- const lastTextWriteAt = useRef7(0);
5303
+ const lastTextWriteAt = useRef8(0);
5241
5304
  const [debouncedSearch, setDebouncedSearch] = useState11(state.search);
5242
5305
  useEffect7(() => {
5243
5306
  if (state.search === debouncedSearch) return;
@@ -6138,7 +6201,7 @@ function parseOptionalNumber(raw) {
6138
6201
  import {
6139
6202
  useCallback as useCallback5,
6140
6203
  useEffect as useEffect9,
6141
- useRef as useRef8,
6204
+ useRef as useRef9,
6142
6205
  useState as useState13
6143
6206
  } from "react";
6144
6207
 
@@ -6182,11 +6245,11 @@ function ColumnResizeHandle({
6182
6245
  onResizeCancel,
6183
6246
  onResizeCommit
6184
6247
  }) {
6185
- const handleRef = useRef8(null);
6186
- const activeResizeRef = useRef8(null);
6187
- const previewRafRef = useRef8(null);
6188
- const queuedWidthRef = useRef8(null);
6189
- const keyboardWidthRef = useRef8(null);
6248
+ const handleRef = useRef9(null);
6249
+ const activeResizeRef = useRef9(null);
6250
+ const previewRafRef = useRef9(null);
6251
+ const queuedWidthRef = useRef9(null);
6252
+ const keyboardWidthRef = useRef9(null);
6190
6253
  const [announcedWidth, setAnnouncedWidth] = useState13(null);
6191
6254
  const bounds = resolveColumnResizeBounds(minWidth, maxWidth);
6192
6255
  const cssVar = columnResizeCssVar(columnId2);
@@ -6643,7 +6706,7 @@ function parseTableViewSnapshot(raw) {
6643
6706
  // src/data-table/MatrxUuidCell.tsx
6644
6707
  import {
6645
6708
  useEffect as useEffect11,
6646
- useRef as useRef9,
6709
+ useRef as useRef10,
6647
6710
  useState as useState15
6648
6711
  } from "react";
6649
6712
  import { jsx as jsx32, jsxs as jsxs22 } from "react/jsx-runtime";
@@ -6688,7 +6751,7 @@ function MatrxUuidCell({
6688
6751
  const [copied, setCopied] = useState15(false);
6689
6752
  const [opening, setOpening] = useState15(false);
6690
6753
  const [peekOpen, setPeekOpen] = useState15(false);
6691
- const timer = useRef9(null);
6754
+ const timer = useRef10(null);
6692
6755
  useEffect11(
6693
6756
  () => () => {
6694
6757
  if (timer.current) clearTimeout(timer.current);
@@ -8051,7 +8114,7 @@ function resolveFilterKind(col, sampleRows) {
8051
8114
  if (values.every((v) => typeof v === "number" && Number.isFinite(v))) {
8052
8115
  return "number";
8053
8116
  }
8054
- const strings = values.map(stringifyCellValue);
8117
+ const strings = values.flatMap(selectCellValues);
8055
8118
  const unique = new Set(strings);
8056
8119
  if (unique.size >= 1 && unique.size <= SELECT_CARDINALITY_CAP && unique.size < strings.length * 0.6) {
8057
8120
  return "select";
@@ -8063,15 +8126,16 @@ function collectSelectOptions(col, rows) {
8063
8126
  const options = [];
8064
8127
  let hasEmpty = false;
8065
8128
  for (const row of rows) {
8066
- const raw = getCellValue(row, col);
8067
- const value = raw == null ? "" : stringifyCellValue(raw);
8068
- if (!value) {
8129
+ const values = selectCellValues(getCellValue(row, col));
8130
+ if (values.length === 0) {
8069
8131
  hasEmpty = true;
8070
8132
  continue;
8071
8133
  }
8072
- if (col.filterOptions?.length || seen.has(value)) continue;
8073
- seen.add(value);
8074
- options.push({ value, label: value });
8134
+ for (const value of values) {
8135
+ if (col.filterOptions?.length || seen.has(value)) continue;
8136
+ seen.add(value);
8137
+ options.push({ value, label: value });
8138
+ }
8075
8139
  }
8076
8140
  const base = col.filterOptions?.length ? [...col.filterOptions] : options.sort((a, b) => a.label.localeCompare(b.label));
8077
8141
  if (hasEmpty) {
@@ -8323,7 +8387,7 @@ function MatrxDataTableCore({
8323
8387
  }) {
8324
8388
  const appendQuery = query?.mode === "controlled-append" ? query : null;
8325
8389
  const appendQueryKey = appendQuery?.pagination.queryKey ?? null;
8326
- const committedAppendQueryKey = useRef10(appendQueryKey);
8390
+ const committedAppendQueryKey = useRef11(appendQueryKey);
8327
8391
  const appendSourceChanged = appendQuery !== null && committedAppendQueryKey.current !== appendQueryKey;
8328
8392
  const data = appendQuery ? appendQuery.pagination.rows : suppliedData;
8329
8393
  const isLoading = appendQuery ? appendQuery.pagination.loading : suppliedLoading;
@@ -8337,7 +8401,7 @@ function MatrxDataTableCore({
8337
8401
  const [savedViewError, setSavedViewError] = useState19(null);
8338
8402
  const [toolbarActionError, setToolbarActionError] = useState19(null);
8339
8403
  const [toolbarActionPending, setToolbarActionPending] = useState19({ refresh: false, add: false });
8340
- const toolbarActionPendingRef = useRef10({ refresh: false, add: false });
8404
+ const toolbarActionPendingRef = useRef11({ refresh: false, add: false });
8341
8405
  const CHECKBOX_TAP_AREA = "h-4 w-4 touch-manipulation";
8342
8406
  const mobileCardsClass = mobileCardsBreakpoint === "lg" ? "lg:hidden" : "sm:hidden";
8343
8407
  const tableWithCardsClass = mobileCardsBreakpoint === "lg" ? "max-lg:hidden" : "max-sm:hidden";
@@ -8475,7 +8539,7 @@ function MatrxDataTableCore({
8475
8539
  const [windowRowSnapshot, setWindowRowSnapshot] = useState19(null);
8476
8540
  const editScopeKey = appendQueryKey === null ? "\0local" : `append:${appendQueryKey}`;
8477
8541
  const [editsByScope, setEditsByScope] = useState19({});
8478
- const editRevisionRef = useRef10({});
8542
+ const editRevisionRef = useRef11({});
8479
8543
  const [savingByScope, setSavingByScope] = useState19({});
8480
8544
  const [confirmForeignDraftDiscard, setConfirmForeignDraftDiscard] = useState19(false);
8481
8545
  const edits = editsByScope[editScopeKey]?.values ?? {};
@@ -8562,11 +8626,11 @@ function MatrxDataTableCore({
8562
8626
  onWindowRowIdChange,
8563
8627
  selectionConfig
8564
8628
  ]);
8565
- const scrollRef = useRef10(null);
8566
- const tableRef = useRef10(null);
8567
- const cardsScrollRef = useRef10(null);
8568
- const previousAppendKeyForScrollReset = useRef10(appendQueryKey);
8569
- useLayoutEffect(() => {
8629
+ const scrollRef = useRef11(null);
8630
+ const tableRef = useRef11(null);
8631
+ const cardsScrollRef = useRef11(null);
8632
+ const previousAppendKeyForScrollReset = useRef11(appendQueryKey);
8633
+ useLayoutEffect2(() => {
8570
8634
  const previous = previousAppendKeyForScrollReset.current;
8571
8635
  previousAppendKeyForScrollReset.current = appendQueryKey;
8572
8636
  if (previous === null || appendQueryKey === null || previous === appendQueryKey) {
@@ -8591,7 +8655,7 @@ function MatrxDataTableCore({
8591
8655
  ...appendScrollPolicy?.mode === "scroll" && appendScrollPolicy.thresholdPx !== void 0 ? { thresholdPx: appendScrollPolicy.thresholdPx } : {},
8592
8656
  ...appendScrollPolicy?.mode === "scroll" && appendScrollPolicy.intentTimeoutMs !== void 0 ? { intentTimeoutMs: appendScrollPolicy.intentTimeoutMs } : {}
8593
8657
  });
8594
- const rootRef = useRef10(null);
8658
+ const rootRef = useRef11(null);
8595
8659
  useClippedContentGuard(rootRef, {
8596
8660
  label: typeof copy === "object" && copy.listLabel ? `Table: ${copy.listLabel}` : "MatrxDataTable"
8597
8661
  });
@@ -8634,11 +8698,11 @@ function MatrxDataTableCore({
8634
8698
  () => normalizeColumnWidthsForColumns(columnState?.widths, columns)
8635
8699
  );
8636
8700
  const [fixedTableGeometry, setFixedTableGeometry] = useState19(null);
8637
- const knownColumnIds = useRef10(new Set(columns.map(columnId)));
8638
- const draggedColumnId = useRef10(null);
8639
- const columnDragActive = useRef10(false);
8640
- const columnDragRaf = useRef10(null);
8641
- const columnDragScrollDirection = useRef10(0);
8701
+ const knownColumnIds = useRef11(new Set(columns.map(columnId)));
8702
+ const draggedColumnId = useRef11(null);
8703
+ const columnDragActive = useRef11(false);
8704
+ const columnDragRaf = useRef11(null);
8705
+ const columnDragScrollDirection = useRef11(0);
8642
8706
  const [columnDragPreview, setColumnDragPreview] = useState19(null);
8643
8707
  const stopColumnDragScroll = useCallback6(() => {
8644
8708
  if (columnDragRaf.current !== null) cancelAnimationFrame(columnDragRaf.current);
@@ -8693,7 +8757,7 @@ function MatrxDataTableCore({
8693
8757
  () => normalizeColumnWidthsForColumns(columnState?.widths ?? columnWidths, columns),
8694
8758
  [columns, columnState?.widths, columnWidths]
8695
8759
  );
8696
- const resizeGestureSnapshotRef = useRef10(null);
8760
+ const resizeGestureSnapshotRef = useRef11(null);
8697
8761
  const measureVisibleColumnWidths = useCallback6(() => {
8698
8762
  const measured = {};
8699
8763
  const headers = tableRef.current ? Array.from(tableRef.current.querySelectorAll(
@@ -8785,7 +8849,7 @@ function MatrxDataTableCore({
8785
8849
  setColumnWidths((current) => normalizeColumnWidthsForColumns(current, columns));
8786
8850
  knownColumnIds.current = new Set(ids);
8787
8851
  }, [columns, columnState]);
8788
- useLayoutEffect(() => {
8852
+ useLayoutEffect2(() => {
8789
8853
  for (const id of columnIds) {
8790
8854
  tableRef.current?.style.removeProperty(columnResizeCssVar(id));
8791
8855
  }
@@ -8794,6 +8858,7 @@ function MatrxDataTableCore({
8794
8858
  () => projectColumnDragOrder(effectiveColumnOrder, columnDragPreview),
8795
8859
  [columnDragPreview, effectiveColumnOrder]
8796
8860
  );
8861
+ useColumnReorderAnimation(tableRef, previewColumnOrder.join("\0"), columnDragPreview !== null);
8797
8862
  const visibleColumns = useMemo7(() => {
8798
8863
  const byId = new Map(columns.map((column) => [columnId(column), column]));
8799
8864
  return previewColumnOrder.map((id) => byId.get(id)).filter(
@@ -8801,14 +8866,14 @@ function MatrxDataTableCore({
8801
8866
  );
8802
8867
  }, [columns, effectiveHiddenColumnIds, previewColumnOrder]);
8803
8868
  const usesMeasuredFixedLayout = visibleColumns.length > 0 && visibleColumns.every((column) => effectiveColumnWidths[columnId(column)] !== void 0);
8804
- useLayoutEffect(() => {
8869
+ useLayoutEffect2(() => {
8805
8870
  if (!usesMeasuredFixedLayout) {
8806
8871
  if (fixedTableGeometry !== null) setFixedTableGeometry(null);
8807
8872
  return;
8808
8873
  }
8809
8874
  if (fixedTableGeometry === null) setFixedTableGeometry(measureFixedTableGeometry());
8810
8875
  }, [fixedTableGeometry, measureFixedTableGeometry, usesMeasuredFixedLayout]);
8811
- useLayoutEffect(() => {
8876
+ useLayoutEffect2(() => {
8812
8877
  if (!usesMeasuredFixedLayout) return;
8813
8878
  const table = tableRef.current;
8814
8879
  if (!table) return;
@@ -8949,7 +9014,7 @@ function MatrxDataTableCore({
8949
9014
  intelligentSearchEnabled,
8950
9015
  searchScope
8951
9016
  ]);
8952
- const lastNotifiedViewRows = useRef10(null);
9017
+ const lastNotifiedViewRows = useRef11(null);
8953
9018
  useEffect13(() => {
8954
9019
  if (!onViewChange) {
8955
9020
  lastNotifiedViewRows.current = null;
@@ -9363,7 +9428,7 @@ function MatrxDataTableCore({
9363
9428
  () => data.filter((row) => selectedIdSet.has(getRowId(row))),
9364
9429
  [data, selectedIdSet, getRowId]
9365
9430
  );
9366
- const lastToggledIndex = useRef10(null);
9431
+ const lastToggledIndex = useRef11(null);
9367
9432
  const setSelectedIds = (next) => selection?.onSelectedIdsChange([...next]);
9368
9433
  const toggleRowSelected = (index, shiftKey) => {
9369
9434
  if (!selection) return;
@@ -10367,6 +10432,7 @@ function MatrxDataTableCore({
10367
10432
  return /* @__PURE__ */ jsx39(
10368
10433
  "td",
10369
10434
  {
10435
+ "data-matrx-table-column-id": columnId(col),
10370
10436
  "data-matrx-column-drag-shadow": isColumnDragShadow ? "true" : void 0,
10371
10437
  className: cn(
10372
10438
  "py-1.5 align-middle lg:py-0.5",