@ai-matrx/records-ui 0.115.36 → 0.115.37

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/dist/index.js CHANGED
@@ -13399,7 +13399,7 @@ function SplitRecordDialog({ tableId, record, document: document2, open, onOpenC
13399
13399
  let madeName = recordNameIn(table.data ?? null, madeDoc, "New record");
13400
13400
  if (titleKey !== null && !titleHeld) {
13401
13401
  const named = `${record.name} (split)`;
13402
- const renamed = await client.recordUpdate({ record_id: created, patch: { [titleKey]: named } });
13402
+ const renamed = await (0, recordVersions_exports.updateRecordAt)(client, { record_id: created, patch: { [titleKey]: named }, version: await (0, recordVersions_exports.readVersionNow)(client, created) });
13403
13403
  if (renamed.ok) {
13404
13404
  madeName = named;
13405
13405
  onChanged?.();
@@ -19036,7 +19036,8 @@ function useGridDrillQuestion(args) {
19036
19036
  const source = useMemo28(() => ({ kind: "table", id: tableId }), [tableId]);
19037
19037
  const saved = useMemo28(() => questionFromGrouping(presentation.grouping), [presentation.grouping]);
19038
19038
  const url = useDrillUrlState({ fallback: saved });
19039
- const requested = args.enabled && (url.question.by.length > (args.plainGroupingIsRows ? 1 : 0) || url.question.across !== null || url.question.where.length > 0 || // `!= null`: a question read by a design-system that does not know the window or the comparison
19039
+ const requested = args.enabled && // Up to three levels are ROWS under nested headers on the merged grid (Airtable's group levels).
19040
+ (url.question.by.length > (args.plainGroupingIsRows ? 3 : 0) || url.question.across !== null || url.question.where.length > 0 || // `!= null`: a question read by a design-system that does not know the window or the comparison
19040
19041
  // yet has them UNDEFINED, and `undefined !== null` asked for drill metadata on every plain grid.
19041
19042
  url.question.window != null || url.question.compare != null);
19042
19043
  const { def } = useDrillDefinition(requested ? source : null);
@@ -23005,7 +23006,7 @@ function SortPanel({
23005
23006
  }
23006
23007
 
23007
23008
  // src/Grid.tsx
23008
- import { pageSortsFor, thenSortsOf } from "@ai-matrx/records/first-page";
23009
+ import { pageSortFor as pageSortFor2, pageSortsFor, thenSortsOf } from "@ai-matrx/records/first-page";
23009
23010
 
23010
23011
  // src/gridValueFilter.ts
23011
23012
  import { useMemo as useMemo32, useRef as useRef31 } from "react";
@@ -24788,10 +24789,17 @@ function GridBody({
24788
24789
  return viewSorts[0]?.field === seatedSort.id ? thenSortsOf(viewSorts, list, seatedSort.id, unsortable) : [];
24789
24790
  }, [seatedSort, manual, fields.data, heldThen, viewSorts]);
24790
24791
  const thenKey = JSON.stringify(thenSorts);
24792
+ const groupThenKeys = rowGroupKey ? (presentation.grouping?.then ?? []).map((t) => t.field).join("|") : "";
24791
24793
  const pageSort = useMemo38(
24792
- () => storePaged ? groupedPageSort(fields.data ?? [], rowGroupKey, pageSortsFor(fields.data ?? [], seatedSort, thenSorts)) : [],
24794
+ () => {
24795
+ if (!storePaged) return [];
24796
+ const sorted = groupedPageSort(fields.data ?? [], rowGroupKey, pageSortsFor(fields.data ?? [], seatedSort, thenSorts));
24797
+ if (!rowGroupKey || groupThenKeys === "") return sorted;
24798
+ const inner2 = groupThenKeys.split("|").flatMap((key) => pageSortFor2(fields.data ?? [], { id: key, direction: "asc" }));
24799
+ return [...sorted.slice(0, 1), ...inner2, ...sorted.slice(1).filter((s) => !inner2.some((i) => i.field === s.field))];
24800
+ },
24793
24801
  // eslint-disable-next-line react-hooks/exhaustive-deps -- thenKey stands for thenSorts
24794
- [storePaged, fields.data, seatedSort, rowGroupKey, thenKey]
24802
+ [storePaged, fields.data, seatedSort, rowGroupKey, thenKey, groupThenKeys]
24795
24803
  );
24796
24804
  const fullSorts = useMemo38(
24797
24805
  () => seatedSort ? [{ field: seatedSort.id, direction: seatedSort.direction }, ...thenSorts] : [],
@@ -25994,12 +26002,15 @@ function GridBody({
25994
26002
  if (field2 === null && !onPresentationChange) return null;
25995
26003
  const rowsGrouped = merged;
25996
26004
  const aggregates = rowsGrouped ? void 0 : view && Object.keys(view.aggregates ?? {}).length > 0 ? view.aggregates : field2 ? { [field2]: { kind: "count" } } : void 0;
25997
- const facts = rowsGrouped ? groupFactsFor(groupFacts, fields.data ?? [], chosenSummaries) : void 0;
26005
+ const topFacts = rowsGrouped ? groupFactsFor(groupFacts, fields.data ?? [], chosenSummaries) : void 0;
26006
+ const facts = topFacts ? (group) => group.ancestors ? void 0 : topFacts(group) : void 0;
26007
+ const thenKeys = rowsGrouped ? (view?.then ?? []).map((t) => t.field) : [];
25998
26008
  return {
25999
26009
  columnId: field2,
26000
26010
  rowNoun: "record",
26011
+ ...thenKeys.length > 0 ? { thenColumnIds: thenKeys } : {},
26001
26012
  ...aggregates ? { aggregates } : {},
26002
- ...rowsGrouped ? { renderLabel: groupLabel2, order: "first-seen", emptyLabel: "No value" } : {},
26013
+ ...rowsGrouped ? { renderLabel: (group) => group.ancestors ? void 0 : groupLabel2(group), order: "first-seen", emptyLabel: "No value" } : {},
26003
26014
  ...facts ? { groupFacts: facts } : {},
26004
26015
  ...!rowsGrouped && view?.order ? { order: view.order } : {},
26005
26016
  ...view?.collapsed ? { collapsed: view.collapsed } : {},
@@ -26020,6 +26031,15 @@ function GridBody({
26020
26031
  }
26021
26032
  });
26022
26033
  },
26034
+ // NESTED GROUPS: the second and third level are the view's `grouping.then` (the store allows three levels).
26035
+ ...rowsGrouped ? {
26036
+ onThenColumnIdsChange: (ids) => {
26037
+ const current = presentation.grouping;
26038
+ if (!current) return;
26039
+ const { then: _was, collapsed: _shut, ...rest } = current;
26040
+ writeLook({ ...presentation, grouping: ids.length > 0 ? { ...rest, then: ids.slice(0, 2).map((field3) => ({ field: field3 })) } : rest });
26041
+ }
26042
+ } : {},
26023
26043
  onCollapsedChange: (collapsed) => {
26024
26044
  const current = presentation.grouping;
26025
26045
  if (!current) return;
@@ -38982,6 +39002,7 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
38982
39002
  return (initialViews.find((v) => v.id === activeViewId) ?? defaultViewOf(initialViews) ?? initialViews[0]).id;
38983
39003
  });
38984
39004
  const readOnMount = useRef50(initialViews === void 0);
39005
+ const pendingPick = useRef50(null);
38985
39006
  const [naming, setNaming] = useState109(false);
38986
39007
  const [draftName, setDraftName] = useState109("");
38987
39008
  const [open, setOpen] = useState109(false);
@@ -39058,7 +39079,9 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
39058
39079
  }, [load]);
39059
39080
  useEffect89(() => {
39060
39081
  if (!views || views.length === 0) return;
39061
- const chosen = views.find((v) => v.id === (activeViewId ?? active)) ?? defaultViewOf(views) ?? views[0];
39082
+ const wanted = pendingPick.current;
39083
+ pendingPick.current = null;
39084
+ const chosen = views.find((v) => v.id === (wanted ?? activeViewId ?? active)) ?? defaultViewOf(views) ?? views[0];
39062
39085
  if (chosen.id !== active) setActive(chosen.id);
39063
39086
  onActiveView?.(chosen);
39064
39087
  }, [views, activeViewId]);
@@ -39073,6 +39096,7 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
39073
39096
  setNamingPersonal(false);
39074
39097
  setDraftName("");
39075
39098
  setActive(written.data);
39099
+ pendingPick.current = written.data;
39076
39100
  await load();
39077
39101
  }
39078
39102
  async function rename(view, name) {
@@ -39143,6 +39167,7 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
39143
39167
  return;
39144
39168
  }
39145
39169
  setActive(written.data);
39170
+ pendingPick.current = written.data;
39146
39171
  await load();
39147
39172
  }
39148
39173
  async function archive(view) {