@ai-matrx/records-ui 0.115.34 → 0.115.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/pickers.cjs CHANGED
@@ -52,9 +52,9 @@ var askOnce_exports = {};
52
52
  __reExport(askOnce_exports, require("@ai-matrx/records/versions"));
53
53
 
54
54
  // src/AddChoicesInline.tsx
55
- var import_react3 = require("react");
56
- var import_react4 = require("@ai-matrx/records/react");
57
- var import_design_system2 = require("@ai-matrx/design-system");
55
+ var import_react6 = require("react");
56
+ var import_react7 = require("@ai-matrx/records/react");
57
+ var import_design_system4 = require("@ai-matrx/design-system");
58
58
 
59
59
  // src/ChoiceListEditor.tsx
60
60
  var import_react = require("react");
@@ -576,14 +576,285 @@ function ChoiceSwatch({ words, color, onColor }) {
576
576
  ] });
577
577
  }
578
578
 
579
- // src/AddChoicesInline.tsx
579
+ // src/Refusal.tsx
580
+ var import_core = require("@ai-matrx/records/core");
581
+ var import_design_system3 = require("@ai-matrx/design-system");
582
+
583
+ // src/ArchivedOrganizationNotice.tsx
584
+ var import_react5 = require("react");
585
+ var import_design_system2 = require("@ai-matrx/design-system");
586
+
587
+ // src/host.tsx
588
+ var import_react3 = require("react");
589
+ var import_react4 = require("@ai-matrx/records/react");
590
+
591
+ // src/rights.ts
592
+ var import_records3 = require("@ai-matrx/records");
593
+ var LEVEL_WORD = {
594
+ viewer: "Viewer",
595
+ commenter: "Commenter",
596
+ edit_content: "Content editor",
597
+ editor: "Editor",
598
+ admin: "Admin"
599
+ };
600
+ var NEEDS = {
601
+ read: "viewer",
602
+ // custom.io_comment_write
603
+ comment: "commenter",
604
+ // custom.record_update / custom.record_write — `edit_content` changes rows and page content;
605
+ // columns, views and settings (structure) stay with admin below, and sharing with admin.
606
+ write: "edit_content",
607
+ // custom.view_designate / view_declare / migrate_merge / record_restore — all ask `editor`: more than
608
+ // changing content (`edit_content`), less than changing columns (`admin`).
609
+ organise: "editor",
610
+ // custom.record_delete
611
+ remove: "editor",
612
+ // custom.share_grant — passing your access on is an administrator's right
613
+ share: "admin",
614
+ // custom.field_declare / field_update / field_retire / table settings
615
+ structure: "admin"
616
+ };
617
+ var NOT_YET = "Still asking the store what you may do here. Nothing is offered until it has answered.";
618
+ var NOTHING_AT_ALL = "You have not been given this. Ask somebody who administers it to share it with you.";
619
+ function sentenceFor(what, level) {
620
+ if (level === null) return NOTHING_AT_ALL;
621
+ const need = LEVEL_WORD[NEEDS[what]];
622
+ const have = LEVEL_WORD[level];
623
+ const doing = {
624
+ read: "open this",
625
+ comment: "leave a comment",
626
+ write: "change anything here",
627
+ organise: "organise this",
628
+ remove: "delete this",
629
+ share: "pass this on to somebody else",
630
+ structure: "change the columns of this table"
631
+ };
632
+ return `You are ${have} here, and it takes ${need} to ${doing[what]}. Ask somebody who is Admin on it to move you up.`;
633
+ }
634
+ function whatYouMayDo(level, known = true) {
635
+ const may = (what) => known && (0, import_records3.atLeast)(level, NEEDS[what]);
636
+ return {
637
+ level: known ? level : null,
638
+ known,
639
+ read: may("read"),
640
+ comment: may("comment"),
641
+ write: may("write"),
642
+ organise: may("organise"),
643
+ remove: may("remove"),
644
+ share: may("share"),
645
+ structure: may("structure"),
646
+ why: (what) => known ? sentenceFor(what, level) : NOT_YET
647
+ };
648
+ }
649
+ var NOT_ANSWERED_YET = whatYouMayDo(null, false);
650
+ var KERNEL_REASON = "This is one of the tables the platform ships, so its columns are not changed from a screen. Make your own table to change columns.";
651
+ function whatYouMayDoWithTable(table, level, known) {
652
+ const base = whatYouMayDo(level, known);
653
+ if (!table?.is_kernel) return table && tableIsLocked(table) ? lockedStructure(base) : base;
654
+ return {
655
+ ...base,
656
+ structure: false,
657
+ why: (what) => what === "structure" ? KERNEL_REASON : base.why(what)
658
+ };
659
+ }
660
+ function tableIsLocked(table) {
661
+ return table?.metadata?.["locked"] === true;
662
+ }
663
+ var DATABASE_LOCKED_REASON = "This database is locked, so its columns and settings are read-only. Unlock it to change them.";
664
+ function lockedStructure(base) {
665
+ return { ...base, structure: false, why: (what) => what === "structure" ? DATABASE_LOCKED_REASON : base.why(what) };
666
+ }
667
+
668
+ // src/host.tsx
580
669
  var import_jsx_runtime2 = require("react/jsx-runtime");
670
+ function tableRights(may, overallReason) {
671
+ return {
672
+ ...may,
673
+ admin: may.structure,
674
+ reason: overallReason ?? (may.structure ? "" : may.why("structure"))
675
+ };
676
+ }
677
+ var NO_RIGHTS = tableRights(NOT_ANSWERED_YET);
678
+ var NO_MEMBERS_REASON = "This app cannot offer the people in your organization on this screen yet, so there is nobody to pick. Type the person's name into a text field for now, and tell us \u2014 it is on our list, not yours.";
679
+ var NO_UPLOAD_REASON = "This screen cannot take a file yet, so there is no chooser here rather than one that loses what you pick. Put a link to the file in a text field for now. It is on our list, not yours.";
680
+ var HostContext = (0, import_react3.createContext)(null);
681
+ function useRecordsUi() {
682
+ return (0, import_react3.useContext)(HostContext) ?? {};
683
+ }
684
+ function quiet(may, say) {
685
+ if (say !== false) return may;
686
+ return { ...may, why: () => "", ..."reason" in may ? { reason: "" } : {} };
687
+ }
688
+ function useTableRights(table) {
689
+ const host = useRecordsUi();
690
+ const asked2 = useTableRightsAsked(table, host);
691
+ return (0, import_react3.useMemo)(() => quiet(asked2, host.sayLevelNeeded), [asked2, host.sayLevelNeeded]);
692
+ }
693
+ function useTableRightsAsked(table, host) {
694
+ const bound = Boolean(host.rights);
695
+ const asked2 = (0, import_react4.useMyLevel)(bound || !table ? null : table.id);
696
+ return (0, import_react3.useMemo)(() => {
697
+ if (!table) return NO_RIGHTS;
698
+ if (host.rights) return host.rights(table);
699
+ if (asked2.loading) return tableRights(NOT_ANSWERED_YET);
700
+ const level = asked2.error ? null : asked2.data;
701
+ return tableRights(whatYouMayDoWithTable(table, level, true));
702
+ }, [host, table, bound, asked2.loading, asked2.error, asked2.data]);
703
+ }
704
+
705
+ // src/ArchivedOrganizationNotice.tsx
706
+ var import_jsx_runtime3 = require("react/jsx-runtime");
707
+ function ArchivedOrganizationNotice({
708
+ organizationId,
709
+ error,
710
+ className
711
+ }) {
712
+ const port = useRecordsUi().archivedOrganization;
713
+ const [mayRestore, setMayRestore] = (0, import_react5.useState)(null);
714
+ const [busy, setBusy] = (0, import_react5.useState)(false);
715
+ const [failed, setFailed] = (0, import_react5.useState)(null);
716
+ (0, import_react5.useEffect)(() => {
717
+ let live = true;
718
+ if (!port) {
719
+ setMayRestore(false);
720
+ return;
721
+ }
722
+ setMayRestore(null);
723
+ port.state(organizationId).then((answer) => {
724
+ if (live) setMayRestore(answer?.mayRestore === true);
725
+ }).catch(() => {
726
+ if (live) setMayRestore(false);
727
+ });
728
+ return () => {
729
+ live = false;
730
+ };
731
+ }, [organizationId, port?.state]);
732
+ const restore = async () => {
733
+ if (!port || busy) return;
734
+ setBusy(true);
735
+ setFailed(null);
736
+ try {
737
+ await port.restore(organizationId);
738
+ if (port.afterRestore) port.afterRestore();
739
+ else if (typeof window !== "undefined") window.location.reload();
740
+ } catch (thrown) {
741
+ setFailed(thrown instanceof Error && thrown.message ? thrown.message : "The organization could not be restored.");
742
+ setBusy(false);
743
+ }
744
+ };
745
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
746
+ import_design_system2.Alert,
747
+ {
748
+ variant: "destructive",
749
+ role: "alert",
750
+ "data-refusal-notice": "",
751
+ "data-archived-organization": organizationId,
752
+ className: (0, import_design_system2.cn)("text-xs", className),
753
+ errorFacts: { message: "This organization is archived", title: "This organization is archived", error, origin: "records-ui/ArchivedOrganizationNotice" },
754
+ children: [
755
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.AlertTitle, { className: "text-xs font-medium", children: "This organization is archived" }),
756
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.AlertDescription, { className: "space-y-1 text-xs", children: [
757
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "opacity-80", children: "Nothing was deleted. Everything here comes back the moment an owner of the organization, or a super admin, restores it." }),
758
+ mayRestore === true ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
759
+ "button",
760
+ {
761
+ type: "button",
762
+ "data-restore-organization": "",
763
+ disabled: busy,
764
+ className: "rounded border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-60",
765
+ onClick: () => void restore(),
766
+ children: busy ? "Restoring..." : "Restore organization"
767
+ }
768
+ ) : null,
769
+ mayRestore === false ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { "data-restore-who": "", className: "opacity-80", children: "Ask an owner of this organization to restore it." }) : null,
770
+ failed ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { "data-restore-refused": "", children: failed }) : null
771
+ ] })
772
+ ]
773
+ }
774
+ );
775
+ }
776
+
777
+ // src/Refusal.tsx
778
+ var import_jsx_runtime4 = require("react/jsx-runtime");
779
+ function RefusalNotice({
780
+ error,
781
+ className,
782
+ actions,
783
+ onKeepEditing,
784
+ onDiscard
785
+ }) {
786
+ const archivedOrg = (0, import_core.archivedOrganizationId)(error);
787
+ if (archivedOrg) {
788
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ArchivedOrganizationNotice, { organizationId: archivedOrg, error, className });
789
+ }
790
+ const plain = refusalForAPerson(error);
791
+ const doors = onKeepEditing || onDiscard ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-wrap items-center gap-1 pt-0.5", "data-refusal-doors": "", children: [
792
+ onKeepEditing ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
793
+ "button",
794
+ {
795
+ type: "button",
796
+ "data-refusal-keep-editing": "",
797
+ className: "rounded border px-2 py-0.5 text-xs hover:bg-muted",
798
+ onClick: onKeepEditing,
799
+ children: "Keep editing"
800
+ }
801
+ ) : null,
802
+ onDiscard ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
803
+ "button",
804
+ {
805
+ type: "button",
806
+ "data-refusal-discard": "",
807
+ className: "rounded border px-2 py-0.5 text-xs hover:bg-muted",
808
+ onClick: onDiscard,
809
+ children: "Discard"
810
+ }
811
+ ) : null
812
+ ] }) : null;
813
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
814
+ import_design_system3.Alert,
815
+ {
816
+ variant: "destructive",
817
+ role: "alert",
818
+ "data-refusal-notice": "",
819
+ className: (0, import_design_system3.cn)("text-xs", className),
820
+ errorFacts: { message: plain.sentence, title: plain.title, error, origin: "records-ui/RefusalNotice" },
821
+ ...plain.forEngineers ? { "data-for-engineers": plain.forEngineers } : {},
822
+ ...error.sqlstate ? { "data-sqlstate": error.sqlstate } : {},
823
+ children: [
824
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.AlertTitle, { className: "text-xs font-medium", children: plain.storeSaid ? plain.sentence : plain.title }),
825
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system3.AlertDescription, { className: "space-y-1 text-xs", children: [
826
+ plain.storeSaid || plain.sentence.replace(/\.$/, "") === plain.title ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: plain.sentence }),
827
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "opacity-80", children: plain.remedy }),
828
+ actions,
829
+ doors
830
+ ] })
831
+ ]
832
+ }
833
+ );
834
+ }
835
+ function RefusalLine({ error, className }) {
836
+ const plain = refusalForAPerson(error);
837
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
838
+ import_design_system3.ErrorBox,
839
+ {
840
+ "data-refusal-line": "",
841
+ className: (0, import_design_system3.cn)("text-xs text-destructive", className),
842
+ message: (0, import_core.archivedOrganizationId)(error) ? "This organization is archived. An owner can restore it." : refusalLineForAPerson(error),
843
+ error,
844
+ origin: "records-ui/RefusalLine",
845
+ ...plain.forEngineers ? { "data-for-engineers": plain.forEngineers } : {}
846
+ }
847
+ );
848
+ }
849
+
850
+ // src/AddChoicesInline.tsx
851
+ var import_jsx_runtime5 = require("react/jsx-runtime");
581
852
  function AddChoicesInline({ field, onAdded, disabled = false }) {
582
- const client = (0, import_react4.useOptionalRecordsClient)();
583
- const [open, setOpen] = (0, import_react3.useState)(false);
584
- const [rows, setRows] = (0, import_react3.useState)(() => [newChoiceRow([])]);
585
- const [saving, setSaving] = (0, import_react3.useState)(false);
586
- const [refused, setRefused] = (0, import_react3.useState)(null);
853
+ const client = (0, import_react7.useOptionalRecordsClient)();
854
+ const [open, setOpen] = (0, import_react6.useState)(false);
855
+ const [rows, setRows] = (0, import_react6.useState)(() => [newChoiceRow([])]);
856
+ const [saving, setSaving] = (0, import_react6.useState)(false);
857
+ const [refused, setRefused] = (0, import_react6.useState)(null);
587
858
  if (!client) return null;
588
859
  const words = rows.map((r) => r.words.trim()).filter((w) => w !== "");
589
860
  const missing = whatTheChoiceListIsMissing(rows);
@@ -593,19 +864,20 @@ function AddChoicesInline({ field, onAdded, disabled = false }) {
593
864
  const done = await client.fieldUpdate({ field_id: field.id, patch: { options_add: words } });
594
865
  setSaving(false);
595
866
  if (!done.ok) {
596
- setRefused(refusalSentence(done.error));
867
+ setRefused(done.error);
597
868
  return;
598
869
  }
599
870
  setOpen(false);
600
871
  setRows([newChoiceRow([])]);
601
872
  onAdded();
602
873
  };
603
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system2.Popover, { open, onOpenChange: setOpen, children: [
604
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system2.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system2.Button, { type: "button", size: "sm", variant: "outline", className: "h-7 self-start text-xs", disabled, "data-records-add-choices": "", children: "Add choices" }) }),
605
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system2.PopoverContent, { className: "w-72 space-y-2 p-3", align: "start", children: [
606
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChoiceListEditor, { isNew: true, rows, onRows: setRows }),
607
- missing || refused ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-[11px] text-destructive", children: missing ?? refused }) : null,
608
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system2.Button, { type: "button", size: "sm", className: "h-7 text-xs", disabled: saving || words.length === 0 || missing !== null, onClick: () => void save(), children: "Save choices" })
874
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.Popover, { open, onOpenChange: setOpen, children: [
875
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Button, { type: "button", size: "sm", variant: "outline", className: "h-7 self-start text-xs", disabled, "data-records-add-choices": "", children: "Add choices" }) }),
876
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.PopoverContent, { className: "w-72 space-y-2 p-3", align: "start", children: [
877
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChoiceListEditor, { isNew: true, rows, onRows: setRows }),
878
+ missing ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[11px] text-muted-foreground", children: missing }) : null,
879
+ refused ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RefusalLine, { error: refused }) : null,
880
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Button, { type: "button", size: "sm", className: "h-7 text-xs", disabled: saving || words.length === 0 || missing !== null, onClick: () => void save(), children: "Save choices" })
609
881
  ] })
610
882
  ] });
611
883
  }
@@ -659,43 +931,43 @@ function isDateLike(value) {
659
931
  }
660
932
 
661
933
  // src/newerKindValues.tsx
662
- var import_react5 = require("react");
934
+ var import_react8 = require("react");
663
935
  var import_source = require("@ai-matrx/content-ir/source");
664
- var import_records3 = require("@ai-matrx/records");
665
- var import_design_system3 = require("@ai-matrx/design-system");
666
- var import_jsx_runtime3 = require("react/jsx-runtime");
667
- var own = (event) => event.stopPropagation();
668
- function newerKindValue(field, value, opts = {}) {
669
- switch ((0, import_records3.newerKindOf)(field)) {
936
+ var import_records4 = require("@ai-matrx/records");
937
+ var import_design_system5 = require("@ai-matrx/design-system");
938
+ var import_jsx_runtime6 = require("react/jsx-runtime");
939
+ var own = (event) => event.stopPropagation();
940
+ function newerKindValue(field, value, opts = {}) {
941
+ switch ((0, import_records4.newerKindOf)(field)) {
670
942
  case "duration": {
671
- const words = (0, import_records3.durationText)(value);
672
- return words === null ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "tabular-nums", "data-records-duration": "", children: words });
943
+ const words = (0, import_records4.durationText)(value);
944
+ return words === null ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "tabular-nums", "data-records-duration": "", children: words });
673
945
  }
674
946
  case "created_by":
675
947
  case "modified_by":
676
- return (0, import_records3.isPersonStamp)(value) ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PersonStampChip, { stamp: value }) : void 0;
948
+ return (0, import_records4.isPersonStamp)(value) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PersonStampChip, { stamp: value }) : void 0;
677
949
  case "address":
678
- return (0, import_records3.isAddressValue)(value) || typeof value === "string" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AddressLink, { value }) : void 0;
950
+ return (0, import_records4.isAddressValue)(value) || typeof value === "string" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AddressLink, { value }) : void 0;
679
951
  case "barcode":
680
- return typeof value === "string" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "inline-flex min-w-0 items-center gap-1 font-mono text-xs", "data-records-barcode": "", title: value, children: [
681
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "aria-hidden": "true", className: "text-muted-foreground", children: "\u25AE\u25AF\u25AE" }),
682
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "truncate", children: value })
952
+ return typeof value === "string" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "inline-flex min-w-0 items-center gap-1 font-mono text-xs", "data-records-barcode": "", title: value, children: [
953
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-hidden": "true", className: "text-muted-foreground", children: "\u25AE\u25AF\u25AE" }),
954
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: value })
683
955
  ] }) : void 0;
684
956
  case "rich_text":
685
- return typeof value === "string" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SafeMarkdown, { text: value, clipped: opts.inCell === true }) : void 0;
957
+ return typeof value === "string" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SafeMarkdown, { text: value, clipped: opts.inCell === true }) : void 0;
686
958
  case "count":
687
- return typeof value === "number" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "tabular-nums", children: value.toLocaleString() }) : void 0;
959
+ return typeof value === "number" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "tabular-nums", children: value.toLocaleString() }) : void 0;
688
960
  default:
689
961
  return void 0;
690
962
  }
691
963
  }
692
964
  function PersonStampChip({ stamp }) {
693
- const words = (0, import_records3.personStampText)(stamp) ?? import_records3.NOT_A_MEMBER_WORDS;
965
+ const words = (0, import_records4.personStampText)(stamp) ?? import_records4.NOT_A_MEMBER_WORDS;
694
966
  const tier = stamp.actor ?? "user";
695
967
  const name = tier === "user" ? stamp.name : null;
696
968
  const initial = tier === "system" ? "\u2699" : tier === "agent" ? "\u2726" : name && name.trim() !== "" ? name.trim()[0].toUpperCase() : "?";
697
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "inline-flex min-w-0 items-center gap-1.5", "data-records-person-stamp": tier, children: [
698
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
969
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "inline-flex min-w-0 items-center gap-1.5", "data-records-person-stamp": tier, children: [
970
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
699
971
  "span",
700
972
  {
701
973
  "aria-hidden": "true",
@@ -703,14 +975,14 @@ function PersonStampChip({ stamp }) {
703
975
  children: initial
704
976
  }
705
977
  ),
706
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: (0, import_design_system3.cn)("truncate", tier === "user" && !name ? "italic text-muted-foreground" : ""), children: words })
978
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: (0, import_design_system5.cn)("truncate", tier === "user" && !name ? "italic text-muted-foreground" : ""), children: words })
707
979
  ] });
708
980
  }
709
981
  function AddressLink({ value }) {
710
- const words = (0, import_records3.addressText)(value);
711
- const href = (0, import_records3.addressMapUrl)(value);
712
- if (!words || !href) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-muted-foreground", children: "\u2014" });
713
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
982
+ const words = (0, import_records4.addressText)(value);
983
+ const href = (0, import_records4.addressMapUrl)(value);
984
+ if (!words || !href) return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-muted-foreground", children: "\u2014" });
985
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
714
986
  "a",
715
987
  {
716
988
  href,
@@ -721,19 +993,19 @@ function AddressLink({ value }) {
721
993
  "data-records-address": "",
722
994
  onClick: own,
723
995
  children: [
724
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "aria-hidden": "true", children: "\u2316" }),
725
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "truncate", children: words })
996
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-hidden": "true", children: "\u2316" }),
997
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: words })
726
998
  ]
727
999
  }
728
1000
  );
729
1001
  }
730
1002
  var STATUS_GROUP_MARK = { todo: "\u25CB", in_progress: "\u25D0", done: "\u25CF" };
731
1003
  function statusMarkOf(field, value, document2) {
732
- if ((0, import_records3.newerKindOf)(field) !== "status" || typeof value !== "string") return null;
1004
+ if ((0, import_records4.newerKindOf)(field) !== "status" || typeof value !== "string") return null;
733
1005
  const chosen = document2?.["_choices"]?.[field.key];
734
1006
  const key = chosen && typeof chosen === "object" && typeof chosen.key === "string" ? chosen.key : value;
735
- const group = (0, import_records3.statusGroupOf)(field, key);
736
- return { mark: STATUS_GROUP_MARK[group], group, words: import_records3.STATUS_GROUP_WORDS[group] };
1007
+ const group = (0, import_records4.statusGroupOf)(field, key);
1008
+ return { mark: STATUS_GROUP_MARK[group], group, words: import_records4.STATUS_GROUP_WORDS[group] };
737
1009
  }
738
1010
  function inline(text, key) {
739
1011
  const out = [];
@@ -742,7 +1014,7 @@ function inline(text, key) {
742
1014
  for (const r of (0, import_source.findInlineCodeSpans)(text)) {
743
1015
  if (r.start < at) continue;
744
1016
  if (r.start > at) out.push(...marks(text.slice(at, r.start), `${key}-m${n++}`));
745
- out.push(/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { className: "rounded bg-muted px-1 font-mono text-[0.9em]", children: (0, import_source.codeSpanText)(text.slice(r.start, r.end)) }, `${key}-c${n++}`));
1017
+ out.push(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { className: "rounded bg-muted px-1 font-mono text-[0.9em]", children: (0, import_source.codeSpanText)(text.slice(r.start, r.end)) }, `${key}-c${n++}`));
746
1018
  at = r.end;
747
1019
  }
748
1020
  if (at < text.length) out.push(...marks(text.slice(at), `${key}-m${n++}`));
@@ -758,14 +1030,14 @@ function marks(text, key) {
758
1030
  if (at > last) out.push(text.slice(last, at));
759
1031
  const tok = m[0];
760
1032
  const k = `${key}-${i++}`;
761
- if (tok.startsWith("**") || tok.startsWith("__")) out.push(/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: tok.slice(2, -2) }, k));
1033
+ if (tok.startsWith("**") || tok.startsWith("__")) out.push(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: tok.slice(2, -2) }, k));
762
1034
  else if (tok.startsWith("[")) {
763
1035
  const link = /^\[([^\]]+)\]\(([^)\s]+)\)$/.exec(tok);
764
- const href = (0, import_records3.safeLinkHref)(link?.[2] ?? "");
1036
+ const href = (0, import_records4.safeLinkHref)(link?.[2] ?? "");
765
1037
  out.push(
766
- href ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: "text-primary underline-offset-2 hover:underline", onClick: own, children: link?.[1] }, k) : link?.[1] ?? tok
1038
+ href ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: "text-primary underline-offset-2 hover:underline", onClick: own, children: link?.[1] }, k) : link?.[1] ?? tok
767
1039
  );
768
- } else out.push(/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("em", { children: tok.slice(1, -1) }, k));
1040
+ } else out.push(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("em", { children: tok.slice(1, -1) }, k));
769
1041
  last = at + tok.length;
770
1042
  }
771
1043
  if (last < text.length) out.push(text.slice(last));
@@ -778,15 +1050,15 @@ function SafeMarkdown({ text, clipped }) {
778
1050
  let para = [];
779
1051
  const flushPara = () => {
780
1052
  if (para.length > 0) {
781
- blocks.push(/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: inline(para.join(" "), `p${blocks.length}`) }, `p${blocks.length}`));
1053
+ blocks.push(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: inline(para.join(" "), `p${blocks.length}`) }, `p${blocks.length}`));
782
1054
  para = [];
783
1055
  }
784
1056
  };
785
1057
  const flushList = () => {
786
1058
  if (list) {
787
- const items = list.items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { children: inline(item, `l${blocks.length}-${i}`) }, i));
1059
+ const items = list.items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: inline(item, `l${blocks.length}-${i}`) }, i));
788
1060
  blocks.push(
789
- list.ordered ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ol", { className: "ml-4 list-decimal", children: items }, `o${blocks.length}`) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "ml-4 list-disc", children: items }, `u${blocks.length}`)
1061
+ list.ordered ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ol", { className: "ml-4 list-decimal", children: items }, `o${blocks.length}`) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "ml-4 list-disc", children: items }, `u${blocks.length}`)
790
1062
  );
791
1063
  list = null;
792
1064
  }
@@ -805,7 +1077,7 @@ function SafeMarkdown({ text, clipped }) {
805
1077
  } else if (heading) {
806
1078
  flushPara();
807
1079
  flushList();
808
- blocks.push(/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "font-semibold", children: inline(heading[2], `h${blocks.length}`) }, `h${blocks.length}`));
1080
+ blocks.push(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "font-semibold", children: inline(heading[2], `h${blocks.length}`) }, `h${blocks.length}`));
809
1081
  } else if (line.trim() === "") {
810
1082
  flushPara();
811
1083
  flushList();
@@ -816,40 +1088,40 @@ function SafeMarkdown({ text, clipped }) {
816
1088
  }
817
1089
  flushPara();
818
1090
  flushList();
819
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1091
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
820
1092
  "span",
821
1093
  {
822
- className: (0, import_design_system3.cn)("block min-w-0 space-y-1 whitespace-normal text-sm", clipped ? "max-h-[4.5em] overflow-hidden" : ""),
1094
+ className: (0, import_design_system5.cn)("block min-w-0 space-y-1 whitespace-normal text-sm", clipped ? "max-h-[4.5em] overflow-hidden" : ""),
823
1095
  "data-records-rich-text": "",
824
1096
  children: blocks
825
1097
  }
826
1098
  );
827
1099
  }
828
1100
  function newerKindControl(props) {
829
- switch ((0, import_records3.newerKindOf)(props.field)) {
1101
+ switch ((0, import_records4.newerKindOf)(props.field)) {
830
1102
  case "duration":
831
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DurationControl, { ...props });
1103
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DurationControl, { ...props });
832
1104
  case "address":
833
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AddressControl, { ...props });
1105
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AddressControl, { ...props });
834
1106
  case "barcode":
835
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BarcodeControl, { ...props });
1107
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BarcodeControl, { ...props });
836
1108
  case "created_by":
837
1109
  case "modified_by":
838
1110
  case "count":
839
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { id: props.id, className: "rounded border border-dashed px-2 py-1.5 text-xs text-muted-foreground", children: props.value === null || props.value === void 0 ? "\u2014" : newerKindValue(props.field, props.value) });
1111
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { id: props.id, className: "rounded border border-dashed px-2 py-1.5 text-xs text-muted-foreground", children: props.value === null || props.value === void 0 ? "\u2014" : newerKindValue(props.field, props.value) });
840
1112
  default:
841
1113
  return void 0;
842
1114
  }
843
1115
  }
844
1116
  function DurationControl({ value, onChange, disabled, id }) {
845
- const [text, setText] = (0, import_react5.useState)(() => (0, import_records3.durationText)(value) ?? "");
846
- const [wrong, setWrong] = (0, import_react5.useState)(false);
847
- (0, import_react5.useEffect)(() => {
848
- setText((0, import_records3.durationText)(value) ?? "");
1117
+ const [text, setText] = (0, import_react8.useState)(() => (0, import_records4.durationText)(value) ?? "");
1118
+ const [wrong, setWrong] = (0, import_react8.useState)(false);
1119
+ (0, import_react8.useEffect)(() => {
1120
+ setText((0, import_records4.durationText)(value) ?? "");
849
1121
  }, [value]);
850
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "flex flex-col gap-1", children: [
851
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
852
- import_design_system3.BasicInput,
1122
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex flex-col gap-1", children: [
1123
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1124
+ import_design_system5.BasicInput,
853
1125
  {
854
1126
  id,
855
1127
  value: text,
@@ -865,16 +1137,16 @@ function DurationControl({ value, onChange, disabled, id }) {
865
1137
  onChange(null);
866
1138
  return;
867
1139
  }
868
- const seconds = (0, import_records3.readTypedDuration)(e.target.value);
1140
+ const seconds = (0, import_records4.readTypedDuration)(e.target.value);
869
1141
  setWrong(seconds === null);
870
1142
  if (seconds !== null) onChange(seconds);
871
1143
  },
872
1144
  onBlur: () => {
873
- if (!wrong) setText((0, import_records3.durationText)(value) ?? "");
1145
+ if (!wrong) setText((0, import_records4.durationText)(value) ?? "");
874
1146
  }
875
1147
  }
876
1148
  ),
877
- wrong ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-[11px] text-destructive", children: "Write it like 45 min, 1:30 or 1h 30m." }) : null
1149
+ wrong ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[11px] text-destructive", children: "Write it like 45 min, 1:30 or 1h 30m." }) : null
878
1150
  ] });
879
1151
  }
880
1152
  var ADDRESS_LABELS = {
@@ -892,14 +1164,14 @@ var ADDRESS_EXAMPLES = {
892
1164
  country: "US"
893
1165
  };
894
1166
  function AddressControl({ value, onChange, disabled, id }) {
895
- const held = (0, import_records3.isAddressValue)(value) ? value : typeof value === "string" && value.trim() !== "" ? { street: value } : {};
1167
+ const held = (0, import_records4.isAddressValue)(value) ? value : typeof value === "string" && value.trim() !== "" ? { street: value } : {};
896
1168
  const set = (part, words) => {
897
1169
  const next = { ...held, [part]: words };
898
1170
  const kept = Object.fromEntries(Object.entries(next).filter(([, v]) => typeof v === "string" && v.trim() !== ""));
899
1171
  onChange(Object.keys(kept).length === 0 ? null : kept);
900
1172
  };
901
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { id, className: "grid grid-cols-2 gap-1.5", "data-records-address-control": "", children: import_records3.ADDRESS_PARTS.map((part) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
902
- import_design_system3.BasicInput,
1173
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { id, className: "grid grid-cols-2 gap-1.5", "data-records-address-control": "", children: import_records4.ADDRESS_PARTS.map((part) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1174
+ import_design_system5.BasicInput,
903
1175
  {
904
1176
  "aria-label": ADDRESS_LABELS[part],
905
1177
  placeholder: ADDRESS_EXAMPLES[part],
@@ -917,13 +1189,13 @@ function barcodeDetector() {
917
1189
  return typeof ctor === "function" ? ctor : null;
918
1190
  }
919
1191
  function BarcodeControl({ value, onChange, disabled, id }) {
920
- const file = (0, import_react5.useRef)(null);
921
- const [said2, setSaid] = (0, import_react5.useState)(null);
1192
+ const file = (0, import_react8.useRef)(null);
1193
+ const [said2, setSaid] = (0, import_react8.useState)(null);
922
1194
  const Detect = barcodeDetector();
923
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "flex flex-col gap-1", children: [
924
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "flex items-center gap-1.5", children: [
925
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
926
- import_design_system3.BasicInput,
1195
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex flex-col gap-1", children: [
1196
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-center gap-1.5", children: [
1197
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1198
+ import_design_system5.BasicInput,
927
1199
  {
928
1200
  id,
929
1201
  className: "font-mono",
@@ -933,8 +1205,8 @@ function BarcodeControl({ value, onChange, disabled, id }) {
933
1205
  onChange: (e) => onChange(e.target.value === "" ? null : e.target.value)
934
1206
  }
935
1207
  ),
936
- Detect && !disabled ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
937
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1208
+ Detect && !disabled ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1209
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
938
1210
  "button",
939
1211
  {
940
1212
  type: "button",
@@ -943,7 +1215,7 @@ function BarcodeControl({ value, onChange, disabled, id }) {
943
1215
  children: "Scan"
944
1216
  }
945
1217
  ),
946
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1218
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
947
1219
  "input",
948
1220
  {
949
1221
  ref: file,
@@ -969,13 +1241,13 @@ function BarcodeControl({ value, onChange, disabled, id }) {
969
1241
  )
970
1242
  ] }) : null
971
1243
  ] }),
972
- said2 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-[11px] text-muted-foreground", children: said2 }) : null
1244
+ said2 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[11px] text-muted-foreground", children: said2 }) : null
973
1245
  ] });
974
1246
  }
975
1247
 
976
1248
  // src/parity.ts
977
- var import_records5 = require("@ai-matrx/records");
978
1249
  var import_records6 = require("@ai-matrx/records");
1250
+ var import_records7 = require("@ai-matrx/records");
979
1251
  var import_text_case = require("@ai-matrx/kit/text-case");
980
1252
 
981
1253
  // src/docs.ts
@@ -984,7 +1256,7 @@ function isSignatureField(field) {
984
1256
  }
985
1257
 
986
1258
  // src/fieldTypes.ts
987
- var import_records4 = require("@ai-matrx/records");
1259
+ var import_records5 = require("@ai-matrx/records");
988
1260
  var LOOK_KINDS = {
989
1261
  rating: { plain: "number", look: ({ ratingMax }) => ({ id: "rating", options: { ratingMax } }) },
990
1262
  time: { plain: "text", look: () => ({ id: "time" }) }
@@ -993,9 +1265,9 @@ function declaredAsLook(kind) {
993
1265
  return kind in LOOK_KINDS && !storePublishesKind(kind);
994
1266
  }
995
1267
  function storePublishesKind(kind) {
996
- return import_records4.DECLARABLE_FIELD_KINDS.some((row) => row.kind === kind);
1268
+ return import_records5.DECLARABLE_FIELD_KINDS.some((row) => row.kind === kind);
997
1269
  }
998
- var STORE_PUBLISHES_ENTITY_REFERENCE = import_records4.DECLARABLE_FIELD_KINDS.some(
1270
+ var STORE_PUBLISHES_ENTITY_REFERENCE = import_records5.DECLARABLE_FIELD_KINDS.some(
999
1271
  (row) => row.kind === "entity_reference"
1000
1272
  );
1001
1273
  var SYSTEM_FIELD_KINDS = ["autonumber", "created_time", "modified_time"];
@@ -1043,7 +1315,7 @@ var FIELD_TYPE_CATALOGUE = [
1043
1315
  { id: "created_by", group: "Worked out", label: "Created by", explanation: "Who made each record. Nobody types it." },
1044
1316
  { id: "modified_by", group: "Worked out", label: "Last changed by", explanation: "Who last changed each record. Nobody types it." }
1045
1317
  ];
1046
- var GATED_KINDS = /* @__PURE__ */ new Set(["entity_reference", ...import_records4.NEWER_FIELD_KINDS]);
1318
+ var GATED_KINDS = /* @__PURE__ */ new Set(["entity_reference", ...import_records5.NEWER_FIELD_KINDS]);
1047
1319
  var FIELD_TYPE_CHOICES = FIELD_TYPE_CATALOGUE.filter(
1048
1320
  (c) => !GATED_KINDS.has(c.id) || storePublishesKind(c.id) || c.id in LOOK_KINDS
1049
1321
  );
@@ -1064,26 +1336,26 @@ function isRelationFieldType(id) {
1064
1336
  return id === "relation";
1065
1337
  }
1066
1338
  function isParityFieldType(id) {
1067
- return import_records4.PARITY_FIELD_TYPES.some((row) => row.parity_type === id);
1339
+ return import_records5.PARITY_FIELD_TYPES.some((row) => row.parity_type === id);
1068
1340
  }
1069
1341
  var ADD_FIELD_SAVE_LABEL = "Create column";
1070
1342
  var EDIT_FIELD_SAVE_LABEL = "Save column";
1071
1343
 
1072
1344
  // src/parity.ts
1073
- var kernelId = (name) => import_records5.KERNEL_TABLES.find((t) => t.name === name)?.id ?? "";
1345
+ var kernelId = (name) => import_records6.KERNEL_TABLES.find((t) => t.name === name)?.id ?? "";
1074
1346
  var KERNEL_FILE_TABLE = kernelId("File");
1075
1347
  var KERNEL_PERSON_TABLE = kernelId("Person");
1076
1348
  var PARITY_MADE_OF = Object.fromEntries(
1077
- import_records5.PARITY_FIELD_TYPES.map((p) => [p.parity_type, p.made_of])
1349
+ import_records6.PARITY_FIELD_TYPES.map((p) => [p.parity_type, p.made_of])
1078
1350
  );
1079
1351
  var KERNEL = { file: KERNEL_FILE_TABLE, person: KERNEL_PERSON_TABLE };
1080
1352
  function editorKindFor(field) {
1081
- return (0, import_records5.fieldKindFor)(field, KERNEL);
1353
+ return (0, import_records6.fieldKindFor)(field, KERNEL);
1082
1354
  }
1083
1355
  function pickableTypeOf(field) {
1084
1356
  if (isSignatureField(field)) return "signature";
1085
- if ((0, import_records6.isButtonField)(field)) return "button";
1086
- const newer = (0, import_records5.newerKindOf)(field);
1357
+ if ((0, import_records7.isButtonField)(field)) return "button";
1358
+ const newer = (0, import_records6.newerKindOf)(field);
1087
1359
  if (newer) return newer;
1088
1360
  const look = displayFormatOf(field)?.id;
1089
1361
  if (look === "rating" && field.type === "range") return "rating";
@@ -1142,23 +1414,23 @@ var import_react11 = require("@ai-matrx/records/react");
1142
1414
  var import_design_system8 = require("@ai-matrx/design-system");
1143
1415
 
1144
1416
  // src/PickOrAdd.tsx
1145
- var import_react6 = require("react");
1417
+ var import_react9 = require("react");
1146
1418
 
1147
1419
  // src/personChip.tsx
1148
- var import_design_system4 = require("@ai-matrx/design-system");
1149
- var import_jsx_runtime4 = require("react/jsx-runtime");
1420
+ var import_design_system6 = require("@ai-matrx/design-system");
1421
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1150
1422
  function initialsOf(name) {
1151
1423
  const words = name.replace(/@.*$/, "").split(/[\s._-]+/).filter((w) => /\p{L}|\d/u.test(w));
1152
1424
  const letters = words.filter((w) => !/^(dr|mr|mrs|ms|prof)\.?$/i.test(w)).slice(0, 2).map((w) => (w.match(/[\p{L}\d]/u)?.[0] ?? "").toUpperCase());
1153
1425
  return letters.join("") || "?";
1154
1426
  }
1155
1427
  function PersonAvatar({ name, size = "sm" }) {
1156
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1428
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1157
1429
  "span",
1158
1430
  {
1159
1431
  "aria-hidden": "true",
1160
1432
  "data-records-person-avatar": "",
1161
- className: (0, import_design_system4.cn)(
1433
+ className: (0, import_design_system6.cn)(
1162
1434
  "inline-flex shrink-0 items-center justify-center rounded-full bg-foreground/10 font-medium text-foreground/80",
1163
1435
  size === "md" ? "size-5 text-[10px]" : "size-4 text-[9px]"
1164
1436
  ),
@@ -1167,35 +1439,35 @@ function PersonAvatar({ name, size = "sm" }) {
1167
1439
  );
1168
1440
  }
1169
1441
  function PersonChip({ name, onRemove, className }) {
1170
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1442
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1171
1443
  "span",
1172
1444
  {
1173
1445
  "data-records-person-chip": "",
1174
1446
  title: name,
1175
- className: (0, import_design_system4.cn)("inline-flex min-w-0 max-w-full items-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-[11px] text-foreground", className),
1447
+ className: (0, import_design_system6.cn)("inline-flex min-w-0 max-w-full items-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-[11px] text-foreground", className),
1176
1448
  children: [
1177
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PersonAvatar, { name }),
1178
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "min-w-0 truncate", children: name }),
1179
- onRemove ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", onClick: onRemove, "aria-label": `Remove ${name}`, className: "shrink-0 opacity-60 hover:opacity-100", children: "\xD7" }) : null
1449
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PersonAvatar, { name }),
1450
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "min-w-0 truncate", children: name }),
1451
+ onRemove ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: onRemove, "aria-label": `Remove ${name}`, className: "shrink-0 opacity-60 hover:opacity-100", children: "\xD7" }) : null
1180
1452
  ]
1181
1453
  }
1182
1454
  );
1183
1455
  }
1184
1456
 
1185
1457
  // src/PickOrAdd.tsx
1186
- var import_design_system5 = require("@ai-matrx/design-system");
1187
- var import_jsx_runtime5 = require("react/jsx-runtime");
1458
+ var import_design_system7 = require("@ai-matrx/design-system");
1459
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1188
1460
  function Glyph({ d, className }) {
1189
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, className, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d }) });
1461
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, className, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d }) });
1190
1462
  }
1191
1463
  var TICK = "m5 12 4 4L19 6";
1192
1464
  var CROSS = "M18 6 6 18M6 6l12 12";
1193
1465
  var PLUS = "M12 5v14M5 12h14";
1194
1466
  function useListKeys(args) {
1195
1467
  const { count, resetOn, onPick, onNothing, onClose, onFinish, onBackspaceEmpty, searchEmpty } = args;
1196
- const [highlight, setHighlight] = (0, import_react6.useState)(0);
1197
- const [moved, setMoved] = (0, import_react6.useState)(false);
1198
- (0, import_react6.useEffect)(() => {
1468
+ const [highlight, setHighlight] = (0, import_react9.useState)(0);
1469
+ const [moved, setMoved] = (0, import_react9.useState)(false);
1470
+ (0, import_react9.useEffect)(() => {
1199
1471
  setHighlight(0);
1200
1472
  setMoved(false);
1201
1473
  }, [resetOn]);
@@ -1240,11 +1512,11 @@ function PickRow({
1240
1512
  onPick,
1241
1513
  onPoint
1242
1514
  }) {
1243
- const ref = (0, import_react6.useRef)(null);
1244
- (0, import_react6.useEffect)(() => {
1515
+ const ref = (0, import_react9.useRef)(null);
1516
+ (0, import_react9.useEffect)(() => {
1245
1517
  if (highlighted) ref.current?.scrollIntoView?.({ block: "nearest" });
1246
1518
  }, [highlighted]);
1247
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1519
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1248
1520
  "button",
1249
1521
  {
1250
1522
  ref,
@@ -1257,19 +1529,19 @@ function PickRow({
1257
1529
  title: title ?? label,
1258
1530
  ...attrs ?? {},
1259
1531
  "data-pick-highlighted": highlighted ? "" : void 0,
1260
- className: (0, import_design_system5.cn)(
1532
+ className: (0, import_design_system7.cn)(
1261
1533
  "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",
1262
1534
  highlighted ? "bg-accent text-accent-foreground" : ""
1263
1535
  ),
1264
1536
  children: [
1265
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "flex size-3.5 shrink-0 items-center justify-center", children: [
1266
- picked ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "data-pick-tick": "", className: "contents", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Glyph, { d: TICK, className: "size-3.5" }) }) : null,
1267
- icon === "plus" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Glyph, { d: PLUS, className: "size-3.5 text-muted-foreground" }) : null
1537
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex size-3.5 shrink-0 items-center justify-center", children: [
1538
+ picked ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "data-pick-tick": "", className: "contents", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Glyph, { d: TICK, className: "size-3.5" }) }) : null,
1539
+ icon === "plus" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Glyph, { d: PLUS, className: "size-3.5 text-muted-foreground" }) : null
1268
1540
  ] }),
1269
- person ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PersonAvatar, { name: label, size: "md" }) : null,
1270
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "min-w-0 flex-1", children: [
1271
- chip ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: (0, import_design_system5.cn)("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__ */ (0, import_jsx_runtime5.jsx)("span", { className: "block truncate", children: label }),
1272
- detail ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "block truncate text-xs text-muted-foreground", "data-tell-apart": "", children: detail }) : null
1541
+ person ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PersonAvatar, { name: label, size: "md" }) : null,
1542
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "min-w-0 flex-1", children: [
1543
+ chip ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: (0, import_design_system7.cn)("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__ */ (0, import_jsx_runtime8.jsx)("span", { className: "block truncate", children: label }),
1544
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "block truncate text-xs text-muted-foreground", "data-tell-apart": "", children: detail }) : null
1273
1545
  ] })
1274
1546
  ]
1275
1547
  }
@@ -1277,26 +1549,26 @@ function PickRow({
1277
1549
  }
1278
1550
  function PickChips({ chips }) {
1279
1551
  if (chips.length === 0) return null;
1280
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex flex-wrap gap-1 px-1 pb-1", "data-pick-chips": "", children: chips.map(
1281
- (c) => c.person ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PersonChip, { name: c.label, onRemove: c.onRemove }, c.id) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1552
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex flex-wrap gap-1 px-1 pb-1", "data-pick-chips": "", children: chips.map(
1553
+ (c) => c.person ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PersonChip, { name: c.label, onRemove: c.onRemove }, c.id) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1282
1554
  "span",
1283
1555
  {
1284
1556
  "data-pick-chip": "",
1285
1557
  title: c.label,
1286
- className: (0, import_design_system5.cn)(
1558
+ className: (0, import_design_system7.cn)(
1287
1559
  "inline-flex max-w-full items-center gap-1 rounded-md border px-1.5 py-0.5 text-xs font-medium",
1288
1560
  c.chip ?? "bg-secondary text-secondary-foreground"
1289
1561
  ),
1290
1562
  children: [
1291
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "min-w-0 truncate", children: c.label }),
1292
- c.onRemove ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1563
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "min-w-0 truncate", children: c.label }),
1564
+ c.onRemove ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1293
1565
  "button",
1294
1566
  {
1295
1567
  type: "button",
1296
1568
  "aria-label": `Remove ${c.label}`,
1297
1569
  onClick: c.onRemove,
1298
1570
  className: "shrink-0 rounded-sm opacity-60 hover:opacity-100",
1299
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Glyph, { d: CROSS, className: "size-3" })
1571
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Glyph, { d: CROSS, className: "size-3" })
1300
1572
  }
1301
1573
  ) : null
1302
1574
  ]
@@ -1351,7 +1623,7 @@ function PickOrAdd({
1351
1623
  searchEmpty: search === ""
1352
1624
  });
1353
1625
  const hasFoot = Boolean(foot) || Boolean(footNote);
1354
- const addRowNode = addRow ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1626
+ const addRowNode = addRow ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1355
1627
  PickRow,
1356
1628
  {
1357
1629
  label: addRow.label,
@@ -1364,10 +1636,10 @@ function PickOrAdd({
1364
1636
  onPoint: () => keys.setHighlight(addAt)
1365
1637
  }
1366
1638
  ) : null;
1367
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Popover, { open, onOpenChange, children: [
1368
- anchored ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.PopoverAnchor, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { "data-pick-anchor": "", className: "flex min-h-6 w-full min-w-0 flex-wrap items-center gap-1", "aria-label": triggerLabel, children }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Button, { id: triggerId, type: "button", size: "sm", variant: "outline", className: triggerSize === "field" ? "h-9" : void 0, "aria-label": triggerLabel, children: triggerText }) }),
1369
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1370
- import_design_system5.PopoverContent,
1639
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system7.Popover, { open, onOpenChange, children: [
1640
+ anchored ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system7.PopoverAnchor, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { "data-pick-anchor": "", className: "flex min-h-6 w-full min-w-0 flex-wrap items-center gap-1", "aria-label": triggerLabel, children }) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system7.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system7.Button, { id: triggerId, type: "button", size: "sm", variant: "outline", className: triggerSize === "field" ? "h-9" : void 0, "aria-label": triggerLabel, children: triggerText }) }),
1641
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1642
+ import_design_system7.PopoverContent,
1371
1643
  {
1372
1644
  sizing: "content",
1373
1645
  padding: "xs",
@@ -1388,9 +1660,9 @@ function PickOrAdd({
1388
1660
  if (anchored) event.preventDefault();
1389
1661
  },
1390
1662
  children: [
1391
- chips ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PickChips, { chips }) : null,
1392
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1393
- import_design_system5.BasicInput,
1663
+ chips ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PickChips, { chips }) : null,
1664
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1665
+ import_design_system7.BasicInput,
1394
1666
  {
1395
1667
  value: search,
1396
1668
  onChange: (e) => onSearch(e.target.value),
@@ -1403,9 +1675,9 @@ function PickOrAdd({
1403
1675
  }
1404
1676
  ),
1405
1677
  notice,
1406
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.ScrollArea, { className: "max-h-64", children: [
1407
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { role: "listbox", "aria-label": triggerLabel, "aria-multiselectable": multi ? true : void 0, children: [
1408
- items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1678
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system7.ScrollArea, { className: "max-h-64", children: [
1679
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { role: "listbox", "aria-label": triggerLabel, "aria-multiselectable": multi ? true : void 0, children: [
1680
+ items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1409
1681
  PickRow,
1410
1682
  {
1411
1683
  label: item.label,
@@ -1426,7 +1698,7 @@ function PickOrAdd({
1426
1698
  ] }),
1427
1699
  items.length === 0 && empty ? empty : null
1428
1700
  ] }),
1429
- hasFoot ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mt-1 border-t pt-1", children: [
1701
+ hasFoot ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mt-1 border-t pt-1", children: [
1430
1702
  foot,
1431
1703
  footNote
1432
1704
  ] }) : null
@@ -1436,277 +1708,6 @@ function PickOrAdd({
1436
1708
  ] });
1437
1709
  }
1438
1710
 
1439
- // src/Refusal.tsx
1440
- var import_core = require("@ai-matrx/records/core");
1441
- var import_design_system7 = require("@ai-matrx/design-system");
1442
-
1443
- // src/ArchivedOrganizationNotice.tsx
1444
- var import_react9 = require("react");
1445
- var import_design_system6 = require("@ai-matrx/design-system");
1446
-
1447
- // src/host.tsx
1448
- var import_react7 = require("react");
1449
- var import_react8 = require("@ai-matrx/records/react");
1450
-
1451
- // src/rights.ts
1452
- var import_records7 = require("@ai-matrx/records");
1453
- var LEVEL_WORD = {
1454
- viewer: "Viewer",
1455
- commenter: "Commenter",
1456
- edit_content: "Content editor",
1457
- editor: "Editor",
1458
- admin: "Admin"
1459
- };
1460
- var NEEDS = {
1461
- read: "viewer",
1462
- // custom.io_comment_write
1463
- comment: "commenter",
1464
- // custom.record_update / custom.record_write — `edit_content` changes rows and page content;
1465
- // columns, views and settings (structure) stay with admin below, and sharing with admin.
1466
- write: "edit_content",
1467
- // custom.view_designate / view_declare / migrate_merge / record_restore — all ask `editor`: more than
1468
- // changing content (`edit_content`), less than changing columns (`admin`).
1469
- organise: "editor",
1470
- // custom.record_delete
1471
- remove: "editor",
1472
- // custom.share_grant — passing your access on is an administrator's right
1473
- share: "admin",
1474
- // custom.field_declare / field_update / field_retire / table settings
1475
- structure: "admin"
1476
- };
1477
- var NOT_YET = "Still asking the store what you may do here. Nothing is offered until it has answered.";
1478
- var NOTHING_AT_ALL = "You have not been given this. Ask somebody who administers it to share it with you.";
1479
- function sentenceFor(what, level) {
1480
- if (level === null) return NOTHING_AT_ALL;
1481
- const need = LEVEL_WORD[NEEDS[what]];
1482
- const have = LEVEL_WORD[level];
1483
- const doing = {
1484
- read: "open this",
1485
- comment: "leave a comment",
1486
- write: "change anything here",
1487
- organise: "organise this",
1488
- remove: "delete this",
1489
- share: "pass this on to somebody else",
1490
- structure: "change the columns of this table"
1491
- };
1492
- return `You are ${have} here, and it takes ${need} to ${doing[what]}. Ask somebody who is Admin on it to move you up.`;
1493
- }
1494
- function whatYouMayDo(level, known = true) {
1495
- const may = (what) => known && (0, import_records7.atLeast)(level, NEEDS[what]);
1496
- return {
1497
- level: known ? level : null,
1498
- known,
1499
- read: may("read"),
1500
- comment: may("comment"),
1501
- write: may("write"),
1502
- organise: may("organise"),
1503
- remove: may("remove"),
1504
- share: may("share"),
1505
- structure: may("structure"),
1506
- why: (what) => known ? sentenceFor(what, level) : NOT_YET
1507
- };
1508
- }
1509
- var NOT_ANSWERED_YET = whatYouMayDo(null, false);
1510
- var KERNEL_REASON = "This is one of the tables the platform ships, so its columns are not changed from a screen. Make your own table to change columns.";
1511
- function whatYouMayDoWithTable(table, level, known) {
1512
- const base = whatYouMayDo(level, known);
1513
- if (!table?.is_kernel) return table && tableIsLocked(table) ? lockedStructure(base) : base;
1514
- return {
1515
- ...base,
1516
- structure: false,
1517
- why: (what) => what === "structure" ? KERNEL_REASON : base.why(what)
1518
- };
1519
- }
1520
- function tableIsLocked(table) {
1521
- return table?.metadata?.["locked"] === true;
1522
- }
1523
- var DATABASE_LOCKED_REASON = "This database is locked, so its columns and settings are read-only. Unlock it to change them.";
1524
- function lockedStructure(base) {
1525
- return { ...base, structure: false, why: (what) => what === "structure" ? DATABASE_LOCKED_REASON : base.why(what) };
1526
- }
1527
-
1528
- // src/host.tsx
1529
- var import_jsx_runtime6 = require("react/jsx-runtime");
1530
- function tableRights(may, overallReason) {
1531
- return {
1532
- ...may,
1533
- admin: may.structure,
1534
- reason: overallReason ?? (may.structure ? "" : may.why("structure"))
1535
- };
1536
- }
1537
- var NO_RIGHTS = tableRights(NOT_ANSWERED_YET);
1538
- var NO_MEMBERS_REASON = "This app cannot offer the people in your organization on this screen yet, so there is nobody to pick. Type the person's name into a text field for now, and tell us \u2014 it is on our list, not yours.";
1539
- var NO_UPLOAD_REASON = "This screen cannot take a file yet, so there is no chooser here rather than one that loses what you pick. Put a link to the file in a text field for now. It is on our list, not yours.";
1540
- var HostContext = (0, import_react7.createContext)(null);
1541
- function useRecordsUi() {
1542
- return (0, import_react7.useContext)(HostContext) ?? {};
1543
- }
1544
- function quiet(may, say) {
1545
- if (say !== false) return may;
1546
- return { ...may, why: () => "", ..."reason" in may ? { reason: "" } : {} };
1547
- }
1548
- function useTableRights(table) {
1549
- const host = useRecordsUi();
1550
- const asked2 = useTableRightsAsked(table, host);
1551
- return (0, import_react7.useMemo)(() => quiet(asked2, host.sayLevelNeeded), [asked2, host.sayLevelNeeded]);
1552
- }
1553
- function useTableRightsAsked(table, host) {
1554
- const bound = Boolean(host.rights);
1555
- const asked2 = (0, import_react8.useMyLevel)(bound || !table ? null : table.id);
1556
- return (0, import_react7.useMemo)(() => {
1557
- if (!table) return NO_RIGHTS;
1558
- if (host.rights) return host.rights(table);
1559
- if (asked2.loading) return tableRights(NOT_ANSWERED_YET);
1560
- const level = asked2.error ? null : asked2.data;
1561
- return tableRights(whatYouMayDoWithTable(table, level, true));
1562
- }, [host, table, bound, asked2.loading, asked2.error, asked2.data]);
1563
- }
1564
-
1565
- // src/ArchivedOrganizationNotice.tsx
1566
- var import_jsx_runtime7 = require("react/jsx-runtime");
1567
- function ArchivedOrganizationNotice({
1568
- organizationId,
1569
- error,
1570
- className
1571
- }) {
1572
- const port = useRecordsUi().archivedOrganization;
1573
- const [mayRestore, setMayRestore] = (0, import_react9.useState)(null);
1574
- const [busy, setBusy] = (0, import_react9.useState)(false);
1575
- const [failed, setFailed] = (0, import_react9.useState)(null);
1576
- (0, import_react9.useEffect)(() => {
1577
- let live = true;
1578
- if (!port) {
1579
- setMayRestore(false);
1580
- return;
1581
- }
1582
- setMayRestore(null);
1583
- port.state(organizationId).then((answer) => {
1584
- if (live) setMayRestore(answer?.mayRestore === true);
1585
- }).catch(() => {
1586
- if (live) setMayRestore(false);
1587
- });
1588
- return () => {
1589
- live = false;
1590
- };
1591
- }, [organizationId, port?.state]);
1592
- const restore = async () => {
1593
- if (!port || busy) return;
1594
- setBusy(true);
1595
- setFailed(null);
1596
- try {
1597
- await port.restore(organizationId);
1598
- if (port.afterRestore) port.afterRestore();
1599
- else if (typeof window !== "undefined") window.location.reload();
1600
- } catch (thrown) {
1601
- setFailed(thrown instanceof Error && thrown.message ? thrown.message : "The organization could not be restored.");
1602
- setBusy(false);
1603
- }
1604
- };
1605
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1606
- import_design_system6.Alert,
1607
- {
1608
- variant: "destructive",
1609
- role: "alert",
1610
- "data-refusal-notice": "",
1611
- "data-archived-organization": organizationId,
1612
- className: (0, import_design_system6.cn)("text-xs", className),
1613
- errorFacts: { message: "This organization is archived", title: "This organization is archived", error, origin: "records-ui/ArchivedOrganizationNotice" },
1614
- children: [
1615
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.AlertTitle, { className: "text-xs font-medium", children: "This organization is archived" }),
1616
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.AlertDescription, { className: "space-y-1 text-xs", children: [
1617
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "opacity-80", children: "Nothing was deleted. Everything here comes back the moment an owner of the organization, or a super admin, restores it." }),
1618
- mayRestore === true ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1619
- "button",
1620
- {
1621
- type: "button",
1622
- "data-restore-organization": "",
1623
- disabled: busy,
1624
- className: "rounded border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-60",
1625
- onClick: () => void restore(),
1626
- children: busy ? "Restoring..." : "Restore organization"
1627
- }
1628
- ) : null,
1629
- mayRestore === false ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { "data-restore-who": "", className: "opacity-80", children: "Ask an owner of this organization to restore it." }) : null,
1630
- failed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { "data-restore-refused": "", children: failed }) : null
1631
- ] })
1632
- ]
1633
- }
1634
- );
1635
- }
1636
-
1637
- // src/Refusal.tsx
1638
- var import_jsx_runtime8 = require("react/jsx-runtime");
1639
- function RefusalNotice({
1640
- error,
1641
- className,
1642
- actions,
1643
- onKeepEditing,
1644
- onDiscard
1645
- }) {
1646
- const archivedOrg = (0, import_core.archivedOrganizationId)(error);
1647
- if (archivedOrg) {
1648
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArchivedOrganizationNotice, { organizationId: archivedOrg, error, className });
1649
- }
1650
- const plain = refusalForAPerson(error);
1651
- const doors = onKeepEditing || onDiscard ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-wrap items-center gap-1 pt-0.5", "data-refusal-doors": "", children: [
1652
- onKeepEditing ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1653
- "button",
1654
- {
1655
- type: "button",
1656
- "data-refusal-keep-editing": "",
1657
- className: "rounded border px-2 py-0.5 text-xs hover:bg-muted",
1658
- onClick: onKeepEditing,
1659
- children: "Keep editing"
1660
- }
1661
- ) : null,
1662
- onDiscard ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1663
- "button",
1664
- {
1665
- type: "button",
1666
- "data-refusal-discard": "",
1667
- className: "rounded border px-2 py-0.5 text-xs hover:bg-muted",
1668
- onClick: onDiscard,
1669
- children: "Discard"
1670
- }
1671
- ) : null
1672
- ] }) : null;
1673
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1674
- import_design_system7.Alert,
1675
- {
1676
- variant: "destructive",
1677
- role: "alert",
1678
- "data-refusal-notice": "",
1679
- className: (0, import_design_system7.cn)("text-xs", className),
1680
- errorFacts: { message: plain.sentence, title: plain.title, error, origin: "records-ui/RefusalNotice" },
1681
- ...plain.forEngineers ? { "data-for-engineers": plain.forEngineers } : {},
1682
- ...error.sqlstate ? { "data-sqlstate": error.sqlstate } : {},
1683
- children: [
1684
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system7.AlertTitle, { className: "text-xs font-medium", children: plain.storeSaid ? plain.sentence : plain.title }),
1685
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system7.AlertDescription, { className: "space-y-1 text-xs", children: [
1686
- plain.storeSaid || plain.sentence.replace(/\.$/, "") === plain.title ? null : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: plain.sentence }),
1687
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "opacity-80", children: plain.remedy }),
1688
- actions,
1689
- doors
1690
- ] })
1691
- ]
1692
- }
1693
- );
1694
- }
1695
- function RefusalLine({ error, className }) {
1696
- const plain = refusalForAPerson(error);
1697
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1698
- import_design_system7.ErrorBox,
1699
- {
1700
- "data-refusal-line": "",
1701
- className: (0, import_design_system7.cn)("text-xs text-destructive", className),
1702
- message: (0, import_core.archivedOrganizationId)(error) ? "This organization is archived. An owner can restore it." : refusalLineForAPerson(error),
1703
- error,
1704
- origin: "records-ui/RefusalLine",
1705
- ...plain.forEngineers ? { "data-for-engineers": plain.forEngineers } : {}
1706
- }
1707
- );
1708
- }
1709
-
1710
1711
  // src/refusals.ts
1711
1712
  var refusals_exports = {};
1712
1713
  __reExport(refusals_exports, require("@ai-matrx/records/versions"));