@ai-matrx/records-ui 0.95.4 → 0.95.10

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.
@@ -10,6 +10,10 @@ interface TableAnywhere {
10
10
  organization_name: string;
11
11
  kind: string | null;
12
12
  kept_by_the_app: boolean;
13
+ /** When the table last changed (the door's own column) — what tells two same-named tables apart. */
14
+ updated_at?: string | null;
15
+ /** Who made it, when the door says. */
16
+ created_by_name?: string | null;
13
17
  }
14
18
  interface TablesAnywhere {
15
19
  loading: boolean;
package/dist/pickers.d.ts CHANGED
@@ -10,6 +10,10 @@ interface TableAnywhere {
10
10
  organization_name: string;
11
11
  kind: string | null;
12
12
  kept_by_the_app: boolean;
13
+ /** When the table last changed (the door's own column) — what tells two same-named tables apart. */
14
+ updated_at?: string | null;
15
+ /** Who made it, when the door says. */
16
+ created_by_name?: string | null;
13
17
  }
14
18
  interface TablesAnywhere {
15
19
  loading: boolean;
package/dist/pickers.js CHANGED
@@ -749,7 +749,12 @@ var REMEDY = {
749
749
  unreachable: "Nothing was changed. Check your connection and open this again.",
750
750
  needs_approval: "Nothing was changed yet. The people who can approve it have been asked.",
751
751
  stale_read: "Open this again in a moment and it will be up to date.",
752
- timed_out: "Nothing was changed. Try a smaller page, or try again in a moment.",
752
+ // 🚨 ONE REMEDY THAT IS TRUE OF EVERY DOOR (lane CHAIR-STORE-PERF, 2026-10-03). The store cancels the
753
+ // WHOLE statement at its clock, so a timed-out door wrote nothing — a create, a column add and a page
754
+ // read alike. "Try a smaller page" was written for the page read and was printed to a person adding
755
+ // one row to a three-row table (clone walk, 2026-10-03; the clock was a lock another lane's
756
+ // rehearsal held, not the row). A door whose page can shrink says so in its own hint, which wins here.
757
+ timed_out: "Nothing was changed. Try again in a moment.",
753
758
  internal: "Nothing you did caused this. Try again, and tell us if it keeps happening."
754
759
  };
755
760
  var ENGINEER_TEXT = [
@@ -989,7 +994,7 @@ function tellApart(rows, nameOf) {
989
994
  // src/RelationPicker.tsx
990
995
  import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
991
996
  var NO_STORE_ON_THIS_SCREEN_REASON = "This question points at a record in somebody's own data, and a page answered without an account is never allowed to search that. Leave it blank \u2014 whoever receives your answer will fill it in.";
992
- function RelationPicker({ field, value, onChange, disabled, id, className, allowCreate = true }) {
997
+ function RelationPicker({ field, value, onChange, disabled, id, className, allowCreate = true, onPicked }) {
993
998
  const client = useOptionalRecordsClient();
994
999
  const [rows, setRows] = useState3(null);
995
1000
  const [words, setWords] = useState3({});
@@ -1081,8 +1086,10 @@ function RelationPicker({ field, value, onChange, disabled, id, className, allow
1081
1086
  const full = field.multi && field.relation_max !== null && picked.length >= field.relation_max;
1082
1087
  const toggle = (recordId) => {
1083
1088
  if (!field.multi) {
1084
- onChange(picked[0] === recordId ? null : recordId);
1089
+ const choosing = picked[0] !== recordId;
1090
+ onChange(choosing ? recordId : null);
1085
1091
  setOpen(false);
1092
+ if (choosing && onPicked) setTimeout(onPicked, 0);
1086
1093
  return;
1087
1094
  }
1088
1095
  const next = new Set(picked);
@@ -3318,7 +3325,7 @@ function FieldControl({ field, value, onChange, disabled, id, autoOpen, onClose,
3318
3325
  }
3319
3326
  return /* @__PURE__ */ jsx16(RelationPicker, { field, value, onChange, disabled, id: inputId });
3320
3327
  case "relation":
3321
- return /* @__PURE__ */ jsx16(RelationPicker, { field, value, onChange, disabled, id: inputId });
3328
+ return /* @__PURE__ */ jsx16(RelationPicker, { field, value, onChange, disabled, id: inputId, onPicked: onCommit });
3322
3329
  default:
3323
3330
  if (typeof value === "boolean" || field.config?.["kind"] === "boolean") {
3324
3331
  return /* @__PURE__ */ jsx16(
@@ -3980,20 +3987,40 @@ function TablePicker({ dataSource, value, onChange, disabled, tables }) {
3980
3987
  const options = tablePickerEntries(
3981
3988
  list.rows.map((t) => ({ ...t, id: t.table_id, name: t.table_name })),
3982
3989
  { keep: value }
3983
- ).entries.map(({ table: t }) => ({
3984
- value: t.table_id,
3985
- // The organization hint already tells two same-named tables apart across organizations.
3986
- label: t.table_name,
3987
- hint: t.organization_name,
3988
- keywords: t.organization_name
3989
- }));
3990
+ ).entries.map(({ table: t }) => t);
3991
+ const sameName = /* @__PURE__ */ new Map();
3992
+ for (const t of options) {
3993
+ const key = `${t.organization_id}|${t.table_name.trim().toLowerCase()}`;
3994
+ sameName.set(key, (sameName.get(key) ?? 0) + 1);
3995
+ }
3996
+ const pickerOptions = options.map((t) => {
3997
+ const twin = (sameName.get(`${t.organization_id}|${t.table_name.trim().toLowerCase()}`) ?? 0) > 1;
3998
+ const row = t;
3999
+ const second = [
4000
+ row.created_by_name ? `by ${row.created_by_name}` : null,
4001
+ row.updated_at ? `changed ${new Date(row.updated_at).toLocaleDateString()}` : null
4002
+ ].filter(Boolean).join(" \xB7 ");
4003
+ return {
4004
+ value: t.table_id,
4005
+ // The organization hint already tells two same-named tables apart across organizations.
4006
+ label: t.table_name,
4007
+ hint: t.organization_name,
4008
+ keywords: t.organization_name,
4009
+ ...twin && second ? {
4010
+ render: /* @__PURE__ */ jsxs16("span", { className: "flex min-w-0 flex-col", children: [
4011
+ /* @__PURE__ */ jsx19("span", { className: "truncate", children: t.table_name }),
4012
+ /* @__PURE__ */ jsx19("span", { className: "truncate text-[11px] text-muted-foreground", children: second })
4013
+ ] })
4014
+ } : {}
4015
+ };
4016
+ });
3990
4017
  const missing = Boolean(value) && !list.loading && !list.error && !list.rows.some((t) => t.table_id === value);
3991
4018
  return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1", children: [
3992
4019
  /* @__PURE__ */ jsx19(
3993
4020
  CreatablePicker,
3994
4021
  {
3995
4022
  value: value || null,
3996
- options,
4023
+ options: pickerOptions,
3997
4024
  onSelect: onChange,
3998
4025
  placeholder: missing ? "Table not available" : "Choose a table",
3999
4026
  searchPlaceholder: "Search tables",
@@ -4515,7 +4542,7 @@ function referencesOf(field, value, kind, labels) {
4515
4542
  }));
4516
4543
  }
4517
4544
  var ARCHIVED_REFERENCE_WORD = "Archived";
4518
- var ARCHIVED_REFERENCE_TIP = "In Trash; restore it to use it again";
4545
+ var ARCHIVED_REFERENCE_TIP = "In the Archived view; restore it to use it again";
4519
4546
  function ReferenceChip({ reference, waiting }) {
4520
4547
  const host = useRecordsUi();
4521
4548
  const words = reference.label ?? (reference.token === "record" ? waiting ?? "Loading\u2026" : WITHHELD_ENTITY_LABEL);