@proteos/ui 0.54.1 → 0.56.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 +679 -321
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +84 -9
- package/dist/index.d.ts +84 -9
- package/dist/index.js +677 -324
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- 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/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/record-filter/chip-value.tsx +6 -5
- package/src/components/record-filter/filter-value-input.tsx +11 -9
- package/src/components/record-filter/operators.test.ts +67 -12
- package/src/components/record-filter/operators.ts +43 -2
- package/src/components/record-filter/types.ts +6 -1
- 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.cjs
CHANGED
|
@@ -873,6 +873,7 @@ function Badge({
|
|
|
873
873
|
hasDot,
|
|
874
874
|
color,
|
|
875
875
|
icon,
|
|
876
|
+
actions,
|
|
876
877
|
className,
|
|
877
878
|
style,
|
|
878
879
|
children,
|
|
@@ -894,11 +895,249 @@ function Badge({
|
|
|
894
895
|
),
|
|
895
896
|
children: [
|
|
896
897
|
Icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { "aria-hidden": true, className: chunkMWAXK66H_cjs.cn("size-3 shrink-0", ICON_TONE[register2]) }) : null,
|
|
897
|
-
children
|
|
898
|
+
children,
|
|
899
|
+
actions ? (
|
|
900
|
+
// Pulled flush with the trailing edge so the chip still reads
|
|
901
|
+
// symmetric around its leading dot / icon.
|
|
902
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center shrink-0 -mr-1", children: actions })
|
|
903
|
+
) : null
|
|
898
904
|
]
|
|
899
905
|
}
|
|
900
906
|
);
|
|
901
907
|
}
|
|
908
|
+
function BadgeAction({ label, onPress, isDisabled = false, children }) {
|
|
909
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
910
|
+
"button",
|
|
911
|
+
{
|
|
912
|
+
type: "button",
|
|
913
|
+
"aria-label": label,
|
|
914
|
+
disabled: isDisabled,
|
|
915
|
+
onClick: (event) => {
|
|
916
|
+
event.stopPropagation();
|
|
917
|
+
onPress();
|
|
918
|
+
},
|
|
919
|
+
className: chunkMWAXK66H_cjs.cn(
|
|
920
|
+
"inline-flex items-center justify-center shrink-0",
|
|
921
|
+
"size-3.5 rounded-full",
|
|
922
|
+
"text-current/70 hover:text-current hover:bg-current/10",
|
|
923
|
+
"outline-none cursor-pointer",
|
|
924
|
+
"focus-visible:shadow-[var(--shadow-focus)]",
|
|
925
|
+
"disabled:opacity-45 disabled:cursor-not-allowed"
|
|
926
|
+
),
|
|
927
|
+
children: children ?? /* @__PURE__ */ jsxRuntime.jsx("svg", { "aria-hidden": true, viewBox: "0 0 10 10", className: "size-2.5", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
928
|
+
"path",
|
|
929
|
+
{
|
|
930
|
+
d: "M2 2l6 6M8 2l-6 6",
|
|
931
|
+
stroke: "currentColor",
|
|
932
|
+
strokeWidth: "1.4",
|
|
933
|
+
strokeLinecap: "round"
|
|
934
|
+
}
|
|
935
|
+
) })
|
|
936
|
+
}
|
|
937
|
+
);
|
|
938
|
+
}
|
|
939
|
+
function TooltipTrigger({
|
|
940
|
+
delay = 500,
|
|
941
|
+
closeDelay = 0,
|
|
942
|
+
...props
|
|
943
|
+
}) {
|
|
944
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.TooltipTrigger, { delay, closeDelay, ...props });
|
|
945
|
+
}
|
|
946
|
+
function Tooltip({ className, offset = 6, ...props }) {
|
|
947
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
948
|
+
reactAriaComponents.Tooltip,
|
|
949
|
+
{
|
|
950
|
+
...props,
|
|
951
|
+
offset,
|
|
952
|
+
className: (renderProps) => chunkMWAXK66H_cjs.cn(
|
|
953
|
+
"z-50 max-w-xs",
|
|
954
|
+
"rounded-md border border-rule bg-surface shadow-[var(--shadow-raised)]",
|
|
955
|
+
"px-2.5 py-1.5",
|
|
956
|
+
"font-mono text-[11.5px] text-ink-2",
|
|
957
|
+
"entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1 entering:duration-150",
|
|
958
|
+
"exiting:animate-out exiting:fade-out-0 exiting:duration-100",
|
|
959
|
+
typeof className === "function" ? className(renderProps) : className
|
|
960
|
+
)
|
|
961
|
+
}
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
var badgeGroupStyles = tailwindVariants.tv({
|
|
965
|
+
base: "flex flex-nowrap items-center gap-1.5 w-full min-w-0",
|
|
966
|
+
variants: {
|
|
967
|
+
// The measuring pass renders every chip plus the overflow chip so their
|
|
968
|
+
// widths can be read; it is hidden so that pass never paints.
|
|
969
|
+
isMeasuring: { true: "invisible", false: "" }
|
|
970
|
+
},
|
|
971
|
+
defaultVariants: { isMeasuring: false }
|
|
972
|
+
});
|
|
973
|
+
function fitBadgeCount(metrics, available) {
|
|
974
|
+
const { itemWidths, overflowWidth, gap } = metrics;
|
|
975
|
+
const total = itemWidths.length;
|
|
976
|
+
if (available <= 0) return total;
|
|
977
|
+
let fullWidth = 0;
|
|
978
|
+
for (let index = 0; index < total; index += 1) {
|
|
979
|
+
fullWidth += (itemWidths[index] ?? 0) + (index > 0 ? gap : 0);
|
|
980
|
+
}
|
|
981
|
+
if (fullWidth <= available) return total;
|
|
982
|
+
let used = 0;
|
|
983
|
+
let count = 0;
|
|
984
|
+
for (let index = 0; index < total; index += 1) {
|
|
985
|
+
const next = used + (itemWidths[index] ?? 0) + gap;
|
|
986
|
+
if (next + overflowWidth > available) break;
|
|
987
|
+
used = next;
|
|
988
|
+
count = index + 1;
|
|
989
|
+
}
|
|
990
|
+
return count;
|
|
991
|
+
}
|
|
992
|
+
var badgeGroupOverflowStyles = tailwindVariants.tv({
|
|
993
|
+
base: [
|
|
994
|
+
badgeStyles({ variant: "neutral", shape: "rounded", hasDot: false }),
|
|
995
|
+
// badgeStyles' register still materializes an empty ::before — hide it,
|
|
996
|
+
// as Badge itself does when no dot should show.
|
|
997
|
+
"before:hidden shrink-0 cursor-pointer whitespace-nowrap",
|
|
998
|
+
"hover:bg-surface-2 hover:text-ink",
|
|
999
|
+
"outline-none focus-visible:shadow-[var(--shadow-focus)]"
|
|
1000
|
+
]
|
|
1001
|
+
});
|
|
1002
|
+
function BadgeGroup({ children, className, ...props }) {
|
|
1003
|
+
const items = react.Children.toArray(children);
|
|
1004
|
+
const signature = items.map((item, index) => react.isValidElement(item) ? String(item.key ?? index) : String(item)).join("");
|
|
1005
|
+
const rootRef = react.useRef(null);
|
|
1006
|
+
const metricsRef = react.useRef(null);
|
|
1007
|
+
const [layout, setLayout] = react.useState({ signature, visibleCount: null });
|
|
1008
|
+
if (layout.signature !== signature) {
|
|
1009
|
+
metricsRef.current = null;
|
|
1010
|
+
setLayout({ signature, visibleCount: null });
|
|
1011
|
+
}
|
|
1012
|
+
const measuring = layout.signature !== signature || layout.visibleCount === null;
|
|
1013
|
+
const visibleCount = measuring ? items.length : layout.visibleCount ?? items.length;
|
|
1014
|
+
const shown = items.slice(0, visibleCount);
|
|
1015
|
+
const hidden = measuring ? items.length : items.length - visibleCount;
|
|
1016
|
+
react.useLayoutEffect(() => {
|
|
1017
|
+
if (!measuring) return;
|
|
1018
|
+
const root = rootRef.current;
|
|
1019
|
+
if (!root) return;
|
|
1020
|
+
const nodes = Array.from(root.children);
|
|
1021
|
+
const metrics = {
|
|
1022
|
+
itemWidths: nodes.slice(0, items.length).map((node) => node.getBoundingClientRect().width),
|
|
1023
|
+
overflowWidth: nodes[items.length]?.getBoundingClientRect().width ?? 0,
|
|
1024
|
+
gap: Number.parseFloat(getComputedStyle(root).columnGap) || 0
|
|
1025
|
+
};
|
|
1026
|
+
metricsRef.current = metrics;
|
|
1027
|
+
setLayout({ signature, visibleCount: fitBadgeCount(metrics, root.clientWidth) });
|
|
1028
|
+
}, [measuring, signature, items.length]);
|
|
1029
|
+
react.useEffect(() => {
|
|
1030
|
+
const root = rootRef.current;
|
|
1031
|
+
if (!root || typeof ResizeObserver === "undefined") return;
|
|
1032
|
+
const observer = new ResizeObserver(() => {
|
|
1033
|
+
const metrics = metricsRef.current;
|
|
1034
|
+
if (!metrics) return;
|
|
1035
|
+
const next = fitBadgeCount(metrics, root.clientWidth);
|
|
1036
|
+
setLayout((prev) => prev.visibleCount === next ? prev : { ...prev, visibleCount: next });
|
|
1037
|
+
});
|
|
1038
|
+
observer.observe(root);
|
|
1039
|
+
return () => observer.disconnect();
|
|
1040
|
+
}, []);
|
|
1041
|
+
react.useEffect(() => {
|
|
1042
|
+
const fonts = typeof document === "undefined" ? void 0 : document.fonts;
|
|
1043
|
+
if (!fonts || fonts.status === "loaded") return;
|
|
1044
|
+
let cancelled = false;
|
|
1045
|
+
void fonts.ready.then(() => {
|
|
1046
|
+
if (cancelled) return;
|
|
1047
|
+
metricsRef.current = null;
|
|
1048
|
+
setLayout((prev) => ({ ...prev, visibleCount: null }));
|
|
1049
|
+
});
|
|
1050
|
+
return () => {
|
|
1051
|
+
cancelled = true;
|
|
1052
|
+
};
|
|
1053
|
+
}, []);
|
|
1054
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1055
|
+
"div",
|
|
1056
|
+
{
|
|
1057
|
+
...props,
|
|
1058
|
+
ref: rootRef,
|
|
1059
|
+
className: chunkMWAXK66H_cjs.cn(badgeGroupStyles({ isMeasuring: measuring }), className),
|
|
1060
|
+
children: [
|
|
1061
|
+
shown.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1062
|
+
"span",
|
|
1063
|
+
{
|
|
1064
|
+
className: "inline-flex shrink-0",
|
|
1065
|
+
children: item
|
|
1066
|
+
},
|
|
1067
|
+
(react.isValidElement(item) ? item.key : null) ?? index
|
|
1068
|
+
)),
|
|
1069
|
+
hidden > 0 ? (
|
|
1070
|
+
// The span swallows the click before it reaches a clickable host row
|
|
1071
|
+
// (React propagation), so opening the overflow never opens the record.
|
|
1072
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: click fence only — the button inside is the interactive element
|
|
1073
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: keyboard handling lives on the button inside
|
|
1074
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex shrink-0", onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
|
|
1075
|
+
/* @__PURE__ */ jsxRuntime.jsxs(TooltipTrigger, { children: [
|
|
1076
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactAriaComponents.Button, { className: badgeGroupOverflowStyles(), children: [
|
|
1077
|
+
"+",
|
|
1078
|
+
hidden,
|
|
1079
|
+
" more"
|
|
1080
|
+
] }),
|
|
1081
|
+
/* @__PURE__ */ jsxRuntime.jsx(Tooltip, { className: "max-w-sm", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-wrap items-center gap-1.5", children: items }) })
|
|
1082
|
+
] }),
|
|
1083
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { placement: "bottom start", panelClassName: "max-w-sm", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-1.5 p-2.5", children: items }) })
|
|
1084
|
+
] }) })
|
|
1085
|
+
) : null
|
|
1086
|
+
]
|
|
1087
|
+
}
|
|
1088
|
+
);
|
|
1089
|
+
}
|
|
1090
|
+
var listboxCheckStyles = tailwindVariants.tv({
|
|
1091
|
+
slots: {
|
|
1092
|
+
box: [
|
|
1093
|
+
"relative inline-flex items-center justify-center shrink-0",
|
|
1094
|
+
"size-[16px] rounded-[3px] border border-ink-4 bg-surface",
|
|
1095
|
+
"transition-[background-color,border-color] duration-150",
|
|
1096
|
+
"group-data-[selected]:bg-ink group-data-[selected]:border-ink"
|
|
1097
|
+
],
|
|
1098
|
+
tick: [
|
|
1099
|
+
"size-3 text-surface transition-opacity duration-150",
|
|
1100
|
+
"opacity-0 group-data-[selected]:opacity-100"
|
|
1101
|
+
]
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
function ListboxCheck() {
|
|
1105
|
+
const { box, tick } = listboxCheckStyles();
|
|
1106
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: box(), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", className: tick(), "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1107
|
+
"path",
|
|
1108
|
+
{
|
|
1109
|
+
d: "M2.5 6.25 5 8.75 9.5 3.75",
|
|
1110
|
+
stroke: "currentColor",
|
|
1111
|
+
strokeWidth: "1.6",
|
|
1112
|
+
strokeLinecap: "round",
|
|
1113
|
+
strokeLinejoin: "round",
|
|
1114
|
+
fill: "none"
|
|
1115
|
+
}
|
|
1116
|
+
) }) });
|
|
1117
|
+
}
|
|
1118
|
+
function useChipRowWrap(ref, isEnabled, signature) {
|
|
1119
|
+
const [hasWrapped, setHasWrapped] = react.useState(false);
|
|
1120
|
+
react.useLayoutEffect(() => {
|
|
1121
|
+
if (!isEnabled) return;
|
|
1122
|
+
const element = ref.current;
|
|
1123
|
+
if (!element) return;
|
|
1124
|
+
const measure = () => {
|
|
1125
|
+
const children = Array.from(element.children);
|
|
1126
|
+
const first = children[0]?.getBoundingClientRect();
|
|
1127
|
+
if (!first || first.height === 0) {
|
|
1128
|
+
setHasWrapped(false);
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
setHasWrapped(children.some((child) => child.getBoundingClientRect().top >= first.bottom - 1));
|
|
1132
|
+
};
|
|
1133
|
+
measure();
|
|
1134
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
1135
|
+
const observer = new ResizeObserver(measure);
|
|
1136
|
+
observer.observe(element);
|
|
1137
|
+
return () => observer.disconnect();
|
|
1138
|
+
}, [ref, isEnabled, signature]);
|
|
1139
|
+
return hasWrapped;
|
|
1140
|
+
}
|
|
902
1141
|
function badgeChrome(option) {
|
|
903
1142
|
return {
|
|
904
1143
|
...option.variant ? { variant: option.variant } : {},
|
|
@@ -922,18 +1161,51 @@ function BadgeMultiSelect({
|
|
|
922
1161
|
size = "md",
|
|
923
1162
|
appearance,
|
|
924
1163
|
autoFocus = false,
|
|
1164
|
+
defaultOpen = false,
|
|
1165
|
+
"aria-label": ariaLabel,
|
|
925
1166
|
className
|
|
926
1167
|
}) {
|
|
1168
|
+
const isCell = appearance === "cell";
|
|
927
1169
|
const styles4 = fieldControlStyles({ size, invalid: isInvalid, appearance });
|
|
928
|
-
const focusWithin =
|
|
929
|
-
const minHeight = appearance === "cell" ? "min-h-[29px]" : fieldMinHeight[size];
|
|
1170
|
+
const focusWithin = isCell ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
|
|
930
1171
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
931
1172
|
const triggerRef = react.useRef(null);
|
|
1173
|
+
const chipsRef = react.useRef(null);
|
|
1174
|
+
const popoverRef = react.useRef(null);
|
|
1175
|
+
const closedByPointerRef = react.useRef(false);
|
|
932
1176
|
react.useEffect(() => {
|
|
933
1177
|
if (autoFocus) triggerRef.current?.focus();
|
|
1178
|
+
if (defaultOpen && !isDisabled) setIsOpen(true);
|
|
934
1179
|
}, []);
|
|
1180
|
+
const wasOpenRef = react.useRef(false);
|
|
1181
|
+
react.useEffect(() => {
|
|
1182
|
+
if (wasOpenRef.current && !isOpen && !closedByPointerRef.current) {
|
|
1183
|
+
const active = document.activeElement;
|
|
1184
|
+
const strandedInList = !active || active === document.body || !!active.closest('[data-rac][role="listbox"]');
|
|
1185
|
+
if (strandedInList) triggerRef.current?.focus();
|
|
1186
|
+
}
|
|
1187
|
+
wasOpenRef.current = isOpen;
|
|
1188
|
+
closedByPointerRef.current = false;
|
|
1189
|
+
}, [isOpen]);
|
|
935
1190
|
const selectedSet = new Set(selectedKeys);
|
|
936
1191
|
const selectedOptions = options.filter((o) => selectedSet.has(o.id));
|
|
1192
|
+
const hasWrapped = useChipRowWrap(
|
|
1193
|
+
chipsRef,
|
|
1194
|
+
isCell,
|
|
1195
|
+
JSON.stringify(selectedOptions.map((o) => o.id))
|
|
1196
|
+
);
|
|
1197
|
+
react.useEffect(() => {
|
|
1198
|
+
if (!isOpen) return;
|
|
1199
|
+
const onPointerDown = (event) => {
|
|
1200
|
+
const target = event.target;
|
|
1201
|
+
if (!(target instanceof Node)) return;
|
|
1202
|
+
if (triggerRef.current?.contains(target) || popoverRef.current?.contains(target)) return;
|
|
1203
|
+
closedByPointerRef.current = true;
|
|
1204
|
+
setIsOpen(false);
|
|
1205
|
+
};
|
|
1206
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
1207
|
+
return () => document.removeEventListener("pointerdown", onPointerDown, true);
|
|
1208
|
+
}, [isOpen]);
|
|
937
1209
|
const listboxOptions = hideSelectedOptions ? options.filter((o) => !selectedSet.has(o.id)) : options;
|
|
938
1210
|
const remove = (id) => {
|
|
939
1211
|
const next = new Set(selectedSet);
|
|
@@ -945,6 +1217,12 @@ function BadgeMultiSelect({
|
|
|
945
1217
|
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
946
1218
|
e.preventDefault();
|
|
947
1219
|
setIsOpen(true);
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
if (e.key === "Escape" && isOpen) {
|
|
1223
|
+
e.preventDefault();
|
|
1224
|
+
e.stopPropagation();
|
|
1225
|
+
setIsOpen(false);
|
|
948
1226
|
}
|
|
949
1227
|
};
|
|
950
1228
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn("grid grid-cols-1 gap-1.5", className), children: [
|
|
@@ -954,6 +1232,7 @@ function BadgeMultiSelect({
|
|
|
954
1232
|
{
|
|
955
1233
|
ref: triggerRef,
|
|
956
1234
|
role: "combobox",
|
|
1235
|
+
"aria-label": ariaLabel,
|
|
957
1236
|
"aria-expanded": isOpen,
|
|
958
1237
|
"aria-haspopup": "listbox",
|
|
959
1238
|
"aria-disabled": isDisabled || void 0,
|
|
@@ -965,34 +1244,53 @@ function BadgeMultiSelect({
|
|
|
965
1244
|
"data-disabled": isDisabled || void 0,
|
|
966
1245
|
className: chunkMWAXK66H_cjs.cn(
|
|
967
1246
|
styles4.box(),
|
|
968
|
-
"flex
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1247
|
+
"flex items-stretch cursor-pointer",
|
|
1248
|
+
// Cell editor: one table row (29px under a 32px row) while the chips
|
|
1249
|
+
// fit on a line; two rows (64px), popping out of the row, once they
|
|
1250
|
+
// wrap — the chips then scroll inside. Field mode grows with its
|
|
1251
|
+
// content like every other chip field.
|
|
1252
|
+
isCell ? hasWrapped ? "h-[64px] p-1" : "h-[29px] px-1 py-0" : [fieldChipPadding[size], fieldMinHeight[size]],
|
|
972
1253
|
focusWithin
|
|
973
1254
|
),
|
|
974
1255
|
children: [
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
// overall height so it matches the Input/Select trigger at the same
|
|
978
|
-
// size.
|
|
979
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: chunkMWAXK66H_cjs.cn("text-ink-4 font-sans px-1", fieldTextStyles[size]), children: placeholder })
|
|
980
|
-
) : selectedOptions.map((o) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
981
|
-
RemovableBadge,
|
|
1256
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1257
|
+
"div",
|
|
982
1258
|
{
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1259
|
+
ref: chipsRef,
|
|
1260
|
+
className: chunkMWAXK66H_cjs.cn(
|
|
1261
|
+
"flex flex-1 flex-wrap items-center gap-1.5 min-w-0",
|
|
1262
|
+
isCell && (hasWrapped ? "content-start overflow-y-auto" : "content-center overflow-hidden")
|
|
1263
|
+
),
|
|
1264
|
+
children: selectedOptions.length === 0 ? (
|
|
1265
|
+
// No vertical padding — wrapper's p-1.5 + min-h-[size] govern the
|
|
1266
|
+
// overall height so it matches the Input/Select trigger at the same
|
|
1267
|
+
// size.
|
|
1268
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: chunkMWAXK66H_cjs.cn("text-ink-4 font-sans px-1", fieldTextStyles[size]), children: placeholder })
|
|
1269
|
+
) : selectedOptions.map((o) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1270
|
+
Badge,
|
|
1271
|
+
{
|
|
1272
|
+
...badgeChrome(o),
|
|
1273
|
+
className: "shrink-0",
|
|
1274
|
+
actions: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1275
|
+
BadgeAction,
|
|
1276
|
+
{
|
|
1277
|
+
label: "Remove",
|
|
1278
|
+
onPress: () => remove(o.id),
|
|
1279
|
+
isDisabled
|
|
1280
|
+
}
|
|
1281
|
+
),
|
|
1282
|
+
children: o.label
|
|
1283
|
+
},
|
|
1284
|
+
o.id
|
|
1285
|
+
))
|
|
1286
|
+
}
|
|
1287
|
+
),
|
|
1288
|
+
isCell ? null : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center pl-1.5 pr-1", children: /* @__PURE__ */ jsxRuntime.jsx(FieldCaret, {}) })
|
|
991
1289
|
]
|
|
992
1290
|
}
|
|
993
1291
|
),
|
|
994
1292
|
description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: fieldHintStyles, children: description }) : null,
|
|
995
|
-
errorMessage &&
|
|
1293
|
+
errorMessage && !isCell ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: fieldErrorStyles, children: errorMessage }) : null,
|
|
996
1294
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
997
1295
|
reactAriaComponents.Popover,
|
|
998
1296
|
{
|
|
@@ -1001,18 +1299,27 @@ function BadgeMultiSelect({
|
|
|
1001
1299
|
triggerRef,
|
|
1002
1300
|
offset: 6,
|
|
1003
1301
|
placement: "bottom start",
|
|
1302
|
+
isNonModal: true,
|
|
1303
|
+
shouldCloseOnInteractOutside: (element) => !triggerRef.current?.contains(element),
|
|
1004
1304
|
className: chunkMWAXK66H_cjs.cn(
|
|
1005
|
-
|
|
1006
|
-
|
|
1305
|
+
// At least as wide as the trigger, wider when a badge needs it —
|
|
1306
|
+
// a narrow table column must not clip its own options.
|
|
1307
|
+
"min-w-[var(--trigger-width)] w-max max-w-[min(28rem,calc(100vw-2rem))]",
|
|
1308
|
+
// Float above modals + full-screen editors, matching Select.
|
|
1309
|
+
"z-[1300]",
|
|
1310
|
+
// The popover element itself takes focus when opened programmatically
|
|
1311
|
+
// (defaultOpen) — no browser outline around the whole panel.
|
|
1312
|
+
"outline-none rounded-md border border-rule bg-surface p-1",
|
|
1007
1313
|
"shadow-[var(--shadow-raised)]",
|
|
1008
1314
|
"entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1",
|
|
1009
1315
|
"exiting:animate-out exiting:fade-out-0 exiting:slide-out-to-top-1"
|
|
1010
1316
|
),
|
|
1011
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1317
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: popoverRef, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1012
1318
|
reactAriaComponents.ListBox,
|
|
1013
1319
|
{
|
|
1014
|
-
"aria-label": typeof label === "string" ? label : "Options",
|
|
1320
|
+
"aria-label": typeof label === "string" ? label : ariaLabel ?? "Options",
|
|
1015
1321
|
selectionMode: "multiple",
|
|
1322
|
+
escapeKeyBehavior: "none",
|
|
1016
1323
|
selectedKeys: selectedSet,
|
|
1017
1324
|
onSelectionChange: (keys) => {
|
|
1018
1325
|
if (keys === "all") {
|
|
@@ -1021,70 +1328,32 @@ function BadgeMultiSelect({
|
|
|
1021
1328
|
}
|
|
1022
1329
|
onSelectionChange(keys);
|
|
1023
1330
|
},
|
|
1331
|
+
autoFocus: "first",
|
|
1024
1332
|
className: "outline-none max-h-72 overflow-auto",
|
|
1025
1333
|
renderEmptyState: () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkMWAXK66H_cjs.cn("px-3 py-2", fieldHintStyles), children: "All options selected" }),
|
|
1026
|
-
children: listboxOptions.map((option) => /* @__PURE__ */ jsxRuntime.
|
|
1334
|
+
children: listboxOptions.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1027
1335
|
reactAriaComponents.ListBoxItem,
|
|
1028
1336
|
{
|
|
1029
1337
|
id: option.id,
|
|
1030
1338
|
textValue: option.label,
|
|
1031
1339
|
...option.isDisabled ? { isDisabled: true } : {},
|
|
1032
1340
|
className: chunkMWAXK66H_cjs.cn(
|
|
1033
|
-
"group flex items-center",
|
|
1034
|
-
"rounded-[6px] px-
|
|
1341
|
+
"group flex items-center gap-2.5",
|
|
1342
|
+
"rounded-[6px] px-2.5 py-1.5",
|
|
1035
1343
|
"cursor-pointer outline-none select-none",
|
|
1344
|
+
// Selection is carried by the check box, not a row fill.
|
|
1036
1345
|
"data-[hovered]:bg-surface-2",
|
|
1037
1346
|
"data-[focused]:bg-surface-2",
|
|
1038
|
-
"data-[selected]:bg-surface-3",
|
|
1039
1347
|
"data-[disabled]:opacity-45 data-[disabled]:cursor-not-allowed"
|
|
1040
1348
|
),
|
|
1041
|
-
children:
|
|
1349
|
+
children: [
|
|
1350
|
+
/* @__PURE__ */ jsxRuntime.jsx(ListboxCheck, {}),
|
|
1351
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { ...badgeChrome(option), children: option.label })
|
|
1352
|
+
]
|
|
1042
1353
|
},
|
|
1043
1354
|
option.id
|
|
1044
1355
|
))
|
|
1045
1356
|
}
|
|
1046
|
-
)
|
|
1047
|
-
}
|
|
1048
|
-
)
|
|
1049
|
-
] });
|
|
1050
|
-
}
|
|
1051
|
-
function RemovableBadge({
|
|
1052
|
-
children,
|
|
1053
|
-
onRemove,
|
|
1054
|
-
isDisabled,
|
|
1055
|
-
...chrome
|
|
1056
|
-
}) {
|
|
1057
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Badge, { ...badgeChrome(chrome), children: [
|
|
1058
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children }),
|
|
1059
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1060
|
-
"button",
|
|
1061
|
-
{
|
|
1062
|
-
type: "button",
|
|
1063
|
-
"aria-label": "Remove",
|
|
1064
|
-
disabled: isDisabled,
|
|
1065
|
-
onClick: (e) => {
|
|
1066
|
-
e.stopPropagation();
|
|
1067
|
-
onRemove();
|
|
1068
|
-
},
|
|
1069
|
-
className: chunkMWAXK66H_cjs.cn(
|
|
1070
|
-
"inline-flex items-center justify-center shrink-0",
|
|
1071
|
-
"size-3.5 rounded-full",
|
|
1072
|
-
"text-current/70 hover:text-current hover:bg-current/10",
|
|
1073
|
-
"outline-none cursor-pointer",
|
|
1074
|
-
"focus-visible:shadow-[var(--shadow-focus)]",
|
|
1075
|
-
"disabled:opacity-45 disabled:cursor-not-allowed",
|
|
1076
|
-
// Pull the button flush with the right edge so the pill still feels
|
|
1077
|
-
// symmetric around the leading dot.
|
|
1078
|
-
"-mr-1"
|
|
1079
|
-
),
|
|
1080
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { "aria-hidden": true, viewBox: "0 0 10 10", className: "size-2.5", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1081
|
-
"path",
|
|
1082
|
-
{
|
|
1083
|
-
d: "M2 2l6 6M8 2l-6 6",
|
|
1084
|
-
stroke: "currentColor",
|
|
1085
|
-
strokeWidth: "1.4",
|
|
1086
|
-
strokeLinecap: "round"
|
|
1087
|
-
}
|
|
1088
1357
|
) })
|
|
1089
1358
|
}
|
|
1090
1359
|
)
|
|
@@ -2688,7 +2957,9 @@ var tableHeaderStyles = tailwindVariants.tv({
|
|
|
2688
2957
|
"border-b border-rule"
|
|
2689
2958
|
],
|
|
2690
2959
|
variants: {
|
|
2691
|
-
|
|
2960
|
+
// z-[4]: above an editing row (z-[3]) — sticky chrome stays on top of
|
|
2961
|
+
// rows scrolling underneath, popped-out editors included.
|
|
2962
|
+
sticky: { true: "sticky top-0 z-[4]", false: "" }
|
|
2692
2963
|
},
|
|
2693
2964
|
defaultVariants: { sticky: false }
|
|
2694
2965
|
});
|
|
@@ -2753,11 +3024,57 @@ function TableHeaderCell({
|
|
|
2753
3024
|
onRemove,
|
|
2754
3025
|
ariaLabel,
|
|
2755
3026
|
sticky = false,
|
|
3027
|
+
onResize,
|
|
3028
|
+
minWidth = 64,
|
|
2756
3029
|
...rest
|
|
2757
3030
|
}) {
|
|
2758
3031
|
const cellRef = react.useRef(null);
|
|
2759
3032
|
const handleRef = react.useRef(null);
|
|
2760
3033
|
const [dragState, setDragState] = react.useState({ kind: "idle" });
|
|
3034
|
+
const [isResizing, setIsResizing] = react.useState(false);
|
|
3035
|
+
const startResize = (event) => {
|
|
3036
|
+
if (!onResize || event.button !== 0) return;
|
|
3037
|
+
const cell = cellRef.current;
|
|
3038
|
+
if (!cell) return;
|
|
3039
|
+
event.preventDefault();
|
|
3040
|
+
event.stopPropagation();
|
|
3041
|
+
const handle = event.currentTarget;
|
|
3042
|
+
const startX = event.clientX;
|
|
3043
|
+
const startWidth = cell.getBoundingClientRect().width;
|
|
3044
|
+
if (typeof handle.setPointerCapture === "function") handle.setPointerCapture(event.pointerId);
|
|
3045
|
+
setIsResizing(true);
|
|
3046
|
+
document.body.style.cursor = "col-resize";
|
|
3047
|
+
let frame = 0;
|
|
3048
|
+
const report = (clientX) => {
|
|
3049
|
+
const next = Math.max(minWidth, Math.round(startWidth + clientX - startX));
|
|
3050
|
+
if (typeof requestAnimationFrame !== "function") {
|
|
3051
|
+
onResize(next);
|
|
3052
|
+
return;
|
|
3053
|
+
}
|
|
3054
|
+
cancelAnimationFrame(frame);
|
|
3055
|
+
frame = requestAnimationFrame(() => onResize(next));
|
|
3056
|
+
};
|
|
3057
|
+
const onMove = (move) => report(move.clientX);
|
|
3058
|
+
const onEnd = () => {
|
|
3059
|
+
handle.removeEventListener("pointermove", onMove);
|
|
3060
|
+
handle.removeEventListener("pointerup", onEnd);
|
|
3061
|
+
handle.removeEventListener("pointercancel", onEnd);
|
|
3062
|
+
document.body.style.cursor = "";
|
|
3063
|
+
setIsResizing(false);
|
|
3064
|
+
};
|
|
3065
|
+
handle.addEventListener("pointermove", onMove);
|
|
3066
|
+
handle.addEventListener("pointerup", onEnd);
|
|
3067
|
+
handle.addEventListener("pointercancel", onEnd);
|
|
3068
|
+
};
|
|
3069
|
+
const resizeByKey = (event) => {
|
|
3070
|
+
if (!onResize) return;
|
|
3071
|
+
const step = event.key === "ArrowRight" ? 8 : event.key === "ArrowLeft" ? -8 : 0;
|
|
3072
|
+
if (step === 0) return;
|
|
3073
|
+
event.preventDefault();
|
|
3074
|
+
event.stopPropagation();
|
|
3075
|
+
const current = cellRef.current?.getBoundingClientRect().width ?? minWidth;
|
|
3076
|
+
onResize(Math.max(minWidth, Math.round(current + step)));
|
|
3077
|
+
};
|
|
2761
3078
|
react.useEffect(() => {
|
|
2762
3079
|
if (!isDraggable || !columnId) return;
|
|
2763
3080
|
const cell = cellRef.current;
|
|
@@ -2775,10 +3092,7 @@ function TableHeaderCell({
|
|
|
2775
3092
|
adapter.dropTargetForElements({
|
|
2776
3093
|
element: cell,
|
|
2777
3094
|
canDrop: ({ source }) => isColumnDragData(source.data) && source.data.columnId !== columnId,
|
|
2778
|
-
getData: ({ input, element }) => closestEdge.attachClosestEdge(
|
|
2779
|
-
{ ...data },
|
|
2780
|
-
{ input, element, allowedEdges: ["left", "right"] }
|
|
2781
|
-
),
|
|
3095
|
+
getData: ({ input, element }) => closestEdge.attachClosestEdge({ ...data }, { input, element, allowedEdges: ["left", "right"] }),
|
|
2782
3096
|
getIsSticky: () => true,
|
|
2783
3097
|
onDragEnter: ({ self }) => {
|
|
2784
3098
|
const edge = closestEdge.extractClosestEdge(self.data);
|
|
@@ -2805,6 +3119,7 @@ function TableHeaderCell({
|
|
|
2805
3119
|
const target = e.target;
|
|
2806
3120
|
if (target.closest('[data-dnd-handle="true"]')) return;
|
|
2807
3121
|
if (target.closest('[data-column-remove="true"]')) return;
|
|
3122
|
+
if (target.closest('[data-column-resize="true"]')) return;
|
|
2808
3123
|
onSortToggle?.();
|
|
2809
3124
|
};
|
|
2810
3125
|
const handleKeyDown = (e) => {
|
|
@@ -2888,6 +3203,42 @@ function TableHeaderCell({
|
|
|
2888
3203
|
dragState.edge === "left" ? "-left-px" : "-right-px"
|
|
2889
3204
|
)
|
|
2890
3205
|
}
|
|
3206
|
+
) : null,
|
|
3207
|
+
onResize ? (
|
|
3208
|
+
// Sits astride the trailing separator: an 8px grab zone with a 2px
|
|
3209
|
+
// bar that lights up on hover, focus and while dragging. A focusable
|
|
3210
|
+
// separator is the ARIA pattern for a resizer (no semantic element
|
|
3211
|
+
// exists for it); its value is the column width when one is known.
|
|
3212
|
+
// biome-ignore lint/a11y/useSemanticElements: interactive vertical resizer — <hr> cannot be one
|
|
3213
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3214
|
+
"span",
|
|
3215
|
+
{
|
|
3216
|
+
role: "separator",
|
|
3217
|
+
"aria-orientation": "vertical",
|
|
3218
|
+
"aria-label": `Resize column ${ariaLabel ?? "column"}`,
|
|
3219
|
+
"aria-valuemin": minWidth,
|
|
3220
|
+
"aria-valuenow": typeof width === "number" ? width : void 0,
|
|
3221
|
+
tabIndex: 0,
|
|
3222
|
+
"data-column-resize": "true",
|
|
3223
|
+
onPointerDown: startResize,
|
|
3224
|
+
onKeyDown: resizeByKey,
|
|
3225
|
+
onClick: (e) => e.stopPropagation(),
|
|
3226
|
+
className: chunkMWAXK66H_cjs.cn(
|
|
3227
|
+
"group/resize absolute inset-y-0 -right-1 z-10 w-2 cursor-col-resize outline-none",
|
|
3228
|
+
"flex justify-center"
|
|
3229
|
+
),
|
|
3230
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3231
|
+
"span",
|
|
3232
|
+
{
|
|
3233
|
+
"aria-hidden": "true",
|
|
3234
|
+
className: chunkMWAXK66H_cjs.cn(
|
|
3235
|
+
"h-full w-0.5 transition-colors",
|
|
3236
|
+
isResizing ? "bg-accent" : "bg-transparent group-hover/resize:bg-accent group-focus-visible/resize:bg-accent"
|
|
3237
|
+
)
|
|
3238
|
+
}
|
|
3239
|
+
)
|
|
3240
|
+
}
|
|
3241
|
+
)
|
|
2891
3242
|
) : null
|
|
2892
3243
|
]
|
|
2893
3244
|
}
|
|
@@ -2941,12 +3292,27 @@ var tableScrollerStyles = tailwindVariants.tv({
|
|
|
2941
3292
|
base: ["relative flex-1 min-h-0 overflow-auto", ...scrollbarChrome]
|
|
2942
3293
|
});
|
|
2943
3294
|
function TableScroller({ className, ref, ...props }) {
|
|
2944
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3295
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3296
|
+
"div",
|
|
3297
|
+
{
|
|
3298
|
+
role: "presentation",
|
|
3299
|
+
ref,
|
|
3300
|
+
...props,
|
|
3301
|
+
className: chunkMWAXK66H_cjs.cn(tableScrollerStyles(), className)
|
|
3302
|
+
}
|
|
3303
|
+
);
|
|
2945
3304
|
}
|
|
2946
3305
|
var rowStripeBg = "bg-[color-mix(in_oklab,var(--color-ink)_var(--row-stripe),var(--color-bg))]";
|
|
2947
3306
|
var rowHoverBg = "hover:bg-[color-mix(in_oklab,var(--color-ink)_var(--row-hover),var(--color-bg))]";
|
|
3307
|
+
var cellEditingRow = "has-[[data-cell-editing]]:z-[3]";
|
|
3308
|
+
var cellEditingCell = "has-[[data-cell-editing]]:z-[3] has-[[data-cell-editing]]:overflow-visible";
|
|
2948
3309
|
var tableRowStyles = tailwindVariants.tv({
|
|
2949
|
-
base: [
|
|
3310
|
+
base: [
|
|
3311
|
+
"relative flex items-stretch",
|
|
3312
|
+
"border-b border-rule-2 last:border-b-0",
|
|
3313
|
+
"bg-bg",
|
|
3314
|
+
cellEditingRow
|
|
3315
|
+
],
|
|
2950
3316
|
variants: {
|
|
2951
3317
|
alt: {
|
|
2952
3318
|
true: rowStripeBg,
|
|
@@ -2957,7 +3323,9 @@ var tableRowStyles = tailwindVariants.tv({
|
|
|
2957
3323
|
false: rowHoverBg
|
|
2958
3324
|
},
|
|
2959
3325
|
absolute: {
|
|
2960
|
-
|
|
3326
|
+
// `top-0` pins the static position: a virtualized row must never
|
|
3327
|
+
// inherit a flow offset from a sibling that is in normal flow.
|
|
3328
|
+
true: "absolute top-0 left-0 right-0",
|
|
2961
3329
|
false: ""
|
|
2962
3330
|
}
|
|
2963
3331
|
},
|
|
@@ -2988,11 +3356,12 @@ function TableRow({
|
|
|
2988
3356
|
}
|
|
2989
3357
|
var tableCellStyles = tailwindVariants.tv({
|
|
2990
3358
|
base: [
|
|
2991
|
-
"flex items-center shrink-0 min-w-0",
|
|
3359
|
+
"relative flex items-center shrink-0 min-w-0",
|
|
2992
3360
|
"px-[14px]",
|
|
2993
3361
|
"whitespace-nowrap overflow-hidden text-ellipsis",
|
|
2994
3362
|
"font-sans text-[13px] tracking-[-0.005em]",
|
|
2995
|
-
"text-ink-2"
|
|
3363
|
+
"text-ink-2",
|
|
3364
|
+
cellEditingCell
|
|
2996
3365
|
],
|
|
2997
3366
|
variants: {
|
|
2998
3367
|
align: {
|
|
@@ -3153,6 +3522,8 @@ function DataTable({
|
|
|
3153
3522
|
enableColumnRemoval = false,
|
|
3154
3523
|
onReorderColumn,
|
|
3155
3524
|
onRemoveColumn,
|
|
3525
|
+
enableColumnResizing = false,
|
|
3526
|
+
onResizeColumn,
|
|
3156
3527
|
variant = "panel",
|
|
3157
3528
|
rowWrapper,
|
|
3158
3529
|
extraRows,
|
|
@@ -3366,7 +3737,6 @@ function DataTable({
|
|
|
3366
3737
|
const showEmpty = !query.isLoading && !query.error && tableRowCount === 0 && !query.isFetchingNextPage;
|
|
3367
3738
|
const showInitialLoading = query.isLoading && tableRowCount === 0;
|
|
3368
3739
|
const showError = !!query.error && tableRowCount === 0;
|
|
3369
|
-
const showEndMarker = !query.isLoading && !query.isFetchingNextPage && !query.hasNextPage && tableRowCount > 0;
|
|
3370
3740
|
const totalSize = virtualizer.getTotalSize();
|
|
3371
3741
|
const virtualItems = virtualizer.getVirtualItems();
|
|
3372
3742
|
const headerGroups = table.getHeaderGroups();
|
|
@@ -3377,84 +3747,108 @@ function DataTable({
|
|
|
3377
3747
|
...ariaLabel !== void 0 ? { "aria-label": ariaLabel } : {},
|
|
3378
3748
|
variant,
|
|
3379
3749
|
className: chunkMWAXK66H_cjs.cn("flex-1 min-h-0", className),
|
|
3380
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
draggable: enableColumnReordering && !!header.column.id,
|
|
3399
|
-
...header.column.id ? { columnId: header.column.id } : {},
|
|
3400
|
-
...headerSize !== void 0 ? { width: headerSize } : {},
|
|
3401
|
-
...sticky !== false ? { sticky } : {},
|
|
3402
|
-
...meta?.cellClassName ? { className: meta.cellClassName } : {},
|
|
3403
|
-
...canSort ? {
|
|
3404
|
-
sortDirection: direction,
|
|
3405
|
-
onSortToggle: () => handleSort?.({})
|
|
3406
|
-
} : {},
|
|
3407
|
-
...enableColumnRemoval && onRemoveColumn && header.column.id ? { onRemove: () => onRemoveColumn(header.column.id) } : {},
|
|
3408
|
-
children: headerNode
|
|
3409
|
-
},
|
|
3410
|
-
header.id
|
|
3411
|
-
);
|
|
3412
|
-
}),
|
|
3413
|
-
/* @__PURE__ */ jsxRuntime.jsx(TableHeaderSpacer, {})
|
|
3414
|
-
] }, group.id)),
|
|
3415
|
-
bodyBefore,
|
|
3416
|
-
showInitialLoading ? loadingState ?? /* @__PURE__ */ jsxRuntime.jsx(DataTableSkeleton, { rowHeight }) : showError ? /* @__PURE__ */ jsxRuntime.jsx("div", { role: "rowgroup", children: errorState ?? (query.error ? /* @__PURE__ */ jsxRuntime.jsx(DataTableError, { error: query.error }) : null) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "rowgroup", children: [
|
|
3417
|
-
showEmpty ? emptyState ?? /* @__PURE__ */ jsxRuntime.jsx(DataTableEmpty, {}) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3418
|
-
"div",
|
|
3419
|
-
{
|
|
3420
|
-
ref: listRef,
|
|
3421
|
-
role: "presentation",
|
|
3422
|
-
style: { height: totalSize, position: "relative", width: "100%" },
|
|
3423
|
-
children: virtualItems.map((vRow) => {
|
|
3424
|
-
const item = listItems[vRow.index];
|
|
3425
|
-
if (!item) return null;
|
|
3426
|
-
const rowStyle = {
|
|
3427
|
-
// Items' `start` includes the virtualizer's scrollMargin
|
|
3428
|
-
// (the list's offset below the sticky header); subtract
|
|
3429
|
-
// it to position relative to the list container.
|
|
3430
|
-
transform: `translateY(${vRow.start - listOffset}px)`,
|
|
3431
|
-
height: vRow.size
|
|
3432
|
-
};
|
|
3433
|
-
if (item.kind === "group") {
|
|
3434
|
-
return /* @__PURE__ */ jsxRuntime.jsx(GroupHeaderRow, { style: rowStyle, children: item.label }, `group:${item.id}`);
|
|
3435
|
-
}
|
|
3750
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3751
|
+
TableScroller,
|
|
3752
|
+
{
|
|
3753
|
+
ref: scrollerRef,
|
|
3754
|
+
className: chunkMWAXK66H_cjs.cn("scroll-pt-[36px]", bodyAfter ? "scroll-pb-8" : void 0),
|
|
3755
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { minWidth: minPanelWidth }, children: [
|
|
3756
|
+
headerGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs(TableHeader, { sticky: true, children: [
|
|
3757
|
+
group.headers.map((header) => {
|
|
3758
|
+
const meta = header.column.columnDef.meta;
|
|
3759
|
+
const align = meta?.align ?? "left";
|
|
3760
|
+
const sticky = meta?.sticky ?? false;
|
|
3761
|
+
const headerSize = header.getSize() || void 0;
|
|
3762
|
+
const headerNode = header.isPlaceholder ? null : reactTable.flexRender(header.column.columnDef.header, header.getContext());
|
|
3763
|
+
const sorted = header.column.getIsSorted();
|
|
3764
|
+
const direction = sorted === false ? null : sorted;
|
|
3765
|
+
const canSort = header.column.getCanSort();
|
|
3766
|
+
const handleSort = header.column.getToggleSortingHandler();
|
|
3767
|
+
const ariaLabel2 = typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : header.column.id;
|
|
3436
3768
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3437
|
-
|
|
3769
|
+
TableHeaderCell,
|
|
3438
3770
|
{
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
...
|
|
3771
|
+
align,
|
|
3772
|
+
ariaLabel: ariaLabel2,
|
|
3773
|
+
draggable: enableColumnReordering && !!header.column.id,
|
|
3774
|
+
...header.column.id ? { columnId: header.column.id } : {},
|
|
3775
|
+
...headerSize !== void 0 ? { width: headerSize } : {},
|
|
3776
|
+
...sticky !== false ? { sticky } : {},
|
|
3777
|
+
...meta?.cellClassName ? { className: meta.cellClassName } : {},
|
|
3778
|
+
...canSort ? {
|
|
3779
|
+
sortDirection: direction,
|
|
3780
|
+
onSortToggle: () => handleSort?.({})
|
|
3781
|
+
} : {},
|
|
3782
|
+
...enableColumnRemoval && onRemoveColumn && header.column.id ? { onRemove: () => onRemoveColumn(header.column.id) } : {},
|
|
3783
|
+
...enableColumnResizing && onResizeColumn && header.column.id ? {
|
|
3784
|
+
onResize: (width) => onResizeColumn({ id: header.column.id, width })
|
|
3785
|
+
} : {},
|
|
3786
|
+
children: headerNode
|
|
3446
3787
|
},
|
|
3447
|
-
|
|
3788
|
+
header.id
|
|
3448
3789
|
);
|
|
3449
|
-
})
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3790
|
+
}),
|
|
3791
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHeaderSpacer, {})
|
|
3792
|
+
] }, group.id)),
|
|
3793
|
+
bodyBefore,
|
|
3794
|
+
showInitialLoading ? loadingState ?? /* @__PURE__ */ jsxRuntime.jsx(DataTableSkeleton, { rowHeight }) : showError ? /* @__PURE__ */ jsxRuntime.jsx("div", { role: "rowgroup", children: errorState ?? (query.error ? /* @__PURE__ */ jsxRuntime.jsx(DataTableError, { error: query.error }) : null) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "rowgroup", children: [
|
|
3795
|
+
showEmpty ? emptyState ?? /* @__PURE__ */ jsxRuntime.jsx(DataTableEmpty, {}) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3796
|
+
"div",
|
|
3797
|
+
{
|
|
3798
|
+
ref: listRef,
|
|
3799
|
+
role: "presentation",
|
|
3800
|
+
style: { height: totalSize, position: "relative", width: "100%" },
|
|
3801
|
+
children: virtualItems.map((vRow) => {
|
|
3802
|
+
const item = listItems[vRow.index];
|
|
3803
|
+
if (!item) return null;
|
|
3804
|
+
const rowStyle = {
|
|
3805
|
+
// Items' `start` includes the virtualizer's scrollMargin
|
|
3806
|
+
// (the list's offset below the sticky header); subtract
|
|
3807
|
+
// it to position relative to the list container.
|
|
3808
|
+
transform: `translateY(${vRow.start - listOffset}px)`,
|
|
3809
|
+
height: vRow.size
|
|
3810
|
+
};
|
|
3811
|
+
if (item.kind === "group") {
|
|
3812
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GroupHeaderRow, { style: rowStyle, children: item.label }, `group:${item.id}`);
|
|
3813
|
+
}
|
|
3814
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3815
|
+
DataRow,
|
|
3816
|
+
{
|
|
3817
|
+
row: item.row,
|
|
3818
|
+
index: item.dataIndex,
|
|
3819
|
+
zebra,
|
|
3820
|
+
onRowClick,
|
|
3821
|
+
style: rowStyle,
|
|
3822
|
+
columnBorders,
|
|
3823
|
+
...rowWrapper ? { rowWrapper } : {}
|
|
3824
|
+
},
|
|
3825
|
+
item.row.id
|
|
3826
|
+
);
|
|
3827
|
+
})
|
|
3828
|
+
}
|
|
3829
|
+
),
|
|
3830
|
+
!showEmpty && /* @__PURE__ */ jsxRuntime.jsx("div", { ref: sentinelRef, "aria-hidden": "true", style: { height: 1, width: "100%" } }),
|
|
3831
|
+
query.isFetchingNextPage ? /* @__PURE__ */ jsxRuntime.jsx(LoaderRow, {}) : null
|
|
3832
|
+
] }),
|
|
3833
|
+
bodyAfter ? (
|
|
3834
|
+
// Sticky to the scroller's bottom edge; `bg-bg` covers the rows
|
|
3835
|
+
// sliding underneath. z-[4] — like the sticky header — stays above an
|
|
3836
|
+
// editing row (z-[3]), so an editor scrolled under the strip is
|
|
3837
|
+
// covered rather than drawn over it.
|
|
3838
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3839
|
+
"div",
|
|
3840
|
+
{
|
|
3841
|
+
className: chunkMWAXK66H_cjs.cn(
|
|
3842
|
+
"sticky bottom-0 z-[4] flex items-center h-8 px-0.5",
|
|
3843
|
+
"border-t border-rule-2 bg-bg"
|
|
3844
|
+
),
|
|
3845
|
+
children: bodyAfter
|
|
3846
|
+
}
|
|
3847
|
+
)
|
|
3848
|
+
) : null
|
|
3849
|
+
] })
|
|
3850
|
+
}
|
|
3851
|
+
)
|
|
3458
3852
|
}
|
|
3459
3853
|
);
|
|
3460
3854
|
}
|
|
@@ -3554,23 +3948,6 @@ function LoaderRow() {
|
|
|
3554
3948
|
}
|
|
3555
3949
|
);
|
|
3556
3950
|
}
|
|
3557
|
-
function EndMarker({ count }) {
|
|
3558
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3559
|
-
"div",
|
|
3560
|
-
{
|
|
3561
|
-
className: chunkMWAXK66H_cjs.cn(
|
|
3562
|
-
"flex items-center justify-center",
|
|
3563
|
-
"h-8 font-mono text-[10.5px] uppercase tracking-[0.08em]",
|
|
3564
|
-
"text-ink-4"
|
|
3565
|
-
),
|
|
3566
|
-
children: [
|
|
3567
|
-
"end \xB7 ",
|
|
3568
|
-
count.toLocaleString(),
|
|
3569
|
-
" rows"
|
|
3570
|
-
]
|
|
3571
|
-
}
|
|
3572
|
-
);
|
|
3573
|
-
}
|
|
3574
3951
|
|
|
3575
3952
|
// src/components/data-table/make-actions-column.ts
|
|
3576
3953
|
function makeActionsColumn({
|
|
@@ -4158,7 +4535,9 @@ function MultiSelect({
|
|
|
4158
4535
|
placement: "bottom start",
|
|
4159
4536
|
className: chunkMWAXK66H_cjs.cn(
|
|
4160
4537
|
"w-[var(--trigger-width)]",
|
|
4161
|
-
|
|
4538
|
+
// The popover element itself takes focus when opened programmatically
|
|
4539
|
+
// (defaultOpen) — no browser outline around the whole panel.
|
|
4540
|
+
"outline-none rounded-md border border-rule bg-surface p-1",
|
|
4162
4541
|
"shadow-[var(--shadow-raised)]",
|
|
4163
4542
|
"entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1",
|
|
4164
4543
|
"exiting:animate-out exiting:fade-out-0 exiting:slide-out-to-top-1"
|
|
@@ -4183,6 +4562,7 @@ function MultiSelect({
|
|
|
4183
4562
|
{
|
|
4184
4563
|
"aria-label": typeof label === "string" ? label : "Options",
|
|
4185
4564
|
selectionMode: "multiple",
|
|
4565
|
+
escapeKeyBehavior: "none",
|
|
4186
4566
|
selectedKeys: selectedSet,
|
|
4187
4567
|
onSelectionChange: (keys) => {
|
|
4188
4568
|
if (keys === "all") {
|
|
@@ -4205,11 +4585,10 @@ function MultiSelect({
|
|
|
4205
4585
|
"cursor-pointer outline-none select-none",
|
|
4206
4586
|
"data-[hovered]:bg-surface-2 data-[hovered]:text-ink",
|
|
4207
4587
|
"data-[focused]:bg-surface-2 data-[focused]:text-ink",
|
|
4208
|
-
"data-[selected]:bg-surface-3 data-[selected]:text-ink",
|
|
4209
4588
|
"data-[disabled]:opacity-45 data-[disabled]:cursor-not-allowed"
|
|
4210
4589
|
),
|
|
4211
4590
|
children: [
|
|
4212
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4591
|
+
/* @__PURE__ */ jsxRuntime.jsx(ListboxCheck, {}),
|
|
4213
4592
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: option.content ?? option.label })
|
|
4214
4593
|
]
|
|
4215
4594
|
},
|
|
@@ -4270,42 +4649,6 @@ function Chip({
|
|
|
4270
4649
|
}
|
|
4271
4650
|
);
|
|
4272
4651
|
}
|
|
4273
|
-
function Checkmark() {
|
|
4274
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4275
|
-
"span",
|
|
4276
|
-
{
|
|
4277
|
-
"aria-hidden": true,
|
|
4278
|
-
className: chunkMWAXK66H_cjs.cn(
|
|
4279
|
-
"relative inline-flex items-center justify-center shrink-0",
|
|
4280
|
-
"size-[16px] rounded-[3px] border border-ink-4 bg-surface",
|
|
4281
|
-
"transition-[background-color,border-color] duration-150",
|
|
4282
|
-
"group-data-[selected]:bg-ink group-data-[selected]:border-ink"
|
|
4283
|
-
),
|
|
4284
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4285
|
-
"svg",
|
|
4286
|
-
{
|
|
4287
|
-
viewBox: "0 0 12 12",
|
|
4288
|
-
className: chunkMWAXK66H_cjs.cn(
|
|
4289
|
-
"size-3 text-surface transition-opacity duration-150",
|
|
4290
|
-
"opacity-0 group-data-[selected]:opacity-100"
|
|
4291
|
-
),
|
|
4292
|
-
"aria-hidden": true,
|
|
4293
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4294
|
-
"path",
|
|
4295
|
-
{
|
|
4296
|
-
d: "M2.5 6.25 5 8.75 9.5 3.75",
|
|
4297
|
-
stroke: "currentColor",
|
|
4298
|
-
strokeWidth: "1.6",
|
|
4299
|
-
strokeLinecap: "round",
|
|
4300
|
-
strokeLinejoin: "round",
|
|
4301
|
-
fill: "none"
|
|
4302
|
-
}
|
|
4303
|
-
)
|
|
4304
|
-
}
|
|
4305
|
-
)
|
|
4306
|
-
}
|
|
4307
|
-
);
|
|
4308
|
-
}
|
|
4309
4652
|
var SEARCH_DEBOUNCE_MS = 250;
|
|
4310
4653
|
function RecipientSelect({
|
|
4311
4654
|
connectionId,
|
|
@@ -5875,7 +6218,8 @@ var OPERATORS = [
|
|
|
5875
6218
|
"relation",
|
|
5876
6219
|
"user",
|
|
5877
6220
|
"principal",
|
|
5878
|
-
"contact-address"
|
|
6221
|
+
"contact-address",
|
|
6222
|
+
"array"
|
|
5879
6223
|
]
|
|
5880
6224
|
},
|
|
5881
6225
|
{
|
|
@@ -5891,10 +6235,19 @@ var OPERATORS = [
|
|
|
5891
6235
|
"relation",
|
|
5892
6236
|
"user",
|
|
5893
6237
|
"principal",
|
|
5894
|
-
"contact-address"
|
|
6238
|
+
"contact-address",
|
|
6239
|
+
"array"
|
|
5895
6240
|
]
|
|
5896
6241
|
},
|
|
5897
6242
|
{ id: "contains", label: "contains", arity: 1, types: ["string", "array", "contact-address"] },
|
|
6243
|
+
{
|
|
6244
|
+
id: "not_contains",
|
|
6245
|
+
label: "does not contain",
|
|
6246
|
+
arity: 1,
|
|
6247
|
+
types: ["string", "array", "contact-address"]
|
|
6248
|
+
},
|
|
6249
|
+
// Array-only: "has every one of these". On a scalar the backend rejects it.
|
|
6250
|
+
{ id: "contains_all", label: "has all of", arity: "n", types: ["array"] },
|
|
5898
6251
|
{ id: "starts_with", label: "starts with", arity: 1, types: ["string", "contact-address"] },
|
|
5899
6252
|
{ id: "ends_with", label: "ends with", arity: 1, types: ["string", "contact-address"] },
|
|
5900
6253
|
{
|
|
@@ -5957,14 +6310,33 @@ var OP_LABEL_OVERRIDES = {
|
|
|
5957
6310
|
integer: { gt: "is greater than", lt: "is less than", eq: "equals", ne: "does not equal" },
|
|
5958
6311
|
currency: { gt: "is greater than", lt: "is less than", eq: "equals", ne: "does not equal" },
|
|
5959
6312
|
datetime: { eq: "is on", ne: "is not on", gt: "is after", lt: "is before" },
|
|
5960
|
-
|
|
6313
|
+
// Arrays filter by set membership, in the words every CRM uses for it.
|
|
6314
|
+
array: {
|
|
6315
|
+
contains: "has",
|
|
6316
|
+
not_contains: "does not have",
|
|
6317
|
+
in: "has any of",
|
|
6318
|
+
not_in: "has none of",
|
|
6319
|
+
contains_all: "has all of",
|
|
6320
|
+
empty: "is empty",
|
|
6321
|
+
not_empty: "is not empty"
|
|
6322
|
+
},
|
|
5961
6323
|
boolean: { eq: "is", ne: "is not" }
|
|
5962
6324
|
};
|
|
6325
|
+
var OP_ORDER_OVERRIDES = {
|
|
6326
|
+
array: ["contains", "not_contains", "in", "contains_all", "not_in", "empty", "not_empty"]
|
|
6327
|
+
};
|
|
5963
6328
|
function operatorsForType(type) {
|
|
5964
|
-
|
|
6329
|
+
const ops = OPERATORS.filter((op) => op.types.includes(type)).map((op) => {
|
|
5965
6330
|
const override = OP_LABEL_OVERRIDES[type]?.[op.id];
|
|
5966
6331
|
return override ? { ...op, label: override } : op;
|
|
5967
6332
|
});
|
|
6333
|
+
const order = OP_ORDER_OVERRIDES[type];
|
|
6334
|
+
if (!order) return ops;
|
|
6335
|
+
return [...ops].sort((a, b) => order.indexOf(a.id) - order.indexOf(b.id));
|
|
6336
|
+
}
|
|
6337
|
+
function isEnumLike(field) {
|
|
6338
|
+
if (field.type === "enum") return true;
|
|
6339
|
+
return field.type === "array" && (field.options?.length ?? 0) > 0;
|
|
5968
6340
|
}
|
|
5969
6341
|
function operatorById(id) {
|
|
5970
6342
|
return OPERATORS.find((o) => o.id === id);
|
|
@@ -6036,7 +6408,7 @@ function ChipItem({
|
|
|
6036
6408
|
const custom = effectiveRenderer({ field, operator, value });
|
|
6037
6409
|
if (custom !== void 0) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
|
|
6038
6410
|
}
|
|
6039
|
-
if (field
|
|
6411
|
+
if (isEnumLike(field)) {
|
|
6040
6412
|
const option = findEnumOption(field, value);
|
|
6041
6413
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6042
6414
|
Badge,
|
|
@@ -6064,7 +6436,7 @@ function formatValue(field, operator, value) {
|
|
|
6064
6436
|
if (arity === "n") {
|
|
6065
6437
|
const arr = Array.isArray(value) ? value : typeof value === "string" && value.length > 0 ? value.split(",") : [];
|
|
6066
6438
|
if (arr.length === 0) return "\u2014";
|
|
6067
|
-
if (field
|
|
6439
|
+
if (isEnumLike(field)) {
|
|
6068
6440
|
const labels = arr.map((v) => findEnumOption(field, v)?.label ?? v);
|
|
6069
6441
|
return labels.length <= 2 ? labels.join(", ") : `${labels[0]}, ${labels[1]} +${labels.length - 2}`;
|
|
6070
6442
|
}
|
|
@@ -6072,7 +6444,7 @@ function formatValue(field, operator, value) {
|
|
|
6072
6444
|
}
|
|
6073
6445
|
if (field.type === "boolean") return value === true || value === "true" ? "true" : "false";
|
|
6074
6446
|
if (value === "" || value == null) return "\u2014";
|
|
6075
|
-
if (field
|
|
6447
|
+
if (isEnumLike(field)) {
|
|
6076
6448
|
return findEnumOption(field, String(value))?.label ?? String(value);
|
|
6077
6449
|
}
|
|
6078
6450
|
if (field.type === "number" || field.type === "integer") {
|
|
@@ -6160,13 +6532,21 @@ function TagInput({
|
|
|
6160
6532
|
}) {
|
|
6161
6533
|
const styles4 = fieldControlStyles({ size, invalid: isInvalid, appearance });
|
|
6162
6534
|
const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
|
|
6163
|
-
const
|
|
6535
|
+
const isCell = appearance === "cell";
|
|
6164
6536
|
const inputRef = react.useRef(null);
|
|
6537
|
+
const chipsRef = react.useRef(null);
|
|
6538
|
+
const hasWrapped = useChipRowWrap(chipsRef, isCell, JSON.stringify(value));
|
|
6165
6539
|
react.useEffect(() => {
|
|
6166
6540
|
if (autoFocus) inputRef.current?.focus();
|
|
6167
6541
|
}, []);
|
|
6168
6542
|
const inputId = react.useId();
|
|
6169
6543
|
const [draft, setDraft] = react.useState("");
|
|
6544
|
+
react.useLayoutEffect(() => {
|
|
6545
|
+
const input = inputRef.current;
|
|
6546
|
+
if (!isCell || !input || document.activeElement !== input) return;
|
|
6547
|
+
if (typeof input.scrollIntoView !== "function") return;
|
|
6548
|
+
input.scrollIntoView({ block: "nearest" });
|
|
6549
|
+
}, [isCell, value]);
|
|
6170
6550
|
const commit = () => {
|
|
6171
6551
|
const v = draft.trim();
|
|
6172
6552
|
if (!v) return;
|
|
@@ -6183,7 +6563,10 @@ function TagInput({
|
|
|
6183
6563
|
const onKeyDown2 = (e) => {
|
|
6184
6564
|
if (e.key === "Enter" || e.key === ",") {
|
|
6185
6565
|
e.preventDefault();
|
|
6186
|
-
|
|
6566
|
+
if (draft.trim()) {
|
|
6567
|
+
e.stopPropagation();
|
|
6568
|
+
commit();
|
|
6569
|
+
}
|
|
6187
6570
|
return;
|
|
6188
6571
|
}
|
|
6189
6572
|
if (e.key === "Backspace" && !draft && value.length > 0) {
|
|
@@ -6193,85 +6576,78 @@ function TagInput({
|
|
|
6193
6576
|
};
|
|
6194
6577
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn("grid grid-cols-1 gap-1.5", className), children: [
|
|
6195
6578
|
label ? /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: inputId, className: fieldLabelStyles, children: label }) : null,
|
|
6196
|
-
/* @__PURE__ */ jsxRuntime.
|
|
6579
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6197
6580
|
"div",
|
|
6198
6581
|
{
|
|
6199
6582
|
"data-invalid": isInvalid || void 0,
|
|
6200
6583
|
"data-disabled": isDisabled || void 0,
|
|
6201
6584
|
className: chunkMWAXK66H_cjs.cn(
|
|
6202
6585
|
styles4.box(),
|
|
6203
|
-
"flex
|
|
6204
|
-
|
|
6205
|
-
|
|
6586
|
+
"flex",
|
|
6587
|
+
// Cell editor: one table row (29px under a 32px row) while the chips
|
|
6588
|
+
// fit on a line; two rows (64px), popping out of the row, once they
|
|
6589
|
+
// wrap — the chips then scroll inside. Field mode grows with its
|
|
6590
|
+
// content.
|
|
6591
|
+
isCell ? hasWrapped ? "h-[64px] p-1" : "h-[29px] px-1 py-0" : [fieldChipPadding[size], fieldMinHeight[size]],
|
|
6206
6592
|
focusWithin
|
|
6207
6593
|
),
|
|
6208
|
-
children:
|
|
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
|
-
|
|
6244
|
-
|
|
6594
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6595
|
+
"div",
|
|
6596
|
+
{
|
|
6597
|
+
ref: chipsRef,
|
|
6598
|
+
className: chunkMWAXK66H_cjs.cn(
|
|
6599
|
+
"flex flex-1 flex-wrap items-center gap-1.5 min-w-0",
|
|
6600
|
+
isCell && (hasWrapped ? "content-start overflow-y-auto" : "content-center overflow-hidden")
|
|
6601
|
+
),
|
|
6602
|
+
children: [
|
|
6603
|
+
value.map((tag, idx) => (
|
|
6604
|
+
// tags are kept unique on commit, so the value alone is a stable key
|
|
6605
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6606
|
+
Badge,
|
|
6607
|
+
{
|
|
6608
|
+
variant: "active",
|
|
6609
|
+
shape: "rounded",
|
|
6610
|
+
hasDot: false,
|
|
6611
|
+
className: "shrink-0",
|
|
6612
|
+
actions: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6613
|
+
BadgeAction,
|
|
6614
|
+
{
|
|
6615
|
+
label: `Remove ${tag}`,
|
|
6616
|
+
onPress: () => remove(idx),
|
|
6617
|
+
isDisabled
|
|
6618
|
+
}
|
|
6619
|
+
),
|
|
6620
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-[10rem] truncate", children: tag })
|
|
6621
|
+
},
|
|
6622
|
+
tag
|
|
6623
|
+
)
|
|
6624
|
+
)),
|
|
6625
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6626
|
+
"input",
|
|
6627
|
+
{
|
|
6628
|
+
ref: inputRef,
|
|
6629
|
+
id: inputId,
|
|
6630
|
+
type: inputType,
|
|
6631
|
+
value: draft,
|
|
6632
|
+
onChange: (e) => setDraft(e.target.value),
|
|
6633
|
+
onKeyDown: onKeyDown2,
|
|
6634
|
+
onBlur: commit,
|
|
6635
|
+
disabled: isDisabled,
|
|
6636
|
+
placeholder: value.length === 0 ? placeholder : "",
|
|
6637
|
+
className: chunkMWAXK66H_cjs.cn(
|
|
6638
|
+
"flex-1 min-w-[6rem] bg-transparent outline-none",
|
|
6639
|
+
"font-sans text-ink placeholder:text-ink-4",
|
|
6640
|
+
fieldTextStyles[size],
|
|
6641
|
+
// No vertical padding — wrapper's p-1.5 + min-h-[size] govern the
|
|
6642
|
+
// overall height so it matches Input/Select at the same size.
|
|
6643
|
+
"px-1.5",
|
|
6644
|
+
"disabled:cursor-not-allowed disabled:opacity-45"
|
|
6245
6645
|
)
|
|
6246
|
-
|
|
6247
|
-
},
|
|
6248
|
-
tag
|
|
6249
|
-
)
|
|
6250
|
-
)),
|
|
6251
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6252
|
-
"input",
|
|
6253
|
-
{
|
|
6254
|
-
ref: inputRef,
|
|
6255
|
-
id: inputId,
|
|
6256
|
-
type: inputType,
|
|
6257
|
-
value: draft,
|
|
6258
|
-
onChange: (e) => setDraft(e.target.value),
|
|
6259
|
-
onKeyDown: onKeyDown2,
|
|
6260
|
-
onBlur: commit,
|
|
6261
|
-
disabled: isDisabled,
|
|
6262
|
-
placeholder: value.length === 0 ? placeholder : "",
|
|
6263
|
-
className: chunkMWAXK66H_cjs.cn(
|
|
6264
|
-
"flex-1 min-w-[6rem] bg-transparent outline-none",
|
|
6265
|
-
"font-sans text-ink placeholder:text-ink-4",
|
|
6266
|
-
fieldTextStyles[size],
|
|
6267
|
-
// No vertical padding — wrapper's p-1.5 + min-h-[size] govern the
|
|
6268
|
-
// overall height so it matches Input/Select at the same size.
|
|
6269
|
-
"px-1.5",
|
|
6270
|
-
"disabled:cursor-not-allowed disabled:opacity-45"
|
|
6646
|
+
}
|
|
6271
6647
|
)
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6648
|
+
]
|
|
6649
|
+
}
|
|
6650
|
+
)
|
|
6275
6651
|
}
|
|
6276
6652
|
),
|
|
6277
6653
|
description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: fieldHintStyles, children: description }) : null,
|
|
@@ -6316,7 +6692,7 @@ function FilterValueInput({
|
|
|
6316
6692
|
}
|
|
6317
6693
|
const leaf = (() => {
|
|
6318
6694
|
if (arity === "n") {
|
|
6319
|
-
if (field
|
|
6695
|
+
if (isEnumLike(field)) {
|
|
6320
6696
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6321
6697
|
EnumMultiValue,
|
|
6322
6698
|
{
|
|
@@ -6343,7 +6719,7 @@ function FilterValueInput({
|
|
|
6343
6719
|
}
|
|
6344
6720
|
);
|
|
6345
6721
|
}
|
|
6346
|
-
if (field
|
|
6722
|
+
if (isEnumLike(field)) {
|
|
6347
6723
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6348
6724
|
EnumSingleValue,
|
|
6349
6725
|
{
|
|
@@ -6504,7 +6880,9 @@ function placeholderFor(field, operator) {
|
|
|
6504
6880
|
if (field.type === "number" || field.type === "integer" || field.type === "currency") return "0";
|
|
6505
6881
|
if (operator === "starts_with") return "starts with\u2026";
|
|
6506
6882
|
if (operator === "ends_with") return "ends with\u2026";
|
|
6507
|
-
if (operator === "contains") return "contains\u2026";
|
|
6883
|
+
if (operator === "contains") return field.type === "array" ? "has\u2026" : "contains\u2026";
|
|
6884
|
+
if (operator === "not_contains")
|
|
6885
|
+
return field.type === "array" ? "does not have\u2026" : "does not contain\u2026";
|
|
6508
6886
|
return "value";
|
|
6509
6887
|
}
|
|
6510
6888
|
function OperatorPicker({
|
|
@@ -8171,31 +8549,6 @@ function ToastRegion({ queue, className }) {
|
|
|
8171
8549
|
}
|
|
8172
8550
|
);
|
|
8173
8551
|
}
|
|
8174
|
-
function TooltipTrigger({
|
|
8175
|
-
delay = 500,
|
|
8176
|
-
closeDelay = 0,
|
|
8177
|
-
...props
|
|
8178
|
-
}) {
|
|
8179
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.TooltipTrigger, { delay, closeDelay, ...props });
|
|
8180
|
-
}
|
|
8181
|
-
function Tooltip({ className, offset = 6, ...props }) {
|
|
8182
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8183
|
-
reactAriaComponents.Tooltip,
|
|
8184
|
-
{
|
|
8185
|
-
...props,
|
|
8186
|
-
offset,
|
|
8187
|
-
className: (renderProps) => chunkMWAXK66H_cjs.cn(
|
|
8188
|
-
"z-50 max-w-xs",
|
|
8189
|
-
"rounded-md border border-rule bg-surface shadow-[var(--shadow-raised)]",
|
|
8190
|
-
"px-2.5 py-1.5",
|
|
8191
|
-
"font-mono text-[11.5px] text-ink-2",
|
|
8192
|
-
"entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1 entering:duration-150",
|
|
8193
|
-
"exiting:animate-out exiting:fade-out-0 exiting:duration-100",
|
|
8194
|
-
typeof className === "function" ? className(renderProps) : className
|
|
8195
|
-
)
|
|
8196
|
-
}
|
|
8197
|
-
);
|
|
8198
|
-
}
|
|
8199
8552
|
|
|
8200
8553
|
Object.defineProperty(exports, "Button", {
|
|
8201
8554
|
enumerable: true,
|
|
@@ -8226,6 +8579,8 @@ exports.AttributeTypeIcon = AttributeTypeIcon;
|
|
|
8226
8579
|
exports.Avatar = Avatar;
|
|
8227
8580
|
exports.AvatarGroup = AvatarGroup;
|
|
8228
8581
|
exports.Badge = Badge;
|
|
8582
|
+
exports.BadgeAction = BadgeAction;
|
|
8583
|
+
exports.BadgeGroup = BadgeGroup;
|
|
8229
8584
|
exports.BadgeMultiSelect = BadgeMultiSelect;
|
|
8230
8585
|
exports.BooleanCell = BooleanCell;
|
|
8231
8586
|
exports.Breadcrumbs = Breadcrumbs;
|
|
@@ -8347,6 +8702,8 @@ exports.arityOf = arityOf;
|
|
|
8347
8702
|
exports.attachmentChipStyles = attachmentChipStyles;
|
|
8348
8703
|
exports.avatarGroupStyles = avatarGroupStyles;
|
|
8349
8704
|
exports.avatarStyles = avatarStyles;
|
|
8705
|
+
exports.badgeGroupOverflowStyles = badgeGroupOverflowStyles;
|
|
8706
|
+
exports.badgeGroupStyles = badgeGroupStyles;
|
|
8350
8707
|
exports.badgeStyles = badgeStyles;
|
|
8351
8708
|
exports.cardStyles = cardStyles2;
|
|
8352
8709
|
exports.channelIcon = channelIcon;
|
|
@@ -8368,6 +8725,7 @@ exports.fieldHintStyles = fieldHintStyles;
|
|
|
8368
8725
|
exports.fieldLabelStyles = fieldLabelStyles;
|
|
8369
8726
|
exports.fileViewerFallbackCardStyles = fileViewerFallbackCardStyles;
|
|
8370
8727
|
exports.fileViewerStyles = fileViewerStyles;
|
|
8728
|
+
exports.fitBadgeCount = fitBadgeCount;
|
|
8371
8729
|
exports.formatFileSize = formatFileSize;
|
|
8372
8730
|
exports.formatValue = formatValue;
|
|
8373
8731
|
exports.iconForContentType = iconForContentType;
|