@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/CHANGELOG.md +21 -0
- package/dist/index.cjs +5408 -4398
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +91 -4
- package/dist/index.d.ts +91 -4
- package/dist/index.js +5054 -4048
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs +261 -153
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js +371 -271
- package/dist/pickers.js.map +1 -1
- package/package.json +5 -4
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
|
|
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
|
|
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
|
|
47
|
+
BasicInput as BasicInput5,
|
|
48
48
|
BasicTextarea as BasicTextarea2,
|
|
49
49
|
Badge as Badge3,
|
|
50
|
-
Button as
|
|
50
|
+
Button as Button7,
|
|
51
51
|
Checkbox,
|
|
52
52
|
Label,
|
|
53
|
-
Popover as
|
|
54
|
-
PopoverContent as
|
|
55
|
-
PopoverTrigger as
|
|
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
|
-
|
|
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 (
|
|
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
|
|
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
|
|
703
|
+
count,
|
|
606
704
|
resetOn: search,
|
|
607
705
|
onPick: (index) => {
|
|
608
706
|
const item = items[index];
|
|
609
|
-
if (item)
|
|
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
|
-
|
|
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) =>
|
|
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-
|
|
748
|
+
className: "mb-1 h-8 text-sm"
|
|
636
749
|
}
|
|
637
750
|
),
|
|
638
751
|
notice,
|
|
639
|
-
/* @__PURE__ */ jsxs2(ScrollArea, { className: "max-h-
|
|
640
|
-
/* @__PURE__ */
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
item.
|
|
651
|
-
index === keys.highlight
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
1464
|
-
const drawing =
|
|
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 =
|
|
1641
|
-
const chased =
|
|
1642
|
-
const timers =
|
|
1643
|
-
const startWaitClock =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
1711
|
-
const flushing =
|
|
1712
|
-
const flush =
|
|
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 =
|
|
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 =
|
|
1762
|
-
const lookupWords =
|
|
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 =
|
|
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
|
|
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 =
|
|
1938
|
+
const input = useRef6(null);
|
|
1820
1939
|
const [over, setOver] = useState6(false);
|
|
1821
|
-
const take =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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 =
|
|
2480
|
+
const onCloseRef = useRef8(onClose);
|
|
2370
2481
|
onCloseRef.current = onClose;
|
|
2371
|
-
const setOpen =
|
|
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 =
|
|
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
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
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
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
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
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
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
|
|
2612
|
-
import { BasicInput as
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
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(
|
|
2932
|
-
/* @__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
|
-
|
|
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
|
|
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(
|
|
3077
|
-
keepOffered ? /* @__PURE__ */ jsx16(
|
|
3078
|
-
/* @__PURE__ */ jsx16(
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
3607
|
-
/* @__PURE__ */ jsx16(
|
|
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 =
|
|
3727
|
+
const onCloseRef = useRef11(onClose);
|
|
3651
3728
|
onCloseRef.current = onClose;
|
|
3652
|
-
const setOpen =
|
|
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
|
|
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
|
-
|
|
3729
|
-
|
|
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
|
-
...
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
4047
|
-
if (!tableId || !organizationId) return /* @__PURE__ */ jsx19(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
4867
|
-
if (tables.loading) return /* @__PURE__ */ jsx24(
|
|
4868
|
-
if (tables.error) return /* @__PURE__ */ jsx24(
|
|
4869
|
-
return /* @__PURE__ */ jsx24(
|
|
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(
|
|
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(
|
|
4885
|
-
unavailable: /* @__PURE__ */ jsx24(
|
|
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(
|
|
4894
|
-
if (fields.error) return /* @__PURE__ */ jsx24(
|
|
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(
|
|
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(
|
|
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(
|
|
4924
|
-
unavailable: /* @__PURE__ */ jsx24(
|
|
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(
|
|
4933
|
-
if (record.error) return /* @__PURE__ */ jsx24(
|
|
4934
|
-
if (!record.data) return /* @__PURE__ */ jsx24(
|
|
4935
|
-
return /* @__PURE__ */ jsx24(
|
|
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
|
|
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(
|
|
4977
|
-
/* @__PURE__ */ jsx25(
|
|
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
|
] });
|