@ai-matrx/records-ui 0.102.0 → 0.102.4

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.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/TablePickers.tsx
4
4
  import { useEffect as useEffect12, useMemo as useMemo7, useState as useState16 } from "react";
5
5
  import { RecordsProvider as RecordsProvider2, useFields, useRecords, useTable } from "@ai-matrx/records/react";
6
- import { Button as Button9, CreatablePicker } from "@ai-matrx/design-system";
6
+ import { Button as Button8, CreatablePicker } from "@ai-matrx/design-system";
7
7
 
8
8
  // src/askOnce.ts
9
9
  var asked = /* @__PURE__ */ new WeakMap();
@@ -40,19 +40,19 @@ function fieldOptionsOnce(client, fieldId) {
40
40
  }
41
41
 
42
42
  // src/editors.tsx
43
- import { useCallback as useCallback4, useEffect as useEffect10, useRef as useRef9, useState as useState14 } from "react";
43
+ import { useCallback as useCallback5, useEffect as useEffect10, useRef as useRef11, useState as useState14 } from "react";
44
44
  import { allowsOtherValues, choiceValuesOf, coerceTypedAnswer, newerKindOf as newerKindOf4, decideTypedChoice, isTheChosen, optionKey as optionKey2, rankTypedMatches as rankTypedMatches3, readTypedTime as readTypedTime2, typedDateText as typedDateText2, typedTimeText as typedTimeText2 } from "@ai-matrx/records";
45
45
  import { useOptionalRecordsClient as useOptionalRecordsClient7 } from "@ai-matrx/records/react";
46
46
  import {
47
- BasicInput as BasicInput6,
47
+ BasicInput as BasicInput5,
48
48
  BasicTextarea as BasicTextarea2,
49
49
  Badge as Badge3,
50
- Button as Button8,
50
+ Button as Button7,
51
51
  Checkbox,
52
52
  Label,
53
- Popover as Popover4,
54
- PopoverContent as PopoverContent4,
55
- PopoverTrigger as PopoverTrigger4,
53
+ Popover as Popover3,
54
+ PopoverContent as PopoverContent3,
55
+ PopoverTrigger as PopoverTrigger3,
56
56
  Select as Select2,
57
57
  SelectContent as SelectContent2,
58
58
  SelectItem as SelectItem2,
@@ -550,38 +550,130 @@ var WITHHELD_RECORD_LABEL = "A record you have not been given access to";
550
550
  var UNREAD_RECORD_LABEL = "Couldn't load this name";
551
551
 
552
552
  // src/RelationPicker.tsx
553
- import { useEffect as useEffect3, useMemo, useState as useState3 } from "react";
553
+ import { useCallback, useEffect as useEffect3, useMemo, useRef as useRef3, useState as useState3 } from "react";
554
554
  import { rankTypedMatches } from "@ai-matrx/records";
555
555
  import { useOptionalRecordsClient } from "@ai-matrx/records/react";
556
556
  import { BasicInput as BasicInput3, Button as Button2, cn as cn4 } from "@ai-matrx/design-system";
557
557
 
558
558
  // src/PickOrAdd.tsx
559
- import { useEffect as useEffect2, useState as useState2 } from "react";
560
- import { BasicInput as BasicInput2, Button, Popover, PopoverContent, PopoverTrigger, ScrollArea, cn as cn2 } from "@ai-matrx/design-system";
559
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
560
+ import { BasicInput as BasicInput2, Button, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ScrollArea, cn as cn2 } from "@ai-matrx/design-system";
561
561
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
562
+ function Glyph({ d, className }) {
563
+ return /* @__PURE__ */ jsx2("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, className, children: /* @__PURE__ */ jsx2("path", { d }) });
564
+ }
565
+ var TICK = "m5 12 4 4L19 6";
566
+ var CROSS = "M18 6 6 18M6 6l12 12";
567
+ var PLUS = "M12 5v14M5 12h14";
562
568
  function useListKeys(args) {
563
- const { count, resetOn, onPick, onNothing, onClose } = args;
569
+ const { count, resetOn, onPick, onNothing, onClose, onFinish, onBackspaceEmpty, searchEmpty } = args;
564
570
  const [highlight, setHighlight] = useState2(0);
565
- useEffect2(() => setHighlight(0), [resetOn]);
571
+ const [moved, setMoved] = useState2(false);
572
+ useEffect2(() => {
573
+ setHighlight(0);
574
+ setMoved(false);
575
+ }, [resetOn]);
566
576
  const at = count === 0 ? -1 : Math.min(highlight, count - 1);
567
577
  const onKeyDown = (event) => {
578
+ if (event.key === "Tab") return;
568
579
  event.stopPropagation();
569
580
  if (event.key === "ArrowDown") {
570
581
  event.preventDefault();
582
+ setMoved(true);
571
583
  if (count > 0) setHighlight((h) => (Math.min(h, count - 1) + 1) % count);
572
584
  } else if (event.key === "ArrowUp") {
573
585
  event.preventDefault();
586
+ setMoved(true);
574
587
  if (count > 0) setHighlight((h) => (Math.min(h, count - 1) - 1 + count) % count);
575
588
  } else if (event.key === "Enter") {
576
589
  event.preventDefault();
577
- if (at >= 0) onPick(at);
590
+ if (onFinish && searchEmpty && !moved) onFinish();
591
+ else if (at >= 0) onPick(at);
578
592
  else onNothing?.();
579
593
  } else if (event.key === "Escape") {
580
594
  event.preventDefault();
581
595
  onClose();
596
+ } else if (event.key === "Backspace" && searchEmpty && onBackspaceEmpty) {
597
+ event.preventDefault();
598
+ onBackspaceEmpty();
582
599
  }
583
600
  };
584
- return { highlight: at, onKeyDown };
601
+ return { highlight: at, setHighlight, onKeyDown };
602
+ }
603
+ function PickRow({
604
+ label,
605
+ detail,
606
+ title,
607
+ chip,
608
+ picked,
609
+ highlighted,
610
+ disabled,
611
+ attrs,
612
+ icon,
613
+ onPick,
614
+ onPoint
615
+ }) {
616
+ const ref = useRef2(null);
617
+ useEffect2(() => {
618
+ if (highlighted) ref.current?.scrollIntoView?.({ block: "nearest" });
619
+ }, [highlighted]);
620
+ return /* @__PURE__ */ jsxs2(
621
+ "button",
622
+ {
623
+ ref,
624
+ type: "button",
625
+ role: "option",
626
+ "aria-selected": picked,
627
+ disabled: disabled ?? false,
628
+ onClick: onPick,
629
+ onMouseMove: onPoint,
630
+ title: title ?? label,
631
+ ...attrs ?? {},
632
+ "data-pick-highlighted": highlighted ? "" : void 0,
633
+ className: cn2(
634
+ "flex w-full min-w-0 items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm outline-none disabled:opacity-50",
635
+ highlighted ? "bg-accent text-accent-foreground" : ""
636
+ ),
637
+ children: [
638
+ /* @__PURE__ */ jsxs2("span", { className: "flex size-3.5 shrink-0 items-center justify-center", children: [
639
+ picked ? /* @__PURE__ */ jsx2("span", { "data-pick-tick": "", className: "contents", children: /* @__PURE__ */ jsx2(Glyph, { d: TICK, className: "size-3.5" }) }) : null,
640
+ icon === "plus" ? /* @__PURE__ */ jsx2(Glyph, { d: PLUS, className: "size-3.5 text-muted-foreground" }) : null
641
+ ] }),
642
+ /* @__PURE__ */ jsxs2("span", { className: "min-w-0 flex-1", children: [
643
+ chip ? /* @__PURE__ */ jsx2("span", { className: cn2("inline-flex max-w-full truncate rounded-md border px-1.5 py-0.5 text-xs font-medium", chip), "data-records-choice-chip": "", children: label }) : /* @__PURE__ */ jsx2("span", { className: "block truncate", children: label }),
644
+ detail ? /* @__PURE__ */ jsx2("span", { className: "block truncate text-xs text-muted-foreground", "data-tell-apart": "", children: detail }) : null
645
+ ] })
646
+ ]
647
+ }
648
+ );
649
+ }
650
+ function PickChips({ chips }) {
651
+ if (chips.length === 0) return null;
652
+ return /* @__PURE__ */ jsx2("div", { className: "flex flex-wrap gap-1 px-1 pb-1", "data-pick-chips": "", children: chips.map((c) => /* @__PURE__ */ jsxs2(
653
+ "span",
654
+ {
655
+ "data-pick-chip": "",
656
+ title: c.label,
657
+ className: cn2(
658
+ "inline-flex max-w-full items-center gap-1 rounded-md border px-1.5 py-0.5 text-xs font-medium",
659
+ c.chip ?? "bg-secondary text-secondary-foreground"
660
+ ),
661
+ children: [
662
+ /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: c.label }),
663
+ c.onRemove ? /* @__PURE__ */ jsx2(
664
+ "button",
665
+ {
666
+ type: "button",
667
+ "aria-label": `Remove ${c.label}`,
668
+ onClick: c.onRemove,
669
+ className: "shrink-0 rounded-sm opacity-60 hover:opacity-100",
670
+ children: /* @__PURE__ */ jsx2(Glyph, { d: CROSS, className: "size-3" })
671
+ }
672
+ ) : null
673
+ ]
674
+ },
675
+ c.id
676
+ )) });
585
677
  }
586
678
  function PickOrAdd({
587
679
  triggerLabel,
@@ -598,30 +690,51 @@ function PickOrAdd({
598
690
  add,
599
691
  foot,
600
692
  footNote,
601
- onEnterWithNoMatch
693
+ onEnterWithNoMatch,
694
+ anchored,
695
+ children,
696
+ chips,
697
+ multi
602
698
  }) {
603
- const hasFoot = Boolean(add) || Boolean(foot) || Boolean(footNote);
699
+ const addRow = add && !foot ? add : null;
700
+ const count = items.length + (addRow ? 1 : 0);
701
+ const removable = (chips ?? []).filter((c) => c.onRemove);
604
702
  const keys = useListKeys({
605
- count: items.length,
703
+ count,
606
704
  resetOn: search,
607
705
  onPick: (index) => {
608
706
  const item = items[index];
609
- if (item) onPick(item.id);
707
+ if (item) {
708
+ if (!item.disabled) onPick(item.id);
709
+ } else if (addRow && !addRow.disabled) addRow.onAdd();
610
710
  },
611
711
  onNothing: onEnterWithNoMatch ?? (add && !add.disabled ? add.onAdd : void 0),
612
- onClose: () => onOpenChange(false)
712
+ onClose: () => onOpenChange(false),
713
+ ...multi ? { onFinish: () => onOpenChange(false) } : {},
714
+ ...removable.length > 0 ? { onBackspaceEmpty: () => removable[removable.length - 1]?.onRemove?.() } : {},
715
+ searchEmpty: search === ""
613
716
  });
717
+ const hasFoot = Boolean(foot) || Boolean(footNote);
614
718
  return /* @__PURE__ */ jsxs2(Popover, { open, onOpenChange, children: [
615
- /* @__PURE__ */ jsx2(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx2(Button, { id: triggerId, type: "button", size: "sm", variant: "outline", "aria-label": triggerLabel, children: triggerText }) }),
719
+ anchored ? /* @__PURE__ */ jsx2(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsx2("div", { className: "flex min-h-6 w-full min-w-0 flex-wrap items-center gap-1", "aria-label": triggerLabel, children }) }) : /* @__PURE__ */ jsx2(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx2(Button, { id: triggerId, type: "button", size: "sm", variant: "outline", "aria-label": triggerLabel, children: triggerText }) }),
616
720
  /* @__PURE__ */ jsxs2(
617
721
  PopoverContent,
618
722
  {
619
723
  sizing: "content",
620
- className: "p-1",
724
+ padding: "xs",
621
725
  align: "start",
726
+ side: "bottom",
727
+ sideOffset: anchored ? 2 : 4,
728
+ animated: false,
622
729
  "data-matrx-cell-editor": "",
623
- onKeyDown: (event) => event.stopPropagation(),
730
+ onKeyDown: (event) => {
731
+ if (event.key !== "Tab") event.stopPropagation();
732
+ },
733
+ onCloseAutoFocus: (event) => {
734
+ if (anchored) event.preventDefault();
735
+ },
624
736
  children: [
737
+ chips ? /* @__PURE__ */ jsx2(PickChips, { chips }) : null,
625
738
  /* @__PURE__ */ jsx2(
626
739
  BasicInput2,
627
740
  {
@@ -632,53 +745,46 @@ function PickOrAdd({
632
745
  "aria-label": `Search \u2014 ${triggerLabel}`,
633
746
  autoFocus: true,
634
747
  autoComplete: "off",
635
- className: "mb-1 h-7 text-xs"
748
+ className: "mb-1 h-8 text-sm"
636
749
  }
637
750
  ),
638
751
  notice,
639
- /* @__PURE__ */ jsxs2(ScrollArea, { className: "max-h-56", children: [
640
- /* @__PURE__ */ jsx2("ul", { role: "listbox", "aria-label": triggerLabel, children: items.map((item, index) => /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsxs2(
641
- "button",
642
- {
643
- type: "button",
644
- onClick: () => onPick(item.id),
645
- title: item.title ?? item.label,
646
- ...item.attrs ?? {},
647
- "data-pick-highlighted": index === keys.highlight ? "" : void 0,
648
- className: cn2(
649
- "w-full truncate rounded px-2 py-1 text-left text-xs hover:bg-muted",
650
- item.picked ? "bg-accent text-accent-foreground" : "",
651
- index === keys.highlight ? "ring-1 ring-ring" : ""
652
- ),
653
- children: [
654
- item.chip ? /* @__PURE__ */ jsx2(
655
- "span",
656
- {
657
- className: cn2("inline-flex max-w-full truncate rounded-md border px-1.5 py-0.5 text-[11px] font-medium", item.chip),
658
- "data-records-choice-chip": "",
659
- children: item.label
660
- }
661
- ) : item.label,
662
- item.detail ? /* @__PURE__ */ jsx2("span", { className: "block truncate text-[11px] text-muted-foreground", "data-tell-apart": "", children: item.detail }) : null
663
- ]
664
- }
665
- ) }, item.id)) }),
752
+ /* @__PURE__ */ jsxs2(ScrollArea, { className: "max-h-64", children: [
753
+ /* @__PURE__ */ jsxs2("div", { role: "listbox", "aria-label": triggerLabel, "aria-multiselectable": multi ? true : void 0, children: [
754
+ items.map((item, index) => /* @__PURE__ */ jsx2(
755
+ PickRow,
756
+ {
757
+ label: item.label,
758
+ detail: item.detail,
759
+ title: item.title,
760
+ chip: item.chip,
761
+ picked: item.picked,
762
+ disabled: item.disabled,
763
+ attrs: item.attrs,
764
+ highlighted: index === keys.highlight,
765
+ onPick: () => onPick(item.id),
766
+ onPoint: () => keys.setHighlight(index)
767
+ },
768
+ item.id
769
+ )),
770
+ addRow ? /* @__PURE__ */ jsx2(
771
+ PickRow,
772
+ {
773
+ label: addRow.label,
774
+ picked: false,
775
+ icon: "plus",
776
+ disabled: addRow.disabled,
777
+ attrs: { "data-pick-add": "" },
778
+ highlighted: items.length === keys.highlight,
779
+ onPick: addRow.onAdd,
780
+ onPoint: () => keys.setHighlight(items.length)
781
+ }
782
+ ) : null
783
+ ] }),
666
784
  items.length === 0 && empty ? empty : null
667
785
  ] }),
668
786
  hasFoot ? /* @__PURE__ */ jsxs2("div", { className: "mt-1 border-t pt-1", children: [
669
- foot ?? (add ? /* @__PURE__ */ jsx2(
670
- Button,
671
- {
672
- type: "button",
673
- size: "sm",
674
- variant: "ghost",
675
- title: add.label,
676
- className: "w-full justify-start text-xs",
677
- disabled: add.disabled ?? false,
678
- onClick: add.onAdd,
679
- children: /* @__PURE__ */ jsx2("span", { className: "block w-full truncate text-left", children: add.label })
680
- }
681
- ) : null),
787
+ foot,
682
788
  footNote
683
789
  ] }) : null
684
790
  ]
@@ -994,13 +1100,19 @@ function tellApart(rows, nameOf2) {
994
1100
  // src/RelationPicker.tsx
995
1101
  import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
996
1102
  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.";
997
- function RelationPicker({ field, value, onChange, disabled, id, className, allowCreate = true, onPicked }) {
1103
+ function RelationPicker({ field, value, onChange, disabled, id, className, allowCreate = true, onPicked, autoOpen, onClose }) {
998
1104
  const client = useOptionalRecordsClient();
999
1105
  const [rows, setRows] = useState3(null);
1000
1106
  const [words, setWords] = useState3({});
1001
1107
  const [refusal2, setRefusal] = useState3(null);
1002
1108
  const [search, setSearch] = useState3("");
1003
- const [open, setOpen] = useState3(false);
1109
+ const [open, setOpenState] = useState3(autoOpen === true);
1110
+ const onCloseRef = useRef3(onClose);
1111
+ onCloseRef.current = onClose;
1112
+ const setOpen = useCallback((next) => {
1113
+ setOpenState(next);
1114
+ if (!next) onCloseRef.current?.();
1115
+ }, []);
1004
1116
  const [target, setTarget] = useState3(null);
1005
1117
  const [targetRefusal, setTargetRefusal] = useState3(null);
1006
1118
  const [creating, setCreating] = useState3(false);
@@ -1136,22 +1248,28 @@ function RelationPicker({ field, value, onChange, disabled, id, className, allow
1136
1248
  };
1137
1249
  const apart = tellApart(rows ?? [], titleOf);
1138
1250
  const visible = rankTypedMatches(rows ?? [], search, (row) => [titleOf(row.id), apart.get(row.id) ?? ""]);
1251
+ const anchored = autoOpen === true;
1252
+ const cellChips = picked.map((recordId) => /* @__PURE__ */ jsx4(
1253
+ RecordChip,
1254
+ {
1255
+ title: titleOf(recordId),
1256
+ ...disabled || anchored ? {} : { onRemove: () => toggle(recordId) }
1257
+ },
1258
+ recordId
1259
+ ));
1139
1260
  return (
1140
1261
  // Never wider than where it is drawn (a grid cell beside a sticky column: B3-07) — chips truncate, the button wraps.
1141
1262
  /* @__PURE__ */ jsxs4("div", { className: cn4("flex min-w-0 max-w-full flex-wrap items-center gap-1", className), children: [
1142
- picked.map((recordId) => /* @__PURE__ */ jsx4(
1143
- RecordChip,
1144
- {
1145
- title: titleOf(recordId),
1146
- ...disabled ? {} : { onRemove: () => toggle(recordId) }
1147
- },
1148
- recordId
1149
- )),
1263
+ anchored && !disabled ? null : cellChips,
1150
1264
  disabled ? null : (
1151
1265
  // THE ONE "PICK OR ADD" BUILDER (PickOrAdd.tsx) — the choice editor draws the same one.
1266
+ // In a grid cell it hangs from the cell's own chips; what is picked heads the list with its ×.
1152
1267
  /* @__PURE__ */ jsx4(
1153
1268
  PickOrAdd,
1154
1269
  {
1270
+ anchored,
1271
+ multi: field.multi,
1272
+ chips: picked.map((recordId) => ({ id: recordId, label: titleOf(recordId), onRemove: () => toggle(recordId) })),
1155
1273
  triggerId: id,
1156
1274
  triggerLabel: `Pick for ${fieldName(field)}`,
1157
1275
  triggerText: picked.length === 0 ? "Pick" : "Change",
@@ -1238,7 +1356,8 @@ function RelationPicker({ field, value, onChange, disabled, id, className, allow
1238
1356
  }
1239
1357
  }
1240
1358
  )
1241
- ) : null
1359
+ ) : null,
1360
+ children: anchored ? cellChips : null
1242
1361
  }
1243
1362
  )
1244
1363
  )
@@ -1247,7 +1366,7 @@ function RelationPicker({ field, value, onChange, disabled, id, className, allow
1247
1366
  }
1248
1367
 
1249
1368
  // src/gridAttachments.tsx
1250
- import { useEffect as useEffect6, useRef as useRef5, useState as useState7 } from "react";
1369
+ import { useEffect as useEffect6, useRef as useRef7, useState as useState7 } from "react";
1251
1370
  import { useOptionalRecordsClient as useOptionalRecordsClient3 } from "@ai-matrx/records/react";
1252
1371
  import { Badge, Button as Button5 } from "@ai-matrx/design-system";
1253
1372
 
@@ -1326,13 +1445,13 @@ function useRecordsUi() {
1326
1445
  }
1327
1446
 
1328
1447
  // src/labels.tsx
1329
- import { createContext as createContext2, useCallback, useContext as useContext2, useEffect as useEffect5, useMemo as useMemo3, useRef as useRef3, useState as useState5 } from "react";
1448
+ import { createContext as createContext2, useCallback as useCallback2, useContext as useContext2, useEffect as useEffect5, useMemo as useMemo3, useRef as useRef5, useState as useState5 } from "react";
1330
1449
  import { useRecordsClient } from "@ai-matrx/records/react";
1331
1450
  import { newerKindExportWords, optionKey } from "@ai-matrx/records";
1332
1451
  import { isUuidShape as isUuidShape2 } from "@ai-matrx/kit/uuid";
1333
1452
 
1334
1453
  // src/signature.tsx
1335
- import { useEffect as useEffect4, useRef as useRef2, useState as useState4 } from "react";
1454
+ import { useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
1336
1455
  import { Button as Button3, ErrorBox as ErrorBox2, cn as cn5 } from "@ai-matrx/design-system";
1337
1456
  import { useOptionalRecordsClient as useOptionalRecordsClient2 } from "@ai-matrx/records/react";
1338
1457
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
@@ -1460,8 +1579,8 @@ function SignaturePad({
1460
1579
  const kept = drawnSignatureOf(value);
1461
1580
  const named = !kept && typeof value === "string" && value !== "" ? value : null;
1462
1581
  const [showPad, setShowPad] = useState4(() => !kept && !named);
1463
- const canvasRef = useRef2(null);
1464
- const drawing = useRef2(false);
1582
+ const canvasRef = useRef4(null);
1583
+ const drawing = useRef4(false);
1465
1584
  const [dirty, setDirty] = useState4(false);
1466
1585
  const [tooBig, setTooBig] = useState4(false);
1467
1586
  useEffect4(() => {
@@ -1637,10 +1756,10 @@ function RecordLabelProvider({ children }) {
1637
1756
  const [iconsOf, setIconsOf] = useState5({});
1638
1757
  const [settled, setSettled] = useState5({});
1639
1758
  const [waitingLines, setWaitingLines] = useState5({});
1640
- const asked3 = useRef3(/* @__PURE__ */ new Set());
1641
- const chased = useRef3(/* @__PURE__ */ new Set());
1642
- const timers = useRef3(/* @__PURE__ */ new Map());
1643
- const startWaitClock = useCallback((field, target) => {
1759
+ const asked3 = useRef5(/* @__PURE__ */ new Set());
1760
+ const chased = useRef5(/* @__PURE__ */ new Set());
1761
+ const timers = useRef5(/* @__PURE__ */ new Map());
1762
+ const startWaitClock = useCallback2((field, target) => {
1644
1763
  if (timers.current.has(field.id)) return;
1645
1764
  timers.current.set(
1646
1765
  field.id,
@@ -1652,7 +1771,7 @@ function RecordLabelProvider({ children }) {
1652
1771
  }, SAY_WHAT_YOU_ARE_WAITING_FOR_AFTER_MS)
1653
1772
  );
1654
1773
  }, []);
1655
- const stopWaitClock = useCallback((fieldId) => {
1774
+ const stopWaitClock = useCallback2((fieldId) => {
1656
1775
  const timer = timers.current.get(fieldId);
1657
1776
  if (timer) {
1658
1777
  clearTimeout(timer);
@@ -1672,7 +1791,7 @@ function RecordLabelProvider({ children }) {
1672
1791
  },
1673
1792
  []
1674
1793
  );
1675
- const want = useCallback(
1794
+ const want = useCallback2(
1676
1795
  (field) => {
1677
1796
  if (!pointsAtRecords(field)) return;
1678
1797
  if (asked3.current.has(field.id)) return;
@@ -1707,9 +1826,9 @@ function RecordLabelProvider({ children }) {
1707
1826
  },
1708
1827
  [client, startWaitClock, stopWaitClock]
1709
1828
  );
1710
- const queued = useRef3(/* @__PURE__ */ new Map());
1711
- const flushing = useRef3(null);
1712
- const flush = useCallback(() => {
1829
+ const queued = useRef5(/* @__PURE__ */ new Map());
1830
+ const flushing = useRef5(null);
1831
+ const flush = useCallback2(() => {
1713
1832
  flushing.current = null;
1714
1833
  const batch = [...queued.current.values()];
1715
1834
  queued.current.clear();
@@ -1739,7 +1858,7 @@ function RecordLabelProvider({ children }) {
1739
1858
  for (const { field } of batch) stopWaitClock(field.id);
1740
1859
  })();
1741
1860
  }, [client, stopWaitClock]);
1742
- const chase = useCallback(
1861
+ const chase = useCallback2(
1743
1862
  (field, id) => {
1744
1863
  const key = `${field.id}:${id}`;
1745
1864
  if (chased.current.has(key)) return;
@@ -1758,8 +1877,8 @@ function RecordLabelProvider({ children }) {
1758
1877
  },
1759
1878
  []
1760
1879
  );
1761
- const rereadFor = useRef3(/* @__PURE__ */ new Set());
1762
- const lookupWords = useCallback(
1880
+ const rereadFor = useRef5(/* @__PURE__ */ new Set());
1881
+ const lookupWords = useCallback2(
1763
1882
  (field, id) => {
1764
1883
  if (field.type === "list" && !isId(id)) {
1765
1884
  const named = names[choiceKeyName(field.id, id)];
@@ -1788,7 +1907,7 @@ function RecordLabelProvider({ children }) {
1788
1907
  },
1789
1908
  [lookupWords, archivedRefs, iconsOf]
1790
1909
  );
1791
- const waiting = useCallback((field) => waitingLines[field.id] ?? null, [waitingLines]);
1910
+ const waiting = useCallback2((field) => waitingLines[field.id] ?? null, [waitingLines]);
1792
1911
  const value = useMemo3(() => ({ lookup, want, waiting }), [lookup, want, waiting]);
1793
1912
  return /* @__PURE__ */ jsx7(LabelContext.Provider, { value, children });
1794
1913
  }
@@ -1801,7 +1920,7 @@ function useRecordLabels(fields) {
1801
1920
  }
1802
1921
 
1803
1922
  // src/FilePicker.tsx
1804
- import { useCallback as useCallback2, useId, useRef as useRef4, useState as useState6 } from "react";
1923
+ import { useCallback as useCallback3, useId, useRef as useRef6, useState as useState6 } from "react";
1805
1924
  import { Button as Button4, cn as cn6 } from "@ai-matrx/design-system";
1806
1925
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1807
1926
  function FilePicker({
@@ -1816,16 +1935,16 @@ function FilePicker({
1816
1935
  className
1817
1936
  }) {
1818
1937
  const inputId = useId();
1819
- const input = useRef4(null);
1938
+ const input = useRef6(null);
1820
1939
  const [over, setOver] = useState6(false);
1821
- const take = useCallback2(
1940
+ const take = useCallback3(
1822
1941
  (file) => {
1823
1942
  if (!file || disabled) return;
1824
1943
  onFile(file);
1825
1944
  },
1826
1945
  [disabled, onFile]
1827
1946
  );
1828
- const onDrop = useCallback2(
1947
+ const onDrop = useCallback3(
1829
1948
  (e) => {
1830
1949
  e.preventDefault();
1831
1950
  setOver(false);
@@ -1998,7 +2117,7 @@ function AttachmentControl({
1998
2117
  const host = useRecordsUi();
1999
2118
  const [busy, setBusy] = useState7(false);
2000
2119
  const [why, setWhy] = useState7(null);
2001
- const latest = useRef5(value);
2120
+ const latest = useRef7(value);
2002
2121
  latest.current = value;
2003
2122
  const multiple = Boolean(field.multi);
2004
2123
  const pick = async () => {
@@ -2019,7 +2138,7 @@ function AttachmentControl({
2019
2138
  setBusy(false);
2020
2139
  onClose?.();
2021
2140
  };
2022
- const opened = useRef5(false);
2141
+ const opened = useRef7(false);
2023
2142
  useEffect6(() => {
2024
2143
  if (!autoOpen || opened.current || !host.pickFiles) return;
2025
2144
  opened.current = true;
@@ -2316,19 +2435,11 @@ function Chips({
2316
2435
  }
2317
2436
 
2318
2437
  // src/PersonPicker.tsx
2319
- import { useCallback as useCallback3, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef6, useState as useState10 } from "react";
2438
+ import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef8, useState as useState10 } from "react";
2320
2439
  import { rankTypedMatches as rankTypedMatches2 } from "@ai-matrx/records";
2321
2440
  import { useOptionalRecordsClient as useOptionalRecordsClient5 } from "@ai-matrx/records/react";
2322
- import {
2323
- BasicInput as BasicInput4,
2324
- Button as Button7,
2325
- Popover as Popover2,
2326
- PopoverContent as PopoverContent2,
2327
- PopoverTrigger as PopoverTrigger2,
2328
- ScrollArea as ScrollArea2,
2329
- cn as cn9
2330
- } from "@ai-matrx/design-system";
2331
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2441
+ import { cn as cn9 } from "@ai-matrx/design-system";
2442
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2332
2443
  function personFromRow(row) {
2333
2444
  const data = row.document ?? {};
2334
2445
  const userId = data["user_id"];
@@ -2366,9 +2477,9 @@ function PersonPicker({ field, value, onChange, disabled, id, className, autoOpe
2366
2477
  const [error, setError] = useState10(null);
2367
2478
  const [search, setSearch] = useState10(initialSearch ?? "");
2368
2479
  const [open, setOpenState] = useState10(autoOpen === true);
2369
- const onCloseRef = useRef6(onClose);
2480
+ const onCloseRef = useRef8(onClose);
2370
2481
  onCloseRef.current = onClose;
2371
- const setOpen = useCallback3((next) => {
2482
+ const setOpen = useCallback4((next) => {
2372
2483
  setOpenState(next);
2373
2484
  if (!next) onCloseRef.current?.();
2374
2485
  }, []);
@@ -2379,7 +2490,7 @@ function PersonPicker({ field, value, onChange, disabled, id, className, autoOpe
2379
2490
  () => Array.isArray(value) ? value.map(String) : value === null || value === void 0 ? [] : [String(value)],
2380
2491
  [value]
2381
2492
  );
2382
- const load = useCallback3(async () => {
2493
+ const load = useCallback4(async () => {
2383
2494
  if (!membersPort || !client) return;
2384
2495
  const [roster, records] = await Promise.all([
2385
2496
  membersPort(),
@@ -2408,16 +2519,6 @@ function PersonPicker({ field, value, onChange, disabled, id, className, autoOpe
2408
2519
  };
2409
2520
  }, [client, personTable, picked.length, people.length]);
2410
2521
  const listed = rankTypedMatches2(members ?? [], search, memberName);
2411
- const keys = useListKeys({
2412
- count: listed.length,
2413
- resetOn: search,
2414
- onPick: (index) => {
2415
- const member = listed[index];
2416
- if (member && !busy) void pickRef.current?.(member);
2417
- },
2418
- onClose: () => setOpen(false)
2419
- });
2420
- const pickRef = useRef6(null);
2421
2522
  if (!membersPort || !client) {
2422
2523
  return /* @__PURE__ */ jsx12("p", { className: cn9("text-xs text-muted-foreground", className), children: NO_MEMBERS_REASON });
2423
2524
  }
@@ -2456,7 +2557,6 @@ function PersonPicker({ field, value, onChange, disabled, id, className, autoOpe
2456
2557
  else next.add(resolved.data);
2457
2558
  onChange(next.size === 0 ? null : [...next]);
2458
2559
  };
2459
- pickRef.current = pick;
2460
2560
  const drop = (recordId) => {
2461
2561
  const next = picked.filter((id2) => id2 !== recordId);
2462
2562
  onChange(next.length === 0 ? null : field.multi ? next : next[0] ?? null);
@@ -2465,79 +2565,56 @@ function PersonPicker({ field, value, onChange, disabled, id, className, autoOpe
2465
2565
  const pickedUserIds = new Set(
2466
2566
  picked.map((recordId) => people.find((p) => p.id === recordId)?.userId).filter(Boolean)
2467
2567
  );
2568
+ const anchored = autoOpen === true;
2569
+ const cellChips = picked.map((recordId) => /* @__PURE__ */ jsx12(
2570
+ RecordChip,
2571
+ {
2572
+ title: nameOfRecord(recordId),
2573
+ ...disabled || anchored ? {} : { onRemove: () => drop(recordId) }
2574
+ },
2575
+ recordId
2576
+ ));
2468
2577
  return /* @__PURE__ */ jsxs10("div", { className: cn9("flex flex-wrap items-center gap-1", className), children: [
2469
- picked.map((recordId) => /* @__PURE__ */ jsx12(
2470
- RecordChip,
2471
- {
2472
- title: nameOfRecord(recordId),
2473
- ...disabled ? {} : { onRemove: () => drop(recordId) }
2474
- },
2475
- recordId
2476
- )),
2477
- disabled ? null : /* @__PURE__ */ jsxs10(Popover2, { open, onOpenChange: setOpen, children: [
2478
- /* @__PURE__ */ jsx12(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsx12(
2479
- Button7,
2480
- {
2481
- id,
2482
- type: "button",
2483
- size: "sm",
2484
- variant: "outline",
2485
- "aria-label": `Pick a person for ${fieldName(field)}`,
2486
- children: picked.length === 0 ? "Pick a person" : "Change"
2487
- }
2488
- ) }),
2489
- /* @__PURE__ */ jsxs10(
2490
- PopoverContent2,
2578
+ anchored && !disabled ? null : cellChips,
2579
+ disabled ? null : (
2580
+ // THE ONE "PICK OR ADD" BUILDER (lane CELL-EDITORS, 2026-10-06): the person list used to carry
2581
+ // its own copy of the list's layout and keys; it now draws the same rows, ticks, highlight and
2582
+ // head chips as every other picker, and in a grid cell hangs from the cell.
2583
+ /* @__PURE__ */ jsx12(
2584
+ PickOrAdd,
2491
2585
  {
2492
- sizing: "content",
2493
- className: "p-1",
2494
- align: "start",
2495
- "data-matrx-cell-editor": "",
2496
- onKeyDown: (event) => event.stopPropagation(),
2497
- children: [
2498
- /* @__PURE__ */ jsx12(
2499
- BasicInput4,
2500
- {
2501
- value: search,
2502
- onChange: (e) => setSearch(e.target.value),
2503
- onKeyDown: keys.onKeyDown,
2504
- autoFocus: true,
2505
- autoComplete: "off",
2506
- "aria-label": `Search people for ${fieldName(field)}`,
2507
- placeholder: "Search people",
2508
- className: "mb-1 h-7 text-xs"
2509
- }
2510
- ),
2586
+ anchored,
2587
+ multi: field.multi,
2588
+ triggerId: id,
2589
+ triggerLabel: `Pick a person for ${fieldName(field)}`,
2590
+ triggerText: picked.length === 0 ? "Pick a person" : "Change",
2591
+ open,
2592
+ onOpenChange: setOpen,
2593
+ search,
2594
+ onSearch: setSearch,
2595
+ chips: picked.map((recordId) => ({ id: recordId, label: nameOfRecord(recordId), onRemove: () => drop(recordId) })),
2596
+ items: visible.map((member) => ({
2597
+ id: member.userId,
2598
+ label: memberName(member),
2599
+ // A name and an email with nothing between them read as one run-on string (verdict,
2600
+ // 19 September). They are two facts, so they are drawn as two.
2601
+ detail: member.email && member.email !== memberName(member) ? member.email : null,
2602
+ picked: pickedUserIds.has(member.userId),
2603
+ disabled: busy
2604
+ })),
2605
+ onPick: (userId) => {
2606
+ const member = visible.find((m) => m.userId === userId);
2607
+ if (member && !busy) void pick(member);
2608
+ },
2609
+ notice: /* @__PURE__ */ jsxs10(Fragment4, { children: [
2511
2610
  error ? /* @__PURE__ */ jsx12(RefusalLine, { error, className: "p-2" }) : null,
2512
- members === null ? /* @__PURE__ */ jsx12("p", { className: "p-2 text-xs text-muted-foreground", children: "Reading the members\u2026" }) : null,
2513
- /* @__PURE__ */ jsxs10(ScrollArea2, { className: "max-h-56", children: [
2514
- /* @__PURE__ */ jsx12("ul", { role: "listbox", "aria-label": `People for ${fieldName(field)}`, children: visible.map((member, index) => /* @__PURE__ */ jsx12("li", { children: /* @__PURE__ */ jsxs10(
2515
- "button",
2516
- {
2517
- type: "button",
2518
- disabled: busy,
2519
- "data-pick-highlighted": index === keys.highlight ? "" : void 0,
2520
- onClick: () => void pick(member),
2521
- className: cn9(
2522
- "w-full truncate rounded px-2 py-1 text-left text-xs hover:bg-muted",
2523
- pickedUserIds.has(member.userId) ? "bg-accent text-accent-foreground" : "",
2524
- index === keys.highlight ? "ring-1 ring-ring" : ""
2525
- ),
2526
- children: [
2527
- /* @__PURE__ */ jsx12("span", { children: memberName(member) }),
2528
- member.email && member.email !== memberName(member) ? /* @__PURE__ */ jsxs10("span", { className: "ml-1.5 opacity-60", children: [
2529
- "\xB7 ",
2530
- member.email
2531
- ] }) : null
2532
- ]
2533
- }
2534
- ) }, member.userId)) }),
2535
- members !== null && visible.length === 0 ? /* @__PURE__ */ jsx12("p", { className: "p-2 text-xs text-muted-foreground", children: members.length === 0 ? "This organization has no other members yet, so there is nobody to assign." : "Nobody in this organization matches." }) : null
2536
- ] })
2537
- ]
2611
+ members === null ? /* @__PURE__ */ jsx12("p", { className: "p-2 text-xs text-muted-foreground", children: "Reading the members\u2026" }) : null
2612
+ ] }),
2613
+ empty: members !== null ? /* @__PURE__ */ jsx12("p", { className: "p-2 text-xs text-muted-foreground", children: members.length === 0 ? "This organization has no other members yet, so there is nobody to assign." : "Nobody in this organization matches." }) : null,
2614
+ children: anchored ? cellChips : null
2538
2615
  }
2539
2616
  )
2540
- ] })
2617
+ )
2541
2618
  ] });
2542
2619
  }
2543
2620
 
@@ -2608,12 +2685,12 @@ function currencyCodeFor(unit) {
2608
2685
  }
2609
2686
 
2610
2687
  // src/formatControls.tsx
2611
- import { useEffect as useEffect8, useRef as useRef8, useState as useState11 } from "react";
2612
- import { BasicInput as BasicInput5, BasicTextarea } from "@ai-matrx/design-system";
2688
+ import { useEffect as useEffect8, useRef as useRef10, useState as useState11 } from "react";
2689
+ import { BasicInput as BasicInput4, BasicTextarea } from "@ai-matrx/design-system";
2613
2690
  import { getFieldFormat as getFieldFormat3, parseFieldInput } from "@ai-matrx/design-system/field-formats";
2614
2691
 
2615
2692
  // src/formattedValue.tsx
2616
- import { useRef as useRef7 } from "react";
2693
+ import { useRef as useRef9 } from "react";
2617
2694
  import { FormattedCell } from "@ai-matrx/design-system/data-table";
2618
2695
  import { formatFieldValue as formatFieldValue2, formatPhone, getFieldFormat as getFieldFormat2 } from "@ai-matrx/design-system/field-formats";
2619
2696
  import { cn as cn10 } from "@ai-matrx/design-system";
@@ -2635,7 +2712,7 @@ function RatingStars({
2635
2712
  label,
2636
2713
  selectFirst
2637
2714
  }) {
2638
- const armed = useRef7(true);
2715
+ const armed = useRef9(true);
2639
2716
  const score = numberOf(value) ?? 0;
2640
2717
  const shown2 = Math.round(score);
2641
2718
  const said = `${shown2} out of ${max}`;
@@ -2785,13 +2862,13 @@ function keptValue(format, raw) {
2785
2862
  }
2786
2863
  function NumberInFormat({ format, value, onChange, disabled, id }) {
2787
2864
  const [text, setText] = useState11(() => typedText(format, value));
2788
- const lastSent = useRef8(void 0);
2865
+ const lastSent = useRef10(void 0);
2789
2866
  useEffect8(() => {
2790
2867
  if (value === lastSent.current) return;
2791
2868
  setText(typedText(format, value));
2792
2869
  }, [value, format]);
2793
2870
  return /* @__PURE__ */ jsx14(
2794
- BasicInput5,
2871
+ BasicInput4,
2795
2872
  {
2796
2873
  id,
2797
2874
  inputMode: "decimal",
@@ -2825,7 +2902,7 @@ function formatControl(args) {
2825
2902
  case "url":
2826
2903
  case "tel":
2827
2904
  return /* @__PURE__ */ jsx14(
2828
- BasicInput5,
2905
+ BasicInput4,
2829
2906
  {
2830
2907
  id,
2831
2908
  type: def.editor,
@@ -2838,7 +2915,7 @@ function formatControl(args) {
2838
2915
  case "color":
2839
2916
  return /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-2", children: [
2840
2917
  /* @__PURE__ */ jsx14(
2841
- BasicInput5,
2918
+ BasicInput4,
2842
2919
  {
2843
2920
  id: `${id}-swatch`,
2844
2921
  type: "color",
@@ -2849,7 +2926,7 @@ function formatControl(args) {
2849
2926
  onChange: (e) => commit(e.target.value)
2850
2927
  }
2851
2928
  ),
2852
- /* @__PURE__ */ jsx14(BasicInput5, { id, value: text, placeholder: "#3b82f6", disabled, onChange: (e) => commit(e.target.value) })
2929
+ /* @__PURE__ */ jsx14(BasicInput4, { id, value: text, placeholder: "#3b82f6", disabled, onChange: (e) => commit(e.target.value) })
2853
2930
  ] });
2854
2931
  case "textarea":
2855
2932
  return /* @__PURE__ */ jsx14(BasicTextarea, { id, rows: 4, value: text, disabled, onChange: (e) => commit(e.target.value) });
@@ -2860,7 +2937,7 @@ function formatControl(args) {
2860
2937
 
2861
2938
  // src/typedDateHelper.tsx
2862
2939
  import { useState as useState12 } from "react";
2863
- import { Popover as Popover3, PopoverContent as PopoverContent3, PopoverTrigger as PopoverTrigger3, cn as cn11 } from "@ai-matrx/design-system";
2940
+ import { Popover as Popover2, PopoverContent as PopoverContent2, PopoverTrigger as PopoverTrigger2, cn as cn11 } from "@ai-matrx/design-system";
2864
2941
  import { readTypedDate, readTypedTime, typedDateText, typedTimeText } from "@ai-matrx/records";
2865
2942
  import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
2866
2943
  var WEEK = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
@@ -2928,8 +3005,8 @@ function TypedDateHelper({ kind, text, onText, label }) {
2928
3005
  const at = new Date(shown2.y, shown2.m + by, 1);
2929
3006
  setMonth({ y: at.getFullYear(), m: at.getMonth() });
2930
3007
  };
2931
- return /* @__PURE__ */ jsxs13(Popover3, { open, onOpenChange: setOpen, children: [
2932
- /* @__PURE__ */ jsx15(PopoverTrigger3, { asChild: true, children: /* @__PURE__ */ jsx15(
3008
+ return /* @__PURE__ */ jsxs13(Popover2, { open, onOpenChange: setOpen, children: [
3009
+ /* @__PURE__ */ jsx15(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsx15(
2933
3010
  "button",
2934
3011
  {
2935
3012
  type: "button",
@@ -2942,7 +3019,7 @@ function TypedDateHelper({ kind, text, onText, label }) {
2942
3019
  }
2943
3020
  ) }),
2944
3021
  /* @__PURE__ */ jsx15(
2945
- PopoverContent3,
3022
+ PopoverContent2,
2946
3023
  {
2947
3024
  sizing: "content",
2948
3025
  align: "start",
@@ -3040,7 +3117,7 @@ function useChoiceNudge(enabled = true) {
3040
3117
  }
3041
3118
 
3042
3119
  // src/editors.tsx
3043
- import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
3120
+ import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
3044
3121
  var CHOICE_EDITOR_ADDS_WHAT_IS_TYPED = true;
3045
3122
  function isChoiceAddition(value) {
3046
3123
  return typeof value === "object" && value !== null && value.addingChoices === true;
@@ -3073,9 +3150,9 @@ function ChoiceAskButtons({
3073
3150
  return /* @__PURE__ */ jsxs14("span", { "data-records-choice-ask": "", role: "group", "aria-label": choiceAskSentence(field, words), className: "flex flex-col gap-1", children: [
3074
3151
  /* @__PURE__ */ jsx16("span", { className: "text-[11px] leading-snug", children: choiceAskSentence(field, words) }),
3075
3152
  /* @__PURE__ */ jsxs14("span", { className: "flex flex-wrap items-center gap-1", children: [
3076
- /* @__PURE__ */ jsx16(Button8, { type: "button", size: "sm", className: "h-6 px-2 text-xs", disabled: busy ?? false, onClick: onAdd, children: "Add" }),
3077
- keepOffered ? /* @__PURE__ */ jsx16(Button8, { type: "button", size: "sm", variant: "outline", className: "h-6 px-2 text-xs", disabled: busy ?? false, onClick: onKeep, children: "Keep as typed" }) : null,
3078
- /* @__PURE__ */ jsx16(Button8, { type: "button", size: "sm", variant: "ghost", className: "h-6 px-2 text-xs", disabled: busy ?? false, onClick: onCancel, children: "Cancel" })
3153
+ /* @__PURE__ */ jsx16(Button7, { type: "button", size: "sm", className: "h-6 px-2 text-xs", disabled: busy ?? false, onClick: onAdd, children: "Add" }),
3154
+ keepOffered ? /* @__PURE__ */ jsx16(Button7, { type: "button", size: "sm", variant: "outline", className: "h-6 px-2 text-xs", disabled: busy ?? false, onClick: onKeep, children: "Keep as typed" }) : null,
3155
+ /* @__PURE__ */ jsx16(Button7, { type: "button", size: "sm", variant: "ghost", className: "h-6 px-2 text-xs", disabled: busy ?? false, onClick: onCancel, children: "Cancel" })
3079
3156
  ] })
3080
3157
  ] });
3081
3158
  }
@@ -3186,7 +3263,7 @@ function TypedTextControl({ field, value, onChange, disabled, id, onCommit, onCa
3186
3263
  ...value.openedAs !== void 0 ? { openedAs: value.openedAs } : {}
3187
3264
  });
3188
3265
  const box = /* @__PURE__ */ jsx16(
3189
- BasicInput6,
3266
+ BasicInput5,
3190
3267
  {
3191
3268
  id,
3192
3269
  value: value.text,
@@ -3224,7 +3301,7 @@ function TypedTextControl({ field, value, onChange, disabled, id, onCommit, onCa
3224
3301
  }
3225
3302
  ) : "refusal" in judged ? /* @__PURE__ */ jsxs14("span", { className: "flex flex-col gap-1", children: [
3226
3303
  /* @__PURE__ */ jsx16("span", { "data-records-typed-refusal": "", role: "status", className: "text-[11px] leading-snug text-amber-700 dark:text-amber-400", children: judged.refusal }),
3227
- judged.cancelOnly && onCancel ? /* @__PURE__ */ jsx16("span", { "data-records-choice-ask": "", children: /* @__PURE__ */ jsx16(Button8, { type: "button", size: "sm", variant: "ghost", className: "h-6 px-2 text-xs", onClick: () => onCancel(), children: "Cancel" }) }) : null
3304
+ judged.cancelOnly && onCancel ? /* @__PURE__ */ jsx16("span", { "data-records-choice-ask": "", children: /* @__PURE__ */ jsx16(Button7, { type: "button", size: "sm", variant: "ghost", className: "h-6 px-2 text-xs", onClick: () => onCancel(), children: "Cancel" }) }) : null
3228
3305
  ] }) : judged.value === null || judged.value === void 0 ? null : /* @__PURE__ */ jsxs14("span", { "data-records-typed-reads-as": "", className: "text-[10px] text-muted-foreground", children: [
3229
3306
  isChoiceAddition(judged.value) ? `Adds ${quoted(judged.value.add)} to the choices for ${fieldName(field)}. ` : null,
3230
3307
  "Reads as",
@@ -3288,7 +3365,7 @@ function FieldControl({ field, value, onChange, disabled, id, autoOpen, onClose,
3288
3365
  case "currency":
3289
3366
  case "percent":
3290
3367
  return /* @__PURE__ */ jsx16(
3291
- BasicInput6,
3368
+ BasicInput5,
3292
3369
  {
3293
3370
  id: inputId,
3294
3371
  type: "number",
@@ -3305,7 +3382,7 @@ function FieldControl({ field, value, onChange, disabled, id, autoOpen, onClose,
3305
3382
  case "phone":
3306
3383
  case "url":
3307
3384
  return /* @__PURE__ */ jsx16(
3308
- BasicInput6,
3385
+ BasicInput5,
3309
3386
  {
3310
3387
  id: inputId,
3311
3388
  type: kind === "email" ? "email" : kind === "phone" ? "tel" : "url",
@@ -3330,7 +3407,7 @@ function FieldControl({ field, value, onChange, disabled, id, autoOpen, onClose,
3330
3407
  }
3331
3408
  return /* @__PURE__ */ jsx16(RelationPicker, { field, value, onChange, disabled, id: inputId });
3332
3409
  case "relation":
3333
- return /* @__PURE__ */ jsx16(RelationPicker, { field, value, onChange, disabled, id: inputId, onPicked: onCommit });
3410
+ return /* @__PURE__ */ jsx16(RelationPicker, { field, value, onChange, disabled, id: inputId, onPicked: onCommit, autoOpen, onClose });
3334
3411
  default:
3335
3412
  if (typeof value === "boolean" || field.config?.["kind"] === "boolean") {
3336
3413
  return /* @__PURE__ */ jsx16(
@@ -3344,7 +3421,7 @@ function FieldControl({ field, value, onChange, disabled, id, autoOpen, onClose,
3344
3421
  );
3345
3422
  }
3346
3423
  return /* @__PURE__ */ jsx16(
3347
- BasicInput6,
3424
+ BasicInput5,
3348
3425
  {
3349
3426
  id: inputId,
3350
3427
  ...ownDetails && isPersonsName(field) ? { autoComplete: "name" } : {},
@@ -3358,7 +3435,7 @@ function FieldControl({ field, value, onChange, disabled, id, autoOpen, onClose,
3358
3435
  function TypedWordsControl({ field, value, onChange, disabled, id }) {
3359
3436
  const [text, setText] = useState14(() => openingText(field, value));
3360
3437
  const [refusal2, setRefusal] = useState14(null);
3361
- const sent = useRef9(value);
3438
+ const sent = useRef11(value);
3362
3439
  useEffect10(() => {
3363
3440
  if (value === sent.current) return;
3364
3441
  sent.current = value;
@@ -3380,7 +3457,7 @@ function TypedWordsControl({ field, value, onChange, disabled, id }) {
3380
3457
  return /* @__PURE__ */ jsxs14("span", { className: "flex flex-col gap-0.5", children: [
3381
3458
  /* @__PURE__ */ jsxs14("span", { className: "flex min-w-0 items-center gap-0.5", children: [
3382
3459
  /* @__PURE__ */ jsx16(
3383
- BasicInput6,
3460
+ BasicInput5,
3384
3461
  {
3385
3462
  id,
3386
3463
  value: text,
@@ -3414,10 +3491,10 @@ function CheckboxControl({ field, value, onChange, disabled, id }) {
3414
3491
  onCheckedChange: (next) => onChange(next === true)
3415
3492
  }
3416
3493
  ),
3417
- unanswered ? /* @__PURE__ */ jsx16("span", { className: "text-xs italic text-muted-foreground", children: "not answered yet" }) : /* @__PURE__ */ jsxs14(Fragment4, { children: [
3494
+ unanswered ? /* @__PURE__ */ jsx16("span", { className: "text-xs italic text-muted-foreground", children: "not answered yet" }) : /* @__PURE__ */ jsxs14(Fragment5, { children: [
3418
3495
  /* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground", children: value === true ? "Yes" : "No" }),
3419
3496
  field.required ? null : /* @__PURE__ */ jsx16(
3420
- Button8,
3497
+ Button7,
3421
3498
  {
3422
3499
  size: "sm",
3423
3500
  variant: "ghost",
@@ -3516,7 +3593,7 @@ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose
3516
3593
  if (!client) {
3517
3594
  return /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
3518
3595
  /* @__PURE__ */ jsx16(
3519
- BasicInput6,
3596
+ BasicInput5,
3520
3597
  {
3521
3598
  id,
3522
3599
  value: value === null || value === void 0 ? "" : String(value),
@@ -3578,7 +3655,7 @@ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose
3578
3655
  const chosen = options.filter((option) => choiceValuesOf(value).some((v) => isTheChosen(option, v)));
3579
3656
  const picked = new Set(chosen.map((option) => optionKey2(option)));
3580
3657
  const toggles = /* @__PURE__ */ jsx16("div", { id: autoOpen ? void 0 : id, className: "flex flex-wrap gap-1", children: options.map((option) => /* @__PURE__ */ jsx16(
3581
- Button8,
3658
+ Button7,
3582
3659
  {
3583
3660
  type: "button",
3584
3661
  size: "sm",
@@ -3596,15 +3673,15 @@ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose
3596
3673
  )) });
3597
3674
  if (!autoOpen) return toggles;
3598
3675
  return /* @__PURE__ */ jsxs14(
3599
- Popover4,
3676
+ Popover3,
3600
3677
  {
3601
3678
  defaultOpen: true,
3602
3679
  onOpenChange: (open) => {
3603
3680
  if (!open) onClose?.();
3604
3681
  },
3605
3682
  children: [
3606
- /* @__PURE__ */ jsx16(PopoverTrigger4, { asChild: true, children: /* @__PURE__ */ jsx16(Button8, { id, type: "button", size: "sm", variant: "outline", className: "h-6 max-w-full truncate", children: chosen.length === 0 ? "Choose" : chosen.map(titleOf).join(", ") }) }),
3607
- /* @__PURE__ */ jsx16(PopoverContent4, { sizing: "content", className: "max-w-[20rem] p-2", align: "start", children: toggles })
3683
+ /* @__PURE__ */ jsx16(PopoverTrigger3, { asChild: true, children: /* @__PURE__ */ jsx16(Button7, { id, type: "button", size: "sm", variant: "outline", className: "h-6 max-w-full truncate", children: chosen.length === 0 ? "Choose" : chosen.map(titleOf).join(", ") }) }),
3684
+ /* @__PURE__ */ jsx16(PopoverContent3, { sizing: "content", className: "max-w-[20rem] p-2", align: "start", children: toggles })
3608
3685
  ]
3609
3686
  }
3610
3687
  );
@@ -3647,9 +3724,9 @@ function OpenChoicePicker({
3647
3724
  const client = useOptionalRecordsClient7();
3648
3725
  const nudge = useChoiceNudge();
3649
3726
  const [open, setOpenState] = useState14(autoOpen === true);
3650
- const onCloseRef = useRef9(onClose);
3727
+ const onCloseRef = useRef11(onClose);
3651
3728
  onCloseRef.current = onClose;
3652
- const setOpen = useCallback4((next) => {
3729
+ const setOpen = useCallback5((next) => {
3653
3730
  setOpenState(next);
3654
3731
  if (!next) onCloseRef.current?.();
3655
3732
  }, []);
@@ -3707,7 +3784,9 @@ function OpenChoicePicker({
3707
3784
  });
3708
3785
  };
3709
3786
  const offList = q !== "" && decided.decision !== "chosen" && decided.decision !== "empty";
3710
- const foot = offList && decided.decision === "ask" ? /* @__PURE__ */ jsx16(
3787
+ const [askingFor, setAskingFor] = useState14(null);
3788
+ const asks = offList && decided.decision === "ask" && (visible.length === 0 || askingFor === q);
3789
+ const foot = asks ? /* @__PURE__ */ jsx16(
3711
3790
  ChoiceAskButtons,
3712
3791
  {
3713
3792
  field,
@@ -3723,17 +3802,36 @@ function OpenChoicePicker({
3723
3802
  }
3724
3803
  }
3725
3804
  ) : null;
3726
- const add = offList && decided.decision === "add" ? { label: `Add \u201C${q}\u201D to the choices`, onAdd: addTyped, disabled: adding } : offList && decided.decision === "keep_as_typed" ? { label: `Keep \u201C${q}\u201D as typed`, onAdd: () => choose(q) } : null;
3805
+ const add = offList && decided.decision === "ask" && !asks ? { label: `Add \u201C${q}\u201D\u2026`, onAdd: () => setAskingFor(q) } : offList && decided.decision === "add" ? { label: `Add \u201C${q}\u201D to the choices`, onAdd: addTyped, disabled: adding } : offList && decided.decision === "keep_as_typed" ? { label: `Keep \u201C${q}\u201D as typed`, onAdd: () => choose(q) } : null;
3806
+ const pickedOptions = current.map((v) => options.find((o) => isTheChosen(o, v)));
3807
+ const cellChips = pickedWords.map((word, i) => {
3808
+ const chip = chipOf(pickedOptions[i], word);
3809
+ return /* @__PURE__ */ jsx16(Badge3, { variant: "outline", className: cn12("text-[11px]", chip.className), "data-records-choice-chip": "", children: word }, word);
3810
+ });
3811
+ const headChips = pickedWords.map((word, i) => {
3812
+ const option = pickedOptions[i];
3813
+ return {
3814
+ id: `${word}-${i}`,
3815
+ label: word,
3816
+ chip: chipOf(option, word).className,
3817
+ onRemove: () => {
3818
+ if (field.multi) choose(option ? optionKey2(option) : String(current[i]));
3819
+ else onChange(null);
3820
+ }
3821
+ };
3822
+ });
3823
+ const anchored = autoOpen === true;
3727
3824
  return /* @__PURE__ */ jsxs14("div", { id, className: "flex flex-wrap items-center gap-1", children: [
3728
- pickedWords.map((word, i) => {
3729
- const chip = chipOf(options.find((o) => isTheChosen(o, current[i])), word);
3730
- return /* @__PURE__ */ jsx16(Badge3, { variant: "outline", className: cn12("text-[11px]", chip.className), "data-records-choice-chip": "", children: word }, word);
3731
- }),
3732
- disabled ? null : (
3825
+ anchored || disabled ? null : cellChips,
3826
+ disabled ? cellChips : (
3733
3827
  // THE ONE "PICK OR ADD" BUILDER (PickOrAdd.tsx) — the relation picker draws the same one.
3828
+ // In a grid cell it hangs from the cell's own chips; no button is drawn in the cell.
3734
3829
  /* @__PURE__ */ jsx16(
3735
3830
  PickOrAdd,
3736
3831
  {
3832
+ anchored,
3833
+ chips: headChips,
3834
+ multi: field.multi,
3737
3835
  triggerLabel: `Pick for ${fieldName(field)}`,
3738
3836
  triggerText: pickedWords.length === 0 ? "Choose" : "Change",
3739
3837
  open,
@@ -3742,6 +3840,7 @@ function OpenChoicePicker({
3742
3840
  onSearch: (next) => {
3743
3841
  setSearch(next);
3744
3842
  setAddRefused(null);
3843
+ setAskingFor(null);
3745
3844
  },
3746
3845
  items: visible.map((option) => ({
3747
3846
  id: option.id,
@@ -3756,14 +3855,15 @@ function OpenChoicePicker({
3756
3855
  empty: q === "" ? /* @__PURE__ */ jsx16("p", { className: "p-2 text-xs text-muted-foreground", children: "No choices yet \u2014 type one to add it." }) : null,
3757
3856
  add,
3758
3857
  foot,
3759
- ...offList && decided.decision === "ask" && !adding ? { onEnterWithNoMatch: addTyped } : {},
3858
+ ...asks && !adding ? { onEnterWithNoMatch: addTyped } : {},
3760
3859
  footNote: addRefused ? /* @__PURE__ */ jsx16(RefusalLine, { error: addRefused }) : offList && decided.decision === "not_a_choice" ? (
3761
3860
  // never_add on a column that takes only its choices: said, never a silent nothing.
3762
- /* @__PURE__ */ jsxs14(Fragment4, { children: [
3861
+ /* @__PURE__ */ jsxs14(Fragment5, { children: [
3763
3862
  /* @__PURE__ */ jsx16("p", { "data-records-typed-refusal": "", className: "p-2 text-xs text-muted-foreground", children: notAChoiceSentence(field, [q]) }),
3764
- autoOpen ? /* @__PURE__ */ jsx16("span", { "data-records-choice-ask": "", className: "px-2 pb-1", children: /* @__PURE__ */ jsx16(Button8, { type: "button", size: "sm", variant: "ghost", className: "h-6 px-2 text-xs", onClick: () => setOpen(false), children: "Cancel" }) }) : null
3863
+ autoOpen ? /* @__PURE__ */ jsx16("span", { "data-records-choice-ask": "", className: "px-2 pb-1", children: /* @__PURE__ */ jsx16(Button7, { type: "button", size: "sm", variant: "ghost", className: "h-6 px-2 text-xs", onClick: () => setOpen(false), children: "Cancel" }) }) : null
3765
3864
  ] })
3766
- ) : null
3865
+ ) : null,
3866
+ children: anchored ? cellChips : null
3767
3867
  }
3768
3868
  )
3769
3869
  )
@@ -3869,7 +3969,7 @@ function ChoiceAnswer({
3869
3969
  const shown2 = q === "" ? choices : choices.filter((c) => c.label.toLowerCase().includes(q));
3870
3970
  return /* @__PURE__ */ jsxs14("div", { id, className: "flex w-full flex-col gap-2", onKeyDown, children: [
3871
3971
  /* @__PURE__ */ jsx16(
3872
- BasicInput6,
3972
+ BasicInput5,
3873
3973
  {
3874
3974
  value: search,
3875
3975
  onChange: (e) => setSearch(e.target.value),
@@ -3887,7 +3987,7 @@ function ChoiceAnswer({
3887
3987
  }
3888
3988
 
3889
3989
  // src/RecordsMount.tsx
3890
- import { useRef as useRef10 } from "react";
3990
+ import { useRef as useRef12 } from "react";
3891
3991
  import { RecordsProvider } from "@ai-matrx/records/react";
3892
3992
  import { jsx as jsx17 } from "react/jsx-runtime";
3893
3993
  function personActor(userId) {
@@ -3895,7 +3995,7 @@ function personActor(userId) {
3895
3995
  }
3896
3996
 
3897
3997
  // src/tablePicking.tsx
3898
- import { useCallback as useCallback5, useEffect as useEffect11, useMemo as useMemo6, useState as useState15 } from "react";
3998
+ import { useCallback as useCallback6, useEffect as useEffect11, useMemo as useMemo6, useState as useState15 } from "react";
3899
3999
  import { withTablePlacement } from "@ai-matrx/records";
3900
4000
  import { useRecordsClient as useRecordsClient2, useTables } from "@ai-matrx/records/react";
3901
4001
  import { Checkbox as Checkbox2, cn as cn13 } from "@ai-matrx/design-system";
@@ -3942,7 +4042,7 @@ function madeOn(stamp) {
3942
4042
  }
3943
4043
 
3944
4044
  // src/TablePickers.tsx
3945
- import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
4045
+ import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
3946
4046
  var SHARED_FOR_MS = 5e3;
3947
4047
  var sharedReads = /* @__PURE__ */ new WeakMap();
3948
4048
  function readTablesAnywhere(dataSource) {
@@ -4043,8 +4143,8 @@ function TableScope({ dataSource, userId, tableId, children, fallback = null, un
4043
4143
  const own3 = useTablesAnywhere(dataSource);
4044
4144
  const list = tables ?? own3;
4045
4145
  const organizationId = list.rows.find((t) => t.table_id === tableId)?.organization_id ?? null;
4046
- if (tableId && !organizationId && !list.loading) return /* @__PURE__ */ jsx19(Fragment5, { children: unavailable ?? fallback });
4047
- if (!tableId || !organizationId) return /* @__PURE__ */ jsx19(Fragment5, { children: fallback });
4146
+ if (tableId && !organizationId && !list.loading) return /* @__PURE__ */ jsx19(Fragment6, { children: unavailable ?? fallback });
4147
+ if (!tableId || !organizationId) return /* @__PURE__ */ jsx19(Fragment6, { children: fallback });
4048
4148
  return /* @__PURE__ */ jsx19(RecordsProvider2, { config: { dataSource, actor: personActor(userId), organizationId }, children });
4049
4149
  }
4050
4150
  function ColumnValuesEditor({ tableId, value, onChange, disabled, addLabel }) {
@@ -4102,7 +4202,7 @@ function ColumnValuesEditor({ tableId, value, onChange, disabled, addLabel }) {
4102
4202
  onRemove: () => setAdding(false)
4103
4203
  }
4104
4204
  ),
4105
- !disabled && !adding && keys.length < all.length && /* @__PURE__ */ jsx19(Button9, { type: "button", variant: "outline", size: "sm", className: "self-start", onClick: () => setAdding(true), children: addLabel })
4205
+ !disabled && !adding && keys.length < all.length && /* @__PURE__ */ jsx19(Button8, { type: "button", variant: "outline", size: "sm", className: "self-start", onClick: () => setAdding(true), children: addLabel })
4106
4206
  ] });
4107
4207
  }
4108
4208
  function ColumnValueRow({
@@ -4134,7 +4234,7 @@ function ColumnValueRow({
4134
4234
  ariaLabel: "Column"
4135
4235
  }
4136
4236
  ) }),
4137
- !disabled && /* @__PURE__ */ jsx19(Button9, { type: "button", variant: "ghost", size: "sm", "aria-label": "Remove", onClick: onRemove, children: "\u2715" })
4237
+ !disabled && /* @__PURE__ */ jsx19(Button8, { type: "button", variant: "ghost", size: "sm", "aria-label": "Remove", onClick: onRemove, children: "\u2715" })
4138
4238
  ] }),
4139
4239
  field ? /* @__PURE__ */ jsx19(FieldControl, { field, value, onChange: onValue, disabled }) : orphan ? /* @__PURE__ */ jsx19("p", { className: "text-[11px] text-muted-foreground", children: value === null || value === void 0 ? "\u2014" : String(value) }) : null
4140
4240
  ] });
@@ -4171,7 +4271,7 @@ function RecordPicker({ tableId, value, onChange, disabled }) {
4171
4271
  import { useEffect as useEffect13, useMemo as useMemo8 } from "react";
4172
4272
  import { isEntityReferenceConfig } from "@ai-matrx/records";
4173
4273
  import { useFields as useFields2, useTable as useTable2 } from "@ai-matrx/records/react";
4174
- import { BasicInput as BasicInput7, Button as Button10, CreatablePicker as CreatablePicker2, cn as cn14 } from "@ai-matrx/design-system";
4274
+ import { BasicInput as BasicInput6, Button as Button9, CreatablePicker as CreatablePicker2, cn as cn14 } from "@ai-matrx/design-system";
4175
4275
  import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
4176
4276
  var DATA_BINDING_SHAPES = [
4177
4277
  { value: "collection", label: "The whole table" },
@@ -4307,7 +4407,7 @@ function BindingDetails({
4307
4407
  const setTemplate = (next) => onChange({ ...binding, transform: { join: "\n", ...binding.transform, name: "list", template: next } });
4308
4408
  return /* @__PURE__ */ jsxs17("div", { className: "flex flex-col gap-2", children: [
4309
4409
  /* @__PURE__ */ jsx20("div", { className: "flex flex-wrap gap-1", role: "radiogroup", "aria-label": "What to read", children: DATA_BINDING_SHAPES.map((s) => /* @__PURE__ */ jsx20(
4310
- Button10,
4410
+ Button9,
4311
4411
  {
4312
4412
  type: "button",
4313
4413
  size: "sm",
@@ -4357,7 +4457,7 @@ function BindingDetails({
4357
4457
  }
4358
4458
  ),
4359
4459
  !disabled && /* @__PURE__ */ jsx20("div", { className: "flex flex-wrap gap-1", children: fieldList.flatMap(bindingPlaceholdersFor).map((p) => /* @__PURE__ */ jsx20(
4360
- Button10,
4460
+ Button9,
4361
4461
  {
4362
4462
  type: "button",
4363
4463
  size: "sm",
@@ -4372,7 +4472,7 @@ function BindingDetails({
4372
4472
  shape === "collection" && /* @__PURE__ */ jsxs17("label", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
4373
4473
  "Up to",
4374
4474
  /* @__PURE__ */ jsx20(
4375
- BasicInput7,
4475
+ BasicInput6,
4376
4476
  {
4377
4477
  type: "number",
4378
4478
  min: 1,
@@ -4391,7 +4491,7 @@ function BindingDetails({
4391
4491
  /* @__PURE__ */ jsxs17("div", { className: "flex flex-wrap items-center gap-1", role: "radiogroup", "aria-label": "If nothing is found", children: [
4392
4492
  /* @__PURE__ */ jsx20("span", { className: "text-xs text-muted-foreground", children: "If nothing is found" }),
4393
4493
  DATA_BINDING_MISSING.map((m) => /* @__PURE__ */ jsx20(
4394
- Button10,
4494
+ Button9,
4395
4495
  {
4396
4496
  type: "button",
4397
4497
  size: "sm",
@@ -4664,7 +4764,7 @@ function formulaSourceArchived(field, document2) {
4664
4764
 
4665
4765
  // src/values.tsx
4666
4766
  import { newerKindWords, sourceArchivedOf as sourceArchivedOf2 } from "@ai-matrx/records";
4667
- import { Fragment as Fragment6, jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
4767
+ import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
4668
4768
  function statusMark(field, item, document2) {
4669
4769
  const mark = statusMarkOf(field, item, document2);
4670
4770
  return mark ? /* @__PURE__ */ jsx23("span", { "aria-label": mark.words, title: mark.words, className: "mr-1", "data-records-status-group": mark.group, children: mark.mark }) : null;
@@ -4860,13 +4960,13 @@ function scalarText(field, value, labels, stillWaitingFor) {
4860
4960
  }
4861
4961
 
4862
4962
  // src/PickedSummaries.tsx
4863
- import { Fragment as Fragment7, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
4963
+ import { Fragment as Fragment8, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
4864
4964
  function TableNameText({ dataSource, tableId }) {
4865
4965
  const tables = useTablesAnywhere(dataSource);
4866
- if (!tableId) return /* @__PURE__ */ jsx24(Fragment7, { children: "\u2014" });
4867
- if (tables.loading) return /* @__PURE__ */ jsx24(Fragment7, { children: "\u2026" });
4868
- if (tables.error) return /* @__PURE__ */ jsx24(Fragment7, { children: "Couldn't load the table's name" });
4869
- return /* @__PURE__ */ jsx24(Fragment7, { children: tables.rows.find((t) => t.table_id === tableId)?.table_name ?? "\u2014" });
4966
+ if (!tableId) return /* @__PURE__ */ jsx24(Fragment8, { children: "\u2014" });
4967
+ if (tables.loading) return /* @__PURE__ */ jsx24(Fragment8, { children: "\u2026" });
4968
+ if (tables.error) return /* @__PURE__ */ jsx24(Fragment8, { children: "Couldn't load the table's name" });
4969
+ return /* @__PURE__ */ jsx24(Fragment8, { children: tables.rows.find((t) => t.table_id === tableId)?.table_name ?? "\u2014" });
4870
4970
  }
4871
4971
  function ColumnValuesText({
4872
4972
  dataSource,
@@ -4874,15 +4974,15 @@ function ColumnValuesText({
4874
4974
  tableId,
4875
4975
  value
4876
4976
  }) {
4877
- if (!tableId) return /* @__PURE__ */ jsx24(Fragment7, { children: "\u2014" });
4977
+ if (!tableId) return /* @__PURE__ */ jsx24(Fragment8, { children: "\u2014" });
4878
4978
  return /* @__PURE__ */ jsx24(
4879
4979
  TableScope,
4880
4980
  {
4881
4981
  dataSource,
4882
4982
  userId,
4883
4983
  tableId,
4884
- fallback: /* @__PURE__ */ jsx24(Fragment7, { children: "\u2026" }),
4885
- unavailable: /* @__PURE__ */ jsx24(Fragment7, { children: "Couldn't load this table's columns" }),
4984
+ fallback: /* @__PURE__ */ jsx24(Fragment8, { children: "\u2026" }),
4985
+ unavailable: /* @__PURE__ */ jsx24(Fragment8, { children: "Couldn't load this table's columns" }),
4886
4986
  children: /* @__PURE__ */ jsx24(RecordLabelProvider, { children: /* @__PURE__ */ jsx24(ColumnValuesWords, { tableId, value }) })
4887
4987
  }
4888
4988
  );
@@ -4890,8 +4990,8 @@ function ColumnValuesText({
4890
4990
  function ColumnValuesWords({ tableId, value }) {
4891
4991
  const fields = useFields3(tableId);
4892
4992
  const labels = useRecordLabels(fields.data ?? void 0);
4893
- if (fields.loading) return /* @__PURE__ */ jsx24(Fragment7, { children: "\u2026" });
4894
- if (fields.error) return /* @__PURE__ */ jsx24(Fragment7, { children: "Couldn't load this table's columns" });
4993
+ if (fields.loading) return /* @__PURE__ */ jsx24(Fragment8, { children: "\u2026" });
4994
+ if (fields.error) return /* @__PURE__ */ jsx24(Fragment8, { children: "Couldn't load this table's columns" });
4895
4995
  const parts = [];
4896
4996
  for (const [key, stored] of Object.entries(value)) {
4897
4997
  if (key.startsWith("_")) continue;
@@ -4905,7 +5005,7 @@ function ColumnValuesWords({ tableId, value }) {
4905
5005
  ] }, key)
4906
5006
  );
4907
5007
  }
4908
- return parts.length ? /* @__PURE__ */ jsx24(Fragment7, { children: parts }) : /* @__PURE__ */ jsx24(Fragment7, { children: "\u2014" });
5008
+ return parts.length ? /* @__PURE__ */ jsx24(Fragment8, { children: parts }) : /* @__PURE__ */ jsx24(Fragment8, { children: "\u2014" });
4909
5009
  }
4910
5010
  function RecordNameText({
4911
5011
  dataSource,
@@ -4913,15 +5013,15 @@ function RecordNameText({
4913
5013
  tableId,
4914
5014
  recordId
4915
5015
  }) {
4916
- if (!tableId || !recordId) return /* @__PURE__ */ jsx24(Fragment7, { children: "\u2014" });
5016
+ if (!tableId || !recordId) return /* @__PURE__ */ jsx24(Fragment8, { children: "\u2014" });
4917
5017
  return /* @__PURE__ */ jsx24(
4918
5018
  TableScope,
4919
5019
  {
4920
5020
  dataSource,
4921
5021
  userId,
4922
5022
  tableId,
4923
- fallback: /* @__PURE__ */ jsx24(Fragment7, { children: "\u2026" }),
4924
- unavailable: /* @__PURE__ */ jsx24(Fragment7, { children: "Couldn't load this record" }),
5023
+ fallback: /* @__PURE__ */ jsx24(Fragment8, { children: "\u2026" }),
5024
+ unavailable: /* @__PURE__ */ jsx24(Fragment8, { children: "Couldn't load this record" }),
4925
5025
  children: /* @__PURE__ */ jsx24(RecordNameWords, { tableId, recordId })
4926
5026
  }
4927
5027
  );
@@ -4929,16 +5029,16 @@ function RecordNameText({
4929
5029
  function RecordNameWords({ tableId, recordId }) {
4930
5030
  const table = useTable3(tableId);
4931
5031
  const record = useRecord(recordId);
4932
- if (record.loading || table.loading) return /* @__PURE__ */ jsx24(Fragment7, { children: "\u2026" });
4933
- if (record.error) return /* @__PURE__ */ jsx24(Fragment7, { children: "Couldn't load this record" });
4934
- if (!record.data) return /* @__PURE__ */ jsx24(Fragment7, { children: "A record you cannot open" });
4935
- return /* @__PURE__ */ jsx24(Fragment7, { children: recordName(record.data.document, table.data?.title_field ?? null) });
5032
+ if (record.loading || table.loading) return /* @__PURE__ */ jsx24(Fragment8, { children: "\u2026" });
5033
+ if (record.error) return /* @__PURE__ */ jsx24(Fragment8, { children: "Couldn't load this record" });
5034
+ if (!record.data) return /* @__PURE__ */ jsx24(Fragment8, { children: "A record you cannot open" });
5035
+ return /* @__PURE__ */ jsx24(Fragment8, { children: recordName(record.data.document, table.data?.title_field ?? null) });
4936
5036
  }
4937
5037
 
4938
5038
  // src/HeldChangeDecision.tsx
4939
5039
  import { useEffect as useEffect15, useState as useState18 } from "react";
4940
5040
  import { RecordsProvider as RecordsProvider3, useRecordsClient as useRecordsClient3 } from "@ai-matrx/records/react";
4941
- import { Button as Button11 } from "@ai-matrx/design-system";
5041
+ import { Button as Button10 } from "@ai-matrx/design-system";
4942
5042
  import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
4943
5043
  function HeldChangeDecision({ dataSource, userId, organizationId, approvalId, onDecided }) {
4944
5044
  return /* @__PURE__ */ jsx25(RecordsProvider3, { config: { dataSource, actor: personActor(userId), organizationId }, children: /* @__PURE__ */ jsx25(Decision, { approvalId, onDecided }) });
@@ -4973,8 +5073,8 @@ function Decision({ approvalId, onDecided }) {
4973
5073
  if (may === null) return /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted-foreground", children: "Checking who can decide\u2026" });
4974
5074
  return /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-1.5", children: [
4975
5075
  may ? /* @__PURE__ */ jsxs22("div", { className: "flex gap-2", children: [
4976
- /* @__PURE__ */ jsx25(Button11, { type: "button", size: "sm", disabled: busy !== null, onClick: () => void decide(true), children: busy === "approve" ? "Approving\u2026" : "Approve" }),
4977
- /* @__PURE__ */ jsx25(Button11, { type: "button", size: "sm", variant: "outline", disabled: busy !== null, onClick: () => void decide(false), children: busy === "refuse" ? "Refusing\u2026" : "Refuse" })
5076
+ /* @__PURE__ */ jsx25(Button10, { type: "button", size: "sm", disabled: busy !== null, onClick: () => void decide(true), children: busy === "approve" ? "Approving\u2026" : "Approve" }),
5077
+ /* @__PURE__ */ jsx25(Button10, { type: "button", size: "sm", variant: "outline", disabled: busy !== null, onClick: () => void decide(false), children: busy === "refuse" ? "Refusing\u2026" : "Refuse" })
4978
5078
  ] }) : !error && /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted-foreground", children: "An owner or admin of this organization decides this." }),
4979
5079
  error ? /* @__PURE__ */ jsx25(RefusalLine, { error }) : null
4980
5080
  ] });