infinity-ui-elements 1.4.1-beta.2 → 1.4.1-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Dropdown/Dropdown.d.ts +99 -0
- package/dist/components/Dropdown/Dropdown.d.ts.map +1 -0
- package/dist/components/Dropdown/Dropdown.stories.d.ts +342 -0
- package/dist/components/Dropdown/Dropdown.stories.d.ts.map +1 -0
- package/dist/components/Dropdown/DropdownMenu.d.ts +90 -0
- package/dist/components/Dropdown/DropdownMenu.d.ts.map +1 -0
- package/dist/components/Dropdown/index.d.ts +3 -0
- package/dist/components/Dropdown/index.d.ts.map +1 -0
- package/dist/components/Link/Link.d.ts.map +1 -1
- package/dist/components/ListItem/ListItem.stories.d.ts.map +1 -1
- package/dist/components/SearchableDropdown/SearchableDropdown.d.ts +103 -0
- package/dist/components/SearchableDropdown/SearchableDropdown.d.ts.map +1 -0
- package/dist/components/SearchableDropdown/SearchableDropdown.stories.d.ts +407 -0
- package/dist/components/SearchableDropdown/SearchableDropdown.stories.d.ts.map +1 -0
- package/dist/components/SearchableDropdown/index.d.ts +2 -0
- package/dist/components/SearchableDropdown/index.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +510 -317
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +512 -315
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1011,6 +1011,303 @@ const Divider = React__namespace.forwardRef(({ className, orientation = "horizon
|
|
|
1011
1011
|
});
|
|
1012
1012
|
Divider.displayName = "Divider";
|
|
1013
1013
|
|
|
1014
|
+
const listItemVariants = classVarianceAuthority.cva("flex items-start gap-3 p-3 rounded-medium transition-colors cursor-pointer", {
|
|
1015
|
+
variants: {
|
|
1016
|
+
variant: {
|
|
1017
|
+
default: `hover:bg-action-fill-neutral-faded
|
|
1018
|
+
focus:bg-action-fill-neutral-faded
|
|
1019
|
+
focus:ring-2
|
|
1020
|
+
ring-action-outline-primary-faded-hover
|
|
1021
|
+
border border-transparent
|
|
1022
|
+
`,
|
|
1023
|
+
bordered: "border border-action-outline-primary-faded hover:bg-surface-fill-primary-subtle",
|
|
1024
|
+
primary: `hover:bg-action-fill-neutral-faded
|
|
1025
|
+
focus:bg-action-fill-neutral-faded
|
|
1026
|
+
focus:ring-2
|
|
1027
|
+
ring-action-outline-primary-faded-hover
|
|
1028
|
+
border border-transparent
|
|
1029
|
+
`,
|
|
1030
|
+
negative: `hover:bg-action-fill-negative-faded
|
|
1031
|
+
focus:bg-action-fill-negative-faded
|
|
1032
|
+
focus:ring-2 ring-action-outline-negative-faded-hover
|
|
1033
|
+
border border-transparent
|
|
1034
|
+
`,
|
|
1035
|
+
},
|
|
1036
|
+
isDisabled: {
|
|
1037
|
+
true: "cursor-not-allowed opacity-60",
|
|
1038
|
+
false: "",
|
|
1039
|
+
},
|
|
1040
|
+
isSelected: {
|
|
1041
|
+
true: "bg-action-fill-primary-faded border-action-outline-primary-faded",
|
|
1042
|
+
false: "",
|
|
1043
|
+
},
|
|
1044
|
+
},
|
|
1045
|
+
defaultVariants: {
|
|
1046
|
+
variant: "default",
|
|
1047
|
+
isDisabled: false,
|
|
1048
|
+
isSelected: false,
|
|
1049
|
+
},
|
|
1050
|
+
});
|
|
1051
|
+
const ChevronRightIcon = ({ className }) => (jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: className, children: jsxRuntime.jsx("path", { d: "M7.5 15L12.5 10L7.5 5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
1052
|
+
const ListItem = React__namespace.forwardRef(({ className, type = "single", leadingIcon, title, description, trailingIcon, showChevron = true, variant = "default", isDisabled = false, isSelected = false, onSelectionChange, checkboxSize = "small", containerClassName, contentClassName, onClick, ...props }, ref) => {
|
|
1053
|
+
const [internalSelected, setInternalSelected] = React__namespace.useState(isSelected);
|
|
1054
|
+
// Sync internal state with prop
|
|
1055
|
+
React__namespace.useEffect(() => {
|
|
1056
|
+
setInternalSelected(isSelected);
|
|
1057
|
+
}, [isSelected]);
|
|
1058
|
+
const handleClick = (e) => {
|
|
1059
|
+
if (isDisabled)
|
|
1060
|
+
return;
|
|
1061
|
+
if (type === "multiple") {
|
|
1062
|
+
const newSelected = !internalSelected;
|
|
1063
|
+
setInternalSelected(newSelected);
|
|
1064
|
+
onSelectionChange?.(newSelected);
|
|
1065
|
+
}
|
|
1066
|
+
onClick?.(e);
|
|
1067
|
+
};
|
|
1068
|
+
const handleCheckboxChange = (e) => {
|
|
1069
|
+
e.stopPropagation();
|
|
1070
|
+
if (isDisabled)
|
|
1071
|
+
return;
|
|
1072
|
+
const newSelected = e.target.checked;
|
|
1073
|
+
setInternalSelected(newSelected);
|
|
1074
|
+
onSelectionChange?.(newSelected);
|
|
1075
|
+
};
|
|
1076
|
+
return (jsxRuntime.jsxs("div", { ref: ref, className: cn(listItemVariants({
|
|
1077
|
+
variant,
|
|
1078
|
+
isDisabled,
|
|
1079
|
+
isSelected: type === "multiple" ? internalSelected : false,
|
|
1080
|
+
}), containerClassName), onClick: handleClick, role: type === "multiple" ? "checkbox" : "button", "aria-checked": type === "multiple" ? internalSelected : undefined, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : 0, ...props, children: [type === "multiple" && (jsxRuntime.jsx(Checkbox, { checked: internalSelected, onChange: handleCheckboxChange, isDisabled: isDisabled, size: checkboxSize, className: "shrink-0 mt-0.5" })), leadingIcon && (jsxRuntime.jsx("div", { className: cn(`shrink-0 flex items-center justify-center mt-0.5`, variant === "primary"
|
|
1081
|
+
? "text-action-ink-primary-normal"
|
|
1082
|
+
: variant === "negative"
|
|
1083
|
+
? "text-action-ink-negative-normal"
|
|
1084
|
+
: "text-action-ink-neutral-subtle", isDisabled && "text-surface-ink-neutral-disabled"), children: leadingIcon })), jsxRuntime.jsxs("div", { className: cn("flex-1 min-w-0 flex flex-col justify-center", contentClassName), children: [jsxRuntime.jsx("div", { className: cn("text-body-medium-regular truncate", variant === "primary"
|
|
1085
|
+
? "text-action-ink-primary-normal"
|
|
1086
|
+
: variant === "negative"
|
|
1087
|
+
? "text-action-ink-negative-normal"
|
|
1088
|
+
: "text-action-ink-neutral-normal", isDisabled && "text-surface-ink-neutral-disabled"), children: title }), description && (jsxRuntime.jsx("div", { className: cn("text-body-small-regular text-surface-ink-neutral-muted mt-0.5 line-clamp-2", isDisabled && "text-surface-ink-neutral-disabled"), children: description }))] }), (trailingIcon || showChevron) && (jsxRuntime.jsx("div", { className: "shrink-0 self-center text-action-ink-neutral-subtle", children: trailingIcon || jsxRuntime.jsx(ChevronRightIcon, {}) }))] }));
|
|
1089
|
+
});
|
|
1090
|
+
ListItem.displayName = "ListItem";
|
|
1091
|
+
|
|
1092
|
+
const linkVariants = classVarianceAuthority.cva("inline-flex items-center gap-1 whitespace-nowrap transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none decoration-1 underline-offset-4", {
|
|
1093
|
+
variants: {
|
|
1094
|
+
type: {
|
|
1095
|
+
anchor: "hover:underline",
|
|
1096
|
+
action: "no-underline cursor-pointer",
|
|
1097
|
+
},
|
|
1098
|
+
color: {
|
|
1099
|
+
primary: "",
|
|
1100
|
+
positive: "",
|
|
1101
|
+
negative: "",
|
|
1102
|
+
notice: "",
|
|
1103
|
+
info: "",
|
|
1104
|
+
neutral: "",
|
|
1105
|
+
},
|
|
1106
|
+
size: {
|
|
1107
|
+
xsmall: "text-body-xsmall-medium gap-1",
|
|
1108
|
+
small: "text-body-small-medium gap-1",
|
|
1109
|
+
medium: "text-body-medium-medium gap-1.5",
|
|
1110
|
+
large: "text-body-large-medium gap-1.5",
|
|
1111
|
+
},
|
|
1112
|
+
isIconOnly: {
|
|
1113
|
+
true: "no-underline",
|
|
1114
|
+
false: "",
|
|
1115
|
+
},
|
|
1116
|
+
isDisabled: {
|
|
1117
|
+
true: "cursor-not-allowed opacity-50",
|
|
1118
|
+
false: "cursor-pointer",
|
|
1119
|
+
},
|
|
1120
|
+
},
|
|
1121
|
+
compoundVariants: [
|
|
1122
|
+
// Primary color variants
|
|
1123
|
+
{
|
|
1124
|
+
color: "primary",
|
|
1125
|
+
class: `text-action-ink-primary-normal
|
|
1126
|
+
hover:text-action-ink-primary-subtle
|
|
1127
|
+
hover:decoration-action-outline-primary-hover
|
|
1128
|
+
disabled:text-action-ink-primary-disabled
|
|
1129
|
+
focus:text-action-ink-primary-hover
|
|
1130
|
+
`,
|
|
1131
|
+
},
|
|
1132
|
+
// Positive color variants
|
|
1133
|
+
{
|
|
1134
|
+
color: "positive",
|
|
1135
|
+
class: `text-action-ink-positive-normal
|
|
1136
|
+
hover:text-action-ink-positive-subtle
|
|
1137
|
+
hover:decoration-action-outline-positive-hover
|
|
1138
|
+
hover:text-action-ink-positive-hover
|
|
1139
|
+
disabled:text-action-ink-positive-disabled
|
|
1140
|
+
focus:text-action-ink-positive-hover
|
|
1141
|
+
`,
|
|
1142
|
+
},
|
|
1143
|
+
// Negative color variants
|
|
1144
|
+
{
|
|
1145
|
+
color: "negative",
|
|
1146
|
+
class: `text-action-ink-negative-normal
|
|
1147
|
+
hover:text-action-ink-negative-subtle
|
|
1148
|
+
hover:decoration-action-outline-negative-hover
|
|
1149
|
+
hover:text-action-ink-negative-hover
|
|
1150
|
+
disabled:text-action-ink-negative-disabled
|
|
1151
|
+
focus:text-action-ink-negative-hover
|
|
1152
|
+
`,
|
|
1153
|
+
},
|
|
1154
|
+
// Notice color variants
|
|
1155
|
+
{
|
|
1156
|
+
color: "notice",
|
|
1157
|
+
class: `text-action-ink-notice-normal
|
|
1158
|
+
hover:text-action-ink-notice-subtle
|
|
1159
|
+
hover:decoration-action-outline-notice-hover
|
|
1160
|
+
hover:text-action-ink-notice-hover
|
|
1161
|
+
disabled:text-action-ink-notice-disabled
|
|
1162
|
+
focus:text-action-ink-notice-hover
|
|
1163
|
+
`,
|
|
1164
|
+
},
|
|
1165
|
+
// Info color variants
|
|
1166
|
+
{
|
|
1167
|
+
color: "info",
|
|
1168
|
+
class: `text-action-ink-info-normal
|
|
1169
|
+
hover:text-action-ink-info-subtle
|
|
1170
|
+
hover:decoration-action-outline-info-hover
|
|
1171
|
+
hover:text-action-ink-info-hover
|
|
1172
|
+
disabled:text-action-ink-info-disabled
|
|
1173
|
+
focus:text-action-ink-info-hover
|
|
1174
|
+
`,
|
|
1175
|
+
},
|
|
1176
|
+
// Neutral color variants
|
|
1177
|
+
{
|
|
1178
|
+
color: "neutral",
|
|
1179
|
+
class: `text-action-ink-neutral-normal
|
|
1180
|
+
hover:text-action-ink-neutral-subtle
|
|
1181
|
+
hover:decoration-action-outline-neutral-hover
|
|
1182
|
+
hover:text-action-ink-neutral-hover
|
|
1183
|
+
disabled:text-action-ink-neutral-disabled
|
|
1184
|
+
focus:text-action-ink-neutral-hover
|
|
1185
|
+
`,
|
|
1186
|
+
},
|
|
1187
|
+
],
|
|
1188
|
+
defaultVariants: {
|
|
1189
|
+
type: "anchor",
|
|
1190
|
+
color: "primary",
|
|
1191
|
+
size: "medium",
|
|
1192
|
+
isIconOnly: false,
|
|
1193
|
+
isDisabled: false,
|
|
1194
|
+
},
|
|
1195
|
+
});
|
|
1196
|
+
const Link = React__namespace.forwardRef(({ className, type = "anchor", color = "primary", size = "medium", isIconOnly = false, isDisabled = false, asChild = false, showIcon = false, icon, leadingIcon, trailingIcon, children, onClick, ...props }, ref) => {
|
|
1197
|
+
const Comp = asChild ? reactSlot.Slot : "a";
|
|
1198
|
+
const handleClick = (e) => {
|
|
1199
|
+
if (isDisabled) {
|
|
1200
|
+
e.preventDefault();
|
|
1201
|
+
return;
|
|
1202
|
+
}
|
|
1203
|
+
onClick?.(e);
|
|
1204
|
+
};
|
|
1205
|
+
// Icon size based on link size
|
|
1206
|
+
const iconSize = {
|
|
1207
|
+
xsmall: 12,
|
|
1208
|
+
small: 14,
|
|
1209
|
+
medium: 16,
|
|
1210
|
+
large: 18,
|
|
1211
|
+
}[size];
|
|
1212
|
+
// Determine what to show as trailing icon
|
|
1213
|
+
// Priority: trailingIcon > (showIcon && icon) > (showIcon && default ExternalLink)
|
|
1214
|
+
const finalTrailingIcon = trailingIcon || (showIcon && (icon || jsxRuntime.jsx(lucideReact.ExternalLink, { size: iconSize })));
|
|
1215
|
+
const linkContent = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [leadingIcon && !isIconOnly && (jsxRuntime.jsx("span", { className: "inline-flex items-center", children: leadingIcon })), !isIconOnly && children, isIconOnly && children, finalTrailingIcon && !isIconOnly && (jsxRuntime.jsx("span", { className: "inline-flex items-center", children: finalTrailingIcon })), isIconOnly &&
|
|
1216
|
+
(leadingIcon || finalTrailingIcon || (jsxRuntime.jsx(lucideReact.ExternalLink, { size: iconSize })))] }));
|
|
1217
|
+
return (jsxRuntime.jsx(Comp, { className: cn(linkVariants({
|
|
1218
|
+
type,
|
|
1219
|
+
color,
|
|
1220
|
+
size,
|
|
1221
|
+
isIconOnly,
|
|
1222
|
+
isDisabled,
|
|
1223
|
+
}), className), ref: ref, onClick: handleClick, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : undefined, ...props, children: linkContent }));
|
|
1224
|
+
});
|
|
1225
|
+
Link.displayName = "Link";
|
|
1226
|
+
|
|
1227
|
+
const DropdownMenu = React__namespace.forwardRef(({ items = [], sectionHeading, isLoading = false, isEmpty = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText = "Primary", secondaryButtonText = "Secondary", onPrimaryClick, onSecondaryClick, showChevron = false, emptyIcon, disableFooter = false, onClose, focusedIndex = -1, className, width = "auto", }, ref) => {
|
|
1228
|
+
const renderContent = () => {
|
|
1229
|
+
if (isLoading) {
|
|
1230
|
+
return (jsxRuntime.jsx("div", { className: "flex flex-col items-center justify-center py-12 px-6", children: jsxRuntime.jsx(lucideReact.Loader2, { className: "w-12 h-12 text-action-ink-primary-normal mb-4 animate-spin" }) }));
|
|
1231
|
+
}
|
|
1232
|
+
if (isEmpty || items.length === 0) {
|
|
1233
|
+
return (jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-8 px-6 text-center", children: [emptyIcon || (jsxRuntime.jsx(lucideReact.Search, { className: "w-12 h-12 text-surface-ink-neutral-muted mb-4" })), jsxRuntime.jsx(Text, { as: "h3", variant: "body", size: "small", weight: "semibold", className: "text-surface-ink-neutral-normal mb-2", children: emptyTitle }), jsxRuntime.jsx(Text, { as: "p", variant: "body", size: "small", weight: "regular", className: "text-surface-ink-neutral-muted mb-3", children: emptyDescription }), emptyLinkText && (jsxRuntime.jsx(Link, { type: "anchor", color: "primary", size: "small", onClick: onEmptyLinkClick, children: emptyLinkText }))] }));
|
|
1234
|
+
}
|
|
1235
|
+
return (jsxRuntime.jsxs("div", { className: "py-3 px-3 max-h-[400px] overflow-y-auto", children: [sectionHeading && (jsxRuntime.jsx(Text, { as: "div", variant: "body", size: "small", weight: "medium", className: "text-surface-ink-neutral-muted px-3 py-2 mb-1", children: sectionHeading })), jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children: items.map((item, index) => (jsxRuntime.jsx(ListItem, { title: item.title, description: item.description, leadingIcon: item.leadingIcon, trailingIcon: item.trailingIcon, showChevron: showChevron, isDisabled: item.isDisabled, isSelected: index === focusedIndex, onClick: () => {
|
|
1236
|
+
item.onClick?.();
|
|
1237
|
+
onClose?.();
|
|
1238
|
+
}, containerClassName: cn(index === focusedIndex && "bg-action-fill-primary-faded") }, item.id))) })] }));
|
|
1239
|
+
};
|
|
1240
|
+
const widthClass = width === "full" ? "w-full" : width === "auto" ? "w-auto" : "";
|
|
1241
|
+
return (jsxRuntime.jsxs("div", { ref: ref, className: cn("bg-surface-fill-primary-normal rounded-large overflow-hidden", widthClass, className), style: {
|
|
1242
|
+
boxShadow: "0 1px 2px rgba(25, 25, 30, 0.1), 0 2px 6px rgba(25, 25, 30, 0.06)",
|
|
1243
|
+
...(width !== "full" && width !== "auto" ? { width } : {}),
|
|
1244
|
+
}, children: [renderContent(), !disableFooter && (jsxRuntime.jsxs("div", { className: "flex flex-col", children: [jsxRuntime.jsx(Divider, { thickness: "thin", variant: "muted" }), jsxRuntime.jsxs("div", { className: "flex items-center gap-3 p-4", children: [jsxRuntime.jsx(Button, { variant: "secondary", color: "primary", size: "medium", isFullWidth: true, onClick: onSecondaryClick, children: secondaryButtonText }), jsxRuntime.jsx(Button, { variant: "primary", color: "primary", size: "medium", isFullWidth: true, onClick: onPrimaryClick, children: primaryButtonText })] })] }))] }));
|
|
1245
|
+
});
|
|
1246
|
+
DropdownMenu.displayName = "DropdownMenu";
|
|
1247
|
+
|
|
1248
|
+
const dropdownVariants = classVarianceAuthority.cva("bg-surface-fill-primary-normal border border-surface-outline-neutral-subtle rounded-large", {
|
|
1249
|
+
variants: {
|
|
1250
|
+
size: {
|
|
1251
|
+
small: "w-64",
|
|
1252
|
+
medium: "w-80",
|
|
1253
|
+
large: "w-96",
|
|
1254
|
+
},
|
|
1255
|
+
},
|
|
1256
|
+
defaultVariants: {
|
|
1257
|
+
size: "medium",
|
|
1258
|
+
},
|
|
1259
|
+
});
|
|
1260
|
+
const Dropdown = React__namespace.forwardRef(({ className, trigger, items = [], sectionHeading, isLoading = false, isEmpty = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText = "Primary", secondaryButtonText = "Secondary", onPrimaryClick, onSecondaryClick, size = "medium", open: controlledOpen, defaultOpen = false, onOpenChange, containerClassName, menuClassName, showChevron = false, emptyIcon, disableFooter = false, ...props }, ref) => {
|
|
1261
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React__namespace.useState(defaultOpen);
|
|
1262
|
+
const isOpen = controlledOpen !== undefined ? controlledOpen : uncontrolledOpen;
|
|
1263
|
+
const dropdownRef = React__namespace.useRef(null);
|
|
1264
|
+
const handleOpenChange = (newOpen) => {
|
|
1265
|
+
if (controlledOpen === undefined) {
|
|
1266
|
+
setUncontrolledOpen(newOpen);
|
|
1267
|
+
}
|
|
1268
|
+
onOpenChange?.(newOpen);
|
|
1269
|
+
};
|
|
1270
|
+
const toggleOpen = () => {
|
|
1271
|
+
handleOpenChange(!isOpen);
|
|
1272
|
+
};
|
|
1273
|
+
// Close dropdown when clicking outside
|
|
1274
|
+
React__namespace.useEffect(() => {
|
|
1275
|
+
const handleClickOutside = (event) => {
|
|
1276
|
+
if (dropdownRef.current &&
|
|
1277
|
+
!dropdownRef.current.contains(event.target)) {
|
|
1278
|
+
handleOpenChange(false);
|
|
1279
|
+
}
|
|
1280
|
+
};
|
|
1281
|
+
if (isOpen) {
|
|
1282
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1283
|
+
return () => {
|
|
1284
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
}, [isOpen]);
|
|
1288
|
+
// Close on escape key
|
|
1289
|
+
React__namespace.useEffect(() => {
|
|
1290
|
+
const handleEscape = (event) => {
|
|
1291
|
+
if (event.key === "Escape") {
|
|
1292
|
+
handleOpenChange(false);
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
if (isOpen) {
|
|
1296
|
+
document.addEventListener("keydown", handleEscape);
|
|
1297
|
+
return () => {
|
|
1298
|
+
document.removeEventListener("keydown", handleEscape);
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
}, [isOpen]);
|
|
1302
|
+
const sizeMap = {
|
|
1303
|
+
small: "w-64",
|
|
1304
|
+
medium: "w-80",
|
|
1305
|
+
large: "w-96",
|
|
1306
|
+
};
|
|
1307
|
+
return (jsxRuntime.jsxs("div", { ref: dropdownRef, className: cn("relative inline-block", containerClassName), ...props, children: [trigger && (jsxRuntime.jsx("div", { onClick: toggleOpen, className: "cursor-pointer", children: trigger })), isOpen && (jsxRuntime.jsx(DropdownMenu, { ref: ref, items: items, sectionHeading: sectionHeading, isLoading: isLoading, isEmpty: isEmpty, emptyTitle: emptyTitle, emptyDescription: emptyDescription, emptyLinkText: emptyLinkText, onEmptyLinkClick: onEmptyLinkClick, primaryButtonText: primaryButtonText, secondaryButtonText: secondaryButtonText, onPrimaryClick: onPrimaryClick, onSecondaryClick: onSecondaryClick, showChevron: showChevron, emptyIcon: emptyIcon, disableFooter: disableFooter, onClose: () => handleOpenChange(false), className: cn("absolute z-50 mt-2", menuClassName, className), width: sizeMap[size] }))] }));
|
|
1308
|
+
});
|
|
1309
|
+
Dropdown.displayName = "Dropdown";
|
|
1310
|
+
|
|
1014
1311
|
const tooltipVariants = classVarianceAuthority.cva("fixed z-50 bg-popup-fill-intense text-action-ink-on-primary-normal rounded-medium border border-popup-outline-subtle flex flex-col p-4 rounded-xlarge min-w-[200px] max-w-[300px] transition-opacity duration-200", {
|
|
1015
1312
|
variants: {
|
|
1016
1313
|
isVisible: {
|
|
@@ -1260,218 +1557,10 @@ const FormHeader = React__namespace.forwardRef(({ label, size = "medium", isOpti
|
|
|
1260
1557
|
gap: "gap-2.5",
|
|
1261
1558
|
},
|
|
1262
1559
|
};
|
|
1263
|
-
const config = sizeConfig[size];
|
|
1264
|
-
return (jsxRuntime.jsxs("div", { ref: ref, className: cn("flex items-center justify-between px-1", config.gap, className), children: [jsxRuntime.jsxs("div", { className: cn("flex items-center", config.gap), children: [jsxRuntime.jsxs("label", { htmlFor: htmlFor, className: cn("flex items-center", labelClassName), children: [jsxRuntime.jsx(Text, { as: "span", variant: "body", size: config.textSize, weight: "semibold", color: "subtle", children: label }), isRequired && (jsxRuntime.jsx(Text, { as: "span", variant: "body", size: config.textSize, weight: "semibold", className: "text-feedback-ink-negative-subtle ml-0.5", children: "*" })), isOptional && (jsxRuntime.jsx(Text, { as: "span", variant: "body", size: config.textSize, weight: "regular", className: "text-surface-ink-neutral-muted ml-1", children: "(optional)" }))] }), infoDescription && (jsxRuntime.jsx(Tooltip, { description: infoDescription, heading: infoHeading, children: jsxRuntime.jsxs("svg", { width: config.iconSize, height: config.iconSize, viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: "text-surface-ink-neutral-muted cursor-help", children: [jsxRuntime.jsx("circle", { cx: "7", cy: "7", r: "6", stroke: "currentColor", strokeWidth: "1" }), jsxRuntime.jsx("path", { d: "M7 6V10M7 4.5V4", stroke: "currentColor", strokeWidth: "1", strokeLinecap: "round" })] }) }))] }), linkText && (jsxRuntime.jsx("a", { href: linkHref, onClick: onLinkClick, className: cn("text-surface-ink-primary-normal hover:text-surface-ink-primary-hover transition-colors cursor-pointer font-display font-semibold leading-tight shrink-0", size === "small" && "text-xs", size === "medium" && "text-xs", size === "large" && "text-sm", linkClassName), children: linkText }))] }));
|
|
1265
|
-
});
|
|
1266
|
-
FormHeader.displayName = "FormHeader";
|
|
1267
|
-
|
|
1268
|
-
const linkVariants = classVarianceAuthority.cva("inline-flex items-center gap-1 whitespace-nowrap transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none underline decoration-1 underline-offset-4", {
|
|
1269
|
-
variants: {
|
|
1270
|
-
type: {
|
|
1271
|
-
anchor: "",
|
|
1272
|
-
action: "cursor-pointer",
|
|
1273
|
-
},
|
|
1274
|
-
color: {
|
|
1275
|
-
primary: "",
|
|
1276
|
-
positive: "",
|
|
1277
|
-
negative: "",
|
|
1278
|
-
notice: "",
|
|
1279
|
-
info: "",
|
|
1280
|
-
neutral: "",
|
|
1281
|
-
},
|
|
1282
|
-
size: {
|
|
1283
|
-
xsmall: "text-body-xsmall-medium gap-1",
|
|
1284
|
-
small: "text-body-small-medium gap-1",
|
|
1285
|
-
medium: "text-body-medium-medium gap-1.5",
|
|
1286
|
-
large: "text-body-large-medium gap-1.5",
|
|
1287
|
-
},
|
|
1288
|
-
isIconOnly: {
|
|
1289
|
-
true: "no-underline",
|
|
1290
|
-
false: "",
|
|
1291
|
-
},
|
|
1292
|
-
isDisabled: {
|
|
1293
|
-
true: "cursor-not-allowed opacity-50",
|
|
1294
|
-
false: "cursor-pointer",
|
|
1295
|
-
},
|
|
1296
|
-
},
|
|
1297
|
-
compoundVariants: [
|
|
1298
|
-
// Primary color variants
|
|
1299
|
-
{
|
|
1300
|
-
color: "primary",
|
|
1301
|
-
class: `text-action-ink-primary-normal
|
|
1302
|
-
hover:text-action-ink-primary-hover
|
|
1303
|
-
disabled:text-action-ink-primary-disabled
|
|
1304
|
-
active:text-action-ink-primary-activated
|
|
1305
|
-
focus:text-action-ink-primary-hover
|
|
1306
|
-
`,
|
|
1307
|
-
},
|
|
1308
|
-
// Positive color variants
|
|
1309
|
-
{
|
|
1310
|
-
color: "positive",
|
|
1311
|
-
class: `text-action-ink-positive-normal
|
|
1312
|
-
hover:text-action-ink-positive-hover
|
|
1313
|
-
disabled:text-action-ink-positive-disabled
|
|
1314
|
-
active:text-action-ink-positive-activated
|
|
1315
|
-
focus:text-action-ink-positive-hover
|
|
1316
|
-
`,
|
|
1317
|
-
},
|
|
1318
|
-
// Negative color variants
|
|
1319
|
-
{
|
|
1320
|
-
color: "negative",
|
|
1321
|
-
class: `text-action-ink-negative-normal
|
|
1322
|
-
hover:text-action-ink-negative-hover
|
|
1323
|
-
disabled:text-action-ink-negative-disabled
|
|
1324
|
-
active:text-action-ink-negative-activated
|
|
1325
|
-
focus:text-action-ink-negative-hover
|
|
1326
|
-
`,
|
|
1327
|
-
},
|
|
1328
|
-
// Notice color variants
|
|
1329
|
-
{
|
|
1330
|
-
color: "notice",
|
|
1331
|
-
class: `text-action-ink-notice-normal
|
|
1332
|
-
hover:text-action-ink-notice-hover
|
|
1333
|
-
disabled:text-action-ink-notice-disabled
|
|
1334
|
-
active:text-action-ink-notice-activated
|
|
1335
|
-
focus:text-action-ink-notice-hover
|
|
1336
|
-
`,
|
|
1337
|
-
},
|
|
1338
|
-
// Info color variants
|
|
1339
|
-
{
|
|
1340
|
-
color: "info",
|
|
1341
|
-
class: `text-action-ink-info-normal
|
|
1342
|
-
hover:text-action-ink-info-hover
|
|
1343
|
-
disabled:text-action-ink-info-disabled
|
|
1344
|
-
active:text-action-ink-info-activated
|
|
1345
|
-
focus:text-action-ink-info-hover
|
|
1346
|
-
`,
|
|
1347
|
-
},
|
|
1348
|
-
// Neutral color variants
|
|
1349
|
-
{
|
|
1350
|
-
color: "neutral",
|
|
1351
|
-
class: `text-action-ink-neutral-normal
|
|
1352
|
-
hover:text-action-ink-neutral-hover
|
|
1353
|
-
disabled:text-action-ink-neutral-disabled
|
|
1354
|
-
active:text-action-ink-neutral-activated
|
|
1355
|
-
focus:text-action-ink-neutral-hover
|
|
1356
|
-
`,
|
|
1357
|
-
},
|
|
1358
|
-
],
|
|
1359
|
-
defaultVariants: {
|
|
1360
|
-
type: "anchor",
|
|
1361
|
-
color: "primary",
|
|
1362
|
-
size: "medium",
|
|
1363
|
-
isIconOnly: false,
|
|
1364
|
-
isDisabled: false,
|
|
1365
|
-
},
|
|
1366
|
-
});
|
|
1367
|
-
const Link = React__namespace.forwardRef(({ className, type = "anchor", color = "primary", size = "medium", isIconOnly = false, isDisabled = false, asChild = false, showIcon = false, icon, leadingIcon, trailingIcon, children, onClick, ...props }, ref) => {
|
|
1368
|
-
const Comp = asChild ? reactSlot.Slot : "a";
|
|
1369
|
-
const handleClick = (e) => {
|
|
1370
|
-
if (isDisabled) {
|
|
1371
|
-
e.preventDefault();
|
|
1372
|
-
return;
|
|
1373
|
-
}
|
|
1374
|
-
onClick?.(e);
|
|
1375
|
-
};
|
|
1376
|
-
// Icon size based on link size
|
|
1377
|
-
const iconSize = {
|
|
1378
|
-
xsmall: 12,
|
|
1379
|
-
small: 14,
|
|
1380
|
-
medium: 16,
|
|
1381
|
-
large: 18,
|
|
1382
|
-
}[size];
|
|
1383
|
-
// Determine what to show as trailing icon
|
|
1384
|
-
// Priority: trailingIcon > (showIcon && icon) > (showIcon && default ExternalLink)
|
|
1385
|
-
const finalTrailingIcon = trailingIcon || (showIcon && (icon || jsxRuntime.jsx(lucideReact.ExternalLink, { size: iconSize })));
|
|
1386
|
-
const linkContent = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [leadingIcon && !isIconOnly && (jsxRuntime.jsx("span", { className: "inline-flex items-center", children: leadingIcon })), !isIconOnly && children, isIconOnly && children, finalTrailingIcon && !isIconOnly && (jsxRuntime.jsx("span", { className: "inline-flex items-center", children: finalTrailingIcon })), isIconOnly &&
|
|
1387
|
-
(leadingIcon || finalTrailingIcon || (jsxRuntime.jsx(lucideReact.ExternalLink, { size: iconSize })))] }));
|
|
1388
|
-
return (jsxRuntime.jsx(Comp, { className: cn(linkVariants({
|
|
1389
|
-
type,
|
|
1390
|
-
color,
|
|
1391
|
-
size,
|
|
1392
|
-
isIconOnly,
|
|
1393
|
-
isDisabled,
|
|
1394
|
-
}), className), ref: ref, onClick: handleClick, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : undefined, ...props, children: linkContent }));
|
|
1395
|
-
});
|
|
1396
|
-
Link.displayName = "Link";
|
|
1397
|
-
|
|
1398
|
-
const listItemVariants = classVarianceAuthority.cva("flex items-start gap-3 p-3 rounded-medium transition-colors cursor-pointer", {
|
|
1399
|
-
variants: {
|
|
1400
|
-
variant: {
|
|
1401
|
-
default: `hover:bg-action-fill-neutral-faded
|
|
1402
|
-
focus:bg-action-fill-neutral-faded
|
|
1403
|
-
focus:ring-2
|
|
1404
|
-
ring-action-outline-primary-faded-hover
|
|
1405
|
-
border border-transparent
|
|
1406
|
-
`,
|
|
1407
|
-
bordered: "border border-action-outline-primary-faded hover:bg-surface-fill-primary-subtle",
|
|
1408
|
-
primary: `hover:bg-action-fill-neutral-faded
|
|
1409
|
-
focus:bg-action-fill-neutral-faded
|
|
1410
|
-
focus:ring-2
|
|
1411
|
-
ring-action-outline-primary-faded-hover
|
|
1412
|
-
border border-transparent
|
|
1413
|
-
`,
|
|
1414
|
-
negative: `hover:bg-action-fill-negative-faded
|
|
1415
|
-
focus:bg-action-fill-negative-faded
|
|
1416
|
-
focus:ring-2 ring-action-outline-negative-faded-hover
|
|
1417
|
-
border border-transparent
|
|
1418
|
-
`,
|
|
1419
|
-
},
|
|
1420
|
-
isDisabled: {
|
|
1421
|
-
true: "cursor-not-allowed opacity-60",
|
|
1422
|
-
false: "",
|
|
1423
|
-
},
|
|
1424
|
-
isSelected: {
|
|
1425
|
-
true: "bg-action-fill-primary-faded border-action-outline-primary-faded",
|
|
1426
|
-
false: "",
|
|
1427
|
-
},
|
|
1428
|
-
},
|
|
1429
|
-
defaultVariants: {
|
|
1430
|
-
variant: "default",
|
|
1431
|
-
isDisabled: false,
|
|
1432
|
-
isSelected: false,
|
|
1433
|
-
},
|
|
1434
|
-
});
|
|
1435
|
-
const ChevronRightIcon = ({ className }) => (jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: className, children: jsxRuntime.jsx("path", { d: "M7.5 15L12.5 10L7.5 5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
1436
|
-
const ListItem = React__namespace.forwardRef(({ className, type = "single", leadingIcon, title, description, trailingIcon, showChevron = true, variant = "default", isDisabled = false, isSelected = false, onSelectionChange, checkboxSize = "small", containerClassName, contentClassName, onClick, ...props }, ref) => {
|
|
1437
|
-
const [internalSelected, setInternalSelected] = React__namespace.useState(isSelected);
|
|
1438
|
-
// Sync internal state with prop
|
|
1439
|
-
React__namespace.useEffect(() => {
|
|
1440
|
-
setInternalSelected(isSelected);
|
|
1441
|
-
}, [isSelected]);
|
|
1442
|
-
const handleClick = (e) => {
|
|
1443
|
-
if (isDisabled)
|
|
1444
|
-
return;
|
|
1445
|
-
if (type === "multiple") {
|
|
1446
|
-
const newSelected = !internalSelected;
|
|
1447
|
-
setInternalSelected(newSelected);
|
|
1448
|
-
onSelectionChange?.(newSelected);
|
|
1449
|
-
}
|
|
1450
|
-
onClick?.(e);
|
|
1451
|
-
};
|
|
1452
|
-
const handleCheckboxChange = (e) => {
|
|
1453
|
-
e.stopPropagation();
|
|
1454
|
-
if (isDisabled)
|
|
1455
|
-
return;
|
|
1456
|
-
const newSelected = e.target.checked;
|
|
1457
|
-
setInternalSelected(newSelected);
|
|
1458
|
-
onSelectionChange?.(newSelected);
|
|
1459
|
-
};
|
|
1460
|
-
return (jsxRuntime.jsxs("div", { ref: ref, className: cn(listItemVariants({
|
|
1461
|
-
variant,
|
|
1462
|
-
isDisabled,
|
|
1463
|
-
isSelected: type === "multiple" ? internalSelected : false,
|
|
1464
|
-
}), containerClassName), onClick: handleClick, role: type === "multiple" ? "checkbox" : "button", "aria-checked": type === "multiple" ? internalSelected : undefined, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : 0, ...props, children: [type === "multiple" && (jsxRuntime.jsx(Checkbox, { checked: internalSelected, onChange: handleCheckboxChange, isDisabled: isDisabled, size: checkboxSize, className: "shrink-0 mt-0.5" })), leadingIcon && (jsxRuntime.jsx("div", { className: cn(`shrink-0 flex items-center justify-center mt-0.5`, variant === "primary"
|
|
1465
|
-
? "text-action-ink-primary-normal"
|
|
1466
|
-
: variant === "negative"
|
|
1467
|
-
? "text-action-ink-negative-normal"
|
|
1468
|
-
: "text-action-ink-neutral-subtle", isDisabled && "text-surface-ink-neutral-disabled"), children: leadingIcon })), jsxRuntime.jsxs("div", { className: cn("flex-1 min-w-0 flex flex-col justify-center", contentClassName), children: [jsxRuntime.jsx("div", { className: cn("text-body-medium-regular truncate", variant === "primary"
|
|
1469
|
-
? "text-action-ink-primary-normal"
|
|
1470
|
-
: variant === "negative"
|
|
1471
|
-
? "text-action-ink-negative-normal"
|
|
1472
|
-
: "text-action-ink-neutral-normal", isDisabled && "text-surface-ink-neutral-disabled"), children: title }), description && (jsxRuntime.jsx("div", { className: cn("text-body-small-regular text-surface-ink-neutral-muted mt-0.5 line-clamp-2", isDisabled && "text-surface-ink-neutral-disabled"), children: description }))] }), (trailingIcon || showChevron) && (jsxRuntime.jsx("div", { className: "shrink-0 self-center text-action-ink-neutral-subtle", children: trailingIcon || jsxRuntime.jsx(ChevronRightIcon, {}) }))] }));
|
|
1560
|
+
const config = sizeConfig[size];
|
|
1561
|
+
return (jsxRuntime.jsxs("div", { ref: ref, className: cn("flex items-center justify-between px-1", config.gap, className), children: [jsxRuntime.jsxs("div", { className: cn("flex items-center", config.gap), children: [jsxRuntime.jsxs("label", { htmlFor: htmlFor, className: cn("flex items-center", labelClassName), children: [jsxRuntime.jsx(Text, { as: "span", variant: "body", size: config.textSize, weight: "semibold", color: "subtle", children: label }), isRequired && (jsxRuntime.jsx(Text, { as: "span", variant: "body", size: config.textSize, weight: "semibold", className: "text-feedback-ink-negative-subtle ml-0.5", children: "*" })), isOptional && (jsxRuntime.jsx(Text, { as: "span", variant: "body", size: config.textSize, weight: "regular", className: "text-surface-ink-neutral-muted ml-1", children: "(optional)" }))] }), infoDescription && (jsxRuntime.jsx(Tooltip, { description: infoDescription, heading: infoHeading, children: jsxRuntime.jsxs("svg", { width: config.iconSize, height: config.iconSize, viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: "text-surface-ink-neutral-muted cursor-help", children: [jsxRuntime.jsx("circle", { cx: "7", cy: "7", r: "6", stroke: "currentColor", strokeWidth: "1" }), jsxRuntime.jsx("path", { d: "M7 6V10M7 4.5V4", stroke: "currentColor", strokeWidth: "1", strokeLinecap: "round" })] }) }))] }), linkText && (jsxRuntime.jsx("a", { href: linkHref, onClick: onLinkClick, className: cn("text-surface-ink-primary-normal hover:text-surface-ink-primary-hover transition-colors cursor-pointer font-display font-semibold leading-tight shrink-0", size === "small" && "text-xs", size === "medium" && "text-xs", size === "large" && "text-sm", linkClassName), children: linkText }))] }));
|
|
1473
1562
|
});
|
|
1474
|
-
|
|
1563
|
+
FormHeader.displayName = "FormHeader";
|
|
1475
1564
|
|
|
1476
1565
|
const radioVariants = classVarianceAuthority.cva("relative inline-flex items-center justify-center shrink-0 border transition-all cursor-pointer rounded-full", {
|
|
1477
1566
|
variants: {
|
|
@@ -1638,6 +1727,214 @@ const Radio = React__namespace.forwardRef(({ label, errorText, size = "medium",
|
|
|
1638
1727
|
});
|
|
1639
1728
|
Radio.displayName = "Radio";
|
|
1640
1729
|
|
|
1730
|
+
const textFieldVariants = classVarianceAuthority.cva("relative flex items-center gap-2 border rounded-medium transition-all font-display font-size-100 leading-100", {
|
|
1731
|
+
variants: {
|
|
1732
|
+
size: {
|
|
1733
|
+
small: "h-[28px] px-3 text-xs gap-2",
|
|
1734
|
+
medium: "h-[36px] px-4 text-sm gap-2",
|
|
1735
|
+
large: "h-[44px] px-5 text-base gap-3",
|
|
1736
|
+
},
|
|
1737
|
+
validationState: {
|
|
1738
|
+
none: `
|
|
1739
|
+
border-action-outline-neutral-faded
|
|
1740
|
+
hover:border-action-outline-primary-hover
|
|
1741
|
+
focus-within:border-action-outline-primary-hover
|
|
1742
|
+
focus-within:ring-2
|
|
1743
|
+
ring-action-outline-primary-faded-hover`,
|
|
1744
|
+
positive: `
|
|
1745
|
+
border-action-outline-positive-default
|
|
1746
|
+
focus-within:border-action-outline-positive-hover
|
|
1747
|
+
focus-within:ring-2
|
|
1748
|
+
ring-action-outline-positive-faded-hover`,
|
|
1749
|
+
negative: `border-action-outline-negative-default
|
|
1750
|
+
focus-within:border-action-outline-negative-hover
|
|
1751
|
+
focus-within:ring-2
|
|
1752
|
+
ring-action-outline-negative-faded-hover`,
|
|
1753
|
+
},
|
|
1754
|
+
isDisabled: {
|
|
1755
|
+
true: `
|
|
1756
|
+
border-[var(--border-width-thinner)]
|
|
1757
|
+
hover:border-action-outline-neutral-disabled
|
|
1758
|
+
border-action-outline-neutral-disabled
|
|
1759
|
+
bg-surface-fill-neutral-intense cursor-not-allowed opacity-60`,
|
|
1760
|
+
false: "bg-surface-fill-neutral-intense",
|
|
1761
|
+
},
|
|
1762
|
+
},
|
|
1763
|
+
defaultVariants: {
|
|
1764
|
+
size: "medium",
|
|
1765
|
+
validationState: "none",
|
|
1766
|
+
isDisabled: false,
|
|
1767
|
+
},
|
|
1768
|
+
});
|
|
1769
|
+
const TextField = React__namespace.forwardRef(({ label, helperText, errorText, successText, size = "medium", validationState = "none", isDisabled = false, isRequired = false, isOptional = false, prefix, suffix, showClearButton = false, infoDescription, infoHeading, linkText, linkHref, onLinkClick, onClear, containerClassName, labelClassName, inputClassName, className, value, onChange, ...props }, ref) => {
|
|
1770
|
+
const [internalValue, setInternalValue] = React__namespace.useState("");
|
|
1771
|
+
const inputValue = value !== undefined ? value : internalValue;
|
|
1772
|
+
const hasValue = inputValue && String(inputValue).length > 0;
|
|
1773
|
+
const handleChange = (e) => {
|
|
1774
|
+
if (onChange) {
|
|
1775
|
+
onChange(e);
|
|
1776
|
+
}
|
|
1777
|
+
else {
|
|
1778
|
+
setInternalValue(e.target.value);
|
|
1779
|
+
}
|
|
1780
|
+
};
|
|
1781
|
+
const handleClear = () => {
|
|
1782
|
+
if (onClear) {
|
|
1783
|
+
onClear();
|
|
1784
|
+
}
|
|
1785
|
+
else {
|
|
1786
|
+
setInternalValue("");
|
|
1787
|
+
}
|
|
1788
|
+
// Focus the input after clearing
|
|
1789
|
+
const input = document.getElementById(props.id || "");
|
|
1790
|
+
if (input) {
|
|
1791
|
+
input.focus();
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
// Determine which helper text to show
|
|
1795
|
+
const displayHelperText = errorText || successText || helperText;
|
|
1796
|
+
const currentValidationState = errorText
|
|
1797
|
+
? "negative"
|
|
1798
|
+
: successText
|
|
1799
|
+
? "positive"
|
|
1800
|
+
: validationState;
|
|
1801
|
+
const sizeConfig = {
|
|
1802
|
+
small: {
|
|
1803
|
+
gap: "gap-2",
|
|
1804
|
+
},
|
|
1805
|
+
medium: {
|
|
1806
|
+
gap: "gap-2",
|
|
1807
|
+
},
|
|
1808
|
+
large: {
|
|
1809
|
+
gap: "gap-3",
|
|
1810
|
+
},
|
|
1811
|
+
};
|
|
1812
|
+
return (jsxRuntime.jsxs("div", { className: cn("w-full flex flex-col", sizeConfig[size].gap, containerClassName), children: [label && (jsxRuntime.jsx(FormHeader, { label: label, size: size, isRequired: isRequired, isOptional: isOptional, infoHeading: infoHeading, infoDescription: infoDescription, linkText: linkText, linkHref: linkHref, onLinkClick: onLinkClick, htmlFor: props.id, className: "mb-2", labelClassName: labelClassName })), jsxRuntime.jsxs("div", { className: cn(textFieldVariants({
|
|
1813
|
+
size,
|
|
1814
|
+
validationState: currentValidationState,
|
|
1815
|
+
isDisabled,
|
|
1816
|
+
}), className), children: [prefix && (jsxRuntime.jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
1817
|
+
? "text-surface-ink-neutral-disabled"
|
|
1818
|
+
: currentValidationState === "positive"
|
|
1819
|
+
? "text-feedback-ink-positive-intense"
|
|
1820
|
+
: currentValidationState === "negative"
|
|
1821
|
+
? "text-feedback-ink-negative-subtle"
|
|
1822
|
+
: "text-surface-ink-neutral-muted"), children: prefix })), jsxRuntime.jsx("input", { ref: ref, value: inputValue, onChange: handleChange, disabled: isDisabled, required: isRequired, className: cn("flex-1 bg-transparent border-none outline-none text-surface-ink-neutral-normal placeholder:text-surface-ink-neutral-muted disabled:cursor-not-allowed disabled:text-surface-ink-neutral-disabled font-display", inputClassName), ...props }), showClearButton && hasValue && !isDisabled && (jsxRuntime.jsx("button", { type: "button", onClick: handleClear, className: "shrink-0 flex items-center justify-center text-surface-ink-neutral-muted hover:text-surface-ink-neutral-normal transition-colors", tabIndex: -1, children: jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsxRuntime.jsx("path", { d: "M12 4L4 12M4 4L12 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })), suffix && (jsxRuntime.jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
1823
|
+
? "text-surface-ink-neutral-disabled"
|
|
1824
|
+
: currentValidationState === "positive"
|
|
1825
|
+
? "text-feedback-ink-positive-intense"
|
|
1826
|
+
: currentValidationState === "negative"
|
|
1827
|
+
? "text-feedback-ink-negative-subtle"
|
|
1828
|
+
: "text-surface-ink-neutral-muted"), children: suffix }))] }), jsxRuntime.jsx(FormFooter, { helperText: displayHelperText, validationState: currentValidationState === "none"
|
|
1829
|
+
? "default"
|
|
1830
|
+
: currentValidationState, size: size, isDisabled: isDisabled, className: "mt-1" })] }));
|
|
1831
|
+
});
|
|
1832
|
+
TextField.displayName = "TextField";
|
|
1833
|
+
|
|
1834
|
+
const defaultFilter = (item, query) => {
|
|
1835
|
+
const searchQuery = query.toLowerCase();
|
|
1836
|
+
return (item.title.toLowerCase().includes(searchQuery) ||
|
|
1837
|
+
(item.description?.toLowerCase().includes(searchQuery) ?? false));
|
|
1838
|
+
};
|
|
1839
|
+
const SearchableDropdown = React__namespace.forwardRef(({ className, items = [], sectionHeading, isLoading = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText = "Primary", secondaryButtonText = "Secondary", onPrimaryClick, onSecondaryClick, dropdownWidth = "full", showChevron = false, emptyIcon, disableFooter = false, onSearchChange, onItemSelect, filterFunction = defaultFilter, searchValue: controlledSearchValue, defaultSearchValue = "", dropdownClassName, minSearchLength = 0, showOnFocus = true, containerClassName, ...textFieldProps }, ref) => {
|
|
1840
|
+
const [uncontrolledSearchValue, setUncontrolledSearchValue] = React__namespace.useState(defaultSearchValue);
|
|
1841
|
+
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
|
1842
|
+
const [focusedIndex, setFocusedIndex] = React__namespace.useState(-1);
|
|
1843
|
+
const dropdownRef = React__namespace.useRef(null);
|
|
1844
|
+
const inputRef = React__namespace.useRef(null);
|
|
1845
|
+
React__namespace.useImperativeHandle(ref, () => inputRef.current);
|
|
1846
|
+
const searchValue = controlledSearchValue !== undefined
|
|
1847
|
+
? controlledSearchValue
|
|
1848
|
+
: uncontrolledSearchValue;
|
|
1849
|
+
const handleSearchChange = (e) => {
|
|
1850
|
+
const newValue = e.target.value;
|
|
1851
|
+
if (controlledSearchValue === undefined) {
|
|
1852
|
+
setUncontrolledSearchValue(newValue);
|
|
1853
|
+
}
|
|
1854
|
+
onSearchChange?.(newValue);
|
|
1855
|
+
// Show dropdown if minimum search length is met
|
|
1856
|
+
if (newValue.length >= minSearchLength) {
|
|
1857
|
+
setIsOpen(true);
|
|
1858
|
+
}
|
|
1859
|
+
else {
|
|
1860
|
+
setIsOpen(false);
|
|
1861
|
+
}
|
|
1862
|
+
};
|
|
1863
|
+
const handleFocus = () => {
|
|
1864
|
+
if (showOnFocus && searchValue.length >= minSearchLength) {
|
|
1865
|
+
setIsOpen(true);
|
|
1866
|
+
}
|
|
1867
|
+
};
|
|
1868
|
+
const handleItemSelect = (item) => {
|
|
1869
|
+
onItemSelect?.(item);
|
|
1870
|
+
if (controlledSearchValue === undefined) {
|
|
1871
|
+
setUncontrolledSearchValue(item.value || item.title);
|
|
1872
|
+
}
|
|
1873
|
+
setIsOpen(false);
|
|
1874
|
+
inputRef.current?.focus();
|
|
1875
|
+
};
|
|
1876
|
+
// Filter items based on search
|
|
1877
|
+
const filteredItems = React__namespace.useMemo(() => {
|
|
1878
|
+
if (!searchValue)
|
|
1879
|
+
return items;
|
|
1880
|
+
return items.filter((item) => filterFunction(item, searchValue));
|
|
1881
|
+
}, [items, searchValue, filterFunction]);
|
|
1882
|
+
// Close dropdown when clicking outside
|
|
1883
|
+
React__namespace.useEffect(() => {
|
|
1884
|
+
const handleClickOutside = (event) => {
|
|
1885
|
+
if (dropdownRef.current &&
|
|
1886
|
+
!dropdownRef.current.contains(event.target)) {
|
|
1887
|
+
setIsOpen(false);
|
|
1888
|
+
}
|
|
1889
|
+
};
|
|
1890
|
+
if (isOpen) {
|
|
1891
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1892
|
+
return () => {
|
|
1893
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1896
|
+
}, [isOpen]);
|
|
1897
|
+
// Handle keyboard navigation
|
|
1898
|
+
const handleKeyDown = (e) => {
|
|
1899
|
+
if (!isOpen) {
|
|
1900
|
+
if (e.key === "ArrowDown" || e.key === "Enter") {
|
|
1901
|
+
setIsOpen(true);
|
|
1902
|
+
e.preventDefault();
|
|
1903
|
+
}
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1906
|
+
switch (e.key) {
|
|
1907
|
+
case "ArrowDown":
|
|
1908
|
+
e.preventDefault();
|
|
1909
|
+
setFocusedIndex((prev) => prev < filteredItems.length - 1 ? prev + 1 : prev);
|
|
1910
|
+
break;
|
|
1911
|
+
case "ArrowUp":
|
|
1912
|
+
e.preventDefault();
|
|
1913
|
+
setFocusedIndex((prev) => (prev > 0 ? prev - 1 : -1));
|
|
1914
|
+
break;
|
|
1915
|
+
case "Enter":
|
|
1916
|
+
e.preventDefault();
|
|
1917
|
+
if (focusedIndex >= 0 && filteredItems[focusedIndex]) {
|
|
1918
|
+
handleItemSelect(filteredItems[focusedIndex]);
|
|
1919
|
+
}
|
|
1920
|
+
break;
|
|
1921
|
+
case "Escape":
|
|
1922
|
+
e.preventDefault();
|
|
1923
|
+
setIsOpen(false);
|
|
1924
|
+
setFocusedIndex(-1);
|
|
1925
|
+
break;
|
|
1926
|
+
}
|
|
1927
|
+
};
|
|
1928
|
+
// Update items with onClick handlers that call handleItemSelect
|
|
1929
|
+
const itemsWithHandlers = filteredItems.map((item) => ({
|
|
1930
|
+
...item,
|
|
1931
|
+
onClick: () => handleItemSelect(item),
|
|
1932
|
+
}));
|
|
1933
|
+
const showDropdown = isOpen && searchValue.length >= minSearchLength;
|
|
1934
|
+
return (jsxRuntime.jsxs("div", { ref: dropdownRef, className: cn("relative", containerClassName), children: [jsxRuntime.jsx(TextField, { ref: inputRef, value: searchValue, onChange: handleSearchChange, onFocus: handleFocus, onKeyDown: handleKeyDown, containerClassName: "mb-0", ...textFieldProps }), showDropdown && (jsxRuntime.jsx(DropdownMenu, { items: itemsWithHandlers, sectionHeading: sectionHeading, isLoading: isLoading, isEmpty: filteredItems.length === 0, emptyTitle: emptyTitle, emptyDescription: emptyDescription, emptyLinkText: emptyLinkText, onEmptyLinkClick: onEmptyLinkClick, primaryButtonText: primaryButtonText, secondaryButtonText: secondaryButtonText, onPrimaryClick: onPrimaryClick, onSecondaryClick: onSecondaryClick, showChevron: showChevron, emptyIcon: emptyIcon, disableFooter: disableFooter, onClose: () => setIsOpen(false), focusedIndex: focusedIndex, className: cn("absolute z-50 mt-2", dropdownClassName), width: dropdownWidth === "full" ? "full" : "auto" }))] }));
|
|
1935
|
+
});
|
|
1936
|
+
SearchableDropdown.displayName = "SearchableDropdown";
|
|
1937
|
+
|
|
1641
1938
|
const switchVariants = classVarianceAuthority.cva("relative inline-flex items-center shrink-0 cursor-pointer rounded-full transition-all duration-200", {
|
|
1642
1939
|
variants: {
|
|
1643
1940
|
size: {
|
|
@@ -1980,121 +2277,20 @@ const TextArea = React__namespace.forwardRef(({ label, helperText, errorText, su
|
|
|
1980
2277
|
});
|
|
1981
2278
|
TextArea.displayName = "TextArea";
|
|
1982
2279
|
|
|
1983
|
-
const textFieldVariants = classVarianceAuthority.cva("relative flex items-center gap-2 border rounded-medium transition-all font-display font-size-100 leading-100", {
|
|
1984
|
-
variants: {
|
|
1985
|
-
size: {
|
|
1986
|
-
small: "h-[28px] px-3 text-xs gap-2",
|
|
1987
|
-
medium: "h-[36px] px-4 text-sm gap-2",
|
|
1988
|
-
large: "h-[44px] px-5 text-base gap-3",
|
|
1989
|
-
},
|
|
1990
|
-
validationState: {
|
|
1991
|
-
none: `
|
|
1992
|
-
border-action-outline-neutral-faded
|
|
1993
|
-
hover:border-action-outline-primary-hover
|
|
1994
|
-
focus-within:border-action-outline-primary-hover
|
|
1995
|
-
focus-within:ring-2
|
|
1996
|
-
ring-action-outline-primary-faded-hover`,
|
|
1997
|
-
positive: `
|
|
1998
|
-
border-action-outline-positive-default
|
|
1999
|
-
focus-within:border-action-outline-positive-hover
|
|
2000
|
-
focus-within:ring-2
|
|
2001
|
-
ring-action-outline-positive-faded-hover`,
|
|
2002
|
-
negative: `border-action-outline-negative-default
|
|
2003
|
-
focus-within:border-action-outline-negative-hover
|
|
2004
|
-
focus-within:ring-2
|
|
2005
|
-
ring-action-outline-negative-faded-hover`,
|
|
2006
|
-
},
|
|
2007
|
-
isDisabled: {
|
|
2008
|
-
true: `
|
|
2009
|
-
border-[var(--border-width-thinner)]
|
|
2010
|
-
hover:border-action-outline-neutral-disabled
|
|
2011
|
-
border-action-outline-neutral-disabled
|
|
2012
|
-
bg-surface-fill-neutral-intense cursor-not-allowed opacity-60`,
|
|
2013
|
-
false: "bg-surface-fill-neutral-intense",
|
|
2014
|
-
},
|
|
2015
|
-
},
|
|
2016
|
-
defaultVariants: {
|
|
2017
|
-
size: "medium",
|
|
2018
|
-
validationState: "none",
|
|
2019
|
-
isDisabled: false,
|
|
2020
|
-
},
|
|
2021
|
-
});
|
|
2022
|
-
const TextField = React__namespace.forwardRef(({ label, helperText, errorText, successText, size = "medium", validationState = "none", isDisabled = false, isRequired = false, isOptional = false, prefix, suffix, showClearButton = false, infoDescription, infoHeading, linkText, linkHref, onLinkClick, onClear, containerClassName, labelClassName, inputClassName, className, value, onChange, ...props }, ref) => {
|
|
2023
|
-
const [internalValue, setInternalValue] = React__namespace.useState("");
|
|
2024
|
-
const inputValue = value !== undefined ? value : internalValue;
|
|
2025
|
-
const hasValue = inputValue && String(inputValue).length > 0;
|
|
2026
|
-
const handleChange = (e) => {
|
|
2027
|
-
if (onChange) {
|
|
2028
|
-
onChange(e);
|
|
2029
|
-
}
|
|
2030
|
-
else {
|
|
2031
|
-
setInternalValue(e.target.value);
|
|
2032
|
-
}
|
|
2033
|
-
};
|
|
2034
|
-
const handleClear = () => {
|
|
2035
|
-
if (onClear) {
|
|
2036
|
-
onClear();
|
|
2037
|
-
}
|
|
2038
|
-
else {
|
|
2039
|
-
setInternalValue("");
|
|
2040
|
-
}
|
|
2041
|
-
// Focus the input after clearing
|
|
2042
|
-
const input = document.getElementById(props.id || "");
|
|
2043
|
-
if (input) {
|
|
2044
|
-
input.focus();
|
|
2045
|
-
}
|
|
2046
|
-
};
|
|
2047
|
-
// Determine which helper text to show
|
|
2048
|
-
const displayHelperText = errorText || successText || helperText;
|
|
2049
|
-
const currentValidationState = errorText
|
|
2050
|
-
? "negative"
|
|
2051
|
-
: successText
|
|
2052
|
-
? "positive"
|
|
2053
|
-
: validationState;
|
|
2054
|
-
const sizeConfig = {
|
|
2055
|
-
small: {
|
|
2056
|
-
gap: "gap-2",
|
|
2057
|
-
},
|
|
2058
|
-
medium: {
|
|
2059
|
-
gap: "gap-2",
|
|
2060
|
-
},
|
|
2061
|
-
large: {
|
|
2062
|
-
gap: "gap-3",
|
|
2063
|
-
},
|
|
2064
|
-
};
|
|
2065
|
-
return (jsxRuntime.jsxs("div", { className: cn("w-full flex flex-col", sizeConfig[size].gap, containerClassName), children: [label && (jsxRuntime.jsx(FormHeader, { label: label, size: size, isRequired: isRequired, isOptional: isOptional, infoHeading: infoHeading, infoDescription: infoDescription, linkText: linkText, linkHref: linkHref, onLinkClick: onLinkClick, htmlFor: props.id, className: "mb-2", labelClassName: labelClassName })), jsxRuntime.jsxs("div", { className: cn(textFieldVariants({
|
|
2066
|
-
size,
|
|
2067
|
-
validationState: currentValidationState,
|
|
2068
|
-
isDisabled,
|
|
2069
|
-
}), className), children: [prefix && (jsxRuntime.jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
2070
|
-
? "text-surface-ink-neutral-disabled"
|
|
2071
|
-
: currentValidationState === "positive"
|
|
2072
|
-
? "text-feedback-ink-positive-intense"
|
|
2073
|
-
: currentValidationState === "negative"
|
|
2074
|
-
? "text-feedback-ink-negative-subtle"
|
|
2075
|
-
: "text-surface-ink-neutral-muted"), children: prefix })), jsxRuntime.jsx("input", { ref: ref, value: inputValue, onChange: handleChange, disabled: isDisabled, required: isRequired, className: cn("flex-1 bg-transparent border-none outline-none text-surface-ink-neutral-normal placeholder:text-surface-ink-neutral-muted disabled:cursor-not-allowed disabled:text-surface-ink-neutral-disabled font-display", inputClassName), ...props }), showClearButton && hasValue && !isDisabled && (jsxRuntime.jsx("button", { type: "button", onClick: handleClear, className: "shrink-0 flex items-center justify-center text-surface-ink-neutral-muted hover:text-surface-ink-neutral-normal transition-colors", tabIndex: -1, children: jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsxRuntime.jsx("path", { d: "M12 4L4 12M4 4L12 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })), suffix && (jsxRuntime.jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
2076
|
-
? "text-surface-ink-neutral-disabled"
|
|
2077
|
-
: currentValidationState === "positive"
|
|
2078
|
-
? "text-feedback-ink-positive-intense"
|
|
2079
|
-
: currentValidationState === "negative"
|
|
2080
|
-
? "text-feedback-ink-negative-subtle"
|
|
2081
|
-
: "text-surface-ink-neutral-muted"), children: suffix }))] }), jsxRuntime.jsx(FormFooter, { helperText: displayHelperText, validationState: currentValidationState === "none"
|
|
2082
|
-
? "default"
|
|
2083
|
-
: currentValidationState, size: size, isDisabled: isDisabled, className: "mt-1" })] }));
|
|
2084
|
-
});
|
|
2085
|
-
TextField.displayName = "TextField";
|
|
2086
|
-
|
|
2087
2280
|
exports.Badge = Badge;
|
|
2088
2281
|
exports.Button = Button;
|
|
2089
2282
|
exports.Checkbox = Checkbox;
|
|
2090
2283
|
exports.Counter = Counter;
|
|
2091
2284
|
exports.Divider = Divider;
|
|
2285
|
+
exports.Dropdown = Dropdown;
|
|
2286
|
+
exports.DropdownMenu = DropdownMenu;
|
|
2092
2287
|
exports.FormFooter = FormFooter;
|
|
2093
2288
|
exports.FormHeader = FormHeader;
|
|
2094
2289
|
exports.Icon = Icon;
|
|
2095
2290
|
exports.Link = Link;
|
|
2096
2291
|
exports.ListItem = ListItem;
|
|
2097
2292
|
exports.Radio = Radio;
|
|
2293
|
+
exports.SearchableDropdown = SearchableDropdown;
|
|
2098
2294
|
exports.Switch = Switch;
|
|
2099
2295
|
exports.TabItem = TabItem;
|
|
2100
2296
|
exports.Tabs = Tabs;
|
|
@@ -2107,6 +2303,7 @@ exports.buttonVariants = buttonVariants;
|
|
|
2107
2303
|
exports.checkboxVariants = checkboxVariants;
|
|
2108
2304
|
exports.cn = cn;
|
|
2109
2305
|
exports.counterVariants = counterVariants;
|
|
2306
|
+
exports.dropdownVariants = dropdownVariants;
|
|
2110
2307
|
exports.getAvailableIcons = getAvailableIcons;
|
|
2111
2308
|
exports.hasIcon = hasIcon;
|
|
2112
2309
|
exports.iconRegistry = iconRegistry;
|