@ai-matrx/records-ui 0.102.11 → 0.102.15

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
@@ -7082,11 +7082,11 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
7082
7082
  discard,
7083
7083
  forget: (cells) => {
7084
7084
  if (cells.length === 0) return;
7085
- for (const cell of cells) versions.current.delete(cell.rowId);
7085
+ for (const cell2 of cells) versions.current.delete(cell2.rowId);
7086
7086
  setOptimistic((held) => {
7087
7087
  let next = null;
7088
- for (const cell of cells) {
7089
- const id = cellKey(cell.rowId, cell.key);
7088
+ for (const cell2 of cells) {
7089
+ const id = cellKey(cell2.rowId, cell2.key);
7090
7090
  if (!(id in held)) continue;
7091
7091
  next = next ?? { ...held };
7092
7092
  delete next[id];
@@ -7562,7 +7562,10 @@ function OpenCell({
7562
7562
  tabIndex: -1,
7563
7563
  className: cn19(
7564
7564
  "relative z-[25] flex w-full min-w-0 max-w-full flex-col gap-1 outline-none",
7565
- FLOATING_EDITOR_NOTE_CLASS
7565
+ FLOATING_EDITOR_NOTE_CLASS,
7566
+ // A field's own input is 36px (h-9); in a 35px row it grew the row 4px. In the cell it is
7567
+ // the row action strip's 32px, so opening a cell never changes the row (STABLE-TABLES).
7568
+ "[&_input:not([type=checkbox]):not([type=radio])]:h-8 [&_input:not([type=checkbox]):not([type=radio])]:py-0"
7566
7569
  ),
7567
7570
  onDoubleClick: (event) => event.stopPropagation(),
7568
7571
  onKeyDown: (event) => {
@@ -7745,15 +7748,28 @@ function BodySkeleton({ layout, embedded, rows }) {
7745
7748
  /* @__PURE__ */ jsx29("div", { className: "flex h-9 items-center gap-6 border-b border-border px-3", children: Array.from({ length: 6 }, (_, i) => /* @__PURE__ */ jsx29(Skeleton2, { shape: "line", width: "sm", className: "w-16" }, i)) }),
7746
7749
  Array.from({ length: Math.min(lineCount, 8) }, (_, i) => /* @__PURE__ */ jsx29("div", { className: "flex h-10 items-center border-b border-border/60 px-3", children: /* @__PURE__ */ jsx29(Skeleton2, { className: "h-6 rounded-md", style: { marginLeft: `${i * 13 % 45}%`, width: `${20 + i * 7 % 25}%` } }) }, i))
7747
7750
  ] });
7748
- case "form":
7749
7751
  case "record":
7752
+ return /* @__PURE__ */ jsxs24("div", { className: "flex min-h-0 flex-1 flex-col gap-2 overflow-hidden", "data-records-skeleton-part": "body", children: [
7753
+ /* @__PURE__ */ jsx29(Skeleton2, { shape: "title", width: "1/2", className: "h-8", "data-records-skeleton-part": "title" }),
7754
+ /* @__PURE__ */ jsxs24("div", { className: "flex h-[38px] items-center gap-2", "data-records-skeleton-part": "actions", children: [
7755
+ /* @__PURE__ */ jsx29(Skeleton2, { shape: "control", width: "sm", className: "h-8" }),
7756
+ /* @__PURE__ */ jsx29(Skeleton2, { shape: "control", width: "sm", className: "h-8" })
7757
+ ] }),
7758
+ /* @__PURE__ */ jsx29("div", { className: "h-px w-full shrink-0 bg-border" }),
7759
+ /* @__PURE__ */ jsx29("div", { className: "grid grid-cols-[minmax(6rem,12rem)_1fr] gap-x-3 gap-y-0.5", "data-records-skeleton-part": "fields", children: Array.from({ length: 6 }, (_, i) => /* @__PURE__ */ jsxs24("div", { className: "contents", children: [
7760
+ /* @__PURE__ */ jsx29(Skeleton2, { shape: "line", width: "2/3", className: "my-[7px]" }),
7761
+ /* @__PURE__ */ jsx29(Skeleton2, { shape: "row", className: "h-7" })
7762
+ ] }, i)) }),
7763
+ /* @__PURE__ */ jsx29(Skeleton2, { shape: "block", height: "lg" })
7764
+ ] });
7765
+ case "form":
7750
7766
  return /* @__PURE__ */ jsxs24("div", { className: "flex min-h-0 flex-1 flex-col gap-4 overflow-hidden", "data-records-skeleton-part": "body", children: [
7751
7767
  /* @__PURE__ */ jsx29(Skeleton2, { shape: "title", width: "1/2" }),
7752
7768
  /* @__PURE__ */ jsx29("div", { className: "grid grid-cols-[minmax(6rem,12rem)_1fr] gap-x-3 gap-y-1.5", children: Array.from({ length: 6 }, (_, i) => /* @__PURE__ */ jsxs24("div", { className: "contents", children: [
7753
7769
  /* @__PURE__ */ jsx29(Skeleton2, { shape: "line", width: "2/3", className: "my-1.5" }),
7754
7770
  /* @__PURE__ */ jsx29(Skeleton2, { shape: "row", className: "h-7" })
7755
7771
  ] }, i)) }),
7756
- layout === "record" ? /* @__PURE__ */ jsx29(Skeleton2, { shape: "block", height: "lg" }) : /* @__PURE__ */ jsx29(Skeleton2, { shape: "control", width: "sm" })
7772
+ /* @__PURE__ */ jsx29(Skeleton2, { shape: "control", width: "sm" })
7757
7773
  ] });
7758
7774
  case "chart":
7759
7775
  return /* @__PURE__ */ jsxs24("div", { className: "flex flex-col gap-2", "data-records-skeleton-part": "body", children: [
@@ -11799,10 +11815,10 @@ function useGridColours(args) {
11799
11815
  submenu: swatches("sel-highlight", void 0, (color) => {
11800
11816
  void (async () => {
11801
11817
  let kept = 0;
11802
- for (const cell of cells) {
11803
- const field2 = idOf(cell.columnKey);
11818
+ for (const cell2 of cells) {
11819
+ const field2 = idOf(cell2.columnKey);
11804
11820
  if (!field2) continue;
11805
- const answer = await client.tableDecorate({ table_id: tableId, path: ["cells", cell.rowId, field2.id], value: color });
11821
+ const answer = await client.tableDecorate({ table_id: tableId, path: ["cells", cell2.rowId, field2.id], value: color });
11806
11822
  if (!answer.ok) {
11807
11823
  notify?.error(`The colour was not kept: ${refusalSentence(answer.error)}`);
11808
11824
  return;
@@ -12256,15 +12272,15 @@ function ActionRowPreview({
12256
12272
  }) {
12257
12273
  const formulas = preview.cells.map((c) => c.formula ?? "").filter((f) => f.trim() !== "");
12258
12274
  const readings = useFormulaReadings(tableId, formulas);
12259
- const afterWords = (cell) => {
12260
- if (cell.how === "compute") {
12261
- const reading = cell.formula ? readings[cell.formula] : void 0;
12275
+ const afterWords = (cell2) => {
12276
+ if (cell2.how === "compute") {
12277
+ const reading = cell2.formula ? readings[cell2.formula] : void 0;
12262
12278
  if (reading && reading.ok === false) return { text: `The store cannot read this formula: ${reading.error}`, note: true };
12263
12279
  const kind = reading && reading.ok ? RESULT_WORDS[reading.result_type] ?? "a value" : "the result";
12264
- return { text: `Worked out when it runs \u2014 ${kind}${cell.formula ? ` from ${cell.formula}` : ""}`, note: true };
12280
+ return { text: `Worked out when it runs \u2014 ${kind}${cell2.formula ? ` from ${cell2.formula}` : ""}`, note: true };
12265
12281
  }
12266
- if (cell.computed && cell.how === null) return { text: words(cell.before) || "empty", note: false };
12267
- return { text: words(cell.after) || "empty", note: false };
12282
+ if (cell2.computed && cell2.how === null) return { text: words(cell2.before) || "empty", note: false };
12283
+ return { text: words(cell2.after) || "empty", note: false };
12268
12284
  };
12269
12285
  return /* @__PURE__ */ jsxs39("div", { className: "flex flex-col gap-1", "data-records-action-row-preview": "", children: [
12270
12286
  /* @__PURE__ */ jsx44("div", { className: "max-w-full overflow-x-auto rounded border", children: /* @__PURE__ */ jsxs39(
@@ -12277,38 +12293,38 @@ function ActionRowPreview({
12277
12293
  children: [
12278
12294
  /* @__PURE__ */ jsxs39("div", { role: "row", className: "contents", children: [
12279
12295
  /* @__PURE__ */ jsx44("span", { role: "columnheader", className: "sticky left-0 bg-muted/60 px-2 py-1" }),
12280
- preview.cells.map((cell) => /* @__PURE__ */ jsx44(
12296
+ preview.cells.map((cell2) => /* @__PURE__ */ jsx44(
12281
12297
  "span",
12282
12298
  {
12283
12299
  role: "columnheader",
12284
- title: cell.name,
12285
- className: cn25("truncate border-l bg-muted/60 px-2 py-1 font-medium", cell.changed ? "text-foreground" : "text-muted-foreground"),
12286
- children: cell.name
12300
+ title: cell2.name,
12301
+ className: cn25("truncate border-l bg-muted/60 px-2 py-1 font-medium", cell2.changed ? "text-foreground" : "text-muted-foreground"),
12302
+ children: cell2.name
12287
12303
  },
12288
- cell.key
12304
+ cell2.key
12289
12305
  ))
12290
12306
  ] }),
12291
12307
  ["before", "after"].map((which) => /* @__PURE__ */ jsxs39("div", { role: "row", className: "contents", "data-preview-row": which, children: [
12292
12308
  /* @__PURE__ */ jsx44("span", { role: "rowheader", className: "sticky left-0 border-t bg-background px-2 py-1 font-medium text-muted-foreground", children: which === "before" ? "Now" : "After" }),
12293
- preview.cells.map((cell) => {
12294
- const shown4 = which === "before" ? { text: words(cell.before) || "empty", note: false } : afterWords(cell);
12309
+ preview.cells.map((cell2) => {
12310
+ const shown4 = which === "before" ? { text: words(cell2.before) || "empty", note: false } : afterWords(cell2);
12295
12311
  return /* @__PURE__ */ jsx44(
12296
12312
  "span",
12297
12313
  {
12298
12314
  role: "cell",
12299
- "data-changed": cell.changed ? "true" : void 0,
12300
- "data-records-preview-cell": cell.key,
12315
+ "data-changed": cell2.changed ? "true" : void 0,
12316
+ "data-records-preview-cell": cell2.key,
12301
12317
  title: shown4.text,
12302
12318
  className: cn25(
12303
12319
  "truncate border-l border-t px-2 py-1",
12304
12320
  shown4.text === "empty" && "italic text-muted-foreground",
12305
- cell.changed && which === "before" && "bg-destructive/10 text-destructive line-through",
12306
- cell.changed && which === "after" && "bg-primary/10 font-medium",
12321
+ cell2.changed && which === "before" && "bg-destructive/10 text-destructive line-through",
12322
+ cell2.changed && which === "after" && "bg-primary/10 font-medium",
12307
12323
  shown4.note && "italic"
12308
12324
  ),
12309
12325
  children: shown4.text
12310
12326
  },
12311
- cell.key
12327
+ cell2.key
12312
12328
  );
12313
12329
  })
12314
12330
  ] }, which))
@@ -13818,15 +13834,15 @@ function planPastedBlock(args) {
13818
13834
  for (const refusal4 of predicted) {
13819
13835
  const key = refusal4.field_key;
13820
13836
  if (key === void 0) continue;
13821
- const cell = built.find((b) => b.key === key && b.refusal === null);
13822
- if (!cell) continue;
13823
- cell.refusal = refusal4.message;
13824
- cell.value = null;
13837
+ const cell2 = built.find((b) => b.key === key && b.refusal === null);
13838
+ if (!cell2) continue;
13839
+ cell2.refusal = refusal4.message;
13840
+ cell2.value = null;
13825
13841
  delete accepted[key];
13826
13842
  refusals.push({
13827
13843
  fromLine,
13828
13844
  column: fieldName(byKey.get(key) ?? { key }),
13829
- raw: cell.raw,
13845
+ raw: cell2.raw,
13830
13846
  why: refusal4.message
13831
13847
  });
13832
13848
  }
@@ -13854,7 +13870,7 @@ function planPastedBlock(args) {
13854
13870
  }
13855
13871
  function documentOf(row) {
13856
13872
  const out = {};
13857
- for (const cell of row.cells) if (cell.refusal === null) out[cell.key] = cell.value;
13873
+ for (const cell2 of row.cells) if (cell2.refusal === null) out[cell2.key] = cell2.value;
13858
13874
  return out;
13859
13875
  }
13860
13876
  var sameWords = (text) => text.trim().replace(/\s+/g, " ").toLowerCase();
@@ -13875,11 +13891,11 @@ function readPasteHeader(args) {
13875
13891
  let named = 0;
13876
13892
  let filled = 0;
13877
13893
  columnKeys.forEach((_, c) => {
13878
- const cell = head[c];
13879
- if (cell === void 0 || cell.trim() === "") return;
13894
+ const cell2 = head[c];
13895
+ if (cell2 === void 0 || cell2.trim() === "") return;
13880
13896
  filled += 1;
13881
- const hits = [...new Set(byName.get(sameWords(cell)) ?? [])];
13882
- const named1 = hits.filter((f) => sameWords(fieldName(f)) === sameWords(cell));
13897
+ const hits = [...new Set(byName.get(sameWords(cell2)) ?? [])];
13898
+ const named1 = hits.filter((f) => sameWords(fieldName(f)) === sameWords(cell2));
13883
13899
  const pick = named1.length > 0 ? named1 : hits;
13884
13900
  if (pick.length !== 1) return;
13885
13901
  const only = pick[0];
@@ -13890,8 +13906,8 @@ function readPasteHeader(args) {
13890
13906
  });
13891
13907
  if (named === 0 || named * 2 < filled) return null;
13892
13908
  const unmatched = columnKeys.flatMap((_, c) => {
13893
- const cell = head[c];
13894
- return mapped[c] === null && cell !== void 0 && cell.trim() !== "" ? [cell.trim()] : [];
13909
+ const cell2 = head[c];
13910
+ return mapped[c] === null && cell2 !== void 0 && cell2.trim() !== "" ? [cell2.trim()] : [];
13895
13911
  });
13896
13912
  return { columnKeys: mapped, unmatched, lines: lines.slice(1) };
13897
13913
  }
@@ -14228,7 +14244,7 @@ function useMergedGridControls(args) {
14228
14244
  }
14229
14245
  } : {},
14230
14246
  clearCells: (cells) => {
14231
- for (const cell of cells) editing.setCell(cell.rowId, cell.columnId, null);
14247
+ for (const cell2 of cells) editing.setCell(cell2.rowId, cell2.columnId, null);
14232
14248
  },
14233
14249
  fillDown: (rowIds, columnIds) => {
14234
14250
  const byId = new Map(rows.map((r) => [r.id, r]));
@@ -16149,22 +16165,22 @@ import {
16149
16165
  import { formatRelativeTime as formatRelativeTime2 } from "@ai-matrx/kit/format";
16150
16166
  import { Fragment as Fragment16, jsx as jsx57, jsxs as jsxs52 } from "react/jsx-runtime";
16151
16167
  var NO_ENRICH_REASON = "Having an agent fill this column is not switched on here yet, so this panel does not offer it rather than offering something that cannot happen. Everything else on this panel works. It is on our list, not yours.";
16152
- function cellState(cell) {
16153
- if (!cell || !cell.agent_owned) return "none";
16154
- if (cell.pinned) return "yours";
16155
- if (cell.absent_reason === "conflicting") return "unsure";
16156
- if (cell.actor === "agent") return "agent";
16168
+ function cellState(cell2) {
16169
+ if (!cell2 || !cell2.agent_owned) return "none";
16170
+ if (cell2.pinned) return "yours";
16171
+ if (cell2.absent_reason === "conflicting") return "unsure";
16172
+ if (cell2.actor === "agent") return "agent";
16157
16173
  return "none";
16158
16174
  }
16159
16175
  function ago(at) {
16160
16176
  return at ? formatRelativeTime2(at, { style: "intl", fallback: "" }) : "";
16161
16177
  }
16162
- function EnrichBadge({ cell, onPin, className }) {
16163
- const state = cellState(cell);
16164
- if (!cell || state === "none") return null;
16165
- const source = cell.source ?? {};
16178
+ function EnrichBadge({ cell: cell2, onPin, className }) {
16179
+ const state = cellState(cell2);
16180
+ if (!cell2 || state === "none") return null;
16181
+ const source = cell2.source ?? {};
16166
16182
  const read = Array.isArray(source.read) ? source.read : [];
16167
- const alternates = cell.alternates ?? [];
16183
+ const alternates = cell2.alternates ?? [];
16168
16184
  const word = state === "yours" ? "yours" : state === "unsure" ? "unsure" : "agent";
16169
16185
  return /* @__PURE__ */ jsxs52(HoverCard, { openDelay: 120, children: [
16170
16186
  /* @__PURE__ */ jsx57(HoverCardTrigger, { asChild: true, children: /* @__PURE__ */ jsxs52("span", { className: cn32("inline-flex items-center gap-1 align-middle", className), children: [
@@ -16176,18 +16192,18 @@ function EnrichBadge({ cell, onPin, className }) {
16176
16192
  children: word
16177
16193
  }
16178
16194
  ),
16179
- cell.stale ? /* @__PURE__ */ jsx57(Badge8, { variant: "outline", className: "text-[10px] font-normal leading-none opacity-70", children: "stale" }) : null
16195
+ cell2.stale ? /* @__PURE__ */ jsx57(Badge8, { variant: "outline", className: "text-[10px] font-normal leading-none opacity-70", children: "stale" }) : null
16180
16196
  ] }) }),
16181
16197
  /* @__PURE__ */ jsxs52(HoverCardContent, { className: "w-80 space-y-2 text-xs", children: [
16182
16198
  /* @__PURE__ */ jsx57("p", { className: "font-medium", children: state === "yours" ? "You typed this one in" : state === "unsure" ? "A model had candidates and committed to none" : "Filled in by a model" }),
16183
- state !== "yours" && cell.on_behalf_of ? /* @__PURE__ */ jsxs52("p", { className: "text-muted-foreground", children: [
16199
+ state !== "yours" && cell2.on_behalf_of ? /* @__PURE__ */ jsxs52("p", { className: "text-muted-foreground", children: [
16184
16200
  "Acting for ",
16185
- cell.on_behalf_of,
16186
- cell.written_at ? `, ${ago(cell.written_at)}` : "",
16201
+ cell2.on_behalf_of,
16202
+ cell2.written_at ? `, ${ago(cell2.written_at)}` : "",
16187
16203
  "."
16188
- ] }) : cell.written_at ? /* @__PURE__ */ jsxs52("p", { className: "text-muted-foreground", children: [
16204
+ ] }) : cell2.written_at ? /* @__PURE__ */ jsxs52("p", { className: "text-muted-foreground", children: [
16189
16205
  "Written ",
16190
- ago(cell.written_at),
16206
+ ago(cell2.written_at),
16191
16207
  "."
16192
16208
  ] }) : null,
16193
16209
  source.model ? /* @__PURE__ */ jsxs52("p", { className: "text-muted-foreground", children: [
@@ -16204,9 +16220,9 @@ function EnrichBadge({ cell, onPin, className }) {
16204
16220
  /* @__PURE__ */ jsx57("p", { className: "text-muted-foreground", children: state === "unsure" ? "What it considered" : "What it nearly said instead" }),
16205
16221
  /* @__PURE__ */ jsx57("ul", { className: "list-inside list-decimal", children: alternates.slice(0, 4).map((a, i) => /* @__PURE__ */ jsx57("li", { children: String(a.value ?? "") }, i)) })
16206
16222
  ] }) : null,
16207
- cell.stale && cell.due_at ? /* @__PURE__ */ jsxs52("p", { className: "text-muted-foreground", children: [
16223
+ cell2.stale && cell2.due_at ? /* @__PURE__ */ jsxs52("p", { className: "text-muted-foreground", children: [
16208
16224
  "Past its date \u2014 it was due to be looked at again ",
16209
- ago(cell.due_at),
16225
+ ago(cell2.due_at),
16210
16226
  ". The value is still here; nothing was overwritten."
16211
16227
  ] }) : null,
16212
16228
  onPin ? /* @__PURE__ */ jsx57(
@@ -16215,8 +16231,8 @@ function EnrichBadge({ cell, onPin, className }) {
16215
16231
  size: "sm",
16216
16232
  variant: "outline",
16217
16233
  className: "w-full",
16218
- onClick: () => void onPin(!cell.pinned),
16219
- children: cell.pinned ? "Let the model fill this in again" : "Keep this one \u2014 stop the model changing it"
16234
+ onClick: () => void onPin(!cell2.pinned),
16235
+ children: cell2.pinned ? "Let the model fill this in again" : "Keep this one \u2014 stop the model changing it"
16220
16236
  }
16221
16237
  ) : null
16222
16238
  ] })
@@ -16239,7 +16255,7 @@ function useEnrichCells(tableId, recordIds) {
16239
16255
  }
16240
16256
  setError(null);
16241
16257
  const next = /* @__PURE__ */ new Map();
16242
- for (const cell of answered.data) next.set(`${cell.record_id}:${cell.field_key}`, cell);
16258
+ for (const cell2 of answered.data) next.set(`${cell2.record_id}:${cell2.field_key}`, cell2);
16243
16259
  setCells(next);
16244
16260
  }, [client, tableId, key]);
16245
16261
  useEffect39(() => {
@@ -16709,7 +16725,7 @@ function columnForField(field2, editing, mayWriteRow, whyNotRow, look, onAskWhoC
16709
16725
  filter: filterRefusal(field2) !== null ? false : editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? "select" : holdsNumbers(field2) ? "number" : "auto",
16710
16726
  // THE MENU'S VALUE LIST WEARS THE CHOICES' COLOURS (lane CELL-EDITORS, night walk 2026-10-06): the
16711
16727
  // same chip the cell draws, never bare words beside a coloured column.
16712
- ...editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? { filterValueClass: (value) => choiceChipLookOf(field2, value).className } : {},
16728
+ ...editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? { filterValueClass: (value, label) => choiceChipLookOf(field2, value, label).className } : {},
16713
16729
  cell: (row) => (
16714
16730
  /*
16715
16731
  * 🚨 A READING QUESTION IS NOT AN EDITING RIGHT. This used to read
@@ -17182,7 +17198,7 @@ function PlanTable({ plan }) {
17182
17198
  const keys = Array.from(new Set(shown4.flatMap((row) => row.cells.map((c) => c.key))));
17183
17199
  if (shown4.length === 0 || keys.length === 0) return null;
17184
17200
  const columnName = /* @__PURE__ */ new Map();
17185
- for (const row of shown4) for (const cell of row.cells) if (!columnName.has(cell.key)) columnName.set(cell.key, cell.column);
17201
+ for (const row of shown4) for (const cell2 of row.cells) if (!columnName.has(cell2.key)) columnName.set(cell2.key, cell2.column);
17186
17202
  return /* @__PURE__ */ jsxs55("div", { className: "overflow-auto rounded border", children: [
17187
17203
  /* @__PURE__ */ jsxs55("table", { className: "w-full text-xs", "data-matrx-paste-plan": true, children: [
17188
17204
  /* @__PURE__ */ jsx60("thead", { className: "bg-muted/50", children: /* @__PURE__ */ jsxs55("tr", { children: [
@@ -17195,18 +17211,18 @@ function PlanTable({ plan }) {
17195
17211
  row.recordId === null ? /* @__PURE__ */ jsx60(Badge9, { variant: "outline", className: "ml-1", children: "new" }) : null
17196
17212
  ] }),
17197
17213
  keys.map((key) => {
17198
- const cell = row.cells.find((c) => c.key === key);
17199
- if (!cell) return /* @__PURE__ */ jsx60("td", { className: "px-2 py-1" }, key);
17200
- if (cell.refusal !== null) {
17201
- return /* @__PURE__ */ jsx60("td", { className: "px-2 py-1 text-muted-foreground line-through", children: cell.raw }, key);
17214
+ const cell2 = row.cells.find((c) => c.key === key);
17215
+ if (!cell2) return /* @__PURE__ */ jsx60("td", { className: "px-2 py-1" }, key);
17216
+ if (cell2.refusal !== null) {
17217
+ return /* @__PURE__ */ jsx60("td", { className: "px-2 py-1 text-muted-foreground line-through", children: cell2.raw }, key);
17202
17218
  }
17203
- return /* @__PURE__ */ jsx60("td", { className: "px-2 py-1", children: cell.value === null ? /* @__PURE__ */ jsx60("span", { className: "text-muted-foreground", children: "cleared" }) : (
17219
+ return /* @__PURE__ */ jsx60("td", { className: "px-2 py-1", children: cell2.value === null ? /* @__PURE__ */ jsx60("span", { className: "text-muted-foreground", children: "cleared" }) : (
17204
17220
  // THE WORDS, NOT THE ID. A choice column stores the option
17205
17221
  // record's id and the person pasted a word; showing the id
17206
17222
  // here made this panel print
17207
17223
  // `530808bf-9f2d-4062-bc09-b8cc3b162f2a` where they had
17208
17224
  // written Drain Cleaning (FIX-10C F8).
17209
- cell.display ?? String(cell.value)
17225
+ cell2.display ?? String(cell2.value)
17210
17226
  ) }, key);
17211
17227
  })
17212
17228
  ] }, row.fromLine)) })
@@ -17520,6 +17536,7 @@ function combineRows(rows, header) {
17520
17536
 
17521
17537
  // src/importRefusals.ts
17522
17538
  import { downloadFile } from "@ai-matrx/kit/download";
17539
+ import { toDelimited } from "@ai-matrx/kit/delimited";
17523
17540
  function reasonShape(reason) {
17524
17541
  return reason.replace(/"[^"]*"/g, '"\u2026"').replace(/“[^”]*”/g, "\u201C\u2026\u201D").replace(/\b\d+(?:[.,]\d+)*\b/g, "N").replace(/\s+/g, " ").trim();
17525
17542
  }
@@ -17535,21 +17552,24 @@ function groupReasons(reasons) {
17535
17552
  }
17536
17553
  return [...groups.values()].sort((a, b) => b.count - a.count);
17537
17554
  }
17538
- function csvCell(value) {
17539
- const text = value === null || value === void 0 ? "" : String(value);
17540
- return /[",\n\r]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
17555
+ function cell(value) {
17556
+ if (value === null || value === void 0) return null;
17557
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? value : String(value);
17541
17558
  }
17542
17559
  function refusedRowsCsv(rows, lineOf = (n) => n + 1) {
17543
17560
  const headers = [];
17544
17561
  for (const r of rows) for (const h of Object.keys(r.source ?? {})) if (!headers.includes(h)) headers.push(h);
17545
- const lines = [[...headers, "Line in your file", "Why it was not added"].map(csvCell).join(",")];
17546
- for (const r of rows) {
17547
- const cells = headers.map((h) => csvCell((r.source ?? {})[h]));
17548
- cells.push(csvCell(typeof r.row === "number" ? lineOf(r.row) : ""));
17549
- cells.push(csvCell(r.reason ?? ""));
17550
- lines.push(cells.join(","));
17551
- }
17552
- return lines.join("\n") + "\n";
17562
+ return toDelimited(
17563
+ [
17564
+ [...headers, "Line in your file", "Why it was not added"],
17565
+ ...rows.map((r) => [
17566
+ ...headers.map((h) => cell((r.source ?? {})[h])),
17567
+ typeof r.row === "number" ? lineOf(r.row) : "",
17568
+ r.reason ?? ""
17569
+ ])
17570
+ ],
17571
+ { trailingNewline: true }
17572
+ );
17553
17573
  }
17554
17574
  function offerDownload(name, text, type = "text/csv") {
17555
17575
  if (typeof document === "undefined" || typeof URL === "undefined" || typeof URL.createObjectURL !== "function") return false;
@@ -19053,18 +19073,18 @@ function splitPipes(line) {
19053
19073
  if (text.startsWith("|")) text = text.slice(1);
19054
19074
  if (text.endsWith("|") && !text.endsWith("\\|")) text = text.slice(0, -1);
19055
19075
  const cells = [];
19056
- let cell = "";
19076
+ let cell2 = "";
19057
19077
  for (let i = 0; i < text.length; i += 1) {
19058
19078
  const ch = text[i];
19059
19079
  if (ch === "\\" && text[i + 1] === "|") {
19060
- cell += "\\|";
19080
+ cell2 += "\\|";
19061
19081
  i += 1;
19062
19082
  } else if (ch === "|") {
19063
- cells.push(cell);
19064
- cell = "";
19065
- } else cell += ch;
19083
+ cells.push(cell2);
19084
+ cell2 = "";
19085
+ } else cell2 += ch;
19066
19086
  }
19067
- cells.push(cell);
19087
+ cells.push(cell2);
19068
19088
  return cells.map(cellWords);
19069
19089
  }
19070
19090
  var LIST_ITEM = /^(\s*)(?:[-*+•]|\d{1,3}[.)])\s+(?:\[[ xX]\]\s+)?(.*)$/;
@@ -19181,33 +19201,33 @@ function shapeFromList(items, name, at) {
19181
19201
  function parseDelimited(text, delimiter) {
19182
19202
  const rows = [];
19183
19203
  let row = [];
19184
- let cell = "";
19204
+ let cell2 = "";
19185
19205
  let quoted2 = false;
19186
19206
  for (let i = 0; i < text.length; i += 1) {
19187
19207
  const ch = text[i];
19188
19208
  if (quoted2) {
19189
19209
  if (ch === '"') {
19190
19210
  if (text[i + 1] === '"') {
19191
- cell += '"';
19211
+ cell2 += '"';
19192
19212
  i += 1;
19193
19213
  } else quoted2 = false;
19194
- } else cell += ch;
19214
+ } else cell2 += ch;
19195
19215
  continue;
19196
19216
  }
19197
- if (ch === '"' && cell.trim() === "") quoted2 = true;
19217
+ if (ch === '"' && cell2.trim() === "") quoted2 = true;
19198
19218
  else if (ch === delimiter) {
19199
- row.push(cell);
19200
- cell = "";
19219
+ row.push(cell2);
19220
+ cell2 = "";
19201
19221
  } else if (ch === "\n" || ch === "\r") {
19202
19222
  if (ch === "\r" && text[i + 1] === "\n") i += 1;
19203
- row.push(cell);
19223
+ row.push(cell2);
19204
19224
  rows.push(row);
19205
19225
  row = [];
19206
- cell = "";
19207
- } else cell += ch;
19226
+ cell2 = "";
19227
+ } else cell2 += ch;
19208
19228
  }
19209
- if (cell.length > 0 || row.length > 0) {
19210
- row.push(cell);
19229
+ if (cell2.length > 0 || row.length > 0) {
19230
+ row.push(cell2);
19211
19231
  rows.push(row);
19212
19232
  }
19213
19233
  return rows.filter((r) => r.some((c) => c.trim() !== ""));
@@ -19510,10 +19530,10 @@ function shapeTextOfNode(node) {
19510
19530
  flushLine();
19511
19531
  const width = Math.max(...rows.map((r) => r.length));
19512
19532
  const pad4 = (r) => [...r, ...Array.from({ length: width - r.length }, () => "")];
19513
- const cell = (c) => c.replace(/\|/g, "\\|").replace(/\s+/g, " ").trim();
19514
- out.push(`| ${pad4(rows[0]).map(cell).join(" | ")} |`);
19533
+ const cell2 = (c) => c.replace(/\|/g, "\\|").replace(/\s+/g, " ").trim();
19534
+ out.push(`| ${pad4(rows[0]).map(cell2).join(" | ")} |`);
19515
19535
  out.push(`|${Array.from({ length: width }, () => "---").join("|")}|`);
19516
- for (const r of rows.slice(1)) out.push(`| ${pad4(r).map(cell).join(" | ")} |`);
19536
+ for (const r of rows.slice(1)) out.push(`| ${pad4(r).map(cell2).join(" | ")} |`);
19517
19537
  rows = [];
19518
19538
  };
19519
19539
  const textOf = (n) => (n.textContent ?? "").replace(/\s+/g, " ").trim();
@@ -19939,12 +19959,12 @@ import { createUndoStack, popRedo, popUndo, pushUndo } from "@ai-matrx/design-sy
19939
19959
  import { Fragment as Fragment22, jsx as jsx66, jsxs as jsxs60 } from "react/jsx-runtime";
19940
19960
  function changesFor(step2, direction, versions = /* @__PURE__ */ new Map()) {
19941
19961
  const byRow = /* @__PURE__ */ new Map();
19942
- for (const cell of step2.cells) {
19943
- if (step2.created?.includes(cell.rowId)) continue;
19944
- const patch = byRow.get(cell.rowId) ?? {};
19945
- const value = direction === "undo" ? cell.before : cell.after;
19946
- patch[cell.key] = value === void 0 ? null : value;
19947
- byRow.set(cell.rowId, patch);
19962
+ for (const cell2 of step2.cells) {
19963
+ if (step2.created?.includes(cell2.rowId)) continue;
19964
+ const patch = byRow.get(cell2.rowId) ?? {};
19965
+ const value = direction === "undo" ? cell2.before : cell2.after;
19966
+ patch[cell2.key] = value === void 0 ? null : value;
19967
+ byRow.set(cell2.rowId, patch);
19948
19968
  }
19949
19969
  const changes = [...byRow].map(([record_id, patch]) => ({
19950
19970
  op: "update",
@@ -19972,7 +19992,7 @@ function useGridUndo(args) {
19972
19992
  const dismiss = useCallback23(() => setNotice(null), []);
19973
19993
  const push = useCallback23((step2) => {
19974
19994
  if (step2.cells.length === 0 && !step2.created?.length && !step2.archived?.length && !step2.retiredField) return;
19975
- for (const cell of step2.cells) if (typeof cell.version === "number") known.current.set(cell.rowId, cell.version);
19995
+ for (const cell2 of step2.cells) if (typeof cell2.version === "number") known.current.set(cell2.rowId, cell2.version);
19976
19996
  counter.current += 1;
19977
19997
  const id = String(counter.current);
19978
19998
  setHeld((was) => {
@@ -20301,13 +20321,12 @@ function useGridAssist(args) {
20301
20321
  const copyRecordReference = useCallback24(
20302
20322
  (rowId) => {
20303
20323
  void (async () => {
20304
- try {
20305
- const text = JSON.stringify({ __kind: tableKindSlug(tableId), _record_id: rowId });
20306
- if (!await copyText(text)) throw new Error("This browser did not let the page write to the clipboard.");
20307
- say2(true, "The record reference is copied.");
20308
- } catch (thrown) {
20309
- say2(false, thrown instanceof Error ? thrown.message : String(thrown));
20324
+ const text = JSON.stringify({ __kind: tableKindSlug(tableId), _record_id: rowId });
20325
+ if (!await copyText(text)) {
20326
+ say2(false, "This browser did not let the page write to the clipboard.");
20327
+ return;
20310
20328
  }
20329
+ say2(true, "The record reference is copied.");
20311
20330
  })();
20312
20331
  },
20313
20332
  [tableId, say2]
@@ -20484,9 +20503,9 @@ function planBulk(args) {
20484
20503
  before: (row.document ?? {})[field2.key] ?? null,
20485
20504
  after: value
20486
20505
  }));
20487
- const changes = cells.map((cell) => ({
20506
+ const changes = cells.map((cell2) => ({
20488
20507
  op: "update",
20489
- record_id: cell.rowId,
20508
+ record_id: cell2.rowId,
20490
20509
  patch: { [field2.key]: value }
20491
20510
  }));
20492
20511
  const many = countOf(cells.length, args.noun, args.nounPlural);
@@ -21922,8 +21941,8 @@ function GridBody({
21922
21941
  pastedNames.set(
21923
21942
  field2.key,
21924
21943
  lines.flatMap((line) => {
21925
- const cell = line[at];
21926
- return typeof cell === "string" ? relationNamesIn2(field2, cell) : [];
21944
+ const cell2 = line[at];
21945
+ return typeof cell2 === "string" ? relationNamesIn2(field2, cell2) : [];
21927
21946
  })
21928
21947
  );
21929
21948
  }
@@ -30969,8 +30988,8 @@ function CalendarView({
30969
30988
  }
30970
30989
  });
30971
30990
  const dayDrop = (fallback) => dropOn((e) => {
30972
- const cell = e.target.closest?.("[data-calendar-day]");
30973
- return { day: cell?.getAttribute("data-calendar-day") ?? fallback, minute: null };
30991
+ const cell2 = e.target.closest?.("[data-calendar-day]");
30992
+ return { day: cell2?.getAttribute("data-calendar-day") ?? fallback, minute: null };
30974
30993
  });
30975
30994
  const minuteAt = (e) => {
30976
30995
  const slot = e.target?.closest?.("[data-calendar-slot]");