@ai-matrx/records-ui 0.109.4 → 0.109.6

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,19 @@
1
1
  # Changelog — @ai-matrx/records-ui
2
2
 
3
+ ## 0.109.6
4
+ ### lane SORT-REACTS (follow-up)
5
+
6
+ - A link's `?sort=` opens the grid sorted and keeps the address's sort: it outranks where the grid opens (the table's own sort, the saved view's — both read after the columns) until the person sorts for herself or presses Reset view. It used to be let go once the columns were known, so a late view sort re-seated the query and rewrote the address.
7
+ - Enter on an edit that MOVES its row leaves the cursor on the edited cell at its new place (the lit row and the keys agree); Tab keeps its own rule. Layout check 9b.
8
+
9
+ **Consumer action:** none.
10
+
11
+ ## 0.109.5
12
+
13
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
14
+ `git diff npm/records-ui/v0.109.4..npm/records-ui/v0.109.5 -- apps/shared/records-ui`).
15
+ No source changes intended and no consumer action required.
16
+
3
17
  ## 0.109.4
4
18
  ### lane TABLE-EDITING-EDGES
5
19
 
package/dist/index.cjs CHANGED
@@ -4288,7 +4288,7 @@ function ReferenceBuilder({
4288
4288
  ] }) }),
4289
4289
  target && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
4290
4290
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_design_system10.Label, { className: "text-xs", children: "It will read" }),
4291
- preview.loading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Reading a few of its records\u2026" }) : (preview.data?.rows.length ?? 0) === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "That table has no records yet, so there is nothing to show here \u2014 this column will still work, and the first record added is the first thing it offers." }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { className: "flex flex-col gap-0.5", children: (preview.data?.rows ?? []).map((row) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("li", { className: "truncate text-[11px] text-foreground", children: previewWords(
4291
+ preview.loading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Reading a few of its records\u2026" }) : (preview.data?.rows?.length ?? 0) === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "That table has no records yet, so there is nothing to show here \u2014 this column will still work, and the first record added is the first thing it offers." }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { className: "flex flex-col gap-0.5", children: (preview.data?.rows ?? []).map((row) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("li", { className: "truncate text-[11px] text-foreground", children: previewWords(
4292
4292
  row.document,
4293
4293
  display,
4294
4294
  titleField
@@ -22236,7 +22236,7 @@ function useRowFollowsItsMove(args) {
22236
22236
  const lastIds = (0, import_react116.useRef)(args.rowIds);
22237
22237
  const frame = (0, import_react116.useRef)(0);
22238
22238
  (0, import_react116.useEffect)(() => () => cancelAnimationFrame(frame.current), []);
22239
- const noteWrite = (0, import_react116.useCallback)((rowId) => {
22239
+ const noteWrite = (0, import_react116.useCallback)((rowId, key) => {
22240
22240
  const box = latest.current.box.current;
22241
22241
  if (!box) return;
22242
22242
  const el = rowEl(box, rowId);
@@ -22245,7 +22245,7 @@ function useRowFollowsItsMove(args) {
22245
22245
  held.current = null;
22246
22246
  return;
22247
22247
  }
22248
- held.current = { rowId, top: el.getBoundingClientRect().top, index, at: Date.now() };
22248
+ held.current = { rowId, key, top: el.getBoundingClientRect().top, index, at: Date.now() };
22249
22249
  }, []);
22250
22250
  (0, import_react116.useLayoutEffect)(() => {
22251
22251
  if (args.rowIds === lastIds.current) return;
@@ -22265,6 +22265,7 @@ function useRowFollowsItsMove(args) {
22265
22265
  }
22266
22266
  if (index === pending.index) return;
22267
22267
  held.current = null;
22268
+ latest.current.onMoved?.(pending.rowId, pending.key);
22268
22269
  const el = rowEl(box, pending.rowId);
22269
22270
  if (!el) {
22270
22271
  bringIntoView(box, pending.rowId, index, args.rowIds);
@@ -23274,6 +23275,9 @@ function GridBody({
23274
23275
  const openingKey = openingSort ? `${openingSort.id}:${openingSort.direction}` : "none";
23275
23276
  const address = useViewAddress();
23276
23277
  const addressSeed = (0, import_react123.useRef)(address?.initial ?? null);
23278
+ const addressSort = (0, import_react123.useRef)(
23279
+ address?.initial?.sort ? { id: address.initial.sort.field, direction: address.initial.sort.direction } : null
23280
+ );
23277
23281
  const [query, setQuery] = (0, import_react123.useState)(() => ({
23278
23282
  page: addressSeed.current?.page ?? 1,
23279
23283
  pageSize,
@@ -23288,11 +23292,15 @@ function GridBody({
23288
23292
  if (seed && fields.data) addressSeed.current = null;
23289
23293
  setQuery((held) => ({
23290
23294
  ...held,
23291
- sort: seed?.sort ? { id: seed.sort.field, direction: seed.sort.direction } : openingSort,
23295
+ sort: addressSort.current ?? openingSort,
23292
23296
  page: seed?.page ?? 1
23293
23297
  }));
23294
23298
  setSeatedOn(openingKey);
23295
23299
  }, [openingKey]);
23300
+ (0, import_react123.useEffect)(() => {
23301
+ const held = addressSort.current;
23302
+ if (held && (query.sort?.id !== held.id || query.sort?.direction !== held.direction)) addressSort.current = null;
23303
+ }, [query.sort]);
23296
23304
  const columnSort = query.sort;
23297
23305
  const overrideKey = sortOverride ? `${sortOverride.field}:${sortOverride.direction}` : "";
23298
23306
  const overrideSeen = (0, import_react123.useRef)(overrideKey);
@@ -23335,6 +23343,7 @@ function GridBody({
23335
23343
  if (resetSeen.current === resetEpoch) return;
23336
23344
  resetSeen.current = resetEpoch;
23337
23345
  addressSeed.current = null;
23346
+ addressSort.current = null;
23338
23347
  setQuery((held) => ({ ...held, sort: openingSort, search: "", anyOf: "", columnFilters: {}, page: 1 }));
23339
23348
  }, [resetEpoch]);
23340
23349
  const [page, setPage] = (0, import_react123.useState)(0);
@@ -23466,6 +23475,7 @@ function GridBody({
23466
23475
  const canWrite = Boolean(editable) && (rights.write || askPerRow && rowIds.some(mayWriteRow));
23467
23476
  const readOnly = !editable || Boolean(host.rights) && !rights.write && !rights.structure;
23468
23477
  const gridBox = (0, import_react123.useRef)(null);
23478
+ const lastExit = (0, import_react123.useRef)(null);
23469
23479
  const pushWritten = (0, import_react123.useRef)(null);
23470
23480
  const sheetController = (0, import_react123.useRef)(null);
23471
23481
  const versions = useRecordVersions(client, rows);
@@ -23486,7 +23496,10 @@ function GridBody({
23486
23496
  * Enter or Cmd-Z works without a click. Sheets and Airtable.
23487
23497
  */
23488
23498
  ...merged ? {
23489
- onEnded: (exit, from, how) => sheetController.current?.endEdit(exit, { rowId: from.rowId, columnId: from.key }, how)
23499
+ onEnded: (exit, from, how) => {
23500
+ lastExit.current = { rowId: from.rowId, key: from.key, exit };
23501
+ sheetController.current?.endEdit(exit, { rowId: from.rowId, columnId: from.key }, how);
23502
+ }
23490
23503
  } : {}
23491
23504
  });
23492
23505
  const editingNow = (0, import_react123.useRef)(editing);
@@ -23514,7 +23527,15 @@ function GridBody({
23514
23527
  sort: sortedField ? { key: sortedField.key, name: fieldName(sortedField) } : null,
23515
23528
  say: (line) => undo.say(line, false, true)
23516
23529
  });
23517
- const rowMove = useRowFollowsItsMove({ box: gridBox, rowIds });
23530
+ const rowMove = useRowFollowsItsMove({
23531
+ box: gridBox,
23532
+ rowIds,
23533
+ onMoved: (rowId, key) => {
23534
+ const exit = lastExit.current;
23535
+ if (!exit || exit.rowId !== rowId || exit.key !== key) return;
23536
+ if (exit.exit === "down" || exit.exit === "stay") sheetController.current?.select({ rowId, columnId: key });
23537
+ }
23538
+ });
23518
23539
  pushWritten.current = (write) => {
23519
23540
  const field2 = (fields.data ?? []).find((f) => f.key === write.key);
23520
23541
  const name = changedRecordName(table.data, rows.find((r) => r.id === write.rowId)?.document ?? {}, write.key, write.after);
@@ -23522,7 +23543,7 @@ function GridBody({
23522
23543
  label: `Changed ${field2 ? fieldName(field2) : (0, import_text_case10.humanizeIdentifier)(write.key)} on ${name}`,
23523
23544
  cells: [{ rowId: write.rowId, key: write.key, before: write.before ?? null, after: write.after ?? null, version: write.version }]
23524
23545
  });
23525
- rowMove.noteWrite(write.rowId);
23546
+ rowMove.noteWrite(write.rowId, write.key);
23526
23547
  noteWriteForView(write, name);
23527
23548
  };
23528
23549
  const storeLayout = useStoreGridLayout(tableId);
@@ -24944,7 +24965,7 @@ function GridBody({
24944
24965
  }
24945
24966
  ) : null,
24946
24967
  question.refused.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("p", { role: "status", "data-records-filter-refused": "", className: "text-xs text-muted-foreground", children: question.refused.join(" ") }) : null,
24947
- storePaged && (serverRead.data?.sortIgnored.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("p", { role: "status", "data-records-sort-ignored": serverRead.data?.sortIgnored.join(" "), className: "text-xs text-muted-foreground", children: "Sort skipped: column not available" }) : null,
24968
+ storePaged && sortIgnoredOf(serverRead.data).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("p", { role: "status", "data-records-sort-ignored": sortIgnoredOf(serverRead.data).join(" "), className: "text-xs text-muted-foreground", children: "Sort skipped: column not available" }) : null,
24948
24969
  runner.outcome && !(merged && runner.outcome.kind === "ran" && runner.outcome.undo !== null) ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ActionOutcomeNotice, { outcome: runner.outcome, onUndo: () => void runner.undo(), onDismiss: runner.dismiss }) : null,
24949
24970
  duplicated ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("p", { role: "status", "data-records-duplicated": "", className: "flex items-center gap-2 rounded border border-border bg-muted/40 px-2 py-1 text-xs", children: [
24950
24971
  /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: duplicated }),
@@ -25346,6 +25367,9 @@ function withoutGoneColumns(query, liveKeys, openingSort) {
25346
25367
  const fallback = openingSort && liveKeys.has(openingSort.id) ? openingSort : null;
25347
25368
  return { ...query, sort: sortGone ? fallback : query.sort, columnFilters, page: 1 };
25348
25369
  }
25370
+ function sortIgnoredOf(answer) {
25371
+ return Array.isArray(answer?.sortIgnored) ? answer.sortIgnored : [];
25372
+ }
25349
25373
 
25350
25374
  // src/RecordsTableCard.tsx
25351
25375
  var import_data_table15 = require("@ai-matrx/design-system/data-table");
@@ -26781,7 +26805,7 @@ function columnFromName(label) {
26781
26805
  if (has(/\b(type|category|kind|tier|plan|platform|channel|source|level)\b/)) return { label, type: "select" };
26782
26806
  if (has(/\b(time|at|scheduled|starts|ends|appointment)\b/) && !has(/\b(date|day)\b/)) return { label, type: "datetime" };
26783
26807
  if (has(/\b(date|day|birthday|deadline|due|dob|born|joined|since|until|start|end|published|posted)\b/)) return { label, type: "date" };
26784
- if (has(/\b(price|cost|amount|revenue|budget|fee|fees|salary|paid|invoice|total|spend|value|rate card|mrr|arr)\b|\$/)) return { label, type: "currency" };
26808
+ if (has(/\b(price|cost|amount|revenue|budget|fee|fees|salary|paid|total|spend|value|rate card|mrr|arr)\b|\$/)) return { label, type: "currency" };
26785
26809
  if (has(/%|\b(percent|percentage|rate|ratio|margin|completion)\b/)) return { label, type: "percent" };
26786
26810
  if (has(/\b(count|qty|quantity|number of|age|score|hours|minutes|units|followers|views|likes|stars|rating|points|#)\b|^#|^no\.? /)) return { label, type: "number" };
26787
26811
  if (has(/\b(done|completed|approved|active|signed|confirmed)\b/)) return { label, type: "checkbox" };