@ai-matrx/records-ui 0.115.33 → 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/CHANGELOG.md +12 -0
- package/dist/index.cjs +6134 -5242
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -6
- package/dist/index.d.ts +50 -6
- package/dist/index.js +5649 -4745
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs +412 -411
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js +374 -373
- package/dist/pickers.js.map +1 -1
- package/package.json +4 -4
package/dist/pickers.js
CHANGED
|
@@ -24,7 +24,7 @@ __reExport(askOnce_exports, versions_star);
|
|
|
24
24
|
import * as versions_star from "@ai-matrx/records/versions";
|
|
25
25
|
|
|
26
26
|
// src/AddChoicesInline.tsx
|
|
27
|
-
import { useState as
|
|
27
|
+
import { useState as useState3 } from "react";
|
|
28
28
|
import { useOptionalRecordsClient } from "@ai-matrx/records/react";
|
|
29
29
|
import { Button as Button2, Popover as Popover2, PopoverContent as PopoverContent2, PopoverTrigger as PopoverTrigger2 } from "@ai-matrx/design-system";
|
|
30
30
|
|
|
@@ -565,14 +565,285 @@ function ChoiceSwatch({ words, color, onColor }) {
|
|
|
565
565
|
] });
|
|
566
566
|
}
|
|
567
567
|
|
|
568
|
+
// src/Refusal.tsx
|
|
569
|
+
import { archivedOrganizationId } from "@ai-matrx/records/core";
|
|
570
|
+
import { Alert as Alert2, AlertDescription as AlertDescription2, AlertTitle as AlertTitle2, ErrorBox, cn as cn3 } from "@ai-matrx/design-system";
|
|
571
|
+
|
|
572
|
+
// src/ArchivedOrganizationNotice.tsx
|
|
573
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
574
|
+
import { Alert, AlertDescription, AlertTitle, cn as cn2 } from "@ai-matrx/design-system";
|
|
575
|
+
|
|
576
|
+
// src/host.tsx
|
|
577
|
+
import { createContext, useContext, useMemo } from "react";
|
|
578
|
+
import { useMyLevel, useMyLevels } from "@ai-matrx/records/react";
|
|
579
|
+
|
|
580
|
+
// src/rights.ts
|
|
581
|
+
import { atLeast } from "@ai-matrx/records";
|
|
582
|
+
var LEVEL_WORD = {
|
|
583
|
+
viewer: "Viewer",
|
|
584
|
+
commenter: "Commenter",
|
|
585
|
+
edit_content: "Content editor",
|
|
586
|
+
editor: "Editor",
|
|
587
|
+
admin: "Admin"
|
|
588
|
+
};
|
|
589
|
+
var NEEDS = {
|
|
590
|
+
read: "viewer",
|
|
591
|
+
// custom.io_comment_write
|
|
592
|
+
comment: "commenter",
|
|
593
|
+
// custom.record_update / custom.record_write — `edit_content` changes rows and page content;
|
|
594
|
+
// columns, views and settings (structure) stay with admin below, and sharing with admin.
|
|
595
|
+
write: "edit_content",
|
|
596
|
+
// custom.view_designate / view_declare / migrate_merge / record_restore — all ask `editor`: more than
|
|
597
|
+
// changing content (`edit_content`), less than changing columns (`admin`).
|
|
598
|
+
organise: "editor",
|
|
599
|
+
// custom.record_delete
|
|
600
|
+
remove: "editor",
|
|
601
|
+
// custom.share_grant — passing your access on is an administrator's right
|
|
602
|
+
share: "admin",
|
|
603
|
+
// custom.field_declare / field_update / field_retire / table settings
|
|
604
|
+
structure: "admin"
|
|
605
|
+
};
|
|
606
|
+
var NOT_YET = "Still asking the store what you may do here. Nothing is offered until it has answered.";
|
|
607
|
+
var NOTHING_AT_ALL = "You have not been given this. Ask somebody who administers it to share it with you.";
|
|
608
|
+
function sentenceFor(what, level) {
|
|
609
|
+
if (level === null) return NOTHING_AT_ALL;
|
|
610
|
+
const need = LEVEL_WORD[NEEDS[what]];
|
|
611
|
+
const have = LEVEL_WORD[level];
|
|
612
|
+
const doing = {
|
|
613
|
+
read: "open this",
|
|
614
|
+
comment: "leave a comment",
|
|
615
|
+
write: "change anything here",
|
|
616
|
+
organise: "organise this",
|
|
617
|
+
remove: "delete this",
|
|
618
|
+
share: "pass this on to somebody else",
|
|
619
|
+
structure: "change the columns of this table"
|
|
620
|
+
};
|
|
621
|
+
return `You are ${have} here, and it takes ${need} to ${doing[what]}. Ask somebody who is Admin on it to move you up.`;
|
|
622
|
+
}
|
|
623
|
+
function whatYouMayDo(level, known = true) {
|
|
624
|
+
const may = (what) => known && atLeast(level, NEEDS[what]);
|
|
625
|
+
return {
|
|
626
|
+
level: known ? level : null,
|
|
627
|
+
known,
|
|
628
|
+
read: may("read"),
|
|
629
|
+
comment: may("comment"),
|
|
630
|
+
write: may("write"),
|
|
631
|
+
organise: may("organise"),
|
|
632
|
+
remove: may("remove"),
|
|
633
|
+
share: may("share"),
|
|
634
|
+
structure: may("structure"),
|
|
635
|
+
why: (what) => known ? sentenceFor(what, level) : NOT_YET
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
var NOT_ANSWERED_YET = whatYouMayDo(null, false);
|
|
639
|
+
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.";
|
|
640
|
+
function whatYouMayDoWithTable(table, level, known) {
|
|
641
|
+
const base = whatYouMayDo(level, known);
|
|
642
|
+
if (!table?.is_kernel) return table && tableIsLocked(table) ? lockedStructure(base) : base;
|
|
643
|
+
return {
|
|
644
|
+
...base,
|
|
645
|
+
structure: false,
|
|
646
|
+
why: (what) => what === "structure" ? KERNEL_REASON : base.why(what)
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
function tableIsLocked(table) {
|
|
650
|
+
return table?.metadata?.["locked"] === true;
|
|
651
|
+
}
|
|
652
|
+
var DATABASE_LOCKED_REASON = "This database is locked, so its columns and settings are read-only. Unlock it to change them.";
|
|
653
|
+
function lockedStructure(base) {
|
|
654
|
+
return { ...base, structure: false, why: (what) => what === "structure" ? DATABASE_LOCKED_REASON : base.why(what) };
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// src/host.tsx
|
|
658
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
659
|
+
function tableRights(may, overallReason) {
|
|
660
|
+
return {
|
|
661
|
+
...may,
|
|
662
|
+
admin: may.structure,
|
|
663
|
+
reason: overallReason ?? (may.structure ? "" : may.why("structure"))
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
var NO_RIGHTS = tableRights(NOT_ANSWERED_YET);
|
|
667
|
+
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.";
|
|
668
|
+
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.";
|
|
669
|
+
var HostContext = createContext(null);
|
|
670
|
+
function useRecordsUi() {
|
|
671
|
+
return useContext(HostContext) ?? {};
|
|
672
|
+
}
|
|
673
|
+
function quiet(may, say) {
|
|
674
|
+
if (say !== false) return may;
|
|
675
|
+
return { ...may, why: () => "", ..."reason" in may ? { reason: "" } : {} };
|
|
676
|
+
}
|
|
677
|
+
function useTableRights(table) {
|
|
678
|
+
const host = useRecordsUi();
|
|
679
|
+
const asked2 = useTableRightsAsked(table, host);
|
|
680
|
+
return useMemo(() => quiet(asked2, host.sayLevelNeeded), [asked2, host.sayLevelNeeded]);
|
|
681
|
+
}
|
|
682
|
+
function useTableRightsAsked(table, host) {
|
|
683
|
+
const bound = Boolean(host.rights);
|
|
684
|
+
const asked2 = useMyLevel(bound || !table ? null : table.id);
|
|
685
|
+
return useMemo(() => {
|
|
686
|
+
if (!table) return NO_RIGHTS;
|
|
687
|
+
if (host.rights) return host.rights(table);
|
|
688
|
+
if (asked2.loading) return tableRights(NOT_ANSWERED_YET);
|
|
689
|
+
const level = asked2.error ? null : asked2.data;
|
|
690
|
+
return tableRights(whatYouMayDoWithTable(table, level, true));
|
|
691
|
+
}, [host, table, bound, asked2.loading, asked2.error, asked2.data]);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// src/ArchivedOrganizationNotice.tsx
|
|
695
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
696
|
+
function ArchivedOrganizationNotice({
|
|
697
|
+
organizationId,
|
|
698
|
+
error,
|
|
699
|
+
className
|
|
700
|
+
}) {
|
|
701
|
+
const port = useRecordsUi().archivedOrganization;
|
|
702
|
+
const [mayRestore, setMayRestore] = useState2(null);
|
|
703
|
+
const [busy, setBusy] = useState2(false);
|
|
704
|
+
const [failed, setFailed] = useState2(null);
|
|
705
|
+
useEffect2(() => {
|
|
706
|
+
let live = true;
|
|
707
|
+
if (!port) {
|
|
708
|
+
setMayRestore(false);
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
setMayRestore(null);
|
|
712
|
+
port.state(organizationId).then((answer) => {
|
|
713
|
+
if (live) setMayRestore(answer?.mayRestore === true);
|
|
714
|
+
}).catch(() => {
|
|
715
|
+
if (live) setMayRestore(false);
|
|
716
|
+
});
|
|
717
|
+
return () => {
|
|
718
|
+
live = false;
|
|
719
|
+
};
|
|
720
|
+
}, [organizationId, port?.state]);
|
|
721
|
+
const restore = async () => {
|
|
722
|
+
if (!port || busy) return;
|
|
723
|
+
setBusy(true);
|
|
724
|
+
setFailed(null);
|
|
725
|
+
try {
|
|
726
|
+
await port.restore(organizationId);
|
|
727
|
+
if (port.afterRestore) port.afterRestore();
|
|
728
|
+
else if (typeof window !== "undefined") window.location.reload();
|
|
729
|
+
} catch (thrown) {
|
|
730
|
+
setFailed(thrown instanceof Error && thrown.message ? thrown.message : "The organization could not be restored.");
|
|
731
|
+
setBusy(false);
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
return /* @__PURE__ */ jsxs2(
|
|
735
|
+
Alert,
|
|
736
|
+
{
|
|
737
|
+
variant: "destructive",
|
|
738
|
+
role: "alert",
|
|
739
|
+
"data-refusal-notice": "",
|
|
740
|
+
"data-archived-organization": organizationId,
|
|
741
|
+
className: cn2("text-xs", className),
|
|
742
|
+
errorFacts: { message: "This organization is archived", title: "This organization is archived", error, origin: "records-ui/ArchivedOrganizationNotice" },
|
|
743
|
+
children: [
|
|
744
|
+
/* @__PURE__ */ jsx3(AlertTitle, { className: "text-xs font-medium", children: "This organization is archived" }),
|
|
745
|
+
/* @__PURE__ */ jsxs2(AlertDescription, { className: "space-y-1 text-xs", children: [
|
|
746
|
+
/* @__PURE__ */ jsx3("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." }),
|
|
747
|
+
mayRestore === true ? /* @__PURE__ */ jsx3(
|
|
748
|
+
"button",
|
|
749
|
+
{
|
|
750
|
+
type: "button",
|
|
751
|
+
"data-restore-organization": "",
|
|
752
|
+
disabled: busy,
|
|
753
|
+
className: "rounded border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-60",
|
|
754
|
+
onClick: () => void restore(),
|
|
755
|
+
children: busy ? "Restoring..." : "Restore organization"
|
|
756
|
+
}
|
|
757
|
+
) : null,
|
|
758
|
+
mayRestore === false ? /* @__PURE__ */ jsx3("p", { "data-restore-who": "", className: "opacity-80", children: "Ask an owner of this organization to restore it." }) : null,
|
|
759
|
+
failed ? /* @__PURE__ */ jsx3("p", { "data-restore-refused": "", children: failed }) : null
|
|
760
|
+
] })
|
|
761
|
+
]
|
|
762
|
+
}
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// src/Refusal.tsx
|
|
767
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
768
|
+
function RefusalNotice({
|
|
769
|
+
error,
|
|
770
|
+
className,
|
|
771
|
+
actions,
|
|
772
|
+
onKeepEditing,
|
|
773
|
+
onDiscard
|
|
774
|
+
}) {
|
|
775
|
+
const archivedOrg = archivedOrganizationId(error);
|
|
776
|
+
if (archivedOrg) {
|
|
777
|
+
return /* @__PURE__ */ jsx4(ArchivedOrganizationNotice, { organizationId: archivedOrg, error, className });
|
|
778
|
+
}
|
|
779
|
+
const plain = refusalForAPerson(error);
|
|
780
|
+
const doors = onKeepEditing || onDiscard ? /* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center gap-1 pt-0.5", "data-refusal-doors": "", children: [
|
|
781
|
+
onKeepEditing ? /* @__PURE__ */ jsx4(
|
|
782
|
+
"button",
|
|
783
|
+
{
|
|
784
|
+
type: "button",
|
|
785
|
+
"data-refusal-keep-editing": "",
|
|
786
|
+
className: "rounded border px-2 py-0.5 text-xs hover:bg-muted",
|
|
787
|
+
onClick: onKeepEditing,
|
|
788
|
+
children: "Keep editing"
|
|
789
|
+
}
|
|
790
|
+
) : null,
|
|
791
|
+
onDiscard ? /* @__PURE__ */ jsx4(
|
|
792
|
+
"button",
|
|
793
|
+
{
|
|
794
|
+
type: "button",
|
|
795
|
+
"data-refusal-discard": "",
|
|
796
|
+
className: "rounded border px-2 py-0.5 text-xs hover:bg-muted",
|
|
797
|
+
onClick: onDiscard,
|
|
798
|
+
children: "Discard"
|
|
799
|
+
}
|
|
800
|
+
) : null
|
|
801
|
+
] }) : null;
|
|
802
|
+
return /* @__PURE__ */ jsxs3(
|
|
803
|
+
Alert2,
|
|
804
|
+
{
|
|
805
|
+
variant: "destructive",
|
|
806
|
+
role: "alert",
|
|
807
|
+
"data-refusal-notice": "",
|
|
808
|
+
className: cn3("text-xs", className),
|
|
809
|
+
errorFacts: { message: plain.sentence, title: plain.title, error, origin: "records-ui/RefusalNotice" },
|
|
810
|
+
...plain.forEngineers ? { "data-for-engineers": plain.forEngineers } : {},
|
|
811
|
+
...error.sqlstate ? { "data-sqlstate": error.sqlstate } : {},
|
|
812
|
+
children: [
|
|
813
|
+
/* @__PURE__ */ jsx4(AlertTitle2, { className: "text-xs font-medium", children: plain.storeSaid ? plain.sentence : plain.title }),
|
|
814
|
+
/* @__PURE__ */ jsxs3(AlertDescription2, { className: "space-y-1 text-xs", children: [
|
|
815
|
+
plain.storeSaid || plain.sentence.replace(/\.$/, "") === plain.title ? null : /* @__PURE__ */ jsx4("p", { children: plain.sentence }),
|
|
816
|
+
/* @__PURE__ */ jsx4("p", { className: "opacity-80", children: plain.remedy }),
|
|
817
|
+
actions,
|
|
818
|
+
doors
|
|
819
|
+
] })
|
|
820
|
+
]
|
|
821
|
+
}
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
function RefusalLine({ error, className }) {
|
|
825
|
+
const plain = refusalForAPerson(error);
|
|
826
|
+
return /* @__PURE__ */ jsx4(
|
|
827
|
+
ErrorBox,
|
|
828
|
+
{
|
|
829
|
+
"data-refusal-line": "",
|
|
830
|
+
className: cn3("text-xs text-destructive", className),
|
|
831
|
+
message: archivedOrganizationId(error) ? "This organization is archived. An owner can restore it." : refusalLineForAPerson(error),
|
|
832
|
+
error,
|
|
833
|
+
origin: "records-ui/RefusalLine",
|
|
834
|
+
...plain.forEngineers ? { "data-for-engineers": plain.forEngineers } : {}
|
|
835
|
+
}
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
|
|
568
839
|
// src/AddChoicesInline.tsx
|
|
569
|
-
import { jsx as
|
|
840
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
570
841
|
function AddChoicesInline({ field, onAdded, disabled = false }) {
|
|
571
842
|
const client = useOptionalRecordsClient();
|
|
572
|
-
const [open, setOpen] =
|
|
573
|
-
const [rows, setRows] =
|
|
574
|
-
const [saving, setSaving] =
|
|
575
|
-
const [refused, setRefused] =
|
|
843
|
+
const [open, setOpen] = useState3(false);
|
|
844
|
+
const [rows, setRows] = useState3(() => [newChoiceRow([])]);
|
|
845
|
+
const [saving, setSaving] = useState3(false);
|
|
846
|
+
const [refused, setRefused] = useState3(null);
|
|
576
847
|
if (!client) return null;
|
|
577
848
|
const words = rows.map((r) => r.words.trim()).filter((w) => w !== "");
|
|
578
849
|
const missing = whatTheChoiceListIsMissing(rows);
|
|
@@ -582,19 +853,20 @@ function AddChoicesInline({ field, onAdded, disabled = false }) {
|
|
|
582
853
|
const done = await client.fieldUpdate({ field_id: field.id, patch: { options_add: words } });
|
|
583
854
|
setSaving(false);
|
|
584
855
|
if (!done.ok) {
|
|
585
|
-
setRefused(
|
|
856
|
+
setRefused(done.error);
|
|
586
857
|
return;
|
|
587
858
|
}
|
|
588
859
|
setOpen(false);
|
|
589
860
|
setRows([newChoiceRow([])]);
|
|
590
861
|
onAdded();
|
|
591
862
|
};
|
|
592
|
-
return /* @__PURE__ */
|
|
593
|
-
/* @__PURE__ */
|
|
594
|
-
/* @__PURE__ */
|
|
595
|
-
/* @__PURE__ */
|
|
596
|
-
missing
|
|
597
|
-
/* @__PURE__ */
|
|
863
|
+
return /* @__PURE__ */ jsxs4(Popover2, { open, onOpenChange: setOpen, children: [
|
|
864
|
+
/* @__PURE__ */ jsx5(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsx5(Button2, { type: "button", size: "sm", variant: "outline", className: "h-7 self-start text-xs", disabled, "data-records-add-choices": "", children: "Add choices" }) }),
|
|
865
|
+
/* @__PURE__ */ jsxs4(PopoverContent2, { className: "w-72 space-y-2 p-3", align: "start", children: [
|
|
866
|
+
/* @__PURE__ */ jsx5(ChoiceListEditor, { isNew: true, rows, onRows: setRows }),
|
|
867
|
+
missing ? /* @__PURE__ */ jsx5("p", { className: "text-[11px] text-muted-foreground", children: missing }) : null,
|
|
868
|
+
refused ? /* @__PURE__ */ jsx5(RefusalLine, { error: refused }) : null,
|
|
869
|
+
/* @__PURE__ */ jsx5(Button2, { type: "button", size: "sm", className: "h-7 text-xs", disabled: saving || words.length === 0 || missing !== null, onClick: () => void save(), children: "Save choices" })
|
|
598
870
|
] })
|
|
599
871
|
] });
|
|
600
872
|
}
|
|
@@ -664,7 +936,7 @@ function isDateLike(value) {
|
|
|
664
936
|
}
|
|
665
937
|
|
|
666
938
|
// src/newerKindValues.tsx
|
|
667
|
-
import { useEffect as
|
|
939
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
|
|
668
940
|
import { codeSpanText, findInlineCodeSpans } from "@ai-matrx/content-ir/source";
|
|
669
941
|
import {
|
|
670
942
|
ADDRESS_PARTS,
|
|
@@ -681,29 +953,29 @@ import {
|
|
|
681
953
|
safeLinkHref,
|
|
682
954
|
statusGroupOf
|
|
683
955
|
} from "@ai-matrx/records";
|
|
684
|
-
import { BasicInput as BasicInput2, cn as
|
|
685
|
-
import { Fragment as Fragment2, jsx as
|
|
956
|
+
import { BasicInput as BasicInput2, cn as cn4 } from "@ai-matrx/design-system";
|
|
957
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
686
958
|
var own = (event) => event.stopPropagation();
|
|
687
959
|
function newerKindValue(field, value, opts = {}) {
|
|
688
960
|
switch (newerKindOf2(field)) {
|
|
689
961
|
case "duration": {
|
|
690
962
|
const words = durationText(value);
|
|
691
|
-
return words === null ? void 0 : /* @__PURE__ */
|
|
963
|
+
return words === null ? void 0 : /* @__PURE__ */ jsx6("span", { className: "tabular-nums", "data-records-duration": "", children: words });
|
|
692
964
|
}
|
|
693
965
|
case "created_by":
|
|
694
966
|
case "modified_by":
|
|
695
|
-
return isPersonStamp(value) ? /* @__PURE__ */
|
|
967
|
+
return isPersonStamp(value) ? /* @__PURE__ */ jsx6(PersonStampChip, { stamp: value }) : void 0;
|
|
696
968
|
case "address":
|
|
697
|
-
return isAddressValue(value) || typeof value === "string" ? /* @__PURE__ */
|
|
969
|
+
return isAddressValue(value) || typeof value === "string" ? /* @__PURE__ */ jsx6(AddressLink, { value }) : void 0;
|
|
698
970
|
case "barcode":
|
|
699
|
-
return typeof value === "string" ? /* @__PURE__ */
|
|
700
|
-
/* @__PURE__ */
|
|
701
|
-
/* @__PURE__ */
|
|
971
|
+
return typeof value === "string" ? /* @__PURE__ */ jsxs5("span", { className: "inline-flex min-w-0 items-center gap-1 font-mono text-xs", "data-records-barcode": "", title: value, children: [
|
|
972
|
+
/* @__PURE__ */ jsx6("span", { "aria-hidden": "true", className: "text-muted-foreground", children: "\u25AE\u25AF\u25AE" }),
|
|
973
|
+
/* @__PURE__ */ jsx6("span", { className: "truncate", children: value })
|
|
702
974
|
] }) : void 0;
|
|
703
975
|
case "rich_text":
|
|
704
|
-
return typeof value === "string" ? /* @__PURE__ */
|
|
976
|
+
return typeof value === "string" ? /* @__PURE__ */ jsx6(SafeMarkdown, { text: value, clipped: opts.inCell === true }) : void 0;
|
|
705
977
|
case "count":
|
|
706
|
-
return typeof value === "number" ? /* @__PURE__ */
|
|
978
|
+
return typeof value === "number" ? /* @__PURE__ */ jsx6("span", { className: "tabular-nums", children: value.toLocaleString() }) : void 0;
|
|
707
979
|
default:
|
|
708
980
|
return void 0;
|
|
709
981
|
}
|
|
@@ -713,8 +985,8 @@ function PersonStampChip({ stamp }) {
|
|
|
713
985
|
const tier = stamp.actor ?? "user";
|
|
714
986
|
const name = tier === "user" ? stamp.name : null;
|
|
715
987
|
const initial = tier === "system" ? "\u2699" : tier === "agent" ? "\u2726" : name && name.trim() !== "" ? name.trim()[0].toUpperCase() : "?";
|
|
716
|
-
return /* @__PURE__ */
|
|
717
|
-
/* @__PURE__ */
|
|
988
|
+
return /* @__PURE__ */ jsxs5("span", { className: "inline-flex min-w-0 items-center gap-1.5", "data-records-person-stamp": tier, children: [
|
|
989
|
+
/* @__PURE__ */ jsx6(
|
|
718
990
|
"span",
|
|
719
991
|
{
|
|
720
992
|
"aria-hidden": "true",
|
|
@@ -722,14 +994,14 @@ function PersonStampChip({ stamp }) {
|
|
|
722
994
|
children: initial
|
|
723
995
|
}
|
|
724
996
|
),
|
|
725
|
-
/* @__PURE__ */
|
|
997
|
+
/* @__PURE__ */ jsx6("span", { className: cn4("truncate", tier === "user" && !name ? "italic text-muted-foreground" : ""), children: words })
|
|
726
998
|
] });
|
|
727
999
|
}
|
|
728
1000
|
function AddressLink({ value }) {
|
|
729
1001
|
const words = addressText(value);
|
|
730
1002
|
const href = addressMapUrl(value);
|
|
731
|
-
if (!words || !href) return /* @__PURE__ */
|
|
732
|
-
return /* @__PURE__ */
|
|
1003
|
+
if (!words || !href) return /* @__PURE__ */ jsx6("span", { className: "text-muted-foreground", children: "\u2014" });
|
|
1004
|
+
return /* @__PURE__ */ jsxs5(
|
|
733
1005
|
"a",
|
|
734
1006
|
{
|
|
735
1007
|
href,
|
|
@@ -740,8 +1012,8 @@ function AddressLink({ value }) {
|
|
|
740
1012
|
"data-records-address": "",
|
|
741
1013
|
onClick: own,
|
|
742
1014
|
children: [
|
|
743
|
-
/* @__PURE__ */
|
|
744
|
-
/* @__PURE__ */
|
|
1015
|
+
/* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: "\u2316" }),
|
|
1016
|
+
/* @__PURE__ */ jsx6("span", { className: "truncate", children: words })
|
|
745
1017
|
]
|
|
746
1018
|
}
|
|
747
1019
|
);
|
|
@@ -761,7 +1033,7 @@ function inline(text, key) {
|
|
|
761
1033
|
for (const r of findInlineCodeSpans(text)) {
|
|
762
1034
|
if (r.start < at) continue;
|
|
763
1035
|
if (r.start > at) out.push(...marks(text.slice(at, r.start), `${key}-m${n++}`));
|
|
764
|
-
out.push(/* @__PURE__ */
|
|
1036
|
+
out.push(/* @__PURE__ */ jsx6("code", { className: "rounded bg-muted px-1 font-mono text-[0.9em]", children: codeSpanText(text.slice(r.start, r.end)) }, `${key}-c${n++}`));
|
|
765
1037
|
at = r.end;
|
|
766
1038
|
}
|
|
767
1039
|
if (at < text.length) out.push(...marks(text.slice(at), `${key}-m${n++}`));
|
|
@@ -777,14 +1049,14 @@ function marks(text, key) {
|
|
|
777
1049
|
if (at > last) out.push(text.slice(last, at));
|
|
778
1050
|
const tok = m[0];
|
|
779
1051
|
const k = `${key}-${i++}`;
|
|
780
|
-
if (tok.startsWith("**") || tok.startsWith("__")) out.push(/* @__PURE__ */
|
|
1052
|
+
if (tok.startsWith("**") || tok.startsWith("__")) out.push(/* @__PURE__ */ jsx6("strong", { children: tok.slice(2, -2) }, k));
|
|
781
1053
|
else if (tok.startsWith("[")) {
|
|
782
1054
|
const link = /^\[([^\]]+)\]\(([^)\s]+)\)$/.exec(tok);
|
|
783
1055
|
const href = safeLinkHref(link?.[2] ?? "");
|
|
784
1056
|
out.push(
|
|
785
|
-
href ? /* @__PURE__ */
|
|
1057
|
+
href ? /* @__PURE__ */ jsx6("a", { href, target: "_blank", rel: "noopener noreferrer", className: "text-primary underline-offset-2 hover:underline", onClick: own, children: link?.[1] }, k) : link?.[1] ?? tok
|
|
786
1058
|
);
|
|
787
|
-
} else out.push(/* @__PURE__ */
|
|
1059
|
+
} else out.push(/* @__PURE__ */ jsx6("em", { children: tok.slice(1, -1) }, k));
|
|
788
1060
|
last = at + tok.length;
|
|
789
1061
|
}
|
|
790
1062
|
if (last < text.length) out.push(text.slice(last));
|
|
@@ -797,15 +1069,15 @@ function SafeMarkdown({ text, clipped }) {
|
|
|
797
1069
|
let para = [];
|
|
798
1070
|
const flushPara = () => {
|
|
799
1071
|
if (para.length > 0) {
|
|
800
|
-
blocks.push(/* @__PURE__ */
|
|
1072
|
+
blocks.push(/* @__PURE__ */ jsx6("p", { children: inline(para.join(" "), `p${blocks.length}`) }, `p${blocks.length}`));
|
|
801
1073
|
para = [];
|
|
802
1074
|
}
|
|
803
1075
|
};
|
|
804
1076
|
const flushList = () => {
|
|
805
1077
|
if (list) {
|
|
806
|
-
const items = list.items.map((item, i) => /* @__PURE__ */
|
|
1078
|
+
const items = list.items.map((item, i) => /* @__PURE__ */ jsx6("li", { children: inline(item, `l${blocks.length}-${i}`) }, i));
|
|
807
1079
|
blocks.push(
|
|
808
|
-
list.ordered ? /* @__PURE__ */
|
|
1080
|
+
list.ordered ? /* @__PURE__ */ jsx6("ol", { className: "ml-4 list-decimal", children: items }, `o${blocks.length}`) : /* @__PURE__ */ jsx6("ul", { className: "ml-4 list-disc", children: items }, `u${blocks.length}`)
|
|
809
1081
|
);
|
|
810
1082
|
list = null;
|
|
811
1083
|
}
|
|
@@ -824,7 +1096,7 @@ function SafeMarkdown({ text, clipped }) {
|
|
|
824
1096
|
} else if (heading) {
|
|
825
1097
|
flushPara();
|
|
826
1098
|
flushList();
|
|
827
|
-
blocks.push(/* @__PURE__ */
|
|
1099
|
+
blocks.push(/* @__PURE__ */ jsx6("p", { className: "font-semibold", children: inline(heading[2], `h${blocks.length}`) }, `h${blocks.length}`));
|
|
828
1100
|
} else if (line.trim() === "") {
|
|
829
1101
|
flushPara();
|
|
830
1102
|
flushList();
|
|
@@ -835,10 +1107,10 @@ function SafeMarkdown({ text, clipped }) {
|
|
|
835
1107
|
}
|
|
836
1108
|
flushPara();
|
|
837
1109
|
flushList();
|
|
838
|
-
return /* @__PURE__ */
|
|
1110
|
+
return /* @__PURE__ */ jsx6(
|
|
839
1111
|
"span",
|
|
840
1112
|
{
|
|
841
|
-
className:
|
|
1113
|
+
className: cn4("block min-w-0 space-y-1 whitespace-normal text-sm", clipped ? "max-h-[4.5em] overflow-hidden" : ""),
|
|
842
1114
|
"data-records-rich-text": "",
|
|
843
1115
|
children: blocks
|
|
844
1116
|
}
|
|
@@ -847,27 +1119,27 @@ function SafeMarkdown({ text, clipped }) {
|
|
|
847
1119
|
function newerKindControl(props) {
|
|
848
1120
|
switch (newerKindOf2(props.field)) {
|
|
849
1121
|
case "duration":
|
|
850
|
-
return /* @__PURE__ */
|
|
1122
|
+
return /* @__PURE__ */ jsx6(DurationControl, { ...props });
|
|
851
1123
|
case "address":
|
|
852
|
-
return /* @__PURE__ */
|
|
1124
|
+
return /* @__PURE__ */ jsx6(AddressControl, { ...props });
|
|
853
1125
|
case "barcode":
|
|
854
|
-
return /* @__PURE__ */
|
|
1126
|
+
return /* @__PURE__ */ jsx6(BarcodeControl, { ...props });
|
|
855
1127
|
case "created_by":
|
|
856
1128
|
case "modified_by":
|
|
857
1129
|
case "count":
|
|
858
|
-
return /* @__PURE__ */
|
|
1130
|
+
return /* @__PURE__ */ jsx6("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) });
|
|
859
1131
|
default:
|
|
860
1132
|
return void 0;
|
|
861
1133
|
}
|
|
862
1134
|
}
|
|
863
1135
|
function DurationControl({ value, onChange, disabled, id }) {
|
|
864
|
-
const [text, setText] =
|
|
865
|
-
const [wrong, setWrong] =
|
|
866
|
-
|
|
1136
|
+
const [text, setText] = useState4(() => durationText(value) ?? "");
|
|
1137
|
+
const [wrong, setWrong] = useState4(false);
|
|
1138
|
+
useEffect3(() => {
|
|
867
1139
|
setText(durationText(value) ?? "");
|
|
868
1140
|
}, [value]);
|
|
869
|
-
return /* @__PURE__ */
|
|
870
|
-
/* @__PURE__ */
|
|
1141
|
+
return /* @__PURE__ */ jsxs5("span", { className: "flex flex-col gap-1", children: [
|
|
1142
|
+
/* @__PURE__ */ jsx6(
|
|
871
1143
|
BasicInput2,
|
|
872
1144
|
{
|
|
873
1145
|
id,
|
|
@@ -893,7 +1165,7 @@ function DurationControl({ value, onChange, disabled, id }) {
|
|
|
893
1165
|
}
|
|
894
1166
|
}
|
|
895
1167
|
),
|
|
896
|
-
wrong ? /* @__PURE__ */
|
|
1168
|
+
wrong ? /* @__PURE__ */ jsx6("span", { className: "text-[11px] text-destructive", children: "Write it like 45 min, 1:30 or 1h 30m." }) : null
|
|
897
1169
|
] });
|
|
898
1170
|
}
|
|
899
1171
|
var ADDRESS_LABELS = {
|
|
@@ -917,7 +1189,7 @@ function AddressControl({ value, onChange, disabled, id }) {
|
|
|
917
1189
|
const kept = Object.fromEntries(Object.entries(next).filter(([, v]) => typeof v === "string" && v.trim() !== ""));
|
|
918
1190
|
onChange(Object.keys(kept).length === 0 ? null : kept);
|
|
919
1191
|
};
|
|
920
|
-
return /* @__PURE__ */
|
|
1192
|
+
return /* @__PURE__ */ jsx6("span", { id, className: "grid grid-cols-2 gap-1.5", "data-records-address-control": "", children: ADDRESS_PARTS.map((part) => /* @__PURE__ */ jsx6(
|
|
921
1193
|
BasicInput2,
|
|
922
1194
|
{
|
|
923
1195
|
"aria-label": ADDRESS_LABELS[part],
|
|
@@ -937,11 +1209,11 @@ function barcodeDetector() {
|
|
|
937
1209
|
}
|
|
938
1210
|
function BarcodeControl({ value, onChange, disabled, id }) {
|
|
939
1211
|
const file = useRef2(null);
|
|
940
|
-
const [said2, setSaid] =
|
|
1212
|
+
const [said2, setSaid] = useState4(null);
|
|
941
1213
|
const Detect = barcodeDetector();
|
|
942
|
-
return /* @__PURE__ */
|
|
943
|
-
/* @__PURE__ */
|
|
944
|
-
/* @__PURE__ */
|
|
1214
|
+
return /* @__PURE__ */ jsxs5("span", { className: "flex flex-col gap-1", children: [
|
|
1215
|
+
/* @__PURE__ */ jsxs5("span", { className: "flex items-center gap-1.5", children: [
|
|
1216
|
+
/* @__PURE__ */ jsx6(
|
|
945
1217
|
BasicInput2,
|
|
946
1218
|
{
|
|
947
1219
|
id,
|
|
@@ -952,8 +1224,8 @@ function BarcodeControl({ value, onChange, disabled, id }) {
|
|
|
952
1224
|
onChange: (e) => onChange(e.target.value === "" ? null : e.target.value)
|
|
953
1225
|
}
|
|
954
1226
|
),
|
|
955
|
-
Detect && !disabled ? /* @__PURE__ */
|
|
956
|
-
/* @__PURE__ */
|
|
1227
|
+
Detect && !disabled ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1228
|
+
/* @__PURE__ */ jsx6(
|
|
957
1229
|
"button",
|
|
958
1230
|
{
|
|
959
1231
|
type: "button",
|
|
@@ -962,7 +1234,7 @@ function BarcodeControl({ value, onChange, disabled, id }) {
|
|
|
962
1234
|
children: "Scan"
|
|
963
1235
|
}
|
|
964
1236
|
),
|
|
965
|
-
/* @__PURE__ */
|
|
1237
|
+
/* @__PURE__ */ jsx6(
|
|
966
1238
|
"input",
|
|
967
1239
|
{
|
|
968
1240
|
ref: file,
|
|
@@ -988,7 +1260,7 @@ function BarcodeControl({ value, onChange, disabled, id }) {
|
|
|
988
1260
|
)
|
|
989
1261
|
] }) : null
|
|
990
1262
|
] }),
|
|
991
|
-
said2 ? /* @__PURE__ */
|
|
1263
|
+
said2 ? /* @__PURE__ */ jsx6("span", { className: "text-[11px] text-muted-foreground", children: said2 }) : null
|
|
992
1264
|
] });
|
|
993
1265
|
}
|
|
994
1266
|
|
|
@@ -1166,23 +1438,23 @@ import { useOptionalRecordsClient as useOptionalRecordsClient2 } from "@ai-matrx
|
|
|
1166
1438
|
import { BasicInput as BasicInput4, Button as Button4, cn as cn7 } from "@ai-matrx/design-system";
|
|
1167
1439
|
|
|
1168
1440
|
// src/PickOrAdd.tsx
|
|
1169
|
-
import { useEffect as
|
|
1441
|
+
import { useEffect as useEffect4, useRef as useRef3, useState as useState5 } from "react";
|
|
1170
1442
|
|
|
1171
1443
|
// src/personChip.tsx
|
|
1172
|
-
import { cn as
|
|
1173
|
-
import { jsx as
|
|
1444
|
+
import { cn as cn5 } from "@ai-matrx/design-system";
|
|
1445
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1174
1446
|
function initialsOf(name) {
|
|
1175
1447
|
const words = name.replace(/@.*$/, "").split(/[\s._-]+/).filter((w) => /\p{L}|\d/u.test(w));
|
|
1176
1448
|
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());
|
|
1177
1449
|
return letters.join("") || "?";
|
|
1178
1450
|
}
|
|
1179
1451
|
function PersonAvatar({ name, size = "sm" }) {
|
|
1180
|
-
return /* @__PURE__ */
|
|
1452
|
+
return /* @__PURE__ */ jsx7(
|
|
1181
1453
|
"span",
|
|
1182
1454
|
{
|
|
1183
1455
|
"aria-hidden": "true",
|
|
1184
1456
|
"data-records-person-avatar": "",
|
|
1185
|
-
className:
|
|
1457
|
+
className: cn5(
|
|
1186
1458
|
"inline-flex shrink-0 items-center justify-center rounded-full bg-foreground/10 font-medium text-foreground/80",
|
|
1187
1459
|
size === "md" ? "size-5 text-[10px]" : "size-4 text-[9px]"
|
|
1188
1460
|
),
|
|
@@ -1191,35 +1463,35 @@ function PersonAvatar({ name, size = "sm" }) {
|
|
|
1191
1463
|
);
|
|
1192
1464
|
}
|
|
1193
1465
|
function PersonChip({ name, onRemove, className }) {
|
|
1194
|
-
return /* @__PURE__ */
|
|
1466
|
+
return /* @__PURE__ */ jsxs6(
|
|
1195
1467
|
"span",
|
|
1196
1468
|
{
|
|
1197
1469
|
"data-records-person-chip": "",
|
|
1198
1470
|
title: name,
|
|
1199
|
-
className:
|
|
1471
|
+
className: cn5("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),
|
|
1200
1472
|
children: [
|
|
1201
|
-
/* @__PURE__ */
|
|
1202
|
-
/* @__PURE__ */
|
|
1203
|
-
onRemove ? /* @__PURE__ */
|
|
1473
|
+
/* @__PURE__ */ jsx7(PersonAvatar, { name }),
|
|
1474
|
+
/* @__PURE__ */ jsx7("span", { className: "min-w-0 truncate", children: name }),
|
|
1475
|
+
onRemove ? /* @__PURE__ */ jsx7("button", { type: "button", onClick: onRemove, "aria-label": `Remove ${name}`, className: "shrink-0 opacity-60 hover:opacity-100", children: "\xD7" }) : null
|
|
1204
1476
|
]
|
|
1205
1477
|
}
|
|
1206
1478
|
);
|
|
1207
1479
|
}
|
|
1208
1480
|
|
|
1209
1481
|
// src/PickOrAdd.tsx
|
|
1210
|
-
import { BasicInput as BasicInput3, Button as Button3, Popover as Popover3, PopoverAnchor, PopoverContent as PopoverContent3, PopoverTrigger as PopoverTrigger3, ScrollArea, cn as
|
|
1211
|
-
import { jsx as
|
|
1482
|
+
import { BasicInput as BasicInput3, Button as Button3, Popover as Popover3, PopoverAnchor, PopoverContent as PopoverContent3, PopoverTrigger as PopoverTrigger3, ScrollArea, cn as cn6 } from "@ai-matrx/design-system";
|
|
1483
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1212
1484
|
function Glyph({ d, className }) {
|
|
1213
|
-
return /* @__PURE__ */
|
|
1485
|
+
return /* @__PURE__ */ jsx8("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, className, children: /* @__PURE__ */ jsx8("path", { d }) });
|
|
1214
1486
|
}
|
|
1215
1487
|
var TICK = "m5 12 4 4L19 6";
|
|
1216
1488
|
var CROSS = "M18 6 6 18M6 6l12 12";
|
|
1217
1489
|
var PLUS = "M12 5v14M5 12h14";
|
|
1218
1490
|
function useListKeys(args) {
|
|
1219
1491
|
const { count, resetOn, onPick, onNothing, onClose, onFinish, onBackspaceEmpty, searchEmpty } = args;
|
|
1220
|
-
const [highlight, setHighlight] =
|
|
1221
|
-
const [moved, setMoved] =
|
|
1222
|
-
|
|
1492
|
+
const [highlight, setHighlight] = useState5(0);
|
|
1493
|
+
const [moved, setMoved] = useState5(false);
|
|
1494
|
+
useEffect4(() => {
|
|
1223
1495
|
setHighlight(0);
|
|
1224
1496
|
setMoved(false);
|
|
1225
1497
|
}, [resetOn]);
|
|
@@ -1265,10 +1537,10 @@ function PickRow({
|
|
|
1265
1537
|
onPoint
|
|
1266
1538
|
}) {
|
|
1267
1539
|
const ref = useRef3(null);
|
|
1268
|
-
|
|
1540
|
+
useEffect4(() => {
|
|
1269
1541
|
if (highlighted) ref.current?.scrollIntoView?.({ block: "nearest" });
|
|
1270
1542
|
}, [highlighted]);
|
|
1271
|
-
return /* @__PURE__ */
|
|
1543
|
+
return /* @__PURE__ */ jsxs7(
|
|
1272
1544
|
"button",
|
|
1273
1545
|
{
|
|
1274
1546
|
ref,
|
|
@@ -1281,19 +1553,19 @@ function PickRow({
|
|
|
1281
1553
|
title: title ?? label,
|
|
1282
1554
|
...attrs ?? {},
|
|
1283
1555
|
"data-pick-highlighted": highlighted ? "" : void 0,
|
|
1284
|
-
className:
|
|
1556
|
+
className: cn6(
|
|
1285
1557
|
"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",
|
|
1286
1558
|
highlighted ? "bg-accent text-accent-foreground" : ""
|
|
1287
1559
|
),
|
|
1288
1560
|
children: [
|
|
1289
|
-
/* @__PURE__ */
|
|
1290
|
-
picked ? /* @__PURE__ */
|
|
1291
|
-
icon === "plus" ? /* @__PURE__ */
|
|
1561
|
+
/* @__PURE__ */ jsxs7("span", { className: "flex size-3.5 shrink-0 items-center justify-center", children: [
|
|
1562
|
+
picked ? /* @__PURE__ */ jsx8("span", { "data-pick-tick": "", className: "contents", children: /* @__PURE__ */ jsx8(Glyph, { d: TICK, className: "size-3.5" }) }) : null,
|
|
1563
|
+
icon === "plus" ? /* @__PURE__ */ jsx8(Glyph, { d: PLUS, className: "size-3.5 text-muted-foreground" }) : null
|
|
1292
1564
|
] }),
|
|
1293
|
-
person ? /* @__PURE__ */
|
|
1294
|
-
/* @__PURE__ */
|
|
1295
|
-
chip ? /* @__PURE__ */
|
|
1296
|
-
detail ? /* @__PURE__ */
|
|
1565
|
+
person ? /* @__PURE__ */ jsx8(PersonAvatar, { name: label, size: "md" }) : null,
|
|
1566
|
+
/* @__PURE__ */ jsxs7("span", { className: "min-w-0 flex-1", children: [
|
|
1567
|
+
chip ? /* @__PURE__ */ jsx8("span", { className: cn6("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__ */ jsx8("span", { className: "block truncate", children: label }),
|
|
1568
|
+
detail ? /* @__PURE__ */ jsx8("span", { className: "block truncate text-xs text-muted-foreground", "data-tell-apart": "", children: detail }) : null
|
|
1297
1569
|
] })
|
|
1298
1570
|
]
|
|
1299
1571
|
}
|
|
@@ -1301,26 +1573,26 @@ function PickRow({
|
|
|
1301
1573
|
}
|
|
1302
1574
|
function PickChips({ chips }) {
|
|
1303
1575
|
if (chips.length === 0) return null;
|
|
1304
|
-
return /* @__PURE__ */
|
|
1305
|
-
(c) => c.person ? /* @__PURE__ */
|
|
1576
|
+
return /* @__PURE__ */ jsx8("div", { className: "flex flex-wrap gap-1 px-1 pb-1", "data-pick-chips": "", children: chips.map(
|
|
1577
|
+
(c) => c.person ? /* @__PURE__ */ jsx8(PersonChip, { name: c.label, onRemove: c.onRemove }, c.id) : /* @__PURE__ */ jsxs7(
|
|
1306
1578
|
"span",
|
|
1307
1579
|
{
|
|
1308
1580
|
"data-pick-chip": "",
|
|
1309
1581
|
title: c.label,
|
|
1310
|
-
className:
|
|
1582
|
+
className: cn6(
|
|
1311
1583
|
"inline-flex max-w-full items-center gap-1 rounded-md border px-1.5 py-0.5 text-xs font-medium",
|
|
1312
1584
|
c.chip ?? "bg-secondary text-secondary-foreground"
|
|
1313
1585
|
),
|
|
1314
1586
|
children: [
|
|
1315
|
-
/* @__PURE__ */
|
|
1316
|
-
c.onRemove ? /* @__PURE__ */
|
|
1587
|
+
/* @__PURE__ */ jsx8("span", { className: "min-w-0 truncate", children: c.label }),
|
|
1588
|
+
c.onRemove ? /* @__PURE__ */ jsx8(
|
|
1317
1589
|
"button",
|
|
1318
1590
|
{
|
|
1319
1591
|
type: "button",
|
|
1320
1592
|
"aria-label": `Remove ${c.label}`,
|
|
1321
1593
|
onClick: c.onRemove,
|
|
1322
1594
|
className: "shrink-0 rounded-sm opacity-60 hover:opacity-100",
|
|
1323
|
-
children: /* @__PURE__ */
|
|
1595
|
+
children: /* @__PURE__ */ jsx8(Glyph, { d: CROSS, className: "size-3" })
|
|
1324
1596
|
}
|
|
1325
1597
|
) : null
|
|
1326
1598
|
]
|
|
@@ -1375,7 +1647,7 @@ function PickOrAdd({
|
|
|
1375
1647
|
searchEmpty: search === ""
|
|
1376
1648
|
});
|
|
1377
1649
|
const hasFoot = Boolean(foot) || Boolean(footNote);
|
|
1378
|
-
const addRowNode = addRow ? /* @__PURE__ */
|
|
1650
|
+
const addRowNode = addRow ? /* @__PURE__ */ jsx8(
|
|
1379
1651
|
PickRow,
|
|
1380
1652
|
{
|
|
1381
1653
|
label: addRow.label,
|
|
@@ -1388,9 +1660,9 @@ function PickOrAdd({
|
|
|
1388
1660
|
onPoint: () => keys.setHighlight(addAt)
|
|
1389
1661
|
}
|
|
1390
1662
|
) : null;
|
|
1391
|
-
return /* @__PURE__ */
|
|
1392
|
-
anchored ? /* @__PURE__ */
|
|
1393
|
-
/* @__PURE__ */
|
|
1663
|
+
return /* @__PURE__ */ jsxs7(Popover3, { open, onOpenChange, children: [
|
|
1664
|
+
anchored ? /* @__PURE__ */ jsx8(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsx8("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__ */ jsx8(PopoverTrigger3, { asChild: true, children: /* @__PURE__ */ jsx8(Button3, { id: triggerId, type: "button", size: "sm", variant: "outline", className: triggerSize === "field" ? "h-9" : void 0, "aria-label": triggerLabel, children: triggerText }) }),
|
|
1665
|
+
/* @__PURE__ */ jsxs7(
|
|
1394
1666
|
PopoverContent3,
|
|
1395
1667
|
{
|
|
1396
1668
|
sizing: "content",
|
|
@@ -1412,8 +1684,8 @@ function PickOrAdd({
|
|
|
1412
1684
|
if (anchored) event.preventDefault();
|
|
1413
1685
|
},
|
|
1414
1686
|
children: [
|
|
1415
|
-
chips ? /* @__PURE__ */
|
|
1416
|
-
/* @__PURE__ */
|
|
1687
|
+
chips ? /* @__PURE__ */ jsx8(PickChips, { chips }) : null,
|
|
1688
|
+
/* @__PURE__ */ jsx8(
|
|
1417
1689
|
BasicInput3,
|
|
1418
1690
|
{
|
|
1419
1691
|
value: search,
|
|
@@ -1427,9 +1699,9 @@ function PickOrAdd({
|
|
|
1427
1699
|
}
|
|
1428
1700
|
),
|
|
1429
1701
|
notice,
|
|
1430
|
-
/* @__PURE__ */
|
|
1431
|
-
/* @__PURE__ */
|
|
1432
|
-
items.map((item, index) => /* @__PURE__ */
|
|
1702
|
+
/* @__PURE__ */ jsxs7(ScrollArea, { className: "max-h-64", children: [
|
|
1703
|
+
/* @__PURE__ */ jsxs7("div", { role: "listbox", "aria-label": triggerLabel, "aria-multiselectable": multi ? true : void 0, children: [
|
|
1704
|
+
items.map((item, index) => /* @__PURE__ */ jsx8(
|
|
1433
1705
|
PickRow,
|
|
1434
1706
|
{
|
|
1435
1707
|
label: item.label,
|
|
@@ -1450,7 +1722,7 @@ function PickOrAdd({
|
|
|
1450
1722
|
] }),
|
|
1451
1723
|
items.length === 0 && empty ? empty : null
|
|
1452
1724
|
] }),
|
|
1453
|
-
hasFoot ? /* @__PURE__ */
|
|
1725
|
+
hasFoot ? /* @__PURE__ */ jsxs7("div", { className: "mt-1 border-t pt-1", children: [
|
|
1454
1726
|
foot,
|
|
1455
1727
|
footNote
|
|
1456
1728
|
] }) : null
|
|
@@ -1460,277 +1732,6 @@ function PickOrAdd({
|
|
|
1460
1732
|
] });
|
|
1461
1733
|
}
|
|
1462
1734
|
|
|
1463
|
-
// src/Refusal.tsx
|
|
1464
|
-
import { archivedOrganizationId } from "@ai-matrx/records/core";
|
|
1465
|
-
import { Alert as Alert2, AlertDescription as AlertDescription2, AlertTitle as AlertTitle2, ErrorBox, cn as cn6 } from "@ai-matrx/design-system";
|
|
1466
|
-
|
|
1467
|
-
// src/ArchivedOrganizationNotice.tsx
|
|
1468
|
-
import { useEffect as useEffect4, useState as useState5 } from "react";
|
|
1469
|
-
import { Alert, AlertDescription, AlertTitle, cn as cn5 } from "@ai-matrx/design-system";
|
|
1470
|
-
|
|
1471
|
-
// src/host.tsx
|
|
1472
|
-
import { createContext, useContext, useMemo } from "react";
|
|
1473
|
-
import { useMyLevel, useMyLevels } from "@ai-matrx/records/react";
|
|
1474
|
-
|
|
1475
|
-
// src/rights.ts
|
|
1476
|
-
import { atLeast } from "@ai-matrx/records";
|
|
1477
|
-
var LEVEL_WORD = {
|
|
1478
|
-
viewer: "Viewer",
|
|
1479
|
-
commenter: "Commenter",
|
|
1480
|
-
edit_content: "Content editor",
|
|
1481
|
-
editor: "Editor",
|
|
1482
|
-
admin: "Admin"
|
|
1483
|
-
};
|
|
1484
|
-
var NEEDS = {
|
|
1485
|
-
read: "viewer",
|
|
1486
|
-
// custom.io_comment_write
|
|
1487
|
-
comment: "commenter",
|
|
1488
|
-
// custom.record_update / custom.record_write — `edit_content` changes rows and page content;
|
|
1489
|
-
// columns, views and settings (structure) stay with admin below, and sharing with admin.
|
|
1490
|
-
write: "edit_content",
|
|
1491
|
-
// custom.view_designate / view_declare / migrate_merge / record_restore — all ask `editor`: more than
|
|
1492
|
-
// changing content (`edit_content`), less than changing columns (`admin`).
|
|
1493
|
-
organise: "editor",
|
|
1494
|
-
// custom.record_delete
|
|
1495
|
-
remove: "editor",
|
|
1496
|
-
// custom.share_grant — passing your access on is an administrator's right
|
|
1497
|
-
share: "admin",
|
|
1498
|
-
// custom.field_declare / field_update / field_retire / table settings
|
|
1499
|
-
structure: "admin"
|
|
1500
|
-
};
|
|
1501
|
-
var NOT_YET = "Still asking the store what you may do here. Nothing is offered until it has answered.";
|
|
1502
|
-
var NOTHING_AT_ALL = "You have not been given this. Ask somebody who administers it to share it with you.";
|
|
1503
|
-
function sentenceFor(what, level) {
|
|
1504
|
-
if (level === null) return NOTHING_AT_ALL;
|
|
1505
|
-
const need = LEVEL_WORD[NEEDS[what]];
|
|
1506
|
-
const have = LEVEL_WORD[level];
|
|
1507
|
-
const doing = {
|
|
1508
|
-
read: "open this",
|
|
1509
|
-
comment: "leave a comment",
|
|
1510
|
-
write: "change anything here",
|
|
1511
|
-
organise: "organise this",
|
|
1512
|
-
remove: "delete this",
|
|
1513
|
-
share: "pass this on to somebody else",
|
|
1514
|
-
structure: "change the columns of this table"
|
|
1515
|
-
};
|
|
1516
|
-
return `You are ${have} here, and it takes ${need} to ${doing[what]}. Ask somebody who is Admin on it to move you up.`;
|
|
1517
|
-
}
|
|
1518
|
-
function whatYouMayDo(level, known = true) {
|
|
1519
|
-
const may = (what) => known && atLeast(level, NEEDS[what]);
|
|
1520
|
-
return {
|
|
1521
|
-
level: known ? level : null,
|
|
1522
|
-
known,
|
|
1523
|
-
read: may("read"),
|
|
1524
|
-
comment: may("comment"),
|
|
1525
|
-
write: may("write"),
|
|
1526
|
-
organise: may("organise"),
|
|
1527
|
-
remove: may("remove"),
|
|
1528
|
-
share: may("share"),
|
|
1529
|
-
structure: may("structure"),
|
|
1530
|
-
why: (what) => known ? sentenceFor(what, level) : NOT_YET
|
|
1531
|
-
};
|
|
1532
|
-
}
|
|
1533
|
-
var NOT_ANSWERED_YET = whatYouMayDo(null, false);
|
|
1534
|
-
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.";
|
|
1535
|
-
function whatYouMayDoWithTable(table, level, known) {
|
|
1536
|
-
const base = whatYouMayDo(level, known);
|
|
1537
|
-
if (!table?.is_kernel) return table && tableIsLocked(table) ? lockedStructure(base) : base;
|
|
1538
|
-
return {
|
|
1539
|
-
...base,
|
|
1540
|
-
structure: false,
|
|
1541
|
-
why: (what) => what === "structure" ? KERNEL_REASON : base.why(what)
|
|
1542
|
-
};
|
|
1543
|
-
}
|
|
1544
|
-
function tableIsLocked(table) {
|
|
1545
|
-
return table?.metadata?.["locked"] === true;
|
|
1546
|
-
}
|
|
1547
|
-
var DATABASE_LOCKED_REASON = "This database is locked, so its columns and settings are read-only. Unlock it to change them.";
|
|
1548
|
-
function lockedStructure(base) {
|
|
1549
|
-
return { ...base, structure: false, why: (what) => what === "structure" ? DATABASE_LOCKED_REASON : base.why(what) };
|
|
1550
|
-
}
|
|
1551
|
-
|
|
1552
|
-
// src/host.tsx
|
|
1553
|
-
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
1554
|
-
function tableRights(may, overallReason) {
|
|
1555
|
-
return {
|
|
1556
|
-
...may,
|
|
1557
|
-
admin: may.structure,
|
|
1558
|
-
reason: overallReason ?? (may.structure ? "" : may.why("structure"))
|
|
1559
|
-
};
|
|
1560
|
-
}
|
|
1561
|
-
var NO_RIGHTS = tableRights(NOT_ANSWERED_YET);
|
|
1562
|
-
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.";
|
|
1563
|
-
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.";
|
|
1564
|
-
var HostContext = createContext(null);
|
|
1565
|
-
function useRecordsUi() {
|
|
1566
|
-
return useContext(HostContext) ?? {};
|
|
1567
|
-
}
|
|
1568
|
-
function quiet(may, say) {
|
|
1569
|
-
if (say !== false) return may;
|
|
1570
|
-
return { ...may, why: () => "", ..."reason" in may ? { reason: "" } : {} };
|
|
1571
|
-
}
|
|
1572
|
-
function useTableRights(table) {
|
|
1573
|
-
const host = useRecordsUi();
|
|
1574
|
-
const asked2 = useTableRightsAsked(table, host);
|
|
1575
|
-
return useMemo(() => quiet(asked2, host.sayLevelNeeded), [asked2, host.sayLevelNeeded]);
|
|
1576
|
-
}
|
|
1577
|
-
function useTableRightsAsked(table, host) {
|
|
1578
|
-
const bound = Boolean(host.rights);
|
|
1579
|
-
const asked2 = useMyLevel(bound || !table ? null : table.id);
|
|
1580
|
-
return useMemo(() => {
|
|
1581
|
-
if (!table) return NO_RIGHTS;
|
|
1582
|
-
if (host.rights) return host.rights(table);
|
|
1583
|
-
if (asked2.loading) return tableRights(NOT_ANSWERED_YET);
|
|
1584
|
-
const level = asked2.error ? null : asked2.data;
|
|
1585
|
-
return tableRights(whatYouMayDoWithTable(table, level, true));
|
|
1586
|
-
}, [host, table, bound, asked2.loading, asked2.error, asked2.data]);
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
|
-
// src/ArchivedOrganizationNotice.tsx
|
|
1590
|
-
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1591
|
-
function ArchivedOrganizationNotice({
|
|
1592
|
-
organizationId,
|
|
1593
|
-
error,
|
|
1594
|
-
className
|
|
1595
|
-
}) {
|
|
1596
|
-
const port = useRecordsUi().archivedOrganization;
|
|
1597
|
-
const [mayRestore, setMayRestore] = useState5(null);
|
|
1598
|
-
const [busy, setBusy] = useState5(false);
|
|
1599
|
-
const [failed, setFailed] = useState5(null);
|
|
1600
|
-
useEffect4(() => {
|
|
1601
|
-
let live = true;
|
|
1602
|
-
if (!port) {
|
|
1603
|
-
setMayRestore(false);
|
|
1604
|
-
return;
|
|
1605
|
-
}
|
|
1606
|
-
setMayRestore(null);
|
|
1607
|
-
port.state(organizationId).then((answer) => {
|
|
1608
|
-
if (live) setMayRestore(answer?.mayRestore === true);
|
|
1609
|
-
}).catch(() => {
|
|
1610
|
-
if (live) setMayRestore(false);
|
|
1611
|
-
});
|
|
1612
|
-
return () => {
|
|
1613
|
-
live = false;
|
|
1614
|
-
};
|
|
1615
|
-
}, [organizationId, port?.state]);
|
|
1616
|
-
const restore = async () => {
|
|
1617
|
-
if (!port || busy) return;
|
|
1618
|
-
setBusy(true);
|
|
1619
|
-
setFailed(null);
|
|
1620
|
-
try {
|
|
1621
|
-
await port.restore(organizationId);
|
|
1622
|
-
if (port.afterRestore) port.afterRestore();
|
|
1623
|
-
else if (typeof window !== "undefined") window.location.reload();
|
|
1624
|
-
} catch (thrown) {
|
|
1625
|
-
setFailed(thrown instanceof Error && thrown.message ? thrown.message : "The organization could not be restored.");
|
|
1626
|
-
setBusy(false);
|
|
1627
|
-
}
|
|
1628
|
-
};
|
|
1629
|
-
return /* @__PURE__ */ jsxs6(
|
|
1630
|
-
Alert,
|
|
1631
|
-
{
|
|
1632
|
-
variant: "destructive",
|
|
1633
|
-
role: "alert",
|
|
1634
|
-
"data-refusal-notice": "",
|
|
1635
|
-
"data-archived-organization": organizationId,
|
|
1636
|
-
className: cn5("text-xs", className),
|
|
1637
|
-
errorFacts: { message: "This organization is archived", title: "This organization is archived", error, origin: "records-ui/ArchivedOrganizationNotice" },
|
|
1638
|
-
children: [
|
|
1639
|
-
/* @__PURE__ */ jsx7(AlertTitle, { className: "text-xs font-medium", children: "This organization is archived" }),
|
|
1640
|
-
/* @__PURE__ */ jsxs6(AlertDescription, { className: "space-y-1 text-xs", children: [
|
|
1641
|
-
/* @__PURE__ */ jsx7("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." }),
|
|
1642
|
-
mayRestore === true ? /* @__PURE__ */ jsx7(
|
|
1643
|
-
"button",
|
|
1644
|
-
{
|
|
1645
|
-
type: "button",
|
|
1646
|
-
"data-restore-organization": "",
|
|
1647
|
-
disabled: busy,
|
|
1648
|
-
className: "rounded border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-60",
|
|
1649
|
-
onClick: () => void restore(),
|
|
1650
|
-
children: busy ? "Restoring..." : "Restore organization"
|
|
1651
|
-
}
|
|
1652
|
-
) : null,
|
|
1653
|
-
mayRestore === false ? /* @__PURE__ */ jsx7("p", { "data-restore-who": "", className: "opacity-80", children: "Ask an owner of this organization to restore it." }) : null,
|
|
1654
|
-
failed ? /* @__PURE__ */ jsx7("p", { "data-restore-refused": "", children: failed }) : null
|
|
1655
|
-
] })
|
|
1656
|
-
]
|
|
1657
|
-
}
|
|
1658
|
-
);
|
|
1659
|
-
}
|
|
1660
|
-
|
|
1661
|
-
// src/Refusal.tsx
|
|
1662
|
-
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1663
|
-
function RefusalNotice({
|
|
1664
|
-
error,
|
|
1665
|
-
className,
|
|
1666
|
-
actions,
|
|
1667
|
-
onKeepEditing,
|
|
1668
|
-
onDiscard
|
|
1669
|
-
}) {
|
|
1670
|
-
const archivedOrg = archivedOrganizationId(error);
|
|
1671
|
-
if (archivedOrg) {
|
|
1672
|
-
return /* @__PURE__ */ jsx8(ArchivedOrganizationNotice, { organizationId: archivedOrg, error, className });
|
|
1673
|
-
}
|
|
1674
|
-
const plain = refusalForAPerson(error);
|
|
1675
|
-
const doors = onKeepEditing || onDiscard ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap items-center gap-1 pt-0.5", "data-refusal-doors": "", children: [
|
|
1676
|
-
onKeepEditing ? /* @__PURE__ */ jsx8(
|
|
1677
|
-
"button",
|
|
1678
|
-
{
|
|
1679
|
-
type: "button",
|
|
1680
|
-
"data-refusal-keep-editing": "",
|
|
1681
|
-
className: "rounded border px-2 py-0.5 text-xs hover:bg-muted",
|
|
1682
|
-
onClick: onKeepEditing,
|
|
1683
|
-
children: "Keep editing"
|
|
1684
|
-
}
|
|
1685
|
-
) : null,
|
|
1686
|
-
onDiscard ? /* @__PURE__ */ jsx8(
|
|
1687
|
-
"button",
|
|
1688
|
-
{
|
|
1689
|
-
type: "button",
|
|
1690
|
-
"data-refusal-discard": "",
|
|
1691
|
-
className: "rounded border px-2 py-0.5 text-xs hover:bg-muted",
|
|
1692
|
-
onClick: onDiscard,
|
|
1693
|
-
children: "Discard"
|
|
1694
|
-
}
|
|
1695
|
-
) : null
|
|
1696
|
-
] }) : null;
|
|
1697
|
-
return /* @__PURE__ */ jsxs7(
|
|
1698
|
-
Alert2,
|
|
1699
|
-
{
|
|
1700
|
-
variant: "destructive",
|
|
1701
|
-
role: "alert",
|
|
1702
|
-
"data-refusal-notice": "",
|
|
1703
|
-
className: cn6("text-xs", className),
|
|
1704
|
-
errorFacts: { message: plain.sentence, title: plain.title, error, origin: "records-ui/RefusalNotice" },
|
|
1705
|
-
...plain.forEngineers ? { "data-for-engineers": plain.forEngineers } : {},
|
|
1706
|
-
...error.sqlstate ? { "data-sqlstate": error.sqlstate } : {},
|
|
1707
|
-
children: [
|
|
1708
|
-
/* @__PURE__ */ jsx8(AlertTitle2, { className: "text-xs font-medium", children: plain.storeSaid ? plain.sentence : plain.title }),
|
|
1709
|
-
/* @__PURE__ */ jsxs7(AlertDescription2, { className: "space-y-1 text-xs", children: [
|
|
1710
|
-
plain.storeSaid || plain.sentence.replace(/\.$/, "") === plain.title ? null : /* @__PURE__ */ jsx8("p", { children: plain.sentence }),
|
|
1711
|
-
/* @__PURE__ */ jsx8("p", { className: "opacity-80", children: plain.remedy }),
|
|
1712
|
-
actions,
|
|
1713
|
-
doors
|
|
1714
|
-
] })
|
|
1715
|
-
]
|
|
1716
|
-
}
|
|
1717
|
-
);
|
|
1718
|
-
}
|
|
1719
|
-
function RefusalLine({ error, className }) {
|
|
1720
|
-
const plain = refusalForAPerson(error);
|
|
1721
|
-
return /* @__PURE__ */ jsx8(
|
|
1722
|
-
ErrorBox,
|
|
1723
|
-
{
|
|
1724
|
-
"data-refusal-line": "",
|
|
1725
|
-
className: cn6("text-xs text-destructive", className),
|
|
1726
|
-
message: archivedOrganizationId(error) ? "This organization is archived. An owner can restore it." : refusalLineForAPerson(error),
|
|
1727
|
-
error,
|
|
1728
|
-
origin: "records-ui/RefusalLine",
|
|
1729
|
-
...plain.forEngineers ? { "data-for-engineers": plain.forEngineers } : {}
|
|
1730
|
-
}
|
|
1731
|
-
);
|
|
1732
|
-
}
|
|
1733
|
-
|
|
1734
1735
|
// src/refusals.ts
|
|
1735
1736
|
var refusals_exports = {};
|
|
1736
1737
|
__reExport(refusals_exports, versions_star2);
|