@proteos/ui 0.54.0 → 0.55.0
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/index.cjs +639 -312
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -7
- package/dist/index.d.ts +79 -7
- package/dist/index.js +637 -315
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/badge/badge.stories.tsx +37 -1
- package/src/components/badge/badge.test.tsx +39 -2
- package/src/components/badge/badge.tsx +65 -1
- package/src/components/badge/index.ts +2 -2
- package/src/components/badge-group/badge-group.stories.tsx +75 -0
- package/src/components/badge-group/badge-group.test.tsx +121 -0
- package/src/components/badge-group/badge-group.tsx +208 -0
- package/src/components/badge-group/index.ts +7 -0
- package/src/components/badge-multi-select/badge-multi-select.stories.tsx +25 -0
- package/src/components/badge-multi-select/badge-multi-select.test.tsx +110 -1
- package/src/components/badge-multi-select/badge-multi-select.tsx +190 -128
- package/src/components/card/card.tsx +1 -1
- package/src/components/data-table/data-table.stories.tsx +53 -2
- package/src/components/data-table/data-table.tsx +45 -25
- package/src/components/field/listbox-check.tsx +44 -0
- package/src/components/field/use-chip-row-wrap.ts +45 -0
- package/src/components/multi-select/multi-select.tsx +8 -39
- package/src/components/table/table.test.tsx +88 -9
- package/src/components/table/table.tsx +139 -13
- package/src/components/tag-input/tag-input.test.tsx +67 -1
- package/src/components/tag-input/tag-input.tsx +98 -64
- package/src/index.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -2,9 +2,9 @@ import { cn, Button, Skeleton } from './chunk-IKAX76MB.js';
|
|
|
2
2
|
export { Button, Skeleton, buttonStyles, cn, skeletonStyles } from './chunk-IKAX76MB.js';
|
|
3
3
|
import { icons, Contact, Paperclip, BookText, Banknote, UsersRound, User, Link2, Braces, Brackets, ToggleLeft, CircleDot, Calendar, Hash, Type, File, FileImage, FileText, FileSpreadsheet, FileArchive, Loader2, X, Shapes, Search, Phone, AudioLines, Video, Mic, AtSign, MessagesSquare, Camera, Send, Linkedin, MessageCircle, Mail, Pipette, Pencil, ChevronDown, GripVertical, SendHorizontal, CircleX, Download, ChevronRight as ChevronRight$1, CircleCheck, CircleAlert, Info } from 'lucide-react';
|
|
4
4
|
import { tv } from 'tailwind-variants';
|
|
5
|
-
import { Tabs as Tabs$1, TabPanel, Tab, TabList, MenuTrigger as MenuTrigger$1, SubmenuTrigger as SubmenuTrigger$1, DialogTrigger, Popover as Popover$1, Dialog, DropZone, Text, FileTrigger, Heading, Label, Input as Input$1, ListBox, ListBoxItem,
|
|
5
|
+
import { Tabs as Tabs$1, TabPanel, Tab, TabList, MenuTrigger as MenuTrigger$1, SubmenuTrigger as SubmenuTrigger$1, DialogTrigger, Popover as Popover$1, Dialog, DropZone, Text, FileTrigger, Heading, Label, Input as Input$1, ListBox, ListBoxItem, TooltipTrigger as TooltipTrigger$1, Tooltip as Tooltip$1, Button as Button$1, Breadcrumbs as Breadcrumbs$1, Breadcrumb, Link, Checkbox as Checkbox$1, CheckboxGroup as CheckboxGroup$1, FieldError, TextField, ComboBox, ComboBoxStateContext, Select as Select$1, SelectValue, ModalOverlay, Modal as Modal$1, DatePicker as DatePicker$1, Group, DateInput, DateSegment, Menu as Menu$1, MenuItem as MenuItem$1, Disclosure, DisclosurePanel, ProgressBar as ProgressBar$1, RadioGroup as RadioGroup$1, Radio as Radio$1, Separator as Separator$1, Switch as Switch$1, TextArea, TimeField as TimeField$1, UNSTABLE_ToastQueue, UNSTABLE_ToastRegion, UNSTABLE_Toast, UNSTABLE_ToastContent, Calendar as Calendar$1, CalendarGrid, CalendarGridHeader, CalendarHeaderCell, CalendarGridBody, CalendarCell, DatePickerStateContext } from 'react-aria-components';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
|
-
import { lazy, createContext, useState, useRef, useMemo, useEffect, useContext, useSyncExternalStore, useCallback,
|
|
7
|
+
import { lazy, createContext, useState, useRef, useMemo, Children, isValidElement, useLayoutEffect, useEffect, useContext, useSyncExternalStore, useCallback, Suspense, useId, Fragment as Fragment$1 } from 'react';
|
|
8
8
|
import { formatAmount, parseAmount } from '@proteos/sdk';
|
|
9
9
|
import { draggable, dropTargetForElements, monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
10
10
|
import { extractClosestEdge, attachClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
@@ -872,6 +872,7 @@ function Badge({
|
|
|
872
872
|
hasDot,
|
|
873
873
|
color,
|
|
874
874
|
icon,
|
|
875
|
+
actions,
|
|
875
876
|
className,
|
|
876
877
|
style,
|
|
877
878
|
children,
|
|
@@ -893,11 +894,249 @@ function Badge({
|
|
|
893
894
|
),
|
|
894
895
|
children: [
|
|
895
896
|
Icon ? /* @__PURE__ */ jsx(Icon, { "aria-hidden": true, className: cn("size-3 shrink-0", ICON_TONE[register2]) }) : null,
|
|
896
|
-
children
|
|
897
|
+
children,
|
|
898
|
+
actions ? (
|
|
899
|
+
// Pulled flush with the trailing edge so the chip still reads
|
|
900
|
+
// symmetric around its leading dot / icon.
|
|
901
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex items-center shrink-0 -mr-1", children: actions })
|
|
902
|
+
) : null
|
|
897
903
|
]
|
|
898
904
|
}
|
|
899
905
|
);
|
|
900
906
|
}
|
|
907
|
+
function BadgeAction({ label, onPress, isDisabled = false, children }) {
|
|
908
|
+
return /* @__PURE__ */ jsx(
|
|
909
|
+
"button",
|
|
910
|
+
{
|
|
911
|
+
type: "button",
|
|
912
|
+
"aria-label": label,
|
|
913
|
+
disabled: isDisabled,
|
|
914
|
+
onClick: (event) => {
|
|
915
|
+
event.stopPropagation();
|
|
916
|
+
onPress();
|
|
917
|
+
},
|
|
918
|
+
className: cn(
|
|
919
|
+
"inline-flex items-center justify-center shrink-0",
|
|
920
|
+
"size-3.5 rounded-full",
|
|
921
|
+
"text-current/70 hover:text-current hover:bg-current/10",
|
|
922
|
+
"outline-none cursor-pointer",
|
|
923
|
+
"focus-visible:shadow-[var(--shadow-focus)]",
|
|
924
|
+
"disabled:opacity-45 disabled:cursor-not-allowed"
|
|
925
|
+
),
|
|
926
|
+
children: children ?? /* @__PURE__ */ jsx("svg", { "aria-hidden": true, viewBox: "0 0 10 10", className: "size-2.5", fill: "none", children: /* @__PURE__ */ jsx(
|
|
927
|
+
"path",
|
|
928
|
+
{
|
|
929
|
+
d: "M2 2l6 6M8 2l-6 6",
|
|
930
|
+
stroke: "currentColor",
|
|
931
|
+
strokeWidth: "1.4",
|
|
932
|
+
strokeLinecap: "round"
|
|
933
|
+
}
|
|
934
|
+
) })
|
|
935
|
+
}
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
function TooltipTrigger({
|
|
939
|
+
delay = 500,
|
|
940
|
+
closeDelay = 0,
|
|
941
|
+
...props
|
|
942
|
+
}) {
|
|
943
|
+
return /* @__PURE__ */ jsx(TooltipTrigger$1, { delay, closeDelay, ...props });
|
|
944
|
+
}
|
|
945
|
+
function Tooltip({ className, offset = 6, ...props }) {
|
|
946
|
+
return /* @__PURE__ */ jsx(
|
|
947
|
+
Tooltip$1,
|
|
948
|
+
{
|
|
949
|
+
...props,
|
|
950
|
+
offset,
|
|
951
|
+
className: (renderProps) => cn(
|
|
952
|
+
"z-50 max-w-xs",
|
|
953
|
+
"rounded-md border border-rule bg-surface shadow-[var(--shadow-raised)]",
|
|
954
|
+
"px-2.5 py-1.5",
|
|
955
|
+
"font-mono text-[11.5px] text-ink-2",
|
|
956
|
+
"entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1 entering:duration-150",
|
|
957
|
+
"exiting:animate-out exiting:fade-out-0 exiting:duration-100",
|
|
958
|
+
typeof className === "function" ? className(renderProps) : className
|
|
959
|
+
)
|
|
960
|
+
}
|
|
961
|
+
);
|
|
962
|
+
}
|
|
963
|
+
var badgeGroupStyles = tv({
|
|
964
|
+
base: "flex flex-nowrap items-center gap-1.5 w-full min-w-0",
|
|
965
|
+
variants: {
|
|
966
|
+
// The measuring pass renders every chip plus the overflow chip so their
|
|
967
|
+
// widths can be read; it is hidden so that pass never paints.
|
|
968
|
+
isMeasuring: { true: "invisible", false: "" }
|
|
969
|
+
},
|
|
970
|
+
defaultVariants: { isMeasuring: false }
|
|
971
|
+
});
|
|
972
|
+
function fitBadgeCount(metrics, available) {
|
|
973
|
+
const { itemWidths, overflowWidth, gap } = metrics;
|
|
974
|
+
const total = itemWidths.length;
|
|
975
|
+
if (available <= 0) return total;
|
|
976
|
+
let fullWidth = 0;
|
|
977
|
+
for (let index = 0; index < total; index += 1) {
|
|
978
|
+
fullWidth += (itemWidths[index] ?? 0) + (index > 0 ? gap : 0);
|
|
979
|
+
}
|
|
980
|
+
if (fullWidth <= available) return total;
|
|
981
|
+
let used = 0;
|
|
982
|
+
let count = 0;
|
|
983
|
+
for (let index = 0; index < total; index += 1) {
|
|
984
|
+
const next = used + (itemWidths[index] ?? 0) + gap;
|
|
985
|
+
if (next + overflowWidth > available) break;
|
|
986
|
+
used = next;
|
|
987
|
+
count = index + 1;
|
|
988
|
+
}
|
|
989
|
+
return count;
|
|
990
|
+
}
|
|
991
|
+
var badgeGroupOverflowStyles = tv({
|
|
992
|
+
base: [
|
|
993
|
+
badgeStyles({ variant: "neutral", shape: "rounded", hasDot: false }),
|
|
994
|
+
// badgeStyles' register still materializes an empty ::before — hide it,
|
|
995
|
+
// as Badge itself does when no dot should show.
|
|
996
|
+
"before:hidden shrink-0 cursor-pointer whitespace-nowrap",
|
|
997
|
+
"hover:bg-surface-2 hover:text-ink",
|
|
998
|
+
"outline-none focus-visible:shadow-[var(--shadow-focus)]"
|
|
999
|
+
]
|
|
1000
|
+
});
|
|
1001
|
+
function BadgeGroup({ children, className, ...props }) {
|
|
1002
|
+
const items = Children.toArray(children);
|
|
1003
|
+
const signature = items.map((item, index) => isValidElement(item) ? String(item.key ?? index) : String(item)).join("");
|
|
1004
|
+
const rootRef = useRef(null);
|
|
1005
|
+
const metricsRef = useRef(null);
|
|
1006
|
+
const [layout, setLayout] = useState({ signature, visibleCount: null });
|
|
1007
|
+
if (layout.signature !== signature) {
|
|
1008
|
+
metricsRef.current = null;
|
|
1009
|
+
setLayout({ signature, visibleCount: null });
|
|
1010
|
+
}
|
|
1011
|
+
const measuring = layout.signature !== signature || layout.visibleCount === null;
|
|
1012
|
+
const visibleCount = measuring ? items.length : layout.visibleCount ?? items.length;
|
|
1013
|
+
const shown = items.slice(0, visibleCount);
|
|
1014
|
+
const hidden = measuring ? items.length : items.length - visibleCount;
|
|
1015
|
+
useLayoutEffect(() => {
|
|
1016
|
+
if (!measuring) return;
|
|
1017
|
+
const root = rootRef.current;
|
|
1018
|
+
if (!root) return;
|
|
1019
|
+
const nodes = Array.from(root.children);
|
|
1020
|
+
const metrics = {
|
|
1021
|
+
itemWidths: nodes.slice(0, items.length).map((node) => node.getBoundingClientRect().width),
|
|
1022
|
+
overflowWidth: nodes[items.length]?.getBoundingClientRect().width ?? 0,
|
|
1023
|
+
gap: Number.parseFloat(getComputedStyle(root).columnGap) || 0
|
|
1024
|
+
};
|
|
1025
|
+
metricsRef.current = metrics;
|
|
1026
|
+
setLayout({ signature, visibleCount: fitBadgeCount(metrics, root.clientWidth) });
|
|
1027
|
+
}, [measuring, signature, items.length]);
|
|
1028
|
+
useEffect(() => {
|
|
1029
|
+
const root = rootRef.current;
|
|
1030
|
+
if (!root || typeof ResizeObserver === "undefined") return;
|
|
1031
|
+
const observer = new ResizeObserver(() => {
|
|
1032
|
+
const metrics = metricsRef.current;
|
|
1033
|
+
if (!metrics) return;
|
|
1034
|
+
const next = fitBadgeCount(metrics, root.clientWidth);
|
|
1035
|
+
setLayout((prev) => prev.visibleCount === next ? prev : { ...prev, visibleCount: next });
|
|
1036
|
+
});
|
|
1037
|
+
observer.observe(root);
|
|
1038
|
+
return () => observer.disconnect();
|
|
1039
|
+
}, []);
|
|
1040
|
+
useEffect(() => {
|
|
1041
|
+
const fonts = typeof document === "undefined" ? void 0 : document.fonts;
|
|
1042
|
+
if (!fonts || fonts.status === "loaded") return;
|
|
1043
|
+
let cancelled = false;
|
|
1044
|
+
void fonts.ready.then(() => {
|
|
1045
|
+
if (cancelled) return;
|
|
1046
|
+
metricsRef.current = null;
|
|
1047
|
+
setLayout((prev) => ({ ...prev, visibleCount: null }));
|
|
1048
|
+
});
|
|
1049
|
+
return () => {
|
|
1050
|
+
cancelled = true;
|
|
1051
|
+
};
|
|
1052
|
+
}, []);
|
|
1053
|
+
return /* @__PURE__ */ jsxs(
|
|
1054
|
+
"div",
|
|
1055
|
+
{
|
|
1056
|
+
...props,
|
|
1057
|
+
ref: rootRef,
|
|
1058
|
+
className: cn(badgeGroupStyles({ isMeasuring: measuring }), className),
|
|
1059
|
+
children: [
|
|
1060
|
+
shown.map((item, index) => /* @__PURE__ */ jsx(
|
|
1061
|
+
"span",
|
|
1062
|
+
{
|
|
1063
|
+
className: "inline-flex shrink-0",
|
|
1064
|
+
children: item
|
|
1065
|
+
},
|
|
1066
|
+
(isValidElement(item) ? item.key : null) ?? index
|
|
1067
|
+
)),
|
|
1068
|
+
hidden > 0 ? (
|
|
1069
|
+
// The span swallows the click before it reaches a clickable host row
|
|
1070
|
+
// (React propagation), so opening the overflow never opens the record.
|
|
1071
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: click fence only — the button inside is the interactive element
|
|
1072
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: keyboard handling lives on the button inside
|
|
1073
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsxs(Popover, { children: [
|
|
1074
|
+
/* @__PURE__ */ jsxs(TooltipTrigger, { children: [
|
|
1075
|
+
/* @__PURE__ */ jsxs(Button$1, { className: badgeGroupOverflowStyles(), children: [
|
|
1076
|
+
"+",
|
|
1077
|
+
hidden,
|
|
1078
|
+
" more"
|
|
1079
|
+
] }),
|
|
1080
|
+
/* @__PURE__ */ jsx(Tooltip, { className: "max-w-sm", children: /* @__PURE__ */ jsx("span", { className: "flex flex-wrap items-center gap-1.5", children: items }) })
|
|
1081
|
+
] }),
|
|
1082
|
+
/* @__PURE__ */ jsx(PopoverContent, { placement: "bottom start", panelClassName: "max-w-sm", children: /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-1.5 p-2.5", children: items }) })
|
|
1083
|
+
] }) })
|
|
1084
|
+
) : null
|
|
1085
|
+
]
|
|
1086
|
+
}
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
var listboxCheckStyles = tv({
|
|
1090
|
+
slots: {
|
|
1091
|
+
box: [
|
|
1092
|
+
"relative inline-flex items-center justify-center shrink-0",
|
|
1093
|
+
"size-[16px] rounded-[3px] border border-ink-4 bg-surface",
|
|
1094
|
+
"transition-[background-color,border-color] duration-150",
|
|
1095
|
+
"group-data-[selected]:bg-ink group-data-[selected]:border-ink"
|
|
1096
|
+
],
|
|
1097
|
+
tick: [
|
|
1098
|
+
"size-3 text-surface transition-opacity duration-150",
|
|
1099
|
+
"opacity-0 group-data-[selected]:opacity-100"
|
|
1100
|
+
]
|
|
1101
|
+
}
|
|
1102
|
+
});
|
|
1103
|
+
function ListboxCheck() {
|
|
1104
|
+
const { box, tick } = listboxCheckStyles();
|
|
1105
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: box(), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", className: tick(), "aria-hidden": true, children: /* @__PURE__ */ jsx(
|
|
1106
|
+
"path",
|
|
1107
|
+
{
|
|
1108
|
+
d: "M2.5 6.25 5 8.75 9.5 3.75",
|
|
1109
|
+
stroke: "currentColor",
|
|
1110
|
+
strokeWidth: "1.6",
|
|
1111
|
+
strokeLinecap: "round",
|
|
1112
|
+
strokeLinejoin: "round",
|
|
1113
|
+
fill: "none"
|
|
1114
|
+
}
|
|
1115
|
+
) }) });
|
|
1116
|
+
}
|
|
1117
|
+
function useChipRowWrap(ref, isEnabled, signature) {
|
|
1118
|
+
const [hasWrapped, setHasWrapped] = useState(false);
|
|
1119
|
+
useLayoutEffect(() => {
|
|
1120
|
+
if (!isEnabled) return;
|
|
1121
|
+
const element = ref.current;
|
|
1122
|
+
if (!element) return;
|
|
1123
|
+
const measure = () => {
|
|
1124
|
+
const children = Array.from(element.children);
|
|
1125
|
+
const first = children[0]?.getBoundingClientRect();
|
|
1126
|
+
if (!first || first.height === 0) {
|
|
1127
|
+
setHasWrapped(false);
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
setHasWrapped(children.some((child) => child.getBoundingClientRect().top >= first.bottom - 1));
|
|
1131
|
+
};
|
|
1132
|
+
measure();
|
|
1133
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
1134
|
+
const observer = new ResizeObserver(measure);
|
|
1135
|
+
observer.observe(element);
|
|
1136
|
+
return () => observer.disconnect();
|
|
1137
|
+
}, [ref, isEnabled, signature]);
|
|
1138
|
+
return hasWrapped;
|
|
1139
|
+
}
|
|
901
1140
|
function badgeChrome(option) {
|
|
902
1141
|
return {
|
|
903
1142
|
...option.variant ? { variant: option.variant } : {},
|
|
@@ -921,18 +1160,51 @@ function BadgeMultiSelect({
|
|
|
921
1160
|
size = "md",
|
|
922
1161
|
appearance,
|
|
923
1162
|
autoFocus = false,
|
|
1163
|
+
defaultOpen = false,
|
|
1164
|
+
"aria-label": ariaLabel,
|
|
924
1165
|
className
|
|
925
1166
|
}) {
|
|
1167
|
+
const isCell = appearance === "cell";
|
|
926
1168
|
const styles4 = fieldControlStyles({ size, invalid: isInvalid, appearance });
|
|
927
|
-
const focusWithin =
|
|
928
|
-
const minHeight = appearance === "cell" ? "min-h-[29px]" : fieldMinHeight[size];
|
|
1169
|
+
const focusWithin = isCell ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
|
|
929
1170
|
const [isOpen, setIsOpen] = useState(false);
|
|
930
1171
|
const triggerRef = useRef(null);
|
|
1172
|
+
const chipsRef = useRef(null);
|
|
1173
|
+
const popoverRef = useRef(null);
|
|
1174
|
+
const closedByPointerRef = useRef(false);
|
|
931
1175
|
useEffect(() => {
|
|
932
1176
|
if (autoFocus) triggerRef.current?.focus();
|
|
1177
|
+
if (defaultOpen && !isDisabled) setIsOpen(true);
|
|
933
1178
|
}, []);
|
|
1179
|
+
const wasOpenRef = useRef(false);
|
|
1180
|
+
useEffect(() => {
|
|
1181
|
+
if (wasOpenRef.current && !isOpen && !closedByPointerRef.current) {
|
|
1182
|
+
const active = document.activeElement;
|
|
1183
|
+
const strandedInList = !active || active === document.body || !!active.closest('[data-rac][role="listbox"]');
|
|
1184
|
+
if (strandedInList) triggerRef.current?.focus();
|
|
1185
|
+
}
|
|
1186
|
+
wasOpenRef.current = isOpen;
|
|
1187
|
+
closedByPointerRef.current = false;
|
|
1188
|
+
}, [isOpen]);
|
|
934
1189
|
const selectedSet = new Set(selectedKeys);
|
|
935
1190
|
const selectedOptions = options.filter((o) => selectedSet.has(o.id));
|
|
1191
|
+
const hasWrapped = useChipRowWrap(
|
|
1192
|
+
chipsRef,
|
|
1193
|
+
isCell,
|
|
1194
|
+
JSON.stringify(selectedOptions.map((o) => o.id))
|
|
1195
|
+
);
|
|
1196
|
+
useEffect(() => {
|
|
1197
|
+
if (!isOpen) return;
|
|
1198
|
+
const onPointerDown = (event) => {
|
|
1199
|
+
const target = event.target;
|
|
1200
|
+
if (!(target instanceof Node)) return;
|
|
1201
|
+
if (triggerRef.current?.contains(target) || popoverRef.current?.contains(target)) return;
|
|
1202
|
+
closedByPointerRef.current = true;
|
|
1203
|
+
setIsOpen(false);
|
|
1204
|
+
};
|
|
1205
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
1206
|
+
return () => document.removeEventListener("pointerdown", onPointerDown, true);
|
|
1207
|
+
}, [isOpen]);
|
|
936
1208
|
const listboxOptions = hideSelectedOptions ? options.filter((o) => !selectedSet.has(o.id)) : options;
|
|
937
1209
|
const remove = (id) => {
|
|
938
1210
|
const next = new Set(selectedSet);
|
|
@@ -944,6 +1216,12 @@ function BadgeMultiSelect({
|
|
|
944
1216
|
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
945
1217
|
e.preventDefault();
|
|
946
1218
|
setIsOpen(true);
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
if (e.key === "Escape" && isOpen) {
|
|
1222
|
+
e.preventDefault();
|
|
1223
|
+
e.stopPropagation();
|
|
1224
|
+
setIsOpen(false);
|
|
947
1225
|
}
|
|
948
1226
|
};
|
|
949
1227
|
return /* @__PURE__ */ jsxs("div", { className: cn("grid grid-cols-1 gap-1.5", className), children: [
|
|
@@ -953,6 +1231,7 @@ function BadgeMultiSelect({
|
|
|
953
1231
|
{
|
|
954
1232
|
ref: triggerRef,
|
|
955
1233
|
role: "combobox",
|
|
1234
|
+
"aria-label": ariaLabel,
|
|
956
1235
|
"aria-expanded": isOpen,
|
|
957
1236
|
"aria-haspopup": "listbox",
|
|
958
1237
|
"aria-disabled": isDisabled || void 0,
|
|
@@ -964,34 +1243,53 @@ function BadgeMultiSelect({
|
|
|
964
1243
|
"data-disabled": isDisabled || void 0,
|
|
965
1244
|
className: cn(
|
|
966
1245
|
styles4.box(),
|
|
967
|
-
"flex
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1246
|
+
"flex items-stretch cursor-pointer",
|
|
1247
|
+
// Cell editor: one table row (29px under a 32px row) while the chips
|
|
1248
|
+
// fit on a line; two rows (64px), popping out of the row, once they
|
|
1249
|
+
// wrap — the chips then scroll inside. Field mode grows with its
|
|
1250
|
+
// content like every other chip field.
|
|
1251
|
+
isCell ? hasWrapped ? "h-[64px] p-1" : "h-[29px] px-1 py-0" : [fieldChipPadding[size], fieldMinHeight[size]],
|
|
971
1252
|
focusWithin
|
|
972
1253
|
),
|
|
973
1254
|
children: [
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
// overall height so it matches the Input/Select trigger at the same
|
|
977
|
-
// size.
|
|
978
|
-
/* @__PURE__ */ jsx("span", { className: cn("text-ink-4 font-sans px-1", fieldTextStyles[size]), children: placeholder })
|
|
979
|
-
) : selectedOptions.map((o) => /* @__PURE__ */ jsx(
|
|
980
|
-
RemovableBadge,
|
|
1255
|
+
/* @__PURE__ */ jsx(
|
|
1256
|
+
"div",
|
|
981
1257
|
{
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
1258
|
+
ref: chipsRef,
|
|
1259
|
+
className: cn(
|
|
1260
|
+
"flex flex-1 flex-wrap items-center gap-1.5 min-w-0",
|
|
1261
|
+
isCell && (hasWrapped ? "content-start overflow-y-auto" : "content-center overflow-hidden")
|
|
1262
|
+
),
|
|
1263
|
+
children: selectedOptions.length === 0 ? (
|
|
1264
|
+
// No vertical padding — wrapper's p-1.5 + min-h-[size] govern the
|
|
1265
|
+
// overall height so it matches the Input/Select trigger at the same
|
|
1266
|
+
// size.
|
|
1267
|
+
/* @__PURE__ */ jsx("span", { className: cn("text-ink-4 font-sans px-1", fieldTextStyles[size]), children: placeholder })
|
|
1268
|
+
) : selectedOptions.map((o) => /* @__PURE__ */ jsx(
|
|
1269
|
+
Badge,
|
|
1270
|
+
{
|
|
1271
|
+
...badgeChrome(o),
|
|
1272
|
+
className: "shrink-0",
|
|
1273
|
+
actions: /* @__PURE__ */ jsx(
|
|
1274
|
+
BadgeAction,
|
|
1275
|
+
{
|
|
1276
|
+
label: "Remove",
|
|
1277
|
+
onPress: () => remove(o.id),
|
|
1278
|
+
isDisabled
|
|
1279
|
+
}
|
|
1280
|
+
),
|
|
1281
|
+
children: o.label
|
|
1282
|
+
},
|
|
1283
|
+
o.id
|
|
1284
|
+
))
|
|
1285
|
+
}
|
|
1286
|
+
),
|
|
1287
|
+
isCell ? null : /* @__PURE__ */ jsx("span", { className: "flex items-center pl-1.5 pr-1", children: /* @__PURE__ */ jsx(FieldCaret, {}) })
|
|
990
1288
|
]
|
|
991
1289
|
}
|
|
992
1290
|
),
|
|
993
1291
|
description ? /* @__PURE__ */ jsx("p", { className: fieldHintStyles, children: description }) : null,
|
|
994
|
-
errorMessage &&
|
|
1292
|
+
errorMessage && !isCell ? /* @__PURE__ */ jsx("p", { className: fieldErrorStyles, children: errorMessage }) : null,
|
|
995
1293
|
/* @__PURE__ */ jsx(
|
|
996
1294
|
Popover$1,
|
|
997
1295
|
{
|
|
@@ -1000,18 +1298,27 @@ function BadgeMultiSelect({
|
|
|
1000
1298
|
triggerRef,
|
|
1001
1299
|
offset: 6,
|
|
1002
1300
|
placement: "bottom start",
|
|
1301
|
+
isNonModal: true,
|
|
1302
|
+
shouldCloseOnInteractOutside: (element) => !triggerRef.current?.contains(element),
|
|
1003
1303
|
className: cn(
|
|
1004
|
-
|
|
1005
|
-
|
|
1304
|
+
// At least as wide as the trigger, wider when a badge needs it —
|
|
1305
|
+
// a narrow table column must not clip its own options.
|
|
1306
|
+
"min-w-[var(--trigger-width)] w-max max-w-[min(28rem,calc(100vw-2rem))]",
|
|
1307
|
+
// Float above modals + full-screen editors, matching Select.
|
|
1308
|
+
"z-[1300]",
|
|
1309
|
+
// The popover element itself takes focus when opened programmatically
|
|
1310
|
+
// (defaultOpen) — no browser outline around the whole panel.
|
|
1311
|
+
"outline-none rounded-md border border-rule bg-surface p-1",
|
|
1006
1312
|
"shadow-[var(--shadow-raised)]",
|
|
1007
1313
|
"entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1",
|
|
1008
1314
|
"exiting:animate-out exiting:fade-out-0 exiting:slide-out-to-top-1"
|
|
1009
1315
|
),
|
|
1010
|
-
children: /* @__PURE__ */ jsx(
|
|
1316
|
+
children: /* @__PURE__ */ jsx("div", { ref: popoverRef, children: /* @__PURE__ */ jsx(
|
|
1011
1317
|
ListBox,
|
|
1012
1318
|
{
|
|
1013
|
-
"aria-label": typeof label === "string" ? label : "Options",
|
|
1319
|
+
"aria-label": typeof label === "string" ? label : ariaLabel ?? "Options",
|
|
1014
1320
|
selectionMode: "multiple",
|
|
1321
|
+
escapeKeyBehavior: "none",
|
|
1015
1322
|
selectedKeys: selectedSet,
|
|
1016
1323
|
onSelectionChange: (keys) => {
|
|
1017
1324
|
if (keys === "all") {
|
|
@@ -1020,70 +1327,32 @@ function BadgeMultiSelect({
|
|
|
1020
1327
|
}
|
|
1021
1328
|
onSelectionChange(keys);
|
|
1022
1329
|
},
|
|
1330
|
+
autoFocus: "first",
|
|
1023
1331
|
className: "outline-none max-h-72 overflow-auto",
|
|
1024
1332
|
renderEmptyState: () => /* @__PURE__ */ jsx("div", { className: cn("px-3 py-2", fieldHintStyles), children: "All options selected" }),
|
|
1025
|
-
children: listboxOptions.map((option) => /* @__PURE__ */
|
|
1333
|
+
children: listboxOptions.map((option) => /* @__PURE__ */ jsxs(
|
|
1026
1334
|
ListBoxItem,
|
|
1027
1335
|
{
|
|
1028
1336
|
id: option.id,
|
|
1029
1337
|
textValue: option.label,
|
|
1030
1338
|
...option.isDisabled ? { isDisabled: true } : {},
|
|
1031
1339
|
className: cn(
|
|
1032
|
-
"group flex items-center",
|
|
1033
|
-
"rounded-[6px] px-
|
|
1340
|
+
"group flex items-center gap-2.5",
|
|
1341
|
+
"rounded-[6px] px-2.5 py-1.5",
|
|
1034
1342
|
"cursor-pointer outline-none select-none",
|
|
1343
|
+
// Selection is carried by the check box, not a row fill.
|
|
1035
1344
|
"data-[hovered]:bg-surface-2",
|
|
1036
1345
|
"data-[focused]:bg-surface-2",
|
|
1037
|
-
"data-[selected]:bg-surface-3",
|
|
1038
1346
|
"data-[disabled]:opacity-45 data-[disabled]:cursor-not-allowed"
|
|
1039
1347
|
),
|
|
1040
|
-
children:
|
|
1348
|
+
children: [
|
|
1349
|
+
/* @__PURE__ */ jsx(ListboxCheck, {}),
|
|
1350
|
+
/* @__PURE__ */ jsx(Badge, { ...badgeChrome(option), children: option.label })
|
|
1351
|
+
]
|
|
1041
1352
|
},
|
|
1042
1353
|
option.id
|
|
1043
1354
|
))
|
|
1044
1355
|
}
|
|
1045
|
-
)
|
|
1046
|
-
}
|
|
1047
|
-
)
|
|
1048
|
-
] });
|
|
1049
|
-
}
|
|
1050
|
-
function RemovableBadge({
|
|
1051
|
-
children,
|
|
1052
|
-
onRemove,
|
|
1053
|
-
isDisabled,
|
|
1054
|
-
...chrome
|
|
1055
|
-
}) {
|
|
1056
|
-
return /* @__PURE__ */ jsxs(Badge, { ...badgeChrome(chrome), children: [
|
|
1057
|
-
/* @__PURE__ */ jsx("span", { children }),
|
|
1058
|
-
/* @__PURE__ */ jsx(
|
|
1059
|
-
"button",
|
|
1060
|
-
{
|
|
1061
|
-
type: "button",
|
|
1062
|
-
"aria-label": "Remove",
|
|
1063
|
-
disabled: isDisabled,
|
|
1064
|
-
onClick: (e) => {
|
|
1065
|
-
e.stopPropagation();
|
|
1066
|
-
onRemove();
|
|
1067
|
-
},
|
|
1068
|
-
className: cn(
|
|
1069
|
-
"inline-flex items-center justify-center shrink-0",
|
|
1070
|
-
"size-3.5 rounded-full",
|
|
1071
|
-
"text-current/70 hover:text-current hover:bg-current/10",
|
|
1072
|
-
"outline-none cursor-pointer",
|
|
1073
|
-
"focus-visible:shadow-[var(--shadow-focus)]",
|
|
1074
|
-
"disabled:opacity-45 disabled:cursor-not-allowed",
|
|
1075
|
-
// Pull the button flush with the right edge so the pill still feels
|
|
1076
|
-
// symmetric around the leading dot.
|
|
1077
|
-
"-mr-1"
|
|
1078
|
-
),
|
|
1079
|
-
children: /* @__PURE__ */ jsx("svg", { "aria-hidden": true, viewBox: "0 0 10 10", className: "size-2.5", fill: "none", children: /* @__PURE__ */ jsx(
|
|
1080
|
-
"path",
|
|
1081
|
-
{
|
|
1082
|
-
d: "M2 2l6 6M8 2l-6 6",
|
|
1083
|
-
stroke: "currentColor",
|
|
1084
|
-
strokeWidth: "1.4",
|
|
1085
|
-
strokeLinecap: "round"
|
|
1086
|
-
}
|
|
1087
1356
|
) })
|
|
1088
1357
|
}
|
|
1089
1358
|
)
|
|
@@ -1195,7 +1464,7 @@ function CardHeader({ className, ...props }) {
|
|
|
1195
1464
|
...props,
|
|
1196
1465
|
className: cn(
|
|
1197
1466
|
"flex justify-between items-center",
|
|
1198
|
-
"px-5 py-
|
|
1467
|
+
"px-5 py-3 border-b border-rule",
|
|
1199
1468
|
"bg-[color-mix(in_oklab,var(--color-surface-2)_60%,var(--color-surface))]",
|
|
1200
1469
|
"font-mono text-[11.5px] uppercase tracking-[0.06em] text-ink-4",
|
|
1201
1470
|
className
|
|
@@ -2687,7 +2956,9 @@ var tableHeaderStyles = tv({
|
|
|
2687
2956
|
"border-b border-rule"
|
|
2688
2957
|
],
|
|
2689
2958
|
variants: {
|
|
2690
|
-
|
|
2959
|
+
// z-[4]: above an editing row (z-[3]) — sticky chrome stays on top of
|
|
2960
|
+
// rows scrolling underneath, popped-out editors included.
|
|
2961
|
+
sticky: { true: "sticky top-0 z-[4]", false: "" }
|
|
2691
2962
|
},
|
|
2692
2963
|
defaultVariants: { sticky: false }
|
|
2693
2964
|
});
|
|
@@ -2752,11 +3023,57 @@ function TableHeaderCell({
|
|
|
2752
3023
|
onRemove,
|
|
2753
3024
|
ariaLabel,
|
|
2754
3025
|
sticky = false,
|
|
3026
|
+
onResize,
|
|
3027
|
+
minWidth = 64,
|
|
2755
3028
|
...rest
|
|
2756
3029
|
}) {
|
|
2757
3030
|
const cellRef = useRef(null);
|
|
2758
3031
|
const handleRef = useRef(null);
|
|
2759
3032
|
const [dragState, setDragState] = useState({ kind: "idle" });
|
|
3033
|
+
const [isResizing, setIsResizing] = useState(false);
|
|
3034
|
+
const startResize = (event) => {
|
|
3035
|
+
if (!onResize || event.button !== 0) return;
|
|
3036
|
+
const cell = cellRef.current;
|
|
3037
|
+
if (!cell) return;
|
|
3038
|
+
event.preventDefault();
|
|
3039
|
+
event.stopPropagation();
|
|
3040
|
+
const handle = event.currentTarget;
|
|
3041
|
+
const startX = event.clientX;
|
|
3042
|
+
const startWidth = cell.getBoundingClientRect().width;
|
|
3043
|
+
if (typeof handle.setPointerCapture === "function") handle.setPointerCapture(event.pointerId);
|
|
3044
|
+
setIsResizing(true);
|
|
3045
|
+
document.body.style.cursor = "col-resize";
|
|
3046
|
+
let frame = 0;
|
|
3047
|
+
const report = (clientX) => {
|
|
3048
|
+
const next = Math.max(minWidth, Math.round(startWidth + clientX - startX));
|
|
3049
|
+
if (typeof requestAnimationFrame !== "function") {
|
|
3050
|
+
onResize(next);
|
|
3051
|
+
return;
|
|
3052
|
+
}
|
|
3053
|
+
cancelAnimationFrame(frame);
|
|
3054
|
+
frame = requestAnimationFrame(() => onResize(next));
|
|
3055
|
+
};
|
|
3056
|
+
const onMove = (move) => report(move.clientX);
|
|
3057
|
+
const onEnd = () => {
|
|
3058
|
+
handle.removeEventListener("pointermove", onMove);
|
|
3059
|
+
handle.removeEventListener("pointerup", onEnd);
|
|
3060
|
+
handle.removeEventListener("pointercancel", onEnd);
|
|
3061
|
+
document.body.style.cursor = "";
|
|
3062
|
+
setIsResizing(false);
|
|
3063
|
+
};
|
|
3064
|
+
handle.addEventListener("pointermove", onMove);
|
|
3065
|
+
handle.addEventListener("pointerup", onEnd);
|
|
3066
|
+
handle.addEventListener("pointercancel", onEnd);
|
|
3067
|
+
};
|
|
3068
|
+
const resizeByKey = (event) => {
|
|
3069
|
+
if (!onResize) return;
|
|
3070
|
+
const step = event.key === "ArrowRight" ? 8 : event.key === "ArrowLeft" ? -8 : 0;
|
|
3071
|
+
if (step === 0) return;
|
|
3072
|
+
event.preventDefault();
|
|
3073
|
+
event.stopPropagation();
|
|
3074
|
+
const current = cellRef.current?.getBoundingClientRect().width ?? minWidth;
|
|
3075
|
+
onResize(Math.max(minWidth, Math.round(current + step)));
|
|
3076
|
+
};
|
|
2760
3077
|
useEffect(() => {
|
|
2761
3078
|
if (!isDraggable || !columnId) return;
|
|
2762
3079
|
const cell = cellRef.current;
|
|
@@ -2774,10 +3091,7 @@ function TableHeaderCell({
|
|
|
2774
3091
|
dropTargetForElements({
|
|
2775
3092
|
element: cell,
|
|
2776
3093
|
canDrop: ({ source }) => isColumnDragData(source.data) && source.data.columnId !== columnId,
|
|
2777
|
-
getData: ({ input, element }) => attachClosestEdge(
|
|
2778
|
-
{ ...data },
|
|
2779
|
-
{ input, element, allowedEdges: ["left", "right"] }
|
|
2780
|
-
),
|
|
3094
|
+
getData: ({ input, element }) => attachClosestEdge({ ...data }, { input, element, allowedEdges: ["left", "right"] }),
|
|
2781
3095
|
getIsSticky: () => true,
|
|
2782
3096
|
onDragEnter: ({ self }) => {
|
|
2783
3097
|
const edge = extractClosestEdge(self.data);
|
|
@@ -2804,6 +3118,7 @@ function TableHeaderCell({
|
|
|
2804
3118
|
const target = e.target;
|
|
2805
3119
|
if (target.closest('[data-dnd-handle="true"]')) return;
|
|
2806
3120
|
if (target.closest('[data-column-remove="true"]')) return;
|
|
3121
|
+
if (target.closest('[data-column-resize="true"]')) return;
|
|
2807
3122
|
onSortToggle?.();
|
|
2808
3123
|
};
|
|
2809
3124
|
const handleKeyDown = (e) => {
|
|
@@ -2887,6 +3202,42 @@ function TableHeaderCell({
|
|
|
2887
3202
|
dragState.edge === "left" ? "-left-px" : "-right-px"
|
|
2888
3203
|
)
|
|
2889
3204
|
}
|
|
3205
|
+
) : null,
|
|
3206
|
+
onResize ? (
|
|
3207
|
+
// Sits astride the trailing separator: an 8px grab zone with a 2px
|
|
3208
|
+
// bar that lights up on hover, focus and while dragging. A focusable
|
|
3209
|
+
// separator is the ARIA pattern for a resizer (no semantic element
|
|
3210
|
+
// exists for it); its value is the column width when one is known.
|
|
3211
|
+
// biome-ignore lint/a11y/useSemanticElements: interactive vertical resizer — <hr> cannot be one
|
|
3212
|
+
/* @__PURE__ */ jsx(
|
|
3213
|
+
"span",
|
|
3214
|
+
{
|
|
3215
|
+
role: "separator",
|
|
3216
|
+
"aria-orientation": "vertical",
|
|
3217
|
+
"aria-label": `Resize column ${ariaLabel ?? "column"}`,
|
|
3218
|
+
"aria-valuemin": minWidth,
|
|
3219
|
+
"aria-valuenow": typeof width === "number" ? width : void 0,
|
|
3220
|
+
tabIndex: 0,
|
|
3221
|
+
"data-column-resize": "true",
|
|
3222
|
+
onPointerDown: startResize,
|
|
3223
|
+
onKeyDown: resizeByKey,
|
|
3224
|
+
onClick: (e) => e.stopPropagation(),
|
|
3225
|
+
className: cn(
|
|
3226
|
+
"group/resize absolute inset-y-0 -right-1 z-10 w-2 cursor-col-resize outline-none",
|
|
3227
|
+
"flex justify-center"
|
|
3228
|
+
),
|
|
3229
|
+
children: /* @__PURE__ */ jsx(
|
|
3230
|
+
"span",
|
|
3231
|
+
{
|
|
3232
|
+
"aria-hidden": "true",
|
|
3233
|
+
className: cn(
|
|
3234
|
+
"h-full w-0.5 transition-colors",
|
|
3235
|
+
isResizing ? "bg-accent" : "bg-transparent group-hover/resize:bg-accent group-focus-visible/resize:bg-accent"
|
|
3236
|
+
)
|
|
3237
|
+
}
|
|
3238
|
+
)
|
|
3239
|
+
}
|
|
3240
|
+
)
|
|
2890
3241
|
) : null
|
|
2891
3242
|
]
|
|
2892
3243
|
}
|
|
@@ -2940,12 +3291,27 @@ var tableScrollerStyles = tv({
|
|
|
2940
3291
|
base: ["relative flex-1 min-h-0 overflow-auto", ...scrollbarChrome]
|
|
2941
3292
|
});
|
|
2942
3293
|
function TableScroller({ className, ref, ...props }) {
|
|
2943
|
-
return /* @__PURE__ */ jsx(
|
|
3294
|
+
return /* @__PURE__ */ jsx(
|
|
3295
|
+
"div",
|
|
3296
|
+
{
|
|
3297
|
+
role: "presentation",
|
|
3298
|
+
ref,
|
|
3299
|
+
...props,
|
|
3300
|
+
className: cn(tableScrollerStyles(), className)
|
|
3301
|
+
}
|
|
3302
|
+
);
|
|
2944
3303
|
}
|
|
2945
3304
|
var rowStripeBg = "bg-[color-mix(in_oklab,var(--color-ink)_var(--row-stripe),var(--color-bg))]";
|
|
2946
3305
|
var rowHoverBg = "hover:bg-[color-mix(in_oklab,var(--color-ink)_var(--row-hover),var(--color-bg))]";
|
|
3306
|
+
var cellEditingRow = "has-[[data-cell-editing]]:z-[3]";
|
|
3307
|
+
var cellEditingCell = "has-[[data-cell-editing]]:z-[3] has-[[data-cell-editing]]:overflow-visible";
|
|
2947
3308
|
var tableRowStyles = tv({
|
|
2948
|
-
base: [
|
|
3309
|
+
base: [
|
|
3310
|
+
"relative flex items-stretch",
|
|
3311
|
+
"border-b border-rule-2 last:border-b-0",
|
|
3312
|
+
"bg-bg",
|
|
3313
|
+
cellEditingRow
|
|
3314
|
+
],
|
|
2949
3315
|
variants: {
|
|
2950
3316
|
alt: {
|
|
2951
3317
|
true: rowStripeBg,
|
|
@@ -2956,7 +3322,9 @@ var tableRowStyles = tv({
|
|
|
2956
3322
|
false: rowHoverBg
|
|
2957
3323
|
},
|
|
2958
3324
|
absolute: {
|
|
2959
|
-
|
|
3325
|
+
// `top-0` pins the static position: a virtualized row must never
|
|
3326
|
+
// inherit a flow offset from a sibling that is in normal flow.
|
|
3327
|
+
true: "absolute top-0 left-0 right-0",
|
|
2960
3328
|
false: ""
|
|
2961
3329
|
}
|
|
2962
3330
|
},
|
|
@@ -2987,11 +3355,12 @@ function TableRow({
|
|
|
2987
3355
|
}
|
|
2988
3356
|
var tableCellStyles = tv({
|
|
2989
3357
|
base: [
|
|
2990
|
-
"flex items-center shrink-0 min-w-0",
|
|
3358
|
+
"relative flex items-center shrink-0 min-w-0",
|
|
2991
3359
|
"px-[14px]",
|
|
2992
3360
|
"whitespace-nowrap overflow-hidden text-ellipsis",
|
|
2993
3361
|
"font-sans text-[13px] tracking-[-0.005em]",
|
|
2994
|
-
"text-ink-2"
|
|
3362
|
+
"text-ink-2",
|
|
3363
|
+
cellEditingCell
|
|
2995
3364
|
],
|
|
2996
3365
|
variants: {
|
|
2997
3366
|
align: {
|
|
@@ -3152,6 +3521,8 @@ function DataTable({
|
|
|
3152
3521
|
enableColumnRemoval = false,
|
|
3153
3522
|
onReorderColumn,
|
|
3154
3523
|
onRemoveColumn,
|
|
3524
|
+
enableColumnResizing = false,
|
|
3525
|
+
onResizeColumn,
|
|
3155
3526
|
variant = "panel",
|
|
3156
3527
|
rowWrapper,
|
|
3157
3528
|
extraRows,
|
|
@@ -3365,7 +3736,6 @@ function DataTable({
|
|
|
3365
3736
|
const showEmpty = !query.isLoading && !query.error && tableRowCount === 0 && !query.isFetchingNextPage;
|
|
3366
3737
|
const showInitialLoading = query.isLoading && tableRowCount === 0;
|
|
3367
3738
|
const showError = !!query.error && tableRowCount === 0;
|
|
3368
|
-
const showEndMarker = !query.isLoading && !query.isFetchingNextPage && !query.hasNextPage && tableRowCount > 0;
|
|
3369
3739
|
const totalSize = virtualizer.getTotalSize();
|
|
3370
3740
|
const virtualItems = virtualizer.getVirtualItems();
|
|
3371
3741
|
const headerGroups = table.getHeaderGroups();
|
|
@@ -3376,84 +3746,108 @@ function DataTable({
|
|
|
3376
3746
|
...ariaLabel !== void 0 ? { "aria-label": ariaLabel } : {},
|
|
3377
3747
|
variant,
|
|
3378
3748
|
className: cn("flex-1 min-h-0", className),
|
|
3379
|
-
children: /* @__PURE__ */ jsx(
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
draggable: enableColumnReordering && !!header.column.id,
|
|
3398
|
-
...header.column.id ? { columnId: header.column.id } : {},
|
|
3399
|
-
...headerSize !== void 0 ? { width: headerSize } : {},
|
|
3400
|
-
...sticky !== false ? { sticky } : {},
|
|
3401
|
-
...meta?.cellClassName ? { className: meta.cellClassName } : {},
|
|
3402
|
-
...canSort ? {
|
|
3403
|
-
sortDirection: direction,
|
|
3404
|
-
onSortToggle: () => handleSort?.({})
|
|
3405
|
-
} : {},
|
|
3406
|
-
...enableColumnRemoval && onRemoveColumn && header.column.id ? { onRemove: () => onRemoveColumn(header.column.id) } : {},
|
|
3407
|
-
children: headerNode
|
|
3408
|
-
},
|
|
3409
|
-
header.id
|
|
3410
|
-
);
|
|
3411
|
-
}),
|
|
3412
|
-
/* @__PURE__ */ jsx(TableHeaderSpacer, {})
|
|
3413
|
-
] }, group.id)),
|
|
3414
|
-
bodyBefore,
|
|
3415
|
-
showInitialLoading ? loadingState ?? /* @__PURE__ */ jsx(DataTableSkeleton, { rowHeight }) : showError ? /* @__PURE__ */ jsx("div", { role: "rowgroup", children: errorState ?? (query.error ? /* @__PURE__ */ jsx(DataTableError, { error: query.error }) : null) }) : /* @__PURE__ */ jsxs("div", { role: "rowgroup", children: [
|
|
3416
|
-
showEmpty ? emptyState ?? /* @__PURE__ */ jsx(DataTableEmpty, {}) : /* @__PURE__ */ jsx(
|
|
3417
|
-
"div",
|
|
3418
|
-
{
|
|
3419
|
-
ref: listRef,
|
|
3420
|
-
role: "presentation",
|
|
3421
|
-
style: { height: totalSize, position: "relative", width: "100%" },
|
|
3422
|
-
children: virtualItems.map((vRow) => {
|
|
3423
|
-
const item = listItems[vRow.index];
|
|
3424
|
-
if (!item) return null;
|
|
3425
|
-
const rowStyle = {
|
|
3426
|
-
// Items' `start` includes the virtualizer's scrollMargin
|
|
3427
|
-
// (the list's offset below the sticky header); subtract
|
|
3428
|
-
// it to position relative to the list container.
|
|
3429
|
-
transform: `translateY(${vRow.start - listOffset}px)`,
|
|
3430
|
-
height: vRow.size
|
|
3431
|
-
};
|
|
3432
|
-
if (item.kind === "group") {
|
|
3433
|
-
return /* @__PURE__ */ jsx(GroupHeaderRow, { style: rowStyle, children: item.label }, `group:${item.id}`);
|
|
3434
|
-
}
|
|
3749
|
+
children: /* @__PURE__ */ jsx(
|
|
3750
|
+
TableScroller,
|
|
3751
|
+
{
|
|
3752
|
+
ref: scrollerRef,
|
|
3753
|
+
className: cn("scroll-pt-[36px]", bodyAfter ? "scroll-pb-8" : void 0),
|
|
3754
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", style: { minWidth: minPanelWidth }, children: [
|
|
3755
|
+
headerGroups.map((group) => /* @__PURE__ */ jsxs(TableHeader, { sticky: true, children: [
|
|
3756
|
+
group.headers.map((header) => {
|
|
3757
|
+
const meta = header.column.columnDef.meta;
|
|
3758
|
+
const align = meta?.align ?? "left";
|
|
3759
|
+
const sticky = meta?.sticky ?? false;
|
|
3760
|
+
const headerSize = header.getSize() || void 0;
|
|
3761
|
+
const headerNode = header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext());
|
|
3762
|
+
const sorted = header.column.getIsSorted();
|
|
3763
|
+
const direction = sorted === false ? null : sorted;
|
|
3764
|
+
const canSort = header.column.getCanSort();
|
|
3765
|
+
const handleSort = header.column.getToggleSortingHandler();
|
|
3766
|
+
const ariaLabel2 = typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : header.column.id;
|
|
3435
3767
|
return /* @__PURE__ */ jsx(
|
|
3436
|
-
|
|
3768
|
+
TableHeaderCell,
|
|
3437
3769
|
{
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
...
|
|
3770
|
+
align,
|
|
3771
|
+
ariaLabel: ariaLabel2,
|
|
3772
|
+
draggable: enableColumnReordering && !!header.column.id,
|
|
3773
|
+
...header.column.id ? { columnId: header.column.id } : {},
|
|
3774
|
+
...headerSize !== void 0 ? { width: headerSize } : {},
|
|
3775
|
+
...sticky !== false ? { sticky } : {},
|
|
3776
|
+
...meta?.cellClassName ? { className: meta.cellClassName } : {},
|
|
3777
|
+
...canSort ? {
|
|
3778
|
+
sortDirection: direction,
|
|
3779
|
+
onSortToggle: () => handleSort?.({})
|
|
3780
|
+
} : {},
|
|
3781
|
+
...enableColumnRemoval && onRemoveColumn && header.column.id ? { onRemove: () => onRemoveColumn(header.column.id) } : {},
|
|
3782
|
+
...enableColumnResizing && onResizeColumn && header.column.id ? {
|
|
3783
|
+
onResize: (width) => onResizeColumn({ id: header.column.id, width })
|
|
3784
|
+
} : {},
|
|
3785
|
+
children: headerNode
|
|
3445
3786
|
},
|
|
3446
|
-
|
|
3787
|
+
header.id
|
|
3447
3788
|
);
|
|
3448
|
-
})
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3789
|
+
}),
|
|
3790
|
+
/* @__PURE__ */ jsx(TableHeaderSpacer, {})
|
|
3791
|
+
] }, group.id)),
|
|
3792
|
+
bodyBefore,
|
|
3793
|
+
showInitialLoading ? loadingState ?? /* @__PURE__ */ jsx(DataTableSkeleton, { rowHeight }) : showError ? /* @__PURE__ */ jsx("div", { role: "rowgroup", children: errorState ?? (query.error ? /* @__PURE__ */ jsx(DataTableError, { error: query.error }) : null) }) : /* @__PURE__ */ jsxs("div", { role: "rowgroup", children: [
|
|
3794
|
+
showEmpty ? emptyState ?? /* @__PURE__ */ jsx(DataTableEmpty, {}) : /* @__PURE__ */ jsx(
|
|
3795
|
+
"div",
|
|
3796
|
+
{
|
|
3797
|
+
ref: listRef,
|
|
3798
|
+
role: "presentation",
|
|
3799
|
+
style: { height: totalSize, position: "relative", width: "100%" },
|
|
3800
|
+
children: virtualItems.map((vRow) => {
|
|
3801
|
+
const item = listItems[vRow.index];
|
|
3802
|
+
if (!item) return null;
|
|
3803
|
+
const rowStyle = {
|
|
3804
|
+
// Items' `start` includes the virtualizer's scrollMargin
|
|
3805
|
+
// (the list's offset below the sticky header); subtract
|
|
3806
|
+
// it to position relative to the list container.
|
|
3807
|
+
transform: `translateY(${vRow.start - listOffset}px)`,
|
|
3808
|
+
height: vRow.size
|
|
3809
|
+
};
|
|
3810
|
+
if (item.kind === "group") {
|
|
3811
|
+
return /* @__PURE__ */ jsx(GroupHeaderRow, { style: rowStyle, children: item.label }, `group:${item.id}`);
|
|
3812
|
+
}
|
|
3813
|
+
return /* @__PURE__ */ jsx(
|
|
3814
|
+
DataRow,
|
|
3815
|
+
{
|
|
3816
|
+
row: item.row,
|
|
3817
|
+
index: item.dataIndex,
|
|
3818
|
+
zebra,
|
|
3819
|
+
onRowClick,
|
|
3820
|
+
style: rowStyle,
|
|
3821
|
+
columnBorders,
|
|
3822
|
+
...rowWrapper ? { rowWrapper } : {}
|
|
3823
|
+
},
|
|
3824
|
+
item.row.id
|
|
3825
|
+
);
|
|
3826
|
+
})
|
|
3827
|
+
}
|
|
3828
|
+
),
|
|
3829
|
+
!showEmpty && /* @__PURE__ */ jsx("div", { ref: sentinelRef, "aria-hidden": "true", style: { height: 1, width: "100%" } }),
|
|
3830
|
+
query.isFetchingNextPage ? /* @__PURE__ */ jsx(LoaderRow, {}) : null
|
|
3831
|
+
] }),
|
|
3832
|
+
bodyAfter ? (
|
|
3833
|
+
// Sticky to the scroller's bottom edge; `bg-bg` covers the rows
|
|
3834
|
+
// sliding underneath. z-[4] — like the sticky header — stays above an
|
|
3835
|
+
// editing row (z-[3]), so an editor scrolled under the strip is
|
|
3836
|
+
// covered rather than drawn over it.
|
|
3837
|
+
/* @__PURE__ */ jsx(
|
|
3838
|
+
"div",
|
|
3839
|
+
{
|
|
3840
|
+
className: cn(
|
|
3841
|
+
"sticky bottom-0 z-[4] flex items-center h-8 px-0.5",
|
|
3842
|
+
"border-t border-rule-2 bg-bg"
|
|
3843
|
+
),
|
|
3844
|
+
children: bodyAfter
|
|
3845
|
+
}
|
|
3846
|
+
)
|
|
3847
|
+
) : null
|
|
3848
|
+
] })
|
|
3849
|
+
}
|
|
3850
|
+
)
|
|
3457
3851
|
}
|
|
3458
3852
|
);
|
|
3459
3853
|
}
|
|
@@ -3553,23 +3947,6 @@ function LoaderRow() {
|
|
|
3553
3947
|
}
|
|
3554
3948
|
);
|
|
3555
3949
|
}
|
|
3556
|
-
function EndMarker({ count }) {
|
|
3557
|
-
return /* @__PURE__ */ jsxs(
|
|
3558
|
-
"div",
|
|
3559
|
-
{
|
|
3560
|
-
className: cn(
|
|
3561
|
-
"flex items-center justify-center",
|
|
3562
|
-
"h-8 font-mono text-[10.5px] uppercase tracking-[0.08em]",
|
|
3563
|
-
"text-ink-4"
|
|
3564
|
-
),
|
|
3565
|
-
children: [
|
|
3566
|
-
"end \xB7 ",
|
|
3567
|
-
count.toLocaleString(),
|
|
3568
|
-
" rows"
|
|
3569
|
-
]
|
|
3570
|
-
}
|
|
3571
|
-
);
|
|
3572
|
-
}
|
|
3573
3950
|
|
|
3574
3951
|
// src/components/data-table/make-actions-column.ts
|
|
3575
3952
|
function makeActionsColumn({
|
|
@@ -4157,7 +4534,9 @@ function MultiSelect({
|
|
|
4157
4534
|
placement: "bottom start",
|
|
4158
4535
|
className: cn(
|
|
4159
4536
|
"w-[var(--trigger-width)]",
|
|
4160
|
-
|
|
4537
|
+
// The popover element itself takes focus when opened programmatically
|
|
4538
|
+
// (defaultOpen) — no browser outline around the whole panel.
|
|
4539
|
+
"outline-none rounded-md border border-rule bg-surface p-1",
|
|
4161
4540
|
"shadow-[var(--shadow-raised)]",
|
|
4162
4541
|
"entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1",
|
|
4163
4542
|
"exiting:animate-out exiting:fade-out-0 exiting:slide-out-to-top-1"
|
|
@@ -4182,6 +4561,7 @@ function MultiSelect({
|
|
|
4182
4561
|
{
|
|
4183
4562
|
"aria-label": typeof label === "string" ? label : "Options",
|
|
4184
4563
|
selectionMode: "multiple",
|
|
4564
|
+
escapeKeyBehavior: "none",
|
|
4185
4565
|
selectedKeys: selectedSet,
|
|
4186
4566
|
onSelectionChange: (keys) => {
|
|
4187
4567
|
if (keys === "all") {
|
|
@@ -4204,11 +4584,10 @@ function MultiSelect({
|
|
|
4204
4584
|
"cursor-pointer outline-none select-none",
|
|
4205
4585
|
"data-[hovered]:bg-surface-2 data-[hovered]:text-ink",
|
|
4206
4586
|
"data-[focused]:bg-surface-2 data-[focused]:text-ink",
|
|
4207
|
-
"data-[selected]:bg-surface-3 data-[selected]:text-ink",
|
|
4208
4587
|
"data-[disabled]:opacity-45 data-[disabled]:cursor-not-allowed"
|
|
4209
4588
|
),
|
|
4210
4589
|
children: [
|
|
4211
|
-
/* @__PURE__ */ jsx(
|
|
4590
|
+
/* @__PURE__ */ jsx(ListboxCheck, {}),
|
|
4212
4591
|
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: option.content ?? option.label })
|
|
4213
4592
|
]
|
|
4214
4593
|
},
|
|
@@ -4269,42 +4648,6 @@ function Chip({
|
|
|
4269
4648
|
}
|
|
4270
4649
|
);
|
|
4271
4650
|
}
|
|
4272
|
-
function Checkmark() {
|
|
4273
|
-
return /* @__PURE__ */ jsx(
|
|
4274
|
-
"span",
|
|
4275
|
-
{
|
|
4276
|
-
"aria-hidden": true,
|
|
4277
|
-
className: cn(
|
|
4278
|
-
"relative inline-flex items-center justify-center shrink-0",
|
|
4279
|
-
"size-[16px] rounded-[3px] border border-ink-4 bg-surface",
|
|
4280
|
-
"transition-[background-color,border-color] duration-150",
|
|
4281
|
-
"group-data-[selected]:bg-ink group-data-[selected]:border-ink"
|
|
4282
|
-
),
|
|
4283
|
-
children: /* @__PURE__ */ jsx(
|
|
4284
|
-
"svg",
|
|
4285
|
-
{
|
|
4286
|
-
viewBox: "0 0 12 12",
|
|
4287
|
-
className: cn(
|
|
4288
|
-
"size-3 text-surface transition-opacity duration-150",
|
|
4289
|
-
"opacity-0 group-data-[selected]:opacity-100"
|
|
4290
|
-
),
|
|
4291
|
-
"aria-hidden": true,
|
|
4292
|
-
children: /* @__PURE__ */ jsx(
|
|
4293
|
-
"path",
|
|
4294
|
-
{
|
|
4295
|
-
d: "M2.5 6.25 5 8.75 9.5 3.75",
|
|
4296
|
-
stroke: "currentColor",
|
|
4297
|
-
strokeWidth: "1.6",
|
|
4298
|
-
strokeLinecap: "round",
|
|
4299
|
-
strokeLinejoin: "round",
|
|
4300
|
-
fill: "none"
|
|
4301
|
-
}
|
|
4302
|
-
)
|
|
4303
|
-
}
|
|
4304
|
-
)
|
|
4305
|
-
}
|
|
4306
|
-
);
|
|
4307
|
-
}
|
|
4308
4651
|
var SEARCH_DEBOUNCE_MS = 250;
|
|
4309
4652
|
function RecipientSelect({
|
|
4310
4653
|
connectionId,
|
|
@@ -6159,13 +6502,21 @@ function TagInput({
|
|
|
6159
6502
|
}) {
|
|
6160
6503
|
const styles4 = fieldControlStyles({ size, invalid: isInvalid, appearance });
|
|
6161
6504
|
const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
|
|
6162
|
-
const
|
|
6505
|
+
const isCell = appearance === "cell";
|
|
6163
6506
|
const inputRef = useRef(null);
|
|
6507
|
+
const chipsRef = useRef(null);
|
|
6508
|
+
const hasWrapped = useChipRowWrap(chipsRef, isCell, JSON.stringify(value));
|
|
6164
6509
|
useEffect(() => {
|
|
6165
6510
|
if (autoFocus) inputRef.current?.focus();
|
|
6166
6511
|
}, []);
|
|
6167
6512
|
const inputId = useId();
|
|
6168
6513
|
const [draft, setDraft] = useState("");
|
|
6514
|
+
useLayoutEffect(() => {
|
|
6515
|
+
const input = inputRef.current;
|
|
6516
|
+
if (!isCell || !input || document.activeElement !== input) return;
|
|
6517
|
+
if (typeof input.scrollIntoView !== "function") return;
|
|
6518
|
+
input.scrollIntoView({ block: "nearest" });
|
|
6519
|
+
}, [isCell, value]);
|
|
6169
6520
|
const commit = () => {
|
|
6170
6521
|
const v = draft.trim();
|
|
6171
6522
|
if (!v) return;
|
|
@@ -6182,7 +6533,10 @@ function TagInput({
|
|
|
6182
6533
|
const onKeyDown2 = (e) => {
|
|
6183
6534
|
if (e.key === "Enter" || e.key === ",") {
|
|
6184
6535
|
e.preventDefault();
|
|
6185
|
-
|
|
6536
|
+
if (draft.trim()) {
|
|
6537
|
+
e.stopPropagation();
|
|
6538
|
+
commit();
|
|
6539
|
+
}
|
|
6186
6540
|
return;
|
|
6187
6541
|
}
|
|
6188
6542
|
if (e.key === "Backspace" && !draft && value.length > 0) {
|
|
@@ -6192,85 +6546,78 @@ function TagInput({
|
|
|
6192
6546
|
};
|
|
6193
6547
|
return /* @__PURE__ */ jsxs("div", { className: cn("grid grid-cols-1 gap-1.5", className), children: [
|
|
6194
6548
|
label ? /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: fieldLabelStyles, children: label }) : null,
|
|
6195
|
-
/* @__PURE__ */
|
|
6549
|
+
/* @__PURE__ */ jsx(
|
|
6196
6550
|
"div",
|
|
6197
6551
|
{
|
|
6198
6552
|
"data-invalid": isInvalid || void 0,
|
|
6199
6553
|
"data-disabled": isDisabled || void 0,
|
|
6200
6554
|
className: cn(
|
|
6201
6555
|
styles4.box(),
|
|
6202
|
-
"flex
|
|
6203
|
-
|
|
6204
|
-
|
|
6556
|
+
"flex",
|
|
6557
|
+
// Cell editor: one table row (29px under a 32px row) while the chips
|
|
6558
|
+
// fit on a line; two rows (64px), popping out of the row, once they
|
|
6559
|
+
// wrap — the chips then scroll inside. Field mode grows with its
|
|
6560
|
+
// content.
|
|
6561
|
+
isCell ? hasWrapped ? "h-[64px] p-1" : "h-[29px] px-1 py-0" : [fieldChipPadding[size], fieldMinHeight[size]],
|
|
6205
6562
|
focusWithin
|
|
6206
6563
|
),
|
|
6207
|
-
children:
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
"
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6564
|
+
children: /* @__PURE__ */ jsxs(
|
|
6565
|
+
"div",
|
|
6566
|
+
{
|
|
6567
|
+
ref: chipsRef,
|
|
6568
|
+
className: cn(
|
|
6569
|
+
"flex flex-1 flex-wrap items-center gap-1.5 min-w-0",
|
|
6570
|
+
isCell && (hasWrapped ? "content-start overflow-y-auto" : "content-center overflow-hidden")
|
|
6571
|
+
),
|
|
6572
|
+
children: [
|
|
6573
|
+
value.map((tag, idx) => (
|
|
6574
|
+
// tags are kept unique on commit, so the value alone is a stable key
|
|
6575
|
+
/* @__PURE__ */ jsx(
|
|
6576
|
+
Badge,
|
|
6577
|
+
{
|
|
6578
|
+
variant: "active",
|
|
6579
|
+
shape: "rounded",
|
|
6580
|
+
hasDot: false,
|
|
6581
|
+
className: "shrink-0",
|
|
6582
|
+
actions: /* @__PURE__ */ jsx(
|
|
6583
|
+
BadgeAction,
|
|
6584
|
+
{
|
|
6585
|
+
label: `Remove ${tag}`,
|
|
6586
|
+
onPress: () => remove(idx),
|
|
6587
|
+
isDisabled
|
|
6588
|
+
}
|
|
6589
|
+
),
|
|
6590
|
+
children: /* @__PURE__ */ jsx("span", { className: "max-w-[10rem] truncate", children: tag })
|
|
6591
|
+
},
|
|
6592
|
+
tag
|
|
6593
|
+
)
|
|
6594
|
+
)),
|
|
6595
|
+
/* @__PURE__ */ jsx(
|
|
6596
|
+
"input",
|
|
6597
|
+
{
|
|
6598
|
+
ref: inputRef,
|
|
6599
|
+
id: inputId,
|
|
6600
|
+
type: inputType,
|
|
6601
|
+
value: draft,
|
|
6602
|
+
onChange: (e) => setDraft(e.target.value),
|
|
6603
|
+
onKeyDown: onKeyDown2,
|
|
6604
|
+
onBlur: commit,
|
|
6605
|
+
disabled: isDisabled,
|
|
6606
|
+
placeholder: value.length === 0 ? placeholder : "",
|
|
6607
|
+
className: cn(
|
|
6608
|
+
"flex-1 min-w-[6rem] bg-transparent outline-none",
|
|
6609
|
+
"font-sans text-ink placeholder:text-ink-4",
|
|
6610
|
+
fieldTextStyles[size],
|
|
6611
|
+
// No vertical padding — wrapper's p-1.5 + min-h-[size] govern the
|
|
6612
|
+
// overall height so it matches Input/Select at the same size.
|
|
6613
|
+
"px-1.5",
|
|
6614
|
+
"disabled:cursor-not-allowed disabled:opacity-45"
|
|
6244
6615
|
)
|
|
6245
|
-
|
|
6246
|
-
},
|
|
6247
|
-
tag
|
|
6248
|
-
)
|
|
6249
|
-
)),
|
|
6250
|
-
/* @__PURE__ */ jsx(
|
|
6251
|
-
"input",
|
|
6252
|
-
{
|
|
6253
|
-
ref: inputRef,
|
|
6254
|
-
id: inputId,
|
|
6255
|
-
type: inputType,
|
|
6256
|
-
value: draft,
|
|
6257
|
-
onChange: (e) => setDraft(e.target.value),
|
|
6258
|
-
onKeyDown: onKeyDown2,
|
|
6259
|
-
onBlur: commit,
|
|
6260
|
-
disabled: isDisabled,
|
|
6261
|
-
placeholder: value.length === 0 ? placeholder : "",
|
|
6262
|
-
className: cn(
|
|
6263
|
-
"flex-1 min-w-[6rem] bg-transparent outline-none",
|
|
6264
|
-
"font-sans text-ink placeholder:text-ink-4",
|
|
6265
|
-
fieldTextStyles[size],
|
|
6266
|
-
// No vertical padding — wrapper's p-1.5 + min-h-[size] govern the
|
|
6267
|
-
// overall height so it matches Input/Select at the same size.
|
|
6268
|
-
"px-1.5",
|
|
6269
|
-
"disabled:cursor-not-allowed disabled:opacity-45"
|
|
6616
|
+
}
|
|
6270
6617
|
)
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6618
|
+
]
|
|
6619
|
+
}
|
|
6620
|
+
)
|
|
6274
6621
|
}
|
|
6275
6622
|
),
|
|
6276
6623
|
description ? /* @__PURE__ */ jsx("p", { className: fieldHintStyles, children: description }) : null,
|
|
@@ -8170,32 +8517,7 @@ function ToastRegion({ queue, className }) {
|
|
|
8170
8517
|
}
|
|
8171
8518
|
);
|
|
8172
8519
|
}
|
|
8173
|
-
function TooltipTrigger({
|
|
8174
|
-
delay = 500,
|
|
8175
|
-
closeDelay = 0,
|
|
8176
|
-
...props
|
|
8177
|
-
}) {
|
|
8178
|
-
return /* @__PURE__ */ jsx(TooltipTrigger$1, { delay, closeDelay, ...props });
|
|
8179
|
-
}
|
|
8180
|
-
function Tooltip({ className, offset = 6, ...props }) {
|
|
8181
|
-
return /* @__PURE__ */ jsx(
|
|
8182
|
-
Tooltip$1,
|
|
8183
|
-
{
|
|
8184
|
-
...props,
|
|
8185
|
-
offset,
|
|
8186
|
-
className: (renderProps) => cn(
|
|
8187
|
-
"z-50 max-w-xs",
|
|
8188
|
-
"rounded-md border border-rule bg-surface shadow-[var(--shadow-raised)]",
|
|
8189
|
-
"px-2.5 py-1.5",
|
|
8190
|
-
"font-mono text-[11.5px] text-ink-2",
|
|
8191
|
-
"entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1 entering:duration-150",
|
|
8192
|
-
"exiting:animate-out exiting:fade-out-0 exiting:duration-100",
|
|
8193
|
-
typeof className === "function" ? className(renderProps) : className
|
|
8194
|
-
)
|
|
8195
|
-
}
|
|
8196
|
-
);
|
|
8197
|
-
}
|
|
8198
8520
|
|
|
8199
|
-
export { ATTRIBUTE_TYPES, ATTRIBUTE_TYPE_ICONS, AttachmentChip, AttributePicker, AttributeType, AttributeTypeIcon, Avatar, AvatarGroup, Badge, BadgeMultiSelect, BooleanCell, Breadcrumbs, COLUMN_DRAG_KIND, CONVERSATION_BRIEF_OUTCOME_LABEL, Card, CardBody, CardContent, CardEyebrow, CardFeatureTitle, CardFooter, CardHeader, CardTitle, ChannelIcon, Checkbox, CheckboxGroup, ChipValue, ColorInput, Combobox, Command, CommandHint, ConversationBriefCard, ConversationBriefPreview, ConversationBriefReview, CurrencyInput, DRAFT_OUTCOME_LABEL, DataTable, DataTableEmpty, DataTableError, DataTableSkeleton, DateCell, DatePicker, DateTimeCell, DateTimePicker, DraftMessageCard, DraftMessageComposer, DraftMessageReview, EmptyState, ErrorAnimation, FIELD_LABEL_SEPARATOR, FieldCaret, FileField, FileViewer, FileViewerFallbackCard, FilterRow, FilterValueInput, IconPicker, ImageAttachment, ImageLightbox, Input, Kbd, LinkCell, MAX_COMPOSER_ATTACHMENT_BYTES, Menu, MenuItem, MenuPopover, MenuTrigger, MessageComposer, Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle, MultiSelect, NavGroup, NavItem, NavSection, OPERATORS, OperatorPicker, Orb, PROTECTED_COMBOS, Popover, PopoverContent, PopoverPanelBody, PopoverPanelFooter, PopoverPanelHeader, PressableCard, ProgressBar, Radio, RadioGroup, RecipientSelect, RecordFilterBuilderPanel, RecordFilterButton, RecordFilterChips, RecordFilterEditor, RenderChipItemProvider, RenderValueInputProvider, SELECTION_COLUMN_ID, SegmentedControl, Select, Separator, SubmenuTrigger, SuccessAnimation, Switch, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TableHeaderSpacer, TableRow, TableScroller, Tabs, TagInput, Textarea, TimeField, ToastRegion, Tooltip, TooltipTrigger, TruncateCell, __resetDraftMessageActions, __resetDraftMessageOutcomes, addLeaf as addFilterLeaf, addPendingLeaf, addSubgroup, arityOf, attachmentChipStyles, avatarGroupStyles, avatarStyles, badgeStyles, cardStyles2 as cardStyles, channelIcon, contactPhoneNumbers, conversationBriefCardStyles, conversationBriefOutcomeFor, countLeaves, createConversationBriefClient, createDraftMessageClient, createToastQueue, defaultValueFor, draftMessageCardStyles, draftMessageComposerStyles, draftOutcomeFor, emptyStateStyles, fieldControlStyles, fieldErrorStyles, fieldHintStyles, fieldLabelStyles, fileViewerFallbackCardStyles, fileViewerStyles, formatFileSize, formatValue, iconForContentType, imageAttachmentStyles, imageLightboxStyles, isColumnDragData, isDialableConversationBrief, isDraftReviewOutcome, isEditableTarget, isPreviewableImageName, joinFieldLabel, makeActionsColumn, messageComposerStyles, namesOf, navItemStyles, normalizeHexColor, operatorById, operatorsForType, parseCombo, progressBarStyles, publishDraftMessageOutcome, rebaseRowOnFieldChange, rebaseRowOnOperatorChange, registerDraftMessageActions, removeLeaf, removeSubgroup, replaceLeaf, resolveLucideIcon, resolveLucideIconName, segmentedControlStyles, setJoiner, subscribeDraftMessageOutcome, summaryFor, tableCellStyles, tableHeaderCellStyles, tabsStyles, terminalKindFor, toastStyles, updateLeaf, updateSubgroup, useAttributeTypeIcon, useCommand, useDiscoveryActive, useDraftMessageActions, useDraftMessageOutcome, useEscapeKey, useInfiniteScrollSentinel, useRenderChipItem, useRenderValueInput, useShowDetails, viewerKindForContentType, wrapLeafInGroup };
|
|
8521
|
+
export { ATTRIBUTE_TYPES, ATTRIBUTE_TYPE_ICONS, AttachmentChip, AttributePicker, AttributeType, AttributeTypeIcon, Avatar, AvatarGroup, Badge, BadgeAction, BadgeGroup, BadgeMultiSelect, BooleanCell, Breadcrumbs, COLUMN_DRAG_KIND, CONVERSATION_BRIEF_OUTCOME_LABEL, Card, CardBody, CardContent, CardEyebrow, CardFeatureTitle, CardFooter, CardHeader, CardTitle, ChannelIcon, Checkbox, CheckboxGroup, ChipValue, ColorInput, Combobox, Command, CommandHint, ConversationBriefCard, ConversationBriefPreview, ConversationBriefReview, CurrencyInput, DRAFT_OUTCOME_LABEL, DataTable, DataTableEmpty, DataTableError, DataTableSkeleton, DateCell, DatePicker, DateTimeCell, DateTimePicker, DraftMessageCard, DraftMessageComposer, DraftMessageReview, EmptyState, ErrorAnimation, FIELD_LABEL_SEPARATOR, FieldCaret, FileField, FileViewer, FileViewerFallbackCard, FilterRow, FilterValueInput, IconPicker, ImageAttachment, ImageLightbox, Input, Kbd, LinkCell, MAX_COMPOSER_ATTACHMENT_BYTES, Menu, MenuItem, MenuPopover, MenuTrigger, MessageComposer, Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle, MultiSelect, NavGroup, NavItem, NavSection, OPERATORS, OperatorPicker, Orb, PROTECTED_COMBOS, Popover, PopoverContent, PopoverPanelBody, PopoverPanelFooter, PopoverPanelHeader, PressableCard, ProgressBar, Radio, RadioGroup, RecipientSelect, RecordFilterBuilderPanel, RecordFilterButton, RecordFilterChips, RecordFilterEditor, RenderChipItemProvider, RenderValueInputProvider, SELECTION_COLUMN_ID, SegmentedControl, Select, Separator, SubmenuTrigger, SuccessAnimation, Switch, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TableHeaderSpacer, TableRow, TableScroller, Tabs, TagInput, Textarea, TimeField, ToastRegion, Tooltip, TooltipTrigger, TruncateCell, __resetDraftMessageActions, __resetDraftMessageOutcomes, addLeaf as addFilterLeaf, addPendingLeaf, addSubgroup, arityOf, attachmentChipStyles, avatarGroupStyles, avatarStyles, badgeGroupOverflowStyles, badgeGroupStyles, badgeStyles, cardStyles2 as cardStyles, channelIcon, contactPhoneNumbers, conversationBriefCardStyles, conversationBriefOutcomeFor, countLeaves, createConversationBriefClient, createDraftMessageClient, createToastQueue, defaultValueFor, draftMessageCardStyles, draftMessageComposerStyles, draftOutcomeFor, emptyStateStyles, fieldControlStyles, fieldErrorStyles, fieldHintStyles, fieldLabelStyles, fileViewerFallbackCardStyles, fileViewerStyles, fitBadgeCount, formatFileSize, formatValue, iconForContentType, imageAttachmentStyles, imageLightboxStyles, isColumnDragData, isDialableConversationBrief, isDraftReviewOutcome, isEditableTarget, isPreviewableImageName, joinFieldLabel, makeActionsColumn, messageComposerStyles, namesOf, navItemStyles, normalizeHexColor, operatorById, operatorsForType, parseCombo, progressBarStyles, publishDraftMessageOutcome, rebaseRowOnFieldChange, rebaseRowOnOperatorChange, registerDraftMessageActions, removeLeaf, removeSubgroup, replaceLeaf, resolveLucideIcon, resolveLucideIconName, segmentedControlStyles, setJoiner, subscribeDraftMessageOutcome, summaryFor, tableCellStyles, tableHeaderCellStyles, tabsStyles, terminalKindFor, toastStyles, updateLeaf, updateSubgroup, useAttributeTypeIcon, useCommand, useDiscoveryActive, useDraftMessageActions, useDraftMessageOutcome, useEscapeKey, useInfiniteScrollSentinel, useRenderChipItem, useRenderValueInput, useShowDetails, viewerKindForContentType, wrapLeafInGroup };
|
|
8200
8522
|
//# sourceMappingURL=index.js.map
|
|
8201
8523
|
//# sourceMappingURL=index.js.map
|