@ai-matrx/records-ui 0.102.9 → 0.102.14

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.cjs CHANGED
@@ -6200,9 +6200,11 @@ function PageGlyph() {
6200
6200
  }
6201
6201
  function ReferenceChip({ reference, waiting }) {
6202
6202
  const host = useRecordsUi();
6203
+ const look = useEmbeddedLook();
6204
+ const pending = reference.label == null && reference.token === "record" && !waiting && !host.renderReference;
6205
+ const pendingMark = /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_design_system19.Skeleton, { "aria-label": "Loading", "data-records-reference-pending": "", className: "inline-block h-3 w-16 shrink-0 rounded-sm align-middle" });
6203
6206
  const words2 = reference.label ?? (reference.token === "record" ? waiting ?? "Loading\u2026" : WITHHELD_ENTITY_LABEL);
6204
6207
  const drawn = host.renderReference ? host.renderReference({ ...reference, label: reference.label ?? words2 }) : null;
6205
- const look = useEmbeddedLook();
6206
6208
  if (look?.plainRelation) {
6207
6209
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6208
6210
  "span",
@@ -6217,7 +6219,7 @@ function ReferenceChip({ reference, waiting }) {
6217
6219
  title: reference.archived ? ARCHIVED_REFERENCE_TIP : words2,
6218
6220
  children: [
6219
6221
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { "aria-hidden": "true", "data-records-reference-icon": "", className: "inline-flex size-4 shrink-0 items-center justify-center text-muted-foreground", children: glyphOf(reference.icon) ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-sm leading-none", children: reference.icon }) : reference.icon && host.renderIcon?.(reference.icon) || /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PageGlyph, {}) }),
6220
- drawn ?? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate", children: words2 }),
6222
+ drawn ?? (pending ? pendingMark : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate", children: words2 })),
6221
6223
  reference.archived ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "shrink-0 text-muted-foreground", children: ARCHIVED_REFERENCE_WORD }) : null
6222
6224
  ]
6223
6225
  }
@@ -6235,7 +6237,7 @@ function ReferenceChip({ reference, waiting }) {
6235
6237
  "data-records-reference-archived": reference.archived ? "" : void 0,
6236
6238
  title: reference.archived ? ARCHIVED_REFERENCE_TIP : words2,
6237
6239
  children: [
6238
- drawn ?? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate", children: words2 }),
6240
+ drawn ?? (pending ? pendingMark : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate", children: words2 })),
6239
6241
  reference.archived ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "shrink-0 text-muted-foreground", children: ARCHIVED_REFERENCE_WORD }) : null
6240
6242
  ]
6241
6243
  }
@@ -7135,6 +7137,8 @@ function cardWords(record, field2, labels) {
7135
7137
 
7136
7138
  // src/gridEditing.tsx
7137
7139
  var import_jsx_runtime28 = require("react/jsx-runtime");
7140
+ var FLOATING_EDITOR_TRAY_CLASS = "pointer-events-none absolute left-0 z-[26] w-max max-w-[24rem] rounded-md border bg-popover px-1.5 py-0.5 shadow-md";
7141
+ var FLOATING_EDITOR_NOTE_CLASS = "[&_[data-records-typed-reads-as]]:pointer-events-none [&_[data-records-typed-reads-as]]:absolute [&_[data-records-typed-reads-as]]:bottom-full [&_[data-records-typed-reads-as]]:left-0 [&_[data-records-typed-reads-as]]:z-[26] [&_[data-records-typed-reads-as]]:mb-1 [&_[data-records-typed-reads-as]]:w-max [&_[data-records-typed-reads-as]]:max-w-[24rem] [&_[data-records-typed-reads-as]]:rounded-md [&_[data-records-typed-reads-as]]:border [&_[data-records-typed-reads-as]]:bg-popover [&_[data-records-typed-reads-as]]:px-1.5 [&_[data-records-typed-reads-as]]:py-0.5 [&_[data-records-typed-reads-as]]:shadow-md";
7138
7142
  var NO_ROWS = [];
7139
7143
  function asksWhoChanged(event) {
7140
7144
  return event.altKey && event.shiftKey && !event.metaKey && !event.ctrlKey && (event.code === "KeyH" || event.key.toLowerCase() === "h");
@@ -7616,11 +7620,11 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
7616
7620
  discard,
7617
7621
  forget: (cells) => {
7618
7622
  if (cells.length === 0) return;
7619
- for (const cell of cells) versions.current.delete(cell.rowId);
7623
+ for (const cell2 of cells) versions.current.delete(cell2.rowId);
7620
7624
  setOptimistic((held) => {
7621
7625
  let next = null;
7622
- for (const cell of cells) {
7623
- const id = cellKey(cell.rowId, cell.key);
7626
+ for (const cell2 of cells) {
7627
+ const id = cellKey(cell2.rowId, cell2.key);
7624
7628
  if (!(id in held)) continue;
7625
7629
  next = next ?? { ...held };
7626
7630
  delete next[id];
@@ -8094,7 +8098,13 @@ function OpenCell({
8094
8098
  "data-matrx-cell-fill": "",
8095
8099
  "data-matrx-cell-editor": "",
8096
8100
  tabIndex: -1,
8097
- className: "relative z-[25] flex w-full min-w-0 max-w-full flex-col gap-1 outline-none",
8101
+ className: (0, import_design_system23.cn)(
8102
+ "relative z-[25] flex w-full min-w-0 max-w-full flex-col gap-1 outline-none",
8103
+ FLOATING_EDITOR_NOTE_CLASS,
8104
+ // A field's own input is 36px (h-9); in a 35px row it grew the row 4px. In the cell it is
8105
+ // the row action strip's 32px, so opening a cell never changes the row (STABLE-TABLES).
8106
+ "[&_input:not([type=checkbox]):not([type=radio])]:h-8 [&_input:not([type=checkbox]):not([type=radio])]:py-0"
8107
+ ),
8098
8108
  onDoubleClick: (event) => event.stopPropagation(),
8099
8109
  onKeyDown: (event) => {
8100
8110
  if (event.target?.closest?.("[data-refusal-notice], [data-records-choice-ask]")) return;
@@ -8149,7 +8159,7 @@ function OpenCell({
8149
8159
  addsChoices: true
8150
8160
  }
8151
8161
  ),
8152
- picker || asksAboutAChoice(draft) ? null : blurCommits ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-[10px] text-muted-foreground", children: multiline ? "\u23CE saves \xB7 \u21E7\u23CE new line \xB7 Esc cancels \xB7 Tab next" : "\u23CE saves \xB7 Esc cancels \xB7 Tab next" }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "flex items-center gap-1", children: [
8162
+ picker || asksAboutAChoice(draft) ? null : blurCommits ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: (0, import_design_system23.cn)("text-[10px] text-muted-foreground", FLOATING_EDITOR_TRAY_CLASS, "top-full mt-1"), "data-records-editor-hint": "", children: multiline ? "\u23CE saves \xB7 \u21E7\u23CE new line \xB7 Esc cancels \xB7 Tab next" : "\u23CE saves \xB7 Esc cancels \xB7 Tab next" }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "flex items-center gap-1", children: [
8153
8163
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_design_system23.Button, { size: "sm", onClick: () => once(() => onCommit(null, "pick")), children: "Save" }),
8154
8164
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_design_system23.Button, { size: "sm", variant: "ghost", onClick: () => once(() => onCancel("pick")), children: "Cancel" })
8155
8165
  ] }),
@@ -10825,7 +10835,7 @@ var ROLLUP_OPERATIONS = ROLLUP_AGG_VALUES.map((value) => ({
10825
10835
  label: ROLLUP_AGG_LABEL[value]
10826
10836
  }));
10827
10837
  var FORMULA_SEPARATOR_LABEL = "Joined by";
10828
- var EDITING_A_WORKED_OUT_COLUMN = "This column works out its answer from the columns picked when it was made. To change what it works out, write it as a formula below \u2014 the store checks it as you type, and a rename alone leaves it exactly as it is.";
10838
+ var EDITING_A_WORKED_OUT_COLUMN = "Written as a formula. Edit it below.";
10829
10839
  var FORMULA_DEFAULT_SEPARATOR = " \u2014 ";
10830
10840
  var FORMULA_OPERATIONS = FORMULA_OP_VALUES.map((value) => ({
10831
10841
  value,
@@ -11210,8 +11220,7 @@ function FieldEditor(props) {
11210
11220
  placeholder: "Day rate",
11211
11221
  onChange: (e) => setLabel(e.target.value)
11212
11222
  }
11213
- ),
11214
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: onEntity ? "What people will read beside the value." : "What people will read at the top of the column." })
11223
+ )
11215
11224
  ] }),
11216
11225
  /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-col gap-1", children: [
11217
11226
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.Label, { className: "text-xs", children: "What it holds" }),
@@ -11222,7 +11231,7 @@ function FieldEditor(props) {
11222
11231
  disabled: editing,
11223
11232
  onValueChange: (next) => setType(next),
11224
11233
  children: [
11225
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectTrigger, { size: "sm", "aria-label": "What this field holds", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectValue, {}) }),
11234
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectTrigger, { size: "sm", "aria-label": "What this field holds", ...choice?.explanation ? { title: choice.explanation } : {}, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectValue, {}) }),
11226
11235
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectContent, { children: FIELD_TYPE_GROUPS.filter((group) => offered.some((c) => c.group === group)).map((group) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system34.SelectGroup, { children: [
11227
11236
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectLabel, { children: group }),
11228
11237
  FIELD_TYPE_CATALOGUE.filter((c) => c.group === group && (c.id === type || offered.includes(c))).map((c) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectItem, { value: c.id, children: c.label }, c.id))
@@ -11230,7 +11239,7 @@ function FieldEditor(props) {
11230
11239
  ]
11231
11240
  }
11232
11241
  ),
11233
- editing && field2 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(FieldRetype, { field: liveField ?? field2, tableId }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: choice?.explanation ?? "" })
11242
+ editing && field2 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(FieldRetype, { field: liveField ?? field2, tableId }) : null
11234
11243
  ] })
11235
11244
  ] }),
11236
11245
  type === "formula" && others.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-col gap-2", children: [
@@ -11268,7 +11277,7 @@ function FieldEditor(props) {
11268
11277
  columns: others
11269
11278
  }
11270
11279
  ) : null
11271
- ] }) : editing && type === "formula" ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "This column works out its answer from other columns, and this table has no other column left for it to read." }) : null,
11280
+ ] }) : editing && type === "formula" ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No other column to read." }) : null,
11272
11281
  editing && field2 && !onEntity && (type === "lookup" || type === "rollup") ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(SourceArchivedNotice, { fieldId: field2.id, tableId }) : null,
11273
11282
  !editing && !(type === "formula" && formulaWritten) || type === "select" || type === "multi_select" || type === "status" || type === "rating" || type === "barcode" || type === "relation" || type === "entity_reference" ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
11274
11283
  TypeQuestions,
@@ -11438,11 +11447,7 @@ function FieldEditor(props) {
11438
11447
  ),
11439
11448
  UNIQUE_LABEL
11440
11449
  ] }) : null,
11441
- rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("p", { className: "text-muted-foreground", children: [
11442
- "No checks. Anything this kind of ",
11443
- onEntity ? "field" : "column",
11444
- " can hold will be accepted."
11445
- ] }) : null,
11450
+ rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-muted-foreground", children: "No checks." }) : null,
11446
11451
  rules.map((rule, index) => rule.kind === "unique" ? null : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex items-center gap-1", children: [
11447
11452
  /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
11448
11453
  import_design_system34.Select,
@@ -11691,8 +11696,7 @@ function TypeQuestions(props) {
11691
11696
  placeholder: "$",
11692
11697
  onChange: (e) => props.setUnit(e.target.value)
11693
11698
  }
11694
- ),
11695
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Shown with every amount, everywhere the value appears \u2014 including where an assistant reads it." })
11699
+ )
11696
11700
  ] });
11697
11701
  }
11698
11702
  if (type === "datetime") {
@@ -11711,7 +11715,7 @@ function TypeQuestions(props) {
11711
11715
  if (type === "lookup" || type === "rollup" || type === "count") {
11712
11716
  const usable = props.relations;
11713
11717
  if (usable.length === 0) {
11714
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: type !== "lookup" ? "No link, Person or File column yet. Add one that holds more than one first." : "No link, Person or File column yet. Add one first." });
11718
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No link, Person or File column yet." });
11715
11719
  }
11716
11720
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "grid gap-3 sm:grid-cols-2", children: [
11717
11721
  /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-col gap-1", children: [
@@ -11757,7 +11761,7 @@ function TypeQuestions(props) {
11757
11761
  }
11758
11762
  if (type === "formula") {
11759
11763
  if (props.others.length === 0) {
11760
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "A worked-out column needs other columns to work from, and this table has none yet." });
11764
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No other columns yet." });
11761
11765
  }
11762
11766
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-col gap-2", children: [
11763
11767
  /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-col gap-1", children: [
@@ -11784,8 +11788,7 @@ function TypeQuestions(props) {
11784
11788
  },
11785
11789
  f.id
11786
11790
  );
11787
- }) }),
11788
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "In the order you pick them. Columns are remembered by which column they are, so renaming one never breaks this." })
11791
+ }) })
11789
11792
  ] }),
11790
11793
  props.formulaOp === "concat" ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-col gap-1", children: [
11791
11794
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.Label, { className: "text-xs", children: FORMULA_SEPARATOR_LABEL }),
@@ -11798,8 +11801,7 @@ function TypeQuestions(props) {
11798
11801
  className: "max-w-[10rem]",
11799
11802
  onChange: (e) => props.setFormulaSeparator(e.target.value)
11800
11803
  }
11801
- ),
11802
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "What goes between the columns. Leave it empty to run them straight together." })
11804
+ )
11803
11805
  ] }) : null
11804
11806
  ] });
11805
11807
  }
@@ -11885,18 +11887,14 @@ function ValueOnTheOtherSide({
11885
11887
  const carried = sample.data?.rows[0]?.document ?? null;
11886
11888
  const offered = declared2.length > 0 ? declared2.map((f) => ({ key: f.key, name: fieldName(f) })) : Object.keys(carried ?? {}).map((key) => ({ key, name: (0, import_text_case5.humanizeIdentifier)(key) }));
11887
11889
  const stillAsking = columns.loading || declared2.length === 0 && sample.loading;
11888
- const body = !relation ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Choose the column above first." }) : stillAsking ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Reading that table's columns\u2026" }) : offered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
11889
- fieldName(relation),
11890
- " points at a table that has no columns to read yet. Add one there first."
11891
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system34.Select, { value, onValueChange: onChange, children: [
11890
+ const body = !relation ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Choose the column above first." }) : stillAsking ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Reading that table's columns\u2026" }) : offered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No columns to read yet." }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system34.Select, { value, onValueChange: onChange, children: [
11892
11891
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectTrigger, { size: "sm", "aria-label": label, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectValue, { placeholder: "Choose a column" }) }),
11893
11892
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectContent, { children: offered.map((column) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.SelectItem, { value: column.key, children: column.name }, column.key)) })
11894
11893
  ] });
11895
11894
  if (compact) return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "mt-1 flex flex-col gap-1", children: body });
11896
11895
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-col gap-1", children: [
11897
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.Label, { className: "text-xs", children: label }),
11898
- body,
11899
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px] text-muted-foreground", children: help })
11896
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.Label, { className: "text-xs", title: help, children: label }),
11897
+ body
11900
11898
  ] });
11901
11899
  }
11902
11900
  function withNumber(rule, key, typed2) {
@@ -12255,10 +12253,10 @@ function useGridColours(args) {
12255
12253
  submenu: swatches("sel-highlight", void 0, (color) => {
12256
12254
  void (async () => {
12257
12255
  let kept = 0;
12258
- for (const cell of cells) {
12259
- const field2 = idOf(cell.columnKey);
12256
+ for (const cell2 of cells) {
12257
+ const field2 = idOf(cell2.columnKey);
12260
12258
  if (!field2) continue;
12261
- const answer = await client.tableDecorate({ table_id: tableId, path: ["cells", cell.rowId, field2.id], value: color });
12259
+ const answer = await client.tableDecorate({ table_id: tableId, path: ["cells", cell2.rowId, field2.id], value: color });
12262
12260
  if (!answer.ok) {
12263
12261
  notify?.error(`The colour was not kept: ${refusalSentence(answer.error)}`);
12264
12262
  return;
@@ -12691,15 +12689,15 @@ function ActionRowPreview({
12691
12689
  }) {
12692
12690
  const formulas = preview.cells.map((c) => c.formula ?? "").filter((f) => f.trim() !== "");
12693
12691
  const readings = useFormulaReadings(tableId, formulas);
12694
- const afterWords = (cell) => {
12695
- if (cell.how === "compute") {
12696
- const reading = cell.formula ? readings[cell.formula] : void 0;
12692
+ const afterWords = (cell2) => {
12693
+ if (cell2.how === "compute") {
12694
+ const reading = cell2.formula ? readings[cell2.formula] : void 0;
12697
12695
  if (reading && reading.ok === false) return { text: `The store cannot read this formula: ${reading.error}`, note: true };
12698
12696
  const kind = reading && reading.ok ? RESULT_WORDS[reading.result_type] ?? "a value" : "the result";
12699
- return { text: `Worked out when it runs \u2014 ${kind}${cell.formula ? ` from ${cell.formula}` : ""}`, note: true };
12697
+ return { text: `Worked out when it runs \u2014 ${kind}${cell2.formula ? ` from ${cell2.formula}` : ""}`, note: true };
12700
12698
  }
12701
- if (cell.computed && cell.how === null) return { text: words(cell.before) || "empty", note: false };
12702
- return { text: words(cell.after) || "empty", note: false };
12699
+ if (cell2.computed && cell2.how === null) return { text: words(cell2.before) || "empty", note: false };
12700
+ return { text: words(cell2.after) || "empty", note: false };
12703
12701
  };
12704
12702
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-col gap-1", "data-records-action-row-preview": "", children: [
12705
12703
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "max-w-full overflow-x-auto rounded border", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
@@ -12712,38 +12710,38 @@ function ActionRowPreview({
12712
12710
  children: [
12713
12711
  /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { role: "row", className: "contents", children: [
12714
12712
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { role: "columnheader", className: "sticky left-0 bg-muted/60 px-2 py-1" }),
12715
- preview.cells.map((cell) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
12713
+ preview.cells.map((cell2) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
12716
12714
  "span",
12717
12715
  {
12718
12716
  role: "columnheader",
12719
- title: cell.name,
12720
- className: (0, import_design_system38.cn)("truncate border-l bg-muted/60 px-2 py-1 font-medium", cell.changed ? "text-foreground" : "text-muted-foreground"),
12721
- children: cell.name
12717
+ title: cell2.name,
12718
+ className: (0, import_design_system38.cn)("truncate border-l bg-muted/60 px-2 py-1 font-medium", cell2.changed ? "text-foreground" : "text-muted-foreground"),
12719
+ children: cell2.name
12722
12720
  },
12723
- cell.key
12721
+ cell2.key
12724
12722
  ))
12725
12723
  ] }),
12726
12724
  ["before", "after"].map((which) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { role: "row", className: "contents", "data-preview-row": which, children: [
12727
12725
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("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" }),
12728
- preview.cells.map((cell) => {
12729
- const shown4 = which === "before" ? { text: words(cell.before) || "empty", note: false } : afterWords(cell);
12726
+ preview.cells.map((cell2) => {
12727
+ const shown4 = which === "before" ? { text: words(cell2.before) || "empty", note: false } : afterWords(cell2);
12730
12728
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
12731
12729
  "span",
12732
12730
  {
12733
12731
  role: "cell",
12734
- "data-changed": cell.changed ? "true" : void 0,
12735
- "data-records-preview-cell": cell.key,
12732
+ "data-changed": cell2.changed ? "true" : void 0,
12733
+ "data-records-preview-cell": cell2.key,
12736
12734
  title: shown4.text,
12737
12735
  className: (0, import_design_system38.cn)(
12738
12736
  "truncate border-l border-t px-2 py-1",
12739
12737
  shown4.text === "empty" && "italic text-muted-foreground",
12740
- cell.changed && which === "before" && "bg-destructive/10 text-destructive line-through",
12741
- cell.changed && which === "after" && "bg-primary/10 font-medium",
12738
+ cell2.changed && which === "before" && "bg-destructive/10 text-destructive line-through",
12739
+ cell2.changed && which === "after" && "bg-primary/10 font-medium",
12742
12740
  shown4.note && "italic"
12743
12741
  ),
12744
12742
  children: shown4.text
12745
12743
  },
12746
- cell.key
12744
+ cell2.key
12747
12745
  );
12748
12746
  })
12749
12747
  ] }, which))
@@ -14213,15 +14211,15 @@ function planPastedBlock(args) {
14213
14211
  for (const refusal4 of predicted) {
14214
14212
  const key = refusal4.field_key;
14215
14213
  if (key === void 0) continue;
14216
- const cell = built.find((b) => b.key === key && b.refusal === null);
14217
- if (!cell) continue;
14218
- cell.refusal = refusal4.message;
14219
- cell.value = null;
14214
+ const cell2 = built.find((b) => b.key === key && b.refusal === null);
14215
+ if (!cell2) continue;
14216
+ cell2.refusal = refusal4.message;
14217
+ cell2.value = null;
14220
14218
  delete accepted[key];
14221
14219
  refusals.push({
14222
14220
  fromLine,
14223
14221
  column: fieldName(byKey.get(key) ?? { key }),
14224
- raw: cell.raw,
14222
+ raw: cell2.raw,
14225
14223
  why: refusal4.message
14226
14224
  });
14227
14225
  }
@@ -14249,7 +14247,7 @@ function planPastedBlock(args) {
14249
14247
  }
14250
14248
  function documentOf(row) {
14251
14249
  const out = {};
14252
- for (const cell of row.cells) if (cell.refusal === null) out[cell.key] = cell.value;
14250
+ for (const cell2 of row.cells) if (cell2.refusal === null) out[cell2.key] = cell2.value;
14253
14251
  return out;
14254
14252
  }
14255
14253
  var sameWords = (text) => text.trim().replace(/\s+/g, " ").toLowerCase();
@@ -14270,11 +14268,11 @@ function readPasteHeader(args) {
14270
14268
  let named = 0;
14271
14269
  let filled = 0;
14272
14270
  columnKeys.forEach((_, c) => {
14273
- const cell = head[c];
14274
- if (cell === void 0 || cell.trim() === "") return;
14271
+ const cell2 = head[c];
14272
+ if (cell2 === void 0 || cell2.trim() === "") return;
14275
14273
  filled += 1;
14276
- const hits = [...new Set(byName.get(sameWords(cell)) ?? [])];
14277
- const named1 = hits.filter((f) => sameWords(fieldName(f)) === sameWords(cell));
14274
+ const hits = [...new Set(byName.get(sameWords(cell2)) ?? [])];
14275
+ const named1 = hits.filter((f) => sameWords(fieldName(f)) === sameWords(cell2));
14278
14276
  const pick = named1.length > 0 ? named1 : hits;
14279
14277
  if (pick.length !== 1) return;
14280
14278
  const only = pick[0];
@@ -14285,8 +14283,8 @@ function readPasteHeader(args) {
14285
14283
  });
14286
14284
  if (named === 0 || named * 2 < filled) return null;
14287
14285
  const unmatched = columnKeys.flatMap((_, c) => {
14288
- const cell = head[c];
14289
- return mapped[c] === null && cell !== void 0 && cell.trim() !== "" ? [cell.trim()] : [];
14286
+ const cell2 = head[c];
14287
+ return mapped[c] === null && cell2 !== void 0 && cell2.trim() !== "" ? [cell2.trim()] : [];
14290
14288
  });
14291
14289
  return { columnKeys: mapped, unmatched, lines: lines.slice(1) };
14292
14290
  }
@@ -14623,7 +14621,7 @@ function useMergedGridControls(args) {
14623
14621
  }
14624
14622
  } : {},
14625
14623
  clearCells: (cells) => {
14626
- for (const cell of cells) editing.setCell(cell.rowId, cell.columnId, null);
14624
+ for (const cell2 of cells) editing.setCell(cell2.rowId, cell2.columnId, null);
14627
14625
  },
14628
14626
  fillDown: (rowIds, columnIds) => {
14629
14627
  const byId = new Map(rows.map((r) => [r.id, r]));
@@ -16501,22 +16499,22 @@ var import_design_system51 = require("@ai-matrx/design-system");
16501
16499
  var import_format4 = require("@ai-matrx/kit/format");
16502
16500
  var import_jsx_runtime57 = require("react/jsx-runtime");
16503
16501
  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.";
16504
- function cellState(cell) {
16505
- if (!cell || !cell.agent_owned) return "none";
16506
- if (cell.pinned) return "yours";
16507
- if (cell.absent_reason === "conflicting") return "unsure";
16508
- if (cell.actor === "agent") return "agent";
16502
+ function cellState(cell2) {
16503
+ if (!cell2 || !cell2.agent_owned) return "none";
16504
+ if (cell2.pinned) return "yours";
16505
+ if (cell2.absent_reason === "conflicting") return "unsure";
16506
+ if (cell2.actor === "agent") return "agent";
16509
16507
  return "none";
16510
16508
  }
16511
16509
  function ago(at) {
16512
16510
  return at ? (0, import_format4.formatRelativeTime)(at, { style: "intl", fallback: "" }) : "";
16513
16511
  }
16514
- function EnrichBadge({ cell, onPin, className }) {
16515
- const state = cellState(cell);
16516
- if (!cell || state === "none") return null;
16517
- const source = cell.source ?? {};
16512
+ function EnrichBadge({ cell: cell2, onPin, className }) {
16513
+ const state = cellState(cell2);
16514
+ if (!cell2 || state === "none") return null;
16515
+ const source = cell2.source ?? {};
16518
16516
  const read = Array.isArray(source.read) ? source.read : [];
16519
- const alternates = cell.alternates ?? [];
16517
+ const alternates = cell2.alternates ?? [];
16520
16518
  const word = state === "yours" ? "yours" : state === "unsure" ? "unsure" : "agent";
16521
16519
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_design_system51.HoverCard, { openDelay: 120, children: [
16522
16520
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system51.HoverCardTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: (0, import_design_system51.cn)("inline-flex items-center gap-1 align-middle", className), children: [
@@ -16528,18 +16526,18 @@ function EnrichBadge({ cell, onPin, className }) {
16528
16526
  children: word
16529
16527
  }
16530
16528
  ),
16531
- cell.stale ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system51.Badge, { variant: "outline", className: "text-[10px] font-normal leading-none opacity-70", children: "stale" }) : null
16529
+ cell2.stale ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system51.Badge, { variant: "outline", className: "text-[10px] font-normal leading-none opacity-70", children: "stale" }) : null
16532
16530
  ] }) }),
16533
16531
  /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_design_system51.HoverCardContent, { className: "w-80 space-y-2 text-xs", children: [
16534
16532
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("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" }),
16535
- state !== "yours" && cell.on_behalf_of ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("p", { className: "text-muted-foreground", children: [
16533
+ state !== "yours" && cell2.on_behalf_of ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("p", { className: "text-muted-foreground", children: [
16536
16534
  "Acting for ",
16537
- cell.on_behalf_of,
16538
- cell.written_at ? `, ${ago(cell.written_at)}` : "",
16535
+ cell2.on_behalf_of,
16536
+ cell2.written_at ? `, ${ago(cell2.written_at)}` : "",
16539
16537
  "."
16540
- ] }) : cell.written_at ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("p", { className: "text-muted-foreground", children: [
16538
+ ] }) : cell2.written_at ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("p", { className: "text-muted-foreground", children: [
16541
16539
  "Written ",
16542
- ago(cell.written_at),
16540
+ ago(cell2.written_at),
16543
16541
  "."
16544
16542
  ] }) : null,
16545
16543
  source.model ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("p", { className: "text-muted-foreground", children: [
@@ -16556,9 +16554,9 @@ function EnrichBadge({ cell, onPin, className }) {
16556
16554
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "text-muted-foreground", children: state === "unsure" ? "What it considered" : "What it nearly said instead" }),
16557
16555
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("ul", { className: "list-inside list-decimal", children: alternates.slice(0, 4).map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("li", { children: String(a.value ?? "") }, i)) })
16558
16556
  ] }) : null,
16559
- cell.stale && cell.due_at ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("p", { className: "text-muted-foreground", children: [
16557
+ cell2.stale && cell2.due_at ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("p", { className: "text-muted-foreground", children: [
16560
16558
  "Past its date \u2014 it was due to be looked at again ",
16561
- ago(cell.due_at),
16559
+ ago(cell2.due_at),
16562
16560
  ". The value is still here; nothing was overwritten."
16563
16561
  ] }) : null,
16564
16562
  onPin ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
@@ -16567,8 +16565,8 @@ function EnrichBadge({ cell, onPin, className }) {
16567
16565
  size: "sm",
16568
16566
  variant: "outline",
16569
16567
  className: "w-full",
16570
- onClick: () => void onPin(!cell.pinned),
16571
- children: cell.pinned ? "Let the model fill this in again" : "Keep this one \u2014 stop the model changing it"
16568
+ onClick: () => void onPin(!cell2.pinned),
16569
+ children: cell2.pinned ? "Let the model fill this in again" : "Keep this one \u2014 stop the model changing it"
16572
16570
  }
16573
16571
  ) : null
16574
16572
  ] })
@@ -16591,7 +16589,7 @@ function useEnrichCells(tableId, recordIds) {
16591
16589
  }
16592
16590
  setError(null);
16593
16591
  const next = /* @__PURE__ */ new Map();
16594
- for (const cell of answered.data) next.set(`${cell.record_id}:${cell.field_key}`, cell);
16592
+ for (const cell2 of answered.data) next.set(`${cell2.record_id}:${cell2.field_key}`, cell2);
16595
16593
  setCells(next);
16596
16594
  }, [client, tableId, key]);
16597
16595
  (0, import_react91.useEffect)(() => {
@@ -17061,7 +17059,7 @@ function columnForField(field2, editing, mayWriteRow, whyNotRow, look, onAskWhoC
17061
17059
  filter: filterRefusal(field2) !== null ? false : editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? "select" : holdsNumbers(field2) ? "number" : "auto",
17062
17060
  // THE MENU'S VALUE LIST WEARS THE CHOICES' COLOURS (lane CELL-EDITORS, night walk 2026-10-06): the
17063
17061
  // same chip the cell draws, never bare words beside a coloured column.
17064
- ...editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? { filterValueClass: (value) => choiceChipLookOf(field2, value).className } : {},
17062
+ ...editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? { filterValueClass: (value, label) => choiceChipLookOf(field2, value, label).className } : {},
17065
17063
  cell: (row) => (
17066
17064
  /*
17067
17065
  * 🚨 A READING QUESTION IS NOT AN EDITING RIGHT. This used to read
@@ -17534,7 +17532,7 @@ function PlanTable({ plan }) {
17534
17532
  const keys = Array.from(new Set(shown4.flatMap((row) => row.cells.map((c) => c.key))));
17535
17533
  if (shown4.length === 0 || keys.length === 0) return null;
17536
17534
  const columnName = /* @__PURE__ */ new Map();
17537
- for (const row of shown4) for (const cell of row.cells) if (!columnName.has(cell.key)) columnName.set(cell.key, cell.column);
17535
+ for (const row of shown4) for (const cell2 of row.cells) if (!columnName.has(cell2.key)) columnName.set(cell2.key, cell2.column);
17538
17536
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "overflow-auto rounded border", children: [
17539
17537
  /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("table", { className: "w-full text-xs", "data-matrx-paste-plan": true, children: [
17540
17538
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("tr", { children: [
@@ -17547,18 +17545,18 @@ function PlanTable({ plan }) {
17547
17545
  row.recordId === null ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_design_system54.Badge, { variant: "outline", className: "ml-1", children: "new" }) : null
17548
17546
  ] }),
17549
17547
  keys.map((key) => {
17550
- const cell = row.cells.find((c) => c.key === key);
17551
- if (!cell) return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("td", { className: "px-2 py-1" }, key);
17552
- if (cell.refusal !== null) {
17553
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("td", { className: "px-2 py-1 text-muted-foreground line-through", children: cell.raw }, key);
17548
+ const cell2 = row.cells.find((c) => c.key === key);
17549
+ if (!cell2) return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("td", { className: "px-2 py-1" }, key);
17550
+ if (cell2.refusal !== null) {
17551
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("td", { className: "px-2 py-1 text-muted-foreground line-through", children: cell2.raw }, key);
17554
17552
  }
17555
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("td", { className: "px-2 py-1", children: cell.value === null ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "text-muted-foreground", children: "cleared" }) : (
17553
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("td", { className: "px-2 py-1", children: cell2.value === null ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "text-muted-foreground", children: "cleared" }) : (
17556
17554
  // THE WORDS, NOT THE ID. A choice column stores the option
17557
17555
  // record's id and the person pasted a word; showing the id
17558
17556
  // here made this panel print
17559
17557
  // `530808bf-9f2d-4062-bc09-b8cc3b162f2a` where they had
17560
17558
  // written Drain Cleaning (FIX-10C F8).
17561
- cell.display ?? String(cell.value)
17559
+ cell2.display ?? String(cell2.value)
17562
17560
  ) }, key);
17563
17561
  })
17564
17562
  ] }, row.fromLine)) })
@@ -17859,6 +17857,7 @@ function combineRows(rows, header) {
17859
17857
 
17860
17858
  // src/importRefusals.ts
17861
17859
  var import_download = require("@ai-matrx/kit/download");
17860
+ var import_delimited = require("@ai-matrx/kit/delimited");
17862
17861
  function reasonShape(reason) {
17863
17862
  return reason.replace(/"[^"]*"/g, '"\u2026"').replace(/“[^”]*”/g, "\u201C\u2026\u201D").replace(/\b\d+(?:[.,]\d+)*\b/g, "N").replace(/\s+/g, " ").trim();
17864
17863
  }
@@ -17874,21 +17873,24 @@ function groupReasons(reasons) {
17874
17873
  }
17875
17874
  return [...groups.values()].sort((a, b) => b.count - a.count);
17876
17875
  }
17877
- function csvCell(value) {
17878
- const text = value === null || value === void 0 ? "" : String(value);
17879
- return /[",\n\r]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
17876
+ function cell(value) {
17877
+ if (value === null || value === void 0) return null;
17878
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? value : String(value);
17880
17879
  }
17881
17880
  function refusedRowsCsv(rows, lineOf = (n) => n + 1) {
17882
17881
  const headers = [];
17883
17882
  for (const r of rows) for (const h of Object.keys(r.source ?? {})) if (!headers.includes(h)) headers.push(h);
17884
- const lines = [[...headers, "Line in your file", "Why it was not added"].map(csvCell).join(",")];
17885
- for (const r of rows) {
17886
- const cells = headers.map((h) => csvCell((r.source ?? {})[h]));
17887
- cells.push(csvCell(typeof r.row === "number" ? lineOf(r.row) : ""));
17888
- cells.push(csvCell(r.reason ?? ""));
17889
- lines.push(cells.join(","));
17890
- }
17891
- return lines.join("\n") + "\n";
17883
+ return (0, import_delimited.toDelimited)(
17884
+ [
17885
+ [...headers, "Line in your file", "Why it was not added"],
17886
+ ...rows.map((r) => [
17887
+ ...headers.map((h) => cell((r.source ?? {})[h])),
17888
+ typeof r.row === "number" ? lineOf(r.row) : "",
17889
+ r.reason ?? ""
17890
+ ])
17891
+ ],
17892
+ { trailingNewline: true }
17893
+ );
17892
17894
  }
17893
17895
  function offerDownload(name, text, type = "text/csv") {
17894
17896
  if (typeof document === "undefined" || typeof URL === "undefined" || typeof URL.createObjectURL !== "function") return false;
@@ -19392,18 +19394,18 @@ function splitPipes(line) {
19392
19394
  if (text.startsWith("|")) text = text.slice(1);
19393
19395
  if (text.endsWith("|") && !text.endsWith("\\|")) text = text.slice(0, -1);
19394
19396
  const cells = [];
19395
- let cell = "";
19397
+ let cell2 = "";
19396
19398
  for (let i = 0; i < text.length; i += 1) {
19397
19399
  const ch = text[i];
19398
19400
  if (ch === "\\" && text[i + 1] === "|") {
19399
- cell += "\\|";
19401
+ cell2 += "\\|";
19400
19402
  i += 1;
19401
19403
  } else if (ch === "|") {
19402
- cells.push(cell);
19403
- cell = "";
19404
- } else cell += ch;
19404
+ cells.push(cell2);
19405
+ cell2 = "";
19406
+ } else cell2 += ch;
19405
19407
  }
19406
- cells.push(cell);
19408
+ cells.push(cell2);
19407
19409
  return cells.map(cellWords);
19408
19410
  }
19409
19411
  var LIST_ITEM = /^(\s*)(?:[-*+•]|\d{1,3}[.)])\s+(?:\[[ xX]\]\s+)?(.*)$/;
@@ -19520,33 +19522,33 @@ function shapeFromList(items, name, at) {
19520
19522
  function parseDelimited(text, delimiter) {
19521
19523
  const rows = [];
19522
19524
  let row = [];
19523
- let cell = "";
19525
+ let cell2 = "";
19524
19526
  let quoted2 = false;
19525
19527
  for (let i = 0; i < text.length; i += 1) {
19526
19528
  const ch = text[i];
19527
19529
  if (quoted2) {
19528
19530
  if (ch === '"') {
19529
19531
  if (text[i + 1] === '"') {
19530
- cell += '"';
19532
+ cell2 += '"';
19531
19533
  i += 1;
19532
19534
  } else quoted2 = false;
19533
- } else cell += ch;
19535
+ } else cell2 += ch;
19534
19536
  continue;
19535
19537
  }
19536
- if (ch === '"' && cell.trim() === "") quoted2 = true;
19538
+ if (ch === '"' && cell2.trim() === "") quoted2 = true;
19537
19539
  else if (ch === delimiter) {
19538
- row.push(cell);
19539
- cell = "";
19540
+ row.push(cell2);
19541
+ cell2 = "";
19540
19542
  } else if (ch === "\n" || ch === "\r") {
19541
19543
  if (ch === "\r" && text[i + 1] === "\n") i += 1;
19542
- row.push(cell);
19544
+ row.push(cell2);
19543
19545
  rows.push(row);
19544
19546
  row = [];
19545
- cell = "";
19546
- } else cell += ch;
19547
+ cell2 = "";
19548
+ } else cell2 += ch;
19547
19549
  }
19548
- if (cell.length > 0 || row.length > 0) {
19549
- row.push(cell);
19550
+ if (cell2.length > 0 || row.length > 0) {
19551
+ row.push(cell2);
19550
19552
  rows.push(row);
19551
19553
  }
19552
19554
  return rows.filter((r) => r.some((c) => c.trim() !== ""));
@@ -19849,10 +19851,10 @@ function shapeTextOfNode(node) {
19849
19851
  flushLine();
19850
19852
  const width = Math.max(...rows.map((r) => r.length));
19851
19853
  const pad4 = (r) => [...r, ...Array.from({ length: width - r.length }, () => "")];
19852
- const cell = (c) => c.replace(/\|/g, "\\|").replace(/\s+/g, " ").trim();
19853
- out.push(`| ${pad4(rows[0]).map(cell).join(" | ")} |`);
19854
+ const cell2 = (c) => c.replace(/\|/g, "\\|").replace(/\s+/g, " ").trim();
19855
+ out.push(`| ${pad4(rows[0]).map(cell2).join(" | ")} |`);
19854
19856
  out.push(`|${Array.from({ length: width }, () => "---").join("|")}|`);
19855
- for (const r of rows.slice(1)) out.push(`| ${pad4(r).map(cell).join(" | ")} |`);
19857
+ for (const r of rows.slice(1)) out.push(`| ${pad4(r).map(cell2).join(" | ")} |`);
19856
19858
  rows = [];
19857
19859
  };
19858
19860
  const textOf = (n) => (n.textContent ?? "").replace(/\s+/g, " ").trim();
@@ -20267,12 +20269,12 @@ var import_data_table10 = require("@ai-matrx/design-system/data-table");
20267
20269
  var import_jsx_runtime66 = require("react/jsx-runtime");
20268
20270
  function changesFor(step2, direction, versions = /* @__PURE__ */ new Map()) {
20269
20271
  const byRow = /* @__PURE__ */ new Map();
20270
- for (const cell of step2.cells) {
20271
- if (step2.created?.includes(cell.rowId)) continue;
20272
- const patch = byRow.get(cell.rowId) ?? {};
20273
- const value = direction === "undo" ? cell.before : cell.after;
20274
- patch[cell.key] = value === void 0 ? null : value;
20275
- byRow.set(cell.rowId, patch);
20272
+ for (const cell2 of step2.cells) {
20273
+ if (step2.created?.includes(cell2.rowId)) continue;
20274
+ const patch = byRow.get(cell2.rowId) ?? {};
20275
+ const value = direction === "undo" ? cell2.before : cell2.after;
20276
+ patch[cell2.key] = value === void 0 ? null : value;
20277
+ byRow.set(cell2.rowId, patch);
20276
20278
  }
20277
20279
  const changes = [...byRow].map(([record_id, patch]) => ({
20278
20280
  op: "update",
@@ -20300,7 +20302,7 @@ function useGridUndo(args) {
20300
20302
  const dismiss = (0, import_react104.useCallback)(() => setNotice(null), []);
20301
20303
  const push = (0, import_react104.useCallback)((step2) => {
20302
20304
  if (step2.cells.length === 0 && !step2.created?.length && !step2.archived?.length && !step2.retiredField) return;
20303
- for (const cell of step2.cells) if (typeof cell.version === "number") known.current.set(cell.rowId, cell.version);
20305
+ for (const cell2 of step2.cells) if (typeof cell2.version === "number") known.current.set(cell2.rowId, cell2.version);
20304
20306
  counter.current += 1;
20305
20307
  const id = String(counter.current);
20306
20308
  setHeld((was) => {
@@ -20629,13 +20631,12 @@ function useGridAssist(args) {
20629
20631
  const copyRecordReference = (0, import_react106.useCallback)(
20630
20632
  (rowId) => {
20631
20633
  void (async () => {
20632
- try {
20633
- const text = JSON.stringify({ __kind: (0, import_core14.tableKindSlug)(tableId), _record_id: rowId });
20634
- if (!await (0, import_clipboard2.copyText)(text)) throw new Error("This browser did not let the page write to the clipboard.");
20635
- say2(true, "The record reference is copied.");
20636
- } catch (thrown) {
20637
- say2(false, thrown instanceof Error ? thrown.message : String(thrown));
20634
+ const text = JSON.stringify({ __kind: (0, import_core14.tableKindSlug)(tableId), _record_id: rowId });
20635
+ if (!await (0, import_clipboard2.copyText)(text)) {
20636
+ say2(false, "This browser did not let the page write to the clipboard.");
20637
+ return;
20638
20638
  }
20639
+ say2(true, "The record reference is copied.");
20639
20640
  })();
20640
20641
  },
20641
20642
  [tableId, say2]
@@ -20802,9 +20803,9 @@ function planBulk(args) {
20802
20803
  before: (row.document ?? {})[field2.key] ?? null,
20803
20804
  after: value
20804
20805
  }));
20805
- const changes = cells.map((cell) => ({
20806
+ const changes = cells.map((cell2) => ({
20806
20807
  op: "update",
20807
- record_id: cell.rowId,
20808
+ record_id: cell2.rowId,
20808
20809
  patch: { [field2.key]: value }
20809
20810
  }));
20810
20811
  const many = countOf(cells.length, args.noun, args.nounPlural);
@@ -22240,8 +22241,8 @@ function GridBody({
22240
22241
  pastedNames.set(
22241
22242
  field2.key,
22242
22243
  lines.flatMap((line) => {
22243
- const cell = line[at];
22244
- return typeof cell === "string" ? (0, import_records36.relationNamesIn)(field2, cell) : [];
22244
+ const cell2 = line[at];
22245
+ return typeof cell2 === "string" ? (0, import_records36.relationNamesIn)(field2, cell2) : [];
22245
22246
  })
22246
22247
  );
22247
22248
  }
@@ -31185,8 +31186,8 @@ function CalendarView({
31185
31186
  }
31186
31187
  });
31187
31188
  const dayDrop = (fallback) => dropOn((e) => {
31188
- const cell = e.target.closest?.("[data-calendar-day]");
31189
- return { day: cell?.getAttribute("data-calendar-day") ?? fallback, minute: null };
31189
+ const cell2 = e.target.closest?.("[data-calendar-day]");
31190
+ return { day: cell2?.getAttribute("data-calendar-day") ?? fallback, minute: null };
31190
31191
  });
31191
31192
  const minuteAt = (e) => {
31192
31193
  const slot = e.target?.closest?.("[data-calendar-slot]");
@@ -46644,7 +46645,33 @@ function LinkedLists({ tableId, recordId }) {
46644
46645
  const links = (fields.data ?? []).filter((field2) => editorKindFor(field2) === "relation");
46645
46646
  const labels = useRecordLabels(links);
46646
46647
  const document2 = record.data?.document;
46648
+ const may = useRecordRights(recordId);
46647
46649
  if (links.length === 0 || !document2) return null;
46650
+ if (may.write) {
46651
+ return /* @__PURE__ */ (0, import_jsx_runtime149.jsxs)("div", { className: "flex flex-col gap-3", "data-record-linked-lists": "", children: [
46652
+ /* @__PURE__ */ (0, import_jsx_runtime149.jsx)(import_design_system134.Separator, {}),
46653
+ /* @__PURE__ */ (0, import_jsx_runtime149.jsx)(
46654
+ RecordFieldsInPlace,
46655
+ {
46656
+ tableId,
46657
+ recordId,
46658
+ fields: links,
46659
+ document: document2,
46660
+ hidden: record.data?.hidden,
46661
+ canWrite: true,
46662
+ reload: () => record.reload(),
46663
+ className: "flex min-w-0 flex-col gap-1",
46664
+ renderLabel: (field2) => {
46665
+ const count = referencesOf(field2, document2[field2.key], "relation", labels).length;
46666
+ return /* @__PURE__ */ (0, import_jsx_runtime149.jsxs)("span", { className: "flex items-center gap-2 pt-2 text-foreground", "data-record-linked-list": field2.key, children: [
46667
+ /* @__PURE__ */ (0, import_jsx_runtime149.jsx)("span", { className: "truncate text-xs font-medium", children: fieldName(field2) }),
46668
+ count > 0 ? /* @__PURE__ */ (0, import_jsx_runtime149.jsx)("span", { className: "text-[11px] text-muted-foreground", children: count }) : null
46669
+ ] });
46670
+ }
46671
+ }
46672
+ )
46673
+ ] });
46674
+ }
46648
46675
  return /* @__PURE__ */ (0, import_jsx_runtime149.jsxs)("div", { className: "flex flex-col gap-3", "data-record-linked-lists": "", children: [
46649
46676
  /* @__PURE__ */ (0, import_jsx_runtime149.jsx)(import_design_system134.Separator, {}),
46650
46677
  links.map((field2) => {