infinity-ui-elements 1.8.58 → 1.8.60
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/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/Select/Select.d.ts +1 -7
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/index.d.ts +1 -1
- package/dist/components/Select/index.d.ts.map +1 -1
- package/dist/components/TextField/TextField.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.esm.js +151 -225
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +149 -224
- package/dist/index.js.map +1 -1
- package/dist/lib/icons.d.ts +2 -0
- package/dist/lib/icons.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Slot } from '@radix-ui/react-slot';
|
|
|
5
5
|
import { PulseLoader, ClipLoader } from 'react-spinners';
|
|
6
6
|
import { clsx } from 'clsx';
|
|
7
7
|
import { twMerge } from 'tailwind-merge';
|
|
8
|
-
import { ExternalLink, Calendar, X, Loader2, Search,
|
|
8
|
+
import { ExternalLink, Calendar, X, Loader2, Search, ChevronLeft, ChevronRight, ChevronDown } from 'lucide-react';
|
|
9
9
|
import { createPortal } from 'react-dom';
|
|
10
10
|
import Calendar$1 from 'react-calendar';
|
|
11
11
|
import 'react-calendar/dist/Calendar.css';
|
|
@@ -38,9 +38,10 @@ import { flexRender } from '@tanstack/react-table';
|
|
|
38
38
|
*/
|
|
39
39
|
const iconRegistry = {
|
|
40
40
|
// Tick/Check icon
|
|
41
|
-
tick: `<svg width="
|
|
42
|
-
<path d="
|
|
43
|
-
</svg
|
|
41
|
+
tick: `<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
42
|
+
<path d="M7.99907 1.77063L8.63188 2.42981L8.69829 2.49915L8.63188 2.56848L3.88188 7.50891L3.80962 7.58411L3.73833 7.50891L0.887741 4.54504L0.821335 4.47571L0.887741 4.40637L1.52153 3.74719L1.5938 3.672L1.66508 3.74719L3.80962 5.97766L7.85454 1.77063L7.9268 1.69543L7.99907 1.77063Z" fill="white" stroke="white" stroke-width="0.2"/>
|
|
43
|
+
</svg>
|
|
44
|
+
`,
|
|
44
45
|
// Alias: check points to the same icon as tick
|
|
45
46
|
check: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
46
47
|
<path d="M10.364 15.1924L19.5564 6L20.9706 7.41421L10.364 18.0208L4 11.6569L5.41422 10.2427L10.364 15.1924Z" fill="#081416"/>
|
|
@@ -68,6 +69,14 @@ const iconRegistry = {
|
|
|
68
69
|
file: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
69
70
|
<path d="M19.1111 21H4.88889C4.39797 21 4 20.5971 4 20.1V3.9C4 3.40295 4.39797 3 4.88889 3H19.1111C19.602 3 20 3.40295 20 3.9V20.1C20 20.5971 19.602 21 19.1111 21ZM18.2222 19.2V4.8H5.77778V19.2H18.2222ZM8.44444 9.3H15.5556V11.1H8.44444V9.3ZM8.44444 12.9H15.5556V14.7H8.44444V12.9Z" fill="#081416"/>
|
|
70
71
|
</svg>
|
|
72
|
+
`,
|
|
73
|
+
chevronDown: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
74
|
+
<path d="M12 13.7272L17.4445 8L19 9.63635L12 17L5 9.63635L6.55555 8L12 13.7272Z" fill="#081416"/>
|
|
75
|
+
</svg>
|
|
76
|
+
`,
|
|
77
|
+
chevronUp: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
78
|
+
<path d="M12 11.2727L6.55555 17L5 15.3637L12 8L19 15.3637L17.4445 17L12 11.2727Z" fill="#081416"/>
|
|
79
|
+
</svg>
|
|
71
80
|
`,
|
|
72
81
|
};
|
|
73
82
|
const Icon = ({ name, size = 24, className = "", style = {}, ...props }) => {
|
|
@@ -1485,9 +1494,9 @@ FormFooter.displayName = "FormFooter";
|
|
|
1485
1494
|
const checkboxVariants = cva("relative inline-flex items-center justify-center shrink-0 transition-all cursor-pointer box-border", {
|
|
1486
1495
|
variants: {
|
|
1487
1496
|
size: {
|
|
1488
|
-
small: "w-[
|
|
1489
|
-
medium: "w-[
|
|
1490
|
-
large: "w-[
|
|
1497
|
+
small: "w-[14px] h-[14px] rounded-small border-[1.5px]",
|
|
1498
|
+
medium: "w-[16px] h-[16px] rounded-small border-[1.5px]",
|
|
1499
|
+
large: "w-[20px] h-[20px] rounded-medium border-[2px]",
|
|
1491
1500
|
},
|
|
1492
1501
|
validationState: {
|
|
1493
1502
|
none: "",
|
|
@@ -1555,7 +1564,6 @@ const Checkbox = React.forwardRef(({ label, errorText, size = "medium", validati
|
|
|
1555
1564
|
const [internalChecked, setInternalChecked] = React.useState(false);
|
|
1556
1565
|
const [showRipple, setShowRipple] = React.useState(false);
|
|
1557
1566
|
const inputRef = React.useRef(null);
|
|
1558
|
-
const rippleTimeoutRef = React.useRef(null);
|
|
1559
1567
|
// Use forwarded ref or internal ref
|
|
1560
1568
|
React.useImperativeHandle(ref, () => inputRef.current);
|
|
1561
1569
|
const isChecked = checked !== undefined ? checked : internalChecked;
|
|
@@ -1565,14 +1573,6 @@ const Checkbox = React.forwardRef(({ label, errorText, size = "medium", validati
|
|
|
1565
1573
|
inputRef.current.indeterminate = isIndeterminate;
|
|
1566
1574
|
}
|
|
1567
1575
|
}, [isIndeterminate]);
|
|
1568
|
-
// Cleanup timeout on unmount
|
|
1569
|
-
React.useEffect(() => {
|
|
1570
|
-
return () => {
|
|
1571
|
-
if (rippleTimeoutRef.current) {
|
|
1572
|
-
clearTimeout(rippleTimeoutRef.current);
|
|
1573
|
-
}
|
|
1574
|
-
};
|
|
1575
|
-
}, []);
|
|
1576
1576
|
const handleChange = (e) => {
|
|
1577
1577
|
if (onChange) {
|
|
1578
1578
|
onChange(e);
|
|
@@ -1582,28 +1582,31 @@ const Checkbox = React.forwardRef(({ label, errorText, size = "medium", validati
|
|
|
1582
1582
|
}
|
|
1583
1583
|
};
|
|
1584
1584
|
const triggerRipple = () => {
|
|
1585
|
-
if (!isDisabled
|
|
1586
|
-
// Clear any existing timeout
|
|
1587
|
-
if (rippleTimeoutRef.current) {
|
|
1588
|
-
clearTimeout(rippleTimeoutRef.current);
|
|
1589
|
-
}
|
|
1585
|
+
if (!isDisabled) {
|
|
1590
1586
|
setShowRipple(true);
|
|
1591
|
-
|
|
1587
|
+
setTimeout(() => {
|
|
1592
1588
|
setShowRipple(false);
|
|
1593
|
-
|
|
1594
|
-
}, 400); // Match animation duration (0.4s)
|
|
1589
|
+
}, 360); // Match animation duration (0.36s)
|
|
1595
1590
|
}
|
|
1596
1591
|
};
|
|
1597
1592
|
const handleContainerClick = () => {
|
|
1598
1593
|
if (!isDisabled && inputRef.current) {
|
|
1599
|
-
|
|
1594
|
+
// Only show ripple when checking or entering indeterminate state (not unchecking)
|
|
1595
|
+
const willBeChecked = !isChecked || isIndeterminate;
|
|
1596
|
+
if (willBeChecked) {
|
|
1597
|
+
triggerRipple();
|
|
1598
|
+
}
|
|
1600
1599
|
inputRef.current.click();
|
|
1601
1600
|
}
|
|
1602
1601
|
};
|
|
1603
1602
|
const handleKeyDown = (e) => {
|
|
1604
1603
|
if ((e.key === " " || e.key === "Enter") && !isDisabled) {
|
|
1605
1604
|
e.preventDefault();
|
|
1606
|
-
|
|
1605
|
+
// Only show ripple when checking or entering indeterminate state (not unchecking)
|
|
1606
|
+
const willBeChecked = !isChecked || isIndeterminate;
|
|
1607
|
+
if (willBeChecked) {
|
|
1608
|
+
triggerRipple();
|
|
1609
|
+
}
|
|
1607
1610
|
inputRef.current?.click();
|
|
1608
1611
|
}
|
|
1609
1612
|
};
|
|
@@ -1612,23 +1615,23 @@ const Checkbox = React.forwardRef(({ label, errorText, size = "medium", validati
|
|
|
1612
1615
|
small: {
|
|
1613
1616
|
gap: "gap-2",
|
|
1614
1617
|
labelSize: "text-body-small-regular",
|
|
1615
|
-
iconSize:
|
|
1618
|
+
iconSize: 7,
|
|
1616
1619
|
},
|
|
1617
1620
|
medium: {
|
|
1618
1621
|
gap: "gap-2",
|
|
1619
1622
|
labelSize: "text-body-small-regular",
|
|
1620
|
-
iconSize:
|
|
1623
|
+
iconSize: 9.6,
|
|
1621
1624
|
},
|
|
1622
1625
|
large: {
|
|
1623
1626
|
gap: "gap-3",
|
|
1624
1627
|
labelSize: "text-body-medium-regular",
|
|
1625
|
-
iconSize:
|
|
1628
|
+
iconSize: 13.33,
|
|
1626
1629
|
},
|
|
1627
1630
|
};
|
|
1628
1631
|
const config = sizeConfig[size];
|
|
1629
1632
|
// Determine if we should show the error text
|
|
1630
1633
|
const shouldShowError = errorText && showErrorText;
|
|
1631
|
-
return (jsxs("div", { className: cn("inline-flex flex-col
|
|
1634
|
+
return (jsxs("div", { className: cn("inline-flex flex-col py-0.5", containerClassName), children: [jsxs("div", { className: cn("inline-flex items-center", config.gap, isDisabled ? "cursor-not-allowed" : "cursor-pointer"), onClick: handleContainerClick, onKeyDown: handleKeyDown, role: "checkbox", "aria-checked": isIndeterminate ? "mixed" : isChecked, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : 0, children: [jsx("input", { ref: inputRef, type: "checkbox", className: "sr-only", checked: isChecked, onChange: handleChange, disabled: isDisabled, ...props }), jsxs("div", { className: "relative inline-flex shrink-0", children: [showRipple && (jsx("div", { className: cn("absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full pointer-events-none w-full h-full", validationState === "error"
|
|
1632
1635
|
? "bg-action-outline-negative-faded"
|
|
1633
1636
|
: "bg-action-outline-primary-faded"), style: {
|
|
1634
1637
|
animation: "var(--animate-checkbox-ripple)",
|
|
@@ -2830,7 +2833,7 @@ const Modal = React.forwardRef(({ isOpen, onClose, title, description, footer, c
|
|
|
2830
2833
|
});
|
|
2831
2834
|
Modal.displayName = "Modal";
|
|
2832
2835
|
|
|
2833
|
-
const
|
|
2836
|
+
const textFieldVariants = cva("relative flex items-center gap-3 border rounded-large transition-all font-functional font-size-100 leading-100", {
|
|
2834
2837
|
variants: {
|
|
2835
2838
|
size: {
|
|
2836
2839
|
small: "h-[28px] px-3 text-xs gap-2",
|
|
@@ -2840,10 +2843,11 @@ const selectVariants = cva("relative flex items-center gap-2 border rounded-larg
|
|
|
2840
2843
|
validationState: {
|
|
2841
2844
|
none: `
|
|
2842
2845
|
border-action-outline-neutral-faded
|
|
2843
|
-
hover:border-action-outline-
|
|
2844
|
-
|
|
2846
|
+
hover:border-action-outline-neutral-faded-hover
|
|
2847
|
+
hover:bg-action-fill-neutral-faded-hover
|
|
2848
|
+
focus-within:border-action-outline-primary-default
|
|
2845
2849
|
focus-within:ring-2
|
|
2846
|
-
ring-
|
|
2850
|
+
ring-surface-outline-primary-muted`,
|
|
2847
2851
|
positive: `
|
|
2848
2852
|
border-action-outline-positive-default
|
|
2849
2853
|
focus-within:border-action-outline-positive-hover
|
|
@@ -2856,11 +2860,13 @@ const selectVariants = cva("relative flex items-center gap-2 border rounded-larg
|
|
|
2856
2860
|
},
|
|
2857
2861
|
isDisabled: {
|
|
2858
2862
|
true: `
|
|
2859
|
-
border
|
|
2860
|
-
hover:border-action-outline-neutral-disabled
|
|
2863
|
+
border
|
|
2861
2864
|
border-action-outline-neutral-disabled
|
|
2862
|
-
|
|
2863
|
-
|
|
2865
|
+
hover:border-action-outline-neutral-disabled
|
|
2866
|
+
bg-surface-fill-neutral-intense
|
|
2867
|
+
hover:bg-surface-fill-neutral-intense
|
|
2868
|
+
cursor-not-allowed`,
|
|
2869
|
+
false: "",
|
|
2864
2870
|
},
|
|
2865
2871
|
},
|
|
2866
2872
|
defaultVariants: {
|
|
@@ -2869,23 +2875,83 @@ const selectVariants = cva("relative flex items-center gap-2 border rounded-larg
|
|
|
2869
2875
|
isDisabled: false,
|
|
2870
2876
|
},
|
|
2871
2877
|
});
|
|
2878
|
+
const TextField = React.forwardRef(({ label, helperText, errorText, successText, size = "medium", validationState = "none", isDisabled = false, isLoading = false, isRequired = false, isOptional = false, prefix, suffix, showClearButton = false, infoDescription, infoHeading, LinkComponent, linkText, linkHref, onLinkClick, onClear, containerClassName, labelClassName, inputClassName, className, value, onChange, ...props }, ref) => {
|
|
2879
|
+
const [internalValue, setInternalValue] = React.useState("");
|
|
2880
|
+
const inputValue = value !== undefined ? value : internalValue;
|
|
2881
|
+
const hasValue = inputValue && String(inputValue).length > 0;
|
|
2882
|
+
const handleChange = (e) => {
|
|
2883
|
+
if (onChange) {
|
|
2884
|
+
onChange(e);
|
|
2885
|
+
}
|
|
2886
|
+
else {
|
|
2887
|
+
setInternalValue(e.target.value);
|
|
2888
|
+
}
|
|
2889
|
+
};
|
|
2890
|
+
const handleClear = () => {
|
|
2891
|
+
if (onClear) {
|
|
2892
|
+
onClear();
|
|
2893
|
+
}
|
|
2894
|
+
else {
|
|
2895
|
+
setInternalValue("");
|
|
2896
|
+
}
|
|
2897
|
+
// Focus the input after clearing
|
|
2898
|
+
const input = document.getElementById(props.id || "");
|
|
2899
|
+
if (input) {
|
|
2900
|
+
input.focus();
|
|
2901
|
+
}
|
|
2902
|
+
};
|
|
2903
|
+
// Determine which helper text to show
|
|
2904
|
+
const displayHelperText = errorText || successText || helperText;
|
|
2905
|
+
const currentValidationState = errorText
|
|
2906
|
+
? "negative"
|
|
2907
|
+
: successText
|
|
2908
|
+
? "positive"
|
|
2909
|
+
: validationState;
|
|
2910
|
+
const sizeConfig = {
|
|
2911
|
+
small: {
|
|
2912
|
+
gap: "gap-2",
|
|
2913
|
+
},
|
|
2914
|
+
medium: {
|
|
2915
|
+
gap: "gap-2",
|
|
2916
|
+
},
|
|
2917
|
+
large: {
|
|
2918
|
+
gap: "gap-3",
|
|
2919
|
+
},
|
|
2920
|
+
};
|
|
2921
|
+
return (jsxs("div", { className: cn("w-full flex flex-col", sizeConfig[size].gap, containerClassName), children: [label && (jsx(FormHeader, { label: label, size: size, isRequired: isRequired, isOptional: isOptional, infoHeading: infoHeading, infoDescription: infoDescription, LinkComponent: LinkComponent, linkText: linkText, linkHref: linkHref, onLinkClick: onLinkClick, htmlFor: props.id, className: "mb-2", labelClassName: labelClassName })), jsxs("div", { className: cn(textFieldVariants({
|
|
2922
|
+
size,
|
|
2923
|
+
validationState: currentValidationState,
|
|
2924
|
+
isDisabled,
|
|
2925
|
+
}), isLoading && "text-field-loading", className), children: [prefix && (jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
2926
|
+
? "text-surface-ink-neutral-disabled"
|
|
2927
|
+
: currentValidationState === "positive"
|
|
2928
|
+
? "text-feedback-ink-positive-intense"
|
|
2929
|
+
: currentValidationState === "negative"
|
|
2930
|
+
? "text-feedback-ink-negative-subtle"
|
|
2931
|
+
: "text-surface-ink-neutral-muted"), children: prefix })), 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", inputClassName), ...props }), showClearButton && hasValue && !isDisabled && (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: jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M12 4L4 12M4 4L12 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })), suffix && (jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
2932
|
+
? "text-surface-ink-neutral-disabled"
|
|
2933
|
+
: currentValidationState === "positive"
|
|
2934
|
+
? "text-feedback-ink-positive-intense"
|
|
2935
|
+
: currentValidationState === "negative"
|
|
2936
|
+
? "text-feedback-ink-negative-subtle"
|
|
2937
|
+
: "text-surface-ink-neutral-muted"), children: suffix }))] }), jsx(FormFooter, { helperText: displayHelperText, validationState: currentValidationState === "none"
|
|
2938
|
+
? "default"
|
|
2939
|
+
: currentValidationState, size: size, isDisabled: isDisabled, className: "mt-1" })] }));
|
|
2940
|
+
});
|
|
2941
|
+
TextField.displayName = "TextField";
|
|
2942
|
+
|
|
2872
2943
|
const Select = React.forwardRef(({ className, options = [], value: controlledValue, defaultValue, onChange, placeholder = "Select an option", label, helperText, errorText, successText, validationState = "none", isDisabled = false, isRequired = false, isOptional = false, isLoading = false, size = "medium", prefix, suffix, showClearButton = false, onClear, showLeadingIcon = false, containerClassName, labelClassName, triggerClassName, menuClassName, menuWidth = "full", sectionHeading, emptyTitle = "No options available", emptyDescription = "There are no options to select from.", emptyIcon, infoHeading, infoDescription, LinkComponent, linkText, linkHref, onLinkClick, ...props }, ref) => {
|
|
2873
2944
|
const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
|
|
2874
2945
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
2875
2946
|
const [dropdownPlacement, setDropdownPlacement] = React.useState("bottom");
|
|
2876
|
-
const
|
|
2947
|
+
const containerRef = React.useRef(null);
|
|
2877
2948
|
const dropdownContainerRef = React.useRef(null);
|
|
2949
|
+
const inputRef = React.useRef(null);
|
|
2950
|
+
React.useImperativeHandle(ref, () => inputRef.current);
|
|
2878
2951
|
const value = controlledValue !== undefined ? controlledValue : uncontrolledValue;
|
|
2879
2952
|
// Find the selected option
|
|
2880
2953
|
const selectedOption = options.find((opt) => opt.value === value);
|
|
2881
2954
|
const hasValue = value !== undefined && value !== "";
|
|
2882
|
-
// Determine which helper text to show
|
|
2883
|
-
const displayHelperText = errorText || successText || helperText;
|
|
2884
|
-
const currentValidationState = errorText
|
|
2885
|
-
? "negative"
|
|
2886
|
-
: successText
|
|
2887
|
-
? "positive"
|
|
2888
|
-
: validationState;
|
|
2889
2955
|
const handleOpenChange = (newOpen) => {
|
|
2890
2956
|
if (!isDisabled && !isLoading) {
|
|
2891
2957
|
setIsOpen(newOpen);
|
|
@@ -2900,9 +2966,9 @@ const Select = React.forwardRef(({ className, options = [], value: controlledVal
|
|
|
2900
2966
|
}
|
|
2901
2967
|
onChange?.(option.value, option);
|
|
2902
2968
|
setIsOpen(false);
|
|
2969
|
+
inputRef.current?.focus();
|
|
2903
2970
|
};
|
|
2904
|
-
const handleClear = (
|
|
2905
|
-
e.stopPropagation();
|
|
2971
|
+
const handleClear = () => {
|
|
2906
2972
|
if (onClear) {
|
|
2907
2973
|
onClear();
|
|
2908
2974
|
}
|
|
@@ -2916,7 +2982,7 @@ const Select = React.forwardRef(({ className, options = [], value: controlledVal
|
|
|
2916
2982
|
const updateDropdownPlacement = React.useCallback(() => {
|
|
2917
2983
|
if (typeof window === "undefined")
|
|
2918
2984
|
return;
|
|
2919
|
-
const trigger =
|
|
2985
|
+
const trigger = containerRef.current;
|
|
2920
2986
|
if (!trigger)
|
|
2921
2987
|
return;
|
|
2922
2988
|
const triggerRect = trigger.getBoundingClientRect();
|
|
@@ -2965,8 +3031,10 @@ const Select = React.forwardRef(({ className, options = [], value: controlledVal
|
|
|
2965
3031
|
// Close dropdown when clicking outside
|
|
2966
3032
|
React.useEffect(() => {
|
|
2967
3033
|
const handleClickOutside = (event) => {
|
|
2968
|
-
if (
|
|
2969
|
-
!
|
|
3034
|
+
if (containerRef.current &&
|
|
3035
|
+
!containerRef.current.contains(event.target) &&
|
|
3036
|
+
dropdownContainerRef.current &&
|
|
3037
|
+
!dropdownContainerRef.current.contains(event.target)) {
|
|
2970
3038
|
handleOpenChange(false);
|
|
2971
3039
|
}
|
|
2972
3040
|
};
|
|
@@ -2992,35 +3060,27 @@ const Select = React.forwardRef(({ className, options = [], value: controlledVal
|
|
|
2992
3060
|
}
|
|
2993
3061
|
}, [isOpen]);
|
|
2994
3062
|
// Handle keyboard navigation
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3063
|
+
const handleKeyDown = (event) => {
|
|
3064
|
+
if (isDisabled || isLoading)
|
|
3065
|
+
return;
|
|
3066
|
+
if (!isOpen && (event.key === "Enter" || event.key === " ")) {
|
|
3067
|
+
event.preventDefault();
|
|
3068
|
+
setIsOpen(true);
|
|
3069
|
+
return;
|
|
3070
|
+
}
|
|
3071
|
+
if (isOpen) {
|
|
3072
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
3000
3073
|
event.preventDefault();
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
if (
|
|
3006
|
-
|
|
3007
|
-
const currentIndex = options.findIndex((opt) => opt.value === value);
|
|
3008
|
-
const nextIndex = event.key === "ArrowDown"
|
|
3009
|
-
? Math.min(currentIndex + 1, options.length - 1)
|
|
3010
|
-
: Math.max(currentIndex - 1, 0);
|
|
3011
|
-
if (options[nextIndex] && !options[nextIndex].isDisabled) {
|
|
3012
|
-
handleSelect(options[nextIndex]);
|
|
3013
|
-
}
|
|
3074
|
+
const currentIndex = options.findIndex((opt) => opt.value === value);
|
|
3075
|
+
const nextIndex = event.key === "ArrowDown"
|
|
3076
|
+
? Math.min(currentIndex + 1, options.length - 1)
|
|
3077
|
+
: Math.max(currentIndex - 1, 0);
|
|
3078
|
+
if (options[nextIndex] && !options[nextIndex].isDisabled) {
|
|
3079
|
+
handleSelect(options[nextIndex]);
|
|
3014
3080
|
}
|
|
3015
3081
|
}
|
|
3016
|
-
};
|
|
3017
|
-
if (selectRef.current) {
|
|
3018
|
-
selectRef.current.addEventListener("keydown", handleKeyDown);
|
|
3019
|
-
return () => {
|
|
3020
|
-
selectRef.current?.removeEventListener("keydown", handleKeyDown);
|
|
3021
|
-
};
|
|
3022
3082
|
}
|
|
3023
|
-
}
|
|
3083
|
+
};
|
|
3024
3084
|
// Transform options to dropdown menu items
|
|
3025
3085
|
const menuItems = options.map((option) => ({
|
|
3026
3086
|
value: option.value,
|
|
@@ -3033,50 +3093,20 @@ const Select = React.forwardRef(({ className, options = [], value: controlledVal
|
|
|
3033
3093
|
onClick: () => handleSelect(option),
|
|
3034
3094
|
}));
|
|
3035
3095
|
const widthStyle = menuWidth === "full" ? "100%" : menuWidth === "auto" ? "auto" : menuWidth;
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
};
|
|
3047
|
-
return (jsxs("div", {
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
isDisabled,
|
|
3051
|
-
}), "relative w-full cursor-pointer", className), onClick: !isDisabled && !isLoading ? toggleOpen : undefined, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-disabled": isDisabled, ...props, children: [prefix ? (jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
3052
|
-
? "text-surface-ink-neutral-disabled"
|
|
3053
|
-
: currentValidationState === "positive"
|
|
3054
|
-
? "text-feedback-ink-positive-intense"
|
|
3055
|
-
: currentValidationState === "negative"
|
|
3056
|
-
? "text-feedback-ink-negative-subtle"
|
|
3057
|
-
: "text-surface-ink-neutral-muted"), children: prefix })) : showLeadingIcon && selectedOption?.leadingIcon ? (jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
3058
|
-
? "text-surface-ink-neutral-disabled"
|
|
3059
|
-
: currentValidationState === "positive"
|
|
3060
|
-
? "text-feedback-ink-positive-intense"
|
|
3061
|
-
: currentValidationState === "negative"
|
|
3062
|
-
? "text-feedback-ink-negative-subtle"
|
|
3063
|
-
: "text-surface-ink-neutral-muted"), children: selectedOption.leadingIcon })) : null, jsx("span", { className: cn("flex-1 text-left truncate", !selectedOption && "text-surface-ink-neutral-muted", isDisabled && "text-surface-ink-neutral-disabled"), children: isLoading ? "Loading..." : selectedOption?.label || placeholder }), showClearButton && hasValue && !isDisabled && !isLoading && (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: jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M12 4L4 12M4 4L12 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })), suffix && !showClearButton && (jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
3064
|
-
? "text-surface-ink-neutral-disabled"
|
|
3065
|
-
: currentValidationState === "positive"
|
|
3066
|
-
? "text-feedback-ink-positive-intense"
|
|
3067
|
-
: currentValidationState === "negative"
|
|
3068
|
-
? "text-feedback-ink-negative-subtle"
|
|
3069
|
-
: "text-surface-ink-neutral-muted"), children: suffix })), jsx(ChevronDown, { className: cn("shrink-0 w-4 h-4 transition-transform", isDisabled
|
|
3070
|
-
? "text-surface-ink-neutral-disabled"
|
|
3071
|
-
: currentValidationState === "positive"
|
|
3072
|
-
? "text-feedback-ink-positive-intense"
|
|
3073
|
-
: currentValidationState === "negative"
|
|
3074
|
-
? "text-feedback-ink-negative-subtle"
|
|
3075
|
-
: "text-surface-ink-neutral-muted", isOpen && "transform rotate-180") }), isOpen && !isDisabled && !isLoading && (jsx("div", { ref: dropdownContainerRef, className: cn("absolute z-50 left-0 right-0", dropdownPlacement === "bottom"
|
|
3076
|
-
? "top-full mt-1"
|
|
3077
|
-
: "bottom-full mb-1"), children: jsx(DropdownMenu, { ref: ref, items: menuItems, sectionHeading: sectionHeading, isEmpty: options.length === 0, emptyTitle: emptyTitle, emptyDescription: emptyDescription, emptyIcon: emptyIcon, disableFooter: true, onClose: () => handleOpenChange(false), className: menuClassName, width: widthStyle }) }))] }), jsx(FormFooter, { helperText: displayHelperText, validationState: currentValidationState === "none"
|
|
3078
|
-
? "default"
|
|
3079
|
-
: currentValidationState, size: size, isDisabled: isDisabled, className: "mt-1" })] }));
|
|
3096
|
+
// Get the display value for the TextField
|
|
3097
|
+
const displayValue = isLoading ? "Loading..." : selectedOption?.label || "";
|
|
3098
|
+
// Build the prefix: either provided prefix or selected option's leadingIcon
|
|
3099
|
+
const displayPrefix = prefix
|
|
3100
|
+
? prefix
|
|
3101
|
+
: showLeadingIcon && selectedOption?.leadingIcon
|
|
3102
|
+
? selectedOption.leadingIcon
|
|
3103
|
+
: undefined;
|
|
3104
|
+
// Build the suffix: include both the optional suffix and the chevron icon
|
|
3105
|
+
const chevronIcon = (jsx(Icon, { name: isOpen ? "chevronUp" : "chevronDown", size: 16, className: "shrink-0 transition-colors" }));
|
|
3106
|
+
const displaySuffix = suffix ? (jsxs(Fragment, { children: [suffix, chevronIcon] })) : (chevronIcon);
|
|
3107
|
+
return (jsxs("div", { ref: containerRef, className: "relative", children: [jsx(TextField, { ref: inputRef, label: label, helperText: helperText, errorText: errorText, successText: successText, validationState: validationState, isDisabled: isDisabled, isRequired: isRequired, isOptional: isOptional, isLoading: isLoading, size: size, prefix: displayPrefix, suffix: displaySuffix, showClearButton: showClearButton && hasValue && !isLoading, onClear: handleClear, placeholder: placeholder, value: displayValue, readOnly: true, containerClassName: containerClassName, labelClassName: labelClassName, className: cn("cursor-pointer", triggerClassName, className), inputClassName: "cursor-pointer", infoHeading: infoHeading, infoDescription: infoDescription, LinkComponent: LinkComponent, linkText: linkText, linkHref: linkHref, onLinkClick: onLinkClick, onClick: toggleOpen, onKeyDown: handleKeyDown, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": isOpen, ...props }), isOpen && !isDisabled && !isLoading && (jsx("div", { ref: dropdownContainerRef, className: cn("absolute z-50 left-0 right-0", dropdownPlacement === "bottom"
|
|
3108
|
+
? "top-full mt-1"
|
|
3109
|
+
: "bottom-full mb-1"), children: jsx(DropdownMenu, { items: menuItems, sectionHeading: sectionHeading, isEmpty: options.length === 0, emptyTitle: emptyTitle, emptyDescription: emptyDescription, emptyIcon: emptyIcon, disableFooter: true, onClose: () => handleOpenChange(false), className: menuClassName, width: widthStyle }) }))] }));
|
|
3080
3110
|
});
|
|
3081
3111
|
Select.displayName = "Select";
|
|
3082
3112
|
|
|
@@ -3504,110 +3534,6 @@ const RadioGroup = React.forwardRef(({ value: controlledValue, defaultValue, onC
|
|
|
3504
3534
|
});
|
|
3505
3535
|
RadioGroup.displayName = "RadioGroup";
|
|
3506
3536
|
|
|
3507
|
-
const textFieldVariants = cva("relative flex items-center gap-2 border rounded-large transition-all font-functional font-size-100 leading-100", {
|
|
3508
|
-
variants: {
|
|
3509
|
-
size: {
|
|
3510
|
-
small: "h-[28px] px-3 text-xs gap-2",
|
|
3511
|
-
medium: "h-[36px] px-4 text-sm gap-2",
|
|
3512
|
-
large: "h-[44px] px-5 text-base gap-3",
|
|
3513
|
-
},
|
|
3514
|
-
validationState: {
|
|
3515
|
-
none: `
|
|
3516
|
-
border-action-outline-neutral-faded
|
|
3517
|
-
hover:border-action-outline-primary-hover
|
|
3518
|
-
focus-within:border-action-outline-primary-hover
|
|
3519
|
-
focus-within:ring-2
|
|
3520
|
-
ring-action-outline-primary-faded-hover`,
|
|
3521
|
-
positive: `
|
|
3522
|
-
border-action-outline-positive-default
|
|
3523
|
-
focus-within:border-action-outline-positive-hover
|
|
3524
|
-
focus-within:ring-2
|
|
3525
|
-
ring-action-outline-positive-faded-hover`,
|
|
3526
|
-
negative: `border-action-outline-negative-default
|
|
3527
|
-
focus-within:border-action-outline-negative-hover
|
|
3528
|
-
focus-within:ring-2
|
|
3529
|
-
ring-action-outline-negative-faded-hover`,
|
|
3530
|
-
},
|
|
3531
|
-
isDisabled: {
|
|
3532
|
-
true: `
|
|
3533
|
-
border-[var(--border-width-thinner)]
|
|
3534
|
-
hover:border-action-outline-neutral-disabled
|
|
3535
|
-
border-action-outline-neutral-disabled
|
|
3536
|
-
bg-surface-fill-neutral-intense cursor-not-allowed opacity-60`,
|
|
3537
|
-
false: "bg-surface-fill-neutral-intense",
|
|
3538
|
-
},
|
|
3539
|
-
},
|
|
3540
|
-
defaultVariants: {
|
|
3541
|
-
size: "medium",
|
|
3542
|
-
validationState: "none",
|
|
3543
|
-
isDisabled: false,
|
|
3544
|
-
},
|
|
3545
|
-
});
|
|
3546
|
-
const TextField = React.forwardRef(({ label, helperText, errorText, successText, size = "medium", validationState = "none", isDisabled = false, isLoading = false, isRequired = false, isOptional = false, prefix, suffix, showClearButton = false, infoDescription, infoHeading, LinkComponent, linkText, linkHref, onLinkClick, onClear, containerClassName, labelClassName, inputClassName, className, value, onChange, ...props }, ref) => {
|
|
3547
|
-
const [internalValue, setInternalValue] = React.useState("");
|
|
3548
|
-
const inputValue = value !== undefined ? value : internalValue;
|
|
3549
|
-
const hasValue = inputValue && String(inputValue).length > 0;
|
|
3550
|
-
const handleChange = (e) => {
|
|
3551
|
-
if (onChange) {
|
|
3552
|
-
onChange(e);
|
|
3553
|
-
}
|
|
3554
|
-
else {
|
|
3555
|
-
setInternalValue(e.target.value);
|
|
3556
|
-
}
|
|
3557
|
-
};
|
|
3558
|
-
const handleClear = () => {
|
|
3559
|
-
if (onClear) {
|
|
3560
|
-
onClear();
|
|
3561
|
-
}
|
|
3562
|
-
else {
|
|
3563
|
-
setInternalValue("");
|
|
3564
|
-
}
|
|
3565
|
-
// Focus the input after clearing
|
|
3566
|
-
const input = document.getElementById(props.id || "");
|
|
3567
|
-
if (input) {
|
|
3568
|
-
input.focus();
|
|
3569
|
-
}
|
|
3570
|
-
};
|
|
3571
|
-
// Determine which helper text to show
|
|
3572
|
-
const displayHelperText = errorText || successText || helperText;
|
|
3573
|
-
const currentValidationState = errorText
|
|
3574
|
-
? "negative"
|
|
3575
|
-
: successText
|
|
3576
|
-
? "positive"
|
|
3577
|
-
: validationState;
|
|
3578
|
-
const sizeConfig = {
|
|
3579
|
-
small: {
|
|
3580
|
-
gap: "gap-2",
|
|
3581
|
-
},
|
|
3582
|
-
medium: {
|
|
3583
|
-
gap: "gap-2",
|
|
3584
|
-
},
|
|
3585
|
-
large: {
|
|
3586
|
-
gap: "gap-3",
|
|
3587
|
-
},
|
|
3588
|
-
};
|
|
3589
|
-
return (jsxs("div", { className: cn("w-full flex flex-col", sizeConfig[size].gap, containerClassName), children: [label && (jsx(FormHeader, { label: label, size: size, isRequired: isRequired, isOptional: isOptional, infoHeading: infoHeading, infoDescription: infoDescription, LinkComponent: LinkComponent, linkText: linkText, linkHref: linkHref, onLinkClick: onLinkClick, htmlFor: props.id, className: "mb-2", labelClassName: labelClassName })), jsxs("div", { className: cn(textFieldVariants({
|
|
3590
|
-
size,
|
|
3591
|
-
validationState: currentValidationState,
|
|
3592
|
-
isDisabled,
|
|
3593
|
-
}), isLoading && "text-field-loading", className), children: [prefix && (jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
3594
|
-
? "text-surface-ink-neutral-disabled"
|
|
3595
|
-
: currentValidationState === "positive"
|
|
3596
|
-
? "text-feedback-ink-positive-intense"
|
|
3597
|
-
: currentValidationState === "negative"
|
|
3598
|
-
? "text-feedback-ink-negative-subtle"
|
|
3599
|
-
: "text-surface-ink-neutral-muted"), children: prefix })), 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", inputClassName), ...props }), showClearButton && hasValue && !isDisabled && (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: jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M12 4L4 12M4 4L12 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })), suffix && (jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
3600
|
-
? "text-surface-ink-neutral-disabled"
|
|
3601
|
-
: currentValidationState === "positive"
|
|
3602
|
-
? "text-feedback-ink-positive-intense"
|
|
3603
|
-
: currentValidationState === "negative"
|
|
3604
|
-
? "text-feedback-ink-negative-subtle"
|
|
3605
|
-
: "text-surface-ink-neutral-muted"), children: suffix }))] }), jsx(FormFooter, { helperText: displayHelperText, validationState: currentValidationState === "none"
|
|
3606
|
-
? "default"
|
|
3607
|
-
: currentValidationState, size: size, isDisabled: isDisabled, className: "mt-1" })] }));
|
|
3608
|
-
});
|
|
3609
|
-
TextField.displayName = "TextField";
|
|
3610
|
-
|
|
3611
3537
|
const defaultFilter = (item, query) => {
|
|
3612
3538
|
const searchQuery = query?.toLowerCase();
|
|
3613
3539
|
return (item.label?.toLowerCase()?.includes(searchQuery) ||
|
|
@@ -5181,5 +5107,5 @@ const UploadBox = React.forwardRef(({ label, helperText, errorText, successText,
|
|
|
5181
5107
|
});
|
|
5182
5108
|
UploadBox.displayName = "UploadBox";
|
|
5183
5109
|
|
|
5184
|
-
export { Alert, Amount, Avatar, AvatarCell, Badge, Button, ButtonGroup, Checkbox, Counter, DatePicker, Divider, Dropdown, DropdownMenu, FormFooter, FormHeader, Icon, IconButton, IconCell, Link, ListItem, Modal, NumberCell, Pagination, Radio, RadioGroup, SearchableDropdown, Select, SelectTextField, SidePanel, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Tooltip, UploadBox, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, datePickerVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectTriggerVariants,
|
|
5110
|
+
export { Alert, Amount, Avatar, AvatarCell, Badge, Button, ButtonGroup, Checkbox, Counter, DatePicker, Divider, Dropdown, DropdownMenu, FormFooter, FormHeader, Icon, IconButton, IconCell, Link, ListItem, Modal, NumberCell, Pagination, Radio, RadioGroup, SearchableDropdown, Select, SelectTextField, SidePanel, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Tooltip, UploadBox, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, datePickerVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectTriggerVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants, uploadBoxVariants };
|
|
5185
5111
|
//# sourceMappingURL=index.esm.js.map
|