@ai-matrx/records-ui 0.48.0 → 0.49.0

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,29 @@
1
1
  # Changelog — @ai-matrx/records-ui
2
2
 
3
+ ## 0.49.0
4
+
5
+ **"Add field" said it worked and the column was not there.**
6
+
7
+ A trip planner loading the fifty-one US National Parks — name, state, date
8
+ established, area — so she could sort a road trip by region. Crew C, driving the
9
+ real screens on 2026-09-21: *"Every 'Add field' attempt appeared to succeed on
10
+ screen (no error text), but a direct fields() read afterward showed only the
11
+ table's default Title column — none of the 5 fields actually persisted."* The grid
12
+ then drew "This table has no columns yet" over fifty-one real, complete rows.
13
+
14
+ The panel closed on the DOOR'S answer. **Success is a read-back now**: after the
15
+ declare it asks the table for its columns and looks for the one it just made, BY
16
+ ID. If it is not there the panel stays open and says so — what is true, that no
17
+ record value was lost, and what to do — instead of reporting a success it has not
18
+ confirmed, which is the one thing a person cannot recover from, because they move
19
+ on.
20
+
21
+ The store's own cause was fixed by lane LIMITS-FIX the same day. This is the half
22
+ that means the SCREEN can never claim it again, whatever the store does next.
23
+ `src/add-field-readback.test.tsx`, three clauses.
24
+
25
+ **Consumer action:** none.
26
+
3
27
  ## 0.48.0
4
28
 
5
29
  **The record panel says when it could not read the footnote.**
package/dist/index.cjs CHANGED
@@ -3800,11 +3800,13 @@ function keyFor(label) {
3800
3800
  if (token === "") return "";
3801
3801
  return /^[a-z]/.test(token) ? token : `f_${token}`;
3802
3802
  }
3803
+ var COLUMN_DID_NOT_LAND = "The store accepted this column and the table does not have it yet. Nothing was lost \u2014 your record values are untouched \u2014 but the column is not there, so this panel is staying open. Press Save again; if it keeps happening, tell us, because the store and the table disagree and that is ours to fix.";
3803
3804
  function FieldEditor({ tableId, field, onSaved, onCancel, onRemoved, className }) {
3804
3805
  const table = (0, import_react27.useTable)(tableId);
3805
3806
  const fields = (0, import_react27.useFields)(tableId);
3806
3807
  const rights = useTableRights(table.data);
3807
3808
  const mutation = (0, import_react27.useFieldMutation)();
3809
+ const client = (0, import_react27.useRecordsClient)();
3808
3810
  const [label, setLabel] = (0, import_react26.useState)(field?.label ?? "");
3809
3811
  const [type, setType] = (0, import_react26.useState)(() => startingType(field));
3810
3812
  const [required, setRequired] = (0, import_react26.useState)(field?.required ?? false);
@@ -3826,6 +3828,7 @@ function FieldEditor({ tableId, field, onSaved, onCancel, onRemoved, className }
3826
3828
  const [formulaOp, setFormulaOp] = (0, import_react26.useState)("concat");
3827
3829
  const [formulaFields, setFormulaFields] = (0, import_react26.useState)([]);
3828
3830
  const [askingToRemove, setAskingToRemove] = (0, import_react26.useState)(false);
3831
+ const [notLanded, setNotLanded] = (0, import_react26.useState)(false);
3829
3832
  const others = (0, import_react26.useMemo)(
3830
3833
  () => (fields.data ?? []).filter((f) => f.id !== field?.id),
3831
3834
  [fields.data, field?.id]
@@ -3891,7 +3894,14 @@ function FieldEditor({ tableId, field, onSaved, onCancel, onRemoved, className }
3891
3894
  ...type === "formula" ? { expr: formulaExpression(formulaOp, formulaFields) } : {}
3892
3895
  };
3893
3896
  const written = await mutation.declare({ table_id: tableId, spec });
3894
- if (written !== null) onSaved?.();
3897
+ if (written === null) return;
3898
+ const landed = await client.fields({ table_id: tableId });
3899
+ if (landed.ok && !landed.data.some((f) => f.id === written)) {
3900
+ setNotLanded(true);
3901
+ return;
3902
+ }
3903
+ setNotLanded(false);
3904
+ onSaved?.();
3895
3905
  };
3896
3906
  const remove = async () => {
3897
3907
  if (!field) return;
@@ -4075,6 +4085,7 @@ function FieldEditor({ tableId, field, onSaved, onCancel, onRemoved, className }
4075
4085
  ] }),
4076
4086
  mutation.error ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(RefusalNotice, { error: mutation.error }) : null,
4077
4087
  missing ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-[11px] text-destructive", children: missing }) : null,
4088
+ notLanded ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-[11px] text-destructive", children: COLUMN_DID_NOT_LAND }) : null,
4078
4089
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
4079
4090
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4080
4091
  import_design_system12.Button,