@ai-matrx/records-ui 0.93.11 → 0.93.13

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,7 +1,19 @@
1
1
  # Changelog — @ai-matrx/records-ui
2
2
 
3
- ## 0.93.11
3
+ ## 0.93.13
4
+
5
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
6
+ `git diff npm/records-ui/v0.93.12..npm/records-ui/v0.93.13 -- apps/shared/records-ui`).
7
+ No source changes intended and no consumer action required.
8
+
9
+ ## 0.93.12
4
10
  ### Unreleased
11
+ ### page-pass shared fix (2026-09-27): the agent door shows each field's value and can set values
12
+
13
+ - `CustomFieldsAgentState.fields[].value` (this record's current value) and `mayFill`; the door gains `checkValues` / `setValues` (one `custom.entity_value_write`, fields named by key or label). New exports `CustomFieldValuesRequest`, `CustomFieldSetResult`. An agent on a template page could neither see nor set the custom fields shown on it.
14
+
15
+ ## 0.93.11
16
+
5
17
  ### page-pass shared fix (2026-09-27): a custom field can be archived where it was added
6
18
 
7
19
  - **`CustomFieldsSection` → Edit → "Remove field"** (for whoever may add one): an inline confirm names the consequence (removed for everyone in the organization; values stay in every record and come back with it), then `custom.entity_field_retire` archives it (soft delete). Adding had no undo anywhere in the UI. Proof: `custom-fields-empty-select-and-agent-door.test.tsx`, red on the previous component.
package/dist/index.cjs CHANGED
@@ -13880,9 +13880,9 @@ function CustomFieldsSection({
13880
13880
  const [removing, setRemoving] = (0, import_react71.useState)(null);
13881
13881
  const fields = (0, import_react71.useMemo)(() => read.data?.fields ?? [], [read.data]);
13882
13882
  const mayAdd = rights.data?.may_declare === true;
13883
- const live = (0, import_react71.useRef)({ fields, rights: rights.data, loading: rights.loading, reload: read.reload });
13883
+ const live = (0, import_react71.useRef)({ fields, rights: rights.data, loading: rights.loading, reload: read.reload, values: read.data?.custom ?? {} });
13884
13884
  (0, import_react71.useEffect)(() => {
13885
- live.current = { fields, rights: rights.data, loading: rights.loading, reload: read.reload };
13885
+ live.current = { fields, rights: rights.data, loading: rights.loading, reload: read.reload, values: read.data?.custom ?? {} };
13886
13886
  });
13887
13887
  (0, import_react71.useEffect)(() => {
13888
13888
  if (!agentDoor) return;
@@ -13894,7 +13894,8 @@ function CustomFieldsSection({
13894
13894
  entityLabel: now.rights?.label ?? null,
13895
13895
  mayAdd: now.rights ? now.rights.may_declare === true : now.loading ? null : false,
13896
13896
  refusal: now.rights && !now.rights.may_declare ? now.rights.reason ?? null : null,
13897
- fields: now.fields.map((f) => ({ key: f.key, label: f.label, type: f.type })),
13897
+ fields: now.fields.map((f) => ({ key: f.key, label: f.label, type: f.type, value: now.values[f.key] })),
13898
+ mayFill: now.rights ? now.rights.may_fill_in !== false : now.loading ? null : false,
13898
13899
  types: ADDABLE_TYPES
13899
13900
  };
13900
13901
  };
@@ -13926,7 +13927,39 @@ function CustomFieldsSection({
13926
13927
  }
13927
13928
  return { ok: true, field_id: declared2.data, label, type };
13928
13929
  };
13929
- return agentDoor({ entityToken, recordId, state, check, addField });
13930
+ const resolveKeys = (values2) => {
13931
+ const now = live.current;
13932
+ const problems = [];
13933
+ const patch = {};
13934
+ const written2 = [];
13935
+ const entries = values2 && typeof values2 === "object" && !Array.isArray(values2) ? Object.entries(values2) : [];
13936
+ if (entries.length === 0) problems.push("Name at least one field and its value.");
13937
+ for (const [name, value] of entries) {
13938
+ const want = name.trim().toLowerCase();
13939
+ const field2 = now.fields.find((f) => f.key.toLowerCase() === want || f.label.trim().toLowerCase() === want);
13940
+ if (!field2) {
13941
+ problems.push(`There is no custom field "${name}". Fields: ${now.fields.map((f) => f.label).join(", ") || "none yet"}.`);
13942
+ continue;
13943
+ }
13944
+ patch[field2.key] = value;
13945
+ written2.push({ key: field2.key, label: field2.label, value });
13946
+ }
13947
+ if (now.rights && now.rights.may_fill_in === false) problems.push("This person may not fill in custom fields on this record.");
13948
+ return { problems, patch, written: written2 };
13949
+ };
13950
+ const checkValues = (values2) => resolveKeys(values2).problems;
13951
+ const setValues = async (values2) => {
13952
+ const { problems, patch, written: written2 } = resolveKeys(values2);
13953
+ if (problems.length > 0) return { ok: false, message: problems.join(" ") };
13954
+ const result = await client.entityValueWrite({ token: entityToken, record_id: recordId, patch });
13955
+ if (!result.ok) {
13956
+ const hint = hintForAPerson(result.error.hint);
13957
+ return { ok: false, message: hint ? `${result.error.message} ${hint}` : result.error.message };
13958
+ }
13959
+ live.current.reload();
13960
+ return { ok: true, written: written2 };
13961
+ };
13962
+ return agentDoor({ entityToken, recordId, state, check, addField, checkValues, setValues });
13930
13963
  }, [agentDoor, client, entityToken, recordId]);
13931
13964
  if (!read.loading && !read.error && fields.length === 0 && !mayAdd) return null;
13932
13965
  if (read.error) return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(RefusalLine, { error: read.error, className });
@@ -16707,7 +16740,7 @@ function PipelineBoard({
16707
16740
  };
16708
16741
  if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(RefusalNotice, { error: fields.error });
16709
16742
  if (error) return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(RefusalNotice, { error });
16710
- if (loading || fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system49.Skeleton, { className: "h-40 w-full" });
16743
+ if (loading || fields.loading && !fields.data) return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system49.Skeleton, { className: "h-40 w-full" });
16711
16744
  if (!definition?.is_pipeline) {
16712
16745
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "rounded border border-dashed p-4 text-xs text-muted-foreground", children: definition?.why ?? "This table has no stage column yet, so there is no board to draw." });
16713
16746
  }
@@ -17404,7 +17437,7 @@ function Board({
17404
17437
  );
17405
17438
  if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(RefusalNotice, { error: fields.error });
17406
17439
  if (records.error) return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(RefusalNotice, { error: records.error });
17407
- if (fields.loading || records.loading) return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_design_system50.Skeleton, { className: "h-40 w-full" });
17440
+ if (fields.loading && !fields.data || records.loading && records.rows.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_design_system50.Skeleton, { className: "h-40 w-full" });
17408
17441
  const all = fields.data ?? [];
17409
17442
  const byKey = (key) => all.find((f) => f.key === key);
17410
17443
  const noRows = records.rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
@@ -20276,7 +20309,7 @@ function CommentThread({ tableId, recordId, fieldKey, className }) {
20276
20309
  return people.filter((p) => !picked.some((already) => already.userId === p.userId)).filter((p) => q === "" || (p.name ?? p.email ?? "").toLowerCase().includes(q)).slice(0, 6);
20277
20310
  }, [mentionQuery, people, picked]);
20278
20311
  if (error) return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(RefusalNotice, { error, className });
20279
- if (!thread || table.loading || fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(import_design_system58.Skeleton, { className: (0, import_design_system58.cn)("h-32 w-full", className) });
20312
+ if (!thread || table.loading && !table.data || fields.loading && !fields.data) return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(import_design_system58.Skeleton, { className: (0, import_design_system58.cn)("h-32 w-full", className) });
20280
20313
  const shown3 = fieldKey ? thread.comments.filter((c) => c.field_key === fieldKey) : thread.comments;
20281
20314
  const roots = shown3.filter((c) => !c.parent_comment_id);
20282
20315
  const repliesOf = (id) => shown3.filter((c) => c.parent_comment_id === id);
@@ -20492,7 +20525,7 @@ function FieldHistoryPanel({
20492
20525
  }, [load]);
20493
20526
  const label = (fields.data ?? []).find((f) => f.key === fieldKey)?.label || humanize(fieldKey);
20494
20527
  if (error) return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(RefusalNotice, { error, className });
20495
- if (!rows || fields.loading || table.loading) return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_design_system59.Skeleton, { className: (0, import_design_system59.cn)("h-40 w-full", className) });
20528
+ if (!rows || fields.loading && !fields.data || table.loading && !table.data) return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_design_system59.Skeleton, { className: (0, import_design_system59.cn)("h-40 w-full", className) });
20496
20529
  async function start(row) {
20497
20530
  setSaid(null);
20498
20531
  setPending({ phase: "asking", recordId: row.record_id, version: row.version });
@@ -22823,7 +22856,7 @@ function ConnectedFormRunner(props) {
22823
22856
  [client, form.subject, form.questions]
22824
22857
  );
22825
22858
  if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(RefusalNotice, { error: fields.error, className });
22826
- if (fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(import_design_system67.Skeleton, { className: (0, import_design_system67.cn)("h-40 w-full", className) });
22859
+ if (fields.loading && !fields.data) return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(import_design_system67.Skeleton, { className: (0, import_design_system67.cn)("h-40 w-full", className) });
22827
22860
  return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
22828
22861
  FormStage,
22829
22862
  {
@@ -24297,7 +24330,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
24297
24330
  }
24298
24331
  );
24299
24332
  }
24300
- if (templates === null || fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_design_system71.Skeleton, { className: (0, import_design_system71.cn)("h-64 w-full", className) });
24333
+ if (templates === null || fields.loading && !fields.data) return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_design_system71.Skeleton, { className: (0, import_design_system71.cn)("h-64 w-full", className) });
24301
24334
  if (!rights.admin) {
24302
24335
  return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: (0, import_design_system71.cn)("text-xs text-muted-foreground", className), children: rights.why("structure") });
24303
24336
  }
@@ -25959,7 +25992,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
25959
25992
  await load();
25960
25993
  onSaved?.({ form_id: formId });
25961
25994
  }
25962
- if (!loaded || fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_design_system77.Skeleton, { className: (0, import_design_system77.cn)("h-64 w-full", className) });
25995
+ if (!loaded || fields.loading && !fields.data) return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_design_system77.Skeleton, { className: (0, import_design_system77.cn)("h-64 w-full", className) });
25963
25996
  if (!rights.structure) {
25964
25997
  return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("p", { className: (0, import_design_system77.cn)("text-xs text-muted-foreground", className), children: rights.why("structure") ?? "Making a booking page needs the admin level on this table, because it lets people with no account take time in your calendar." });
25965
25998
  }
@@ -27248,7 +27281,7 @@ function EmbedFrame({
27248
27281
  setTokenId(null);
27249
27282
  }, [client, tokenId]);
27250
27283
  if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(RefusalNotice, { error: table.error, className });
27251
- if (table.loading) return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_design_system83.Skeleton, { className: (0, import_design_system83.cn)("h-48 w-full", className) });
27284
+ if (table.loading && !table.data) return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_design_system83.Skeleton, { className: (0, import_design_system83.cn)("h-48 w-full", className) });
27252
27285
  if (!rights.admin) {
27253
27286
  return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("p", { className: (0, import_design_system83.cn)("rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", className), children: [
27254
27287
  rights.why("structure"),
@@ -28829,7 +28862,7 @@ function TablePage({
28829
28862
  headerNode,
28830
28863
  /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(RefusalNotice, { error: table.error })
28831
28864
  ] });
28832
- if (table.loading) return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
28865
+ if (table.loading && !table.data) return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
28833
28866
  headerNode,
28834
28867
  /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(import_design_system88.Skeleton, { className: "h-40 w-full" })
28835
28868
  ] });