@ai-matrx/records-ui 0.113.16 → 0.113.18

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/pickers.cjs CHANGED
@@ -5686,13 +5686,16 @@ function ButtonSettingsEditor({
5686
5686
  }) {
5687
5687
  const client = (0, import_react40.useOptionalRecordsClient)();
5688
5688
  const [actions, setActions] = (0, import_react39.useState)(null);
5689
+ const [actionsRefused, setActionsRefused] = (0, import_react39.useState)(null);
5689
5690
  const [automations, setAutomations] = (0, import_react39.useState)(null);
5690
5691
  (0, import_react39.useEffect)(() => {
5691
5692
  if (!client || !tableId) return;
5692
5693
  let live = true;
5693
5694
  if (value.do === "run_action" && actions === null) {
5694
5695
  void client.rowActions({ table_id: tableId }).then((got) => {
5695
- if (live) setActions(got.ok ? (got.data?.actions ?? []).filter((a) => a.id).map((a) => ({ id: a.id, name: a.name })) : []);
5696
+ if (!live) return;
5697
+ if (!got.ok) return setActionsRefused(got.error);
5698
+ setActions((got.data?.actions ?? []).filter((a) => a.id));
5696
5699
  });
5697
5700
  }
5698
5701
  if (value.do === "run_automation" && automations === null) {
@@ -5766,16 +5769,32 @@ function ButtonSettingsEditor({
5766
5769
  ] }),
5767
5770
  value.url && (0, import_records22.buttonUrlPlaceholders)(value.url).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "truncate text-[11px] text-muted-foreground", "data-records-button-url-words": "", children: buttonUrlInWords(value.url, fields) }) : null
5768
5771
  ] }) : null,
5769
- value.do === "run_action" ? actions && actions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-xs text-muted-foreground", children: "No row actions yet. Add one in Table settings." }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5770
- PickOne,
5771
- {
5772
- label: "Row action",
5773
- value: value.action_id ?? "",
5774
- placeholder: actions ? "Choose a row action" : "Reading row actions\u2026",
5775
- onChange: (id) => set({ action_id: id }),
5776
- options: (actions ?? []).map((a) => ({ value: a.id, label: a.name }))
5777
- }
5778
- ) : null,
5772
+ value.do === "run_action" ? !tableId ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-xs text-muted-foreground", children: "Row actions belong to a table" }) : actionsRefused ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(RefusalLine, { error: actionsRefused }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-2", "data-records-button-action": "", children: [
5773
+ actions === null || actions.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5774
+ PickOne,
5775
+ {
5776
+ label: "Row action",
5777
+ value: value.action_id ?? "",
5778
+ placeholder: actions ? "Choose a row action" : "Reading row actions\u2026",
5779
+ attrs: { "data-records-button-action-pick": "" },
5780
+ onChange: (id) => set({ action_id: id }),
5781
+ options: (actions ?? []).map((a) => ({ value: a.id, label: a.name }))
5782
+ }
5783
+ ) : null,
5784
+ actions !== null ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5785
+ NewRowAction,
5786
+ {
5787
+ tableId,
5788
+ label: value.label,
5789
+ actions,
5790
+ columns,
5791
+ onMade: (made, all) => {
5792
+ setActions(all);
5793
+ set({ action_id: made });
5794
+ }
5795
+ }
5796
+ ) : null
5797
+ ] }) : null,
5779
5798
  value.do === "run_automation" ? automations && automations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-xs text-muted-foreground", children: "No automations yet. Add one in Table settings." }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5780
5799
  PickOne,
5781
5800
  {
@@ -5788,6 +5807,70 @@ function ButtonSettingsEditor({
5788
5807
  ) : null
5789
5808
  ] });
5790
5809
  }
5810
+ function settableColumns(columns) {
5811
+ return columns.filter((f) => {
5812
+ const kind = editorKindFor(f);
5813
+ return f.type !== "formula" && kind !== "formula" && kind !== "lookup" && kind !== "rollup" && !(f.type === "text" && f.format === "button");
5814
+ });
5815
+ }
5816
+ function NewRowAction({
5817
+ tableId,
5818
+ label,
5819
+ actions,
5820
+ columns,
5821
+ onMade
5822
+ }) {
5823
+ const client = (0, import_react40.useOptionalRecordsClient)();
5824
+ const settable = settableColumns(columns);
5825
+ const [fieldId, setFieldId] = (0, import_react39.useState)("");
5826
+ const [setTo, setSetTo] = (0, import_react39.useState)("");
5827
+ const [busy, setBusy] = (0, import_react39.useState)(false);
5828
+ const [refused, setRefused] = (0, import_react39.useState)(null);
5829
+ if (settable.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-xs text-muted-foreground", children: "No column to set" });
5830
+ const make = async () => {
5831
+ if (!client || fieldId === "") return;
5832
+ setBusy(true);
5833
+ setRefused(null);
5834
+ const name = label.trim() || "Set fields";
5835
+ const kept = actions.map((a) => ({ ...a.id ? { id: a.id } : {}, name: a.name, kind: a.kind ?? "update", ...a.color !== void 0 ? { color: a.color } : {}, ...a.icon ? { icon: a.icon } : {}, ...a.confirm !== void 0 ? { confirm: a.confirm } : {}, ...a.steps ? { steps: a.steps } : {}, ...a.prompt ? { prompt: a.prompt } : {} }));
5836
+ const declared = await client.actionDeclare({
5837
+ table_id: tableId,
5838
+ actions: [...kept, { name, kind: "update", confirm: false, steps: [setTo === "" ? { field: fieldId, set: "clear" } : { field: fieldId, set: "value", value: setTo }] }]
5839
+ });
5840
+ if (!declared.ok) {
5841
+ setBusy(false);
5842
+ return setRefused(declared.error);
5843
+ }
5844
+ const reread = await client.rowActions({ table_id: tableId });
5845
+ setBusy(false);
5846
+ if (!reread.ok) return setRefused(reread.error);
5847
+ const all = (reread.data?.actions ?? []).filter((a) => a.id);
5848
+ const before = new Set(actions.map((a) => a.id));
5849
+ const made = all.find((a) => !before.has(a.id) && a.name === name) ?? all.find((a) => !before.has(a.id));
5850
+ if (!made?.id) return setRefused({ code: "internal", message: "The row action was saved but could not be read back.", hint: "Reopen this column's settings and pick it from the list." });
5851
+ onMade(made.id, all);
5852
+ };
5853
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1", "data-records-button-new-action": "", children: [
5854
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_design_system26.Label, { className: "text-xs", children: "New row action" }),
5855
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
5856
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5857
+ PickOne,
5858
+ {
5859
+ label: "Column to set",
5860
+ className: "h-8 w-40 text-xs",
5861
+ value: fieldId,
5862
+ placeholder: "Column",
5863
+ attrs: { "data-records-button-action-field": "" },
5864
+ onChange: setFieldId,
5865
+ options: settable.map((f) => ({ value: f.id, label: fieldName(f) }))
5866
+ }
5867
+ ),
5868
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_design_system26.BasicInput, { className: "h-8 w-32 text-xs", placeholder: "Value", "aria-label": "Value", "data-records-button-action-value": "", value: setTo, onChange: (e) => setSetTo(e.target.value) }),
5869
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_design_system26.Button, { type: "button", size: "sm", variant: "outline", disabled: busy || fieldId === "", "data-records-button-action-make": "", onClick: () => void make(), children: busy ? "Making\u2026" : "Make" })
5870
+ ] }),
5871
+ refused ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(RefusalLine, { error: refused }) : null
5872
+ ] });
5873
+ }
5791
5874
 
5792
5875
  // src/FieldEditor.tsx
5793
5876
  var import_records24 = require("@ai-matrx/records");
@@ -6040,9 +6123,10 @@ function FieldEditor(props) {
6040
6123
  const noun = onEntity ? "field" : "column";
6041
6124
  const nameTaken = columnNameTakenBy(label, others.map(fieldName));
6042
6125
  const listsChoices = type === "select" || type === "multi_select" || type === "status";
6043
- const missing = editing ? formulaMissing ?? (listsChoices ? whatTheChoiceListIsMissing(choiceList) : null) : formulaMissing ?? (listsChoices ? whatTheChoiceListIsMissing(newChoices) : null) ?? (type === "formula" && formulaWritten ? null : whatIsMissing(
6126
+ const buttonMissing = type === "button" && buttonSettings.do ? (0, import_records23.buttonNeeds)(buttonSettings) : null;
6127
+ const missing = buttonMissing ?? (editing ? formulaMissing ?? (listsChoices ? whatTheChoiceListIsMissing(choiceList) : null) : formulaMissing ?? (listsChoices ? whatTheChoiceListIsMissing(newChoices) : null) ?? (type === "formula" && formulaWritten ? null : whatIsMissing(
6044
6128
  type === "count" ? { type: "rollup", label, options, via, pick, agg: "count", of, relations: totalSources, formulaFields, relationTarget, allowedTypes, noun } : { type, label, options, via, pick, agg, of, relations: sourcesFor(type), formulaFields, relationTarget, allowedTypes, noun }
6045
- ));
6129
+ )));
6046
6130
  const missingShown = missing && (attempted || formulaMissing) ? missing : null;
6047
6131
  const removeConsequence = field ? `${archiveConfirmSentence(`the field \u201C${fieldName(field)}\u201D`)} Its values stay in every record and come back with it.${linkReaders.length > 0 ? ` ${readersSentence(linkReaders.length, farTable.data?.name ?? null)}` : ""}` : "";
6048
6132
  const save = async () => {
@@ -6193,6 +6277,13 @@ function FieldEditor(props) {
6193
6277
  }
6194
6278
  }
6195
6279
  setBackfillError(null);
6280
+ if (type === "relation" && relationTarget === tableId && dependency && !onEntity) {
6281
+ const marked = await client.fieldUpdate({ field_id: written, patch: { dependency: true } });
6282
+ if (!marked.ok) {
6283
+ setBackfillError(marked.error);
6284
+ return;
6285
+ }
6286
+ }
6196
6287
  if (type === "relation" && showOnOther && otherTable.data && otherTable.data.id !== tableId) {
6197
6288
  const made = await client.relationReverseField({ field_id: written });
6198
6289
  if (!made.ok) {
@@ -6367,7 +6458,7 @@ function FieldEditor(props) {
6367
6458
  onChange: setRollupFilter
6368
6459
  }
6369
6460
  ) : null,
6370
- editing && field && !(type === "select" || type === "multi_select" || type === "status") ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(FieldFormatPicker, { field, value: showsAs, onValue: setShowsAs }) : null,
6461
+ editing && field && !(type === "select" || type === "multi_select" || type === "status" || type === "autonumber") ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(FieldFormatPicker, { field, value: showsAs, onValue: setShowsAs }) : null,
6371
6462
  /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-wrap items-center gap-4", children: [
6372
6463
  /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1.5", children: [
6373
6464
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
@@ -6415,6 +6506,10 @@ function FieldEditor(props) {
6415
6506
  "Show on ",
6416
6507
  otherTable.data.name ?? "the other table"
6417
6508
  ] }) : null,
6509
+ !field && type === "relation" && relationTarget === tableId ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1.5", title: "A timeline draws a line to each record this one waits on", children: [
6510
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_design_system27.Checkbox, { checked: dependency, "aria-label": "Waits on the linked records", "data-records-dependency": "", onCheckedChange: (v) => setDependency(v === true) }),
6511
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Waits on the linked records" })
6512
+ ] }) : null,
6418
6513
  !field && type === "relation" && relationTarget === tableId ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1.5", children: [
6419
6514
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6420
6515
  import_design_system27.Checkbox,