infinity-ui-elements 1.8.29 → 1.8.32

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.js CHANGED
@@ -2098,7 +2098,7 @@ const formatDateDefault = (date) => {
2098
2098
  day: "numeric",
2099
2099
  });
2100
2100
  };
2101
- const DatePicker = React__namespace.forwardRef(({ className, value: controlledValue, defaultValue, onChange, placeholder = "Select a date", label, helperText, errorText, successText, validationState = "none", isDisabled = false, isRequired = false, isOptional = false, size = "medium", showClearButton = false, onClear, containerClassName, labelClassName, triggerClassName, calendarClassName, minDate, maxDate, formatDate = formatDateDefault, infoHeading, infoDescription, LinkComponent, linkText, linkHref, onLinkClick, ...props }, ref) => {
2101
+ const DatePicker = React__namespace.forwardRef(({ className, value: controlledValue, defaultValue, onChange, placeholder = "Select a date", label, helperText, errorText, successText, validationState = "none", isDisabled = false, isRequired = false, isOptional = false, size = "medium", showClearButton = true, onClear, containerClassName, labelClassName, triggerClassName, calendarClassName, minDate, maxDate, formatDate = formatDateDefault, infoHeading, infoDescription, LinkComponent, linkText, linkHref, onLinkClick, ...props }, ref) => {
2102
2102
  const [uncontrolledValue, setUncontrolledValue] = React__namespace.useState(parseDate(defaultValue));
2103
2103
  const [isOpen, setIsOpen] = React__namespace.useState(false);
2104
2104
  const datePickerRef = React__namespace.useRef(null);
@@ -2251,7 +2251,7 @@ const DatePicker = React__namespace.forwardRef(({ className, value: controlledVa
2251
2251
  ? "text-feedback-ink-positive-intense"
2252
2252
  : currentValidationState === "negative"
2253
2253
  ? "text-feedback-ink-negative-subtle"
2254
- : "text-surface-ink-neutral-muted") }), jsxRuntime.jsx("span", { className: cn("flex-1 text-left truncate", !hasValue && "text-surface-ink-neutral-muted", isDisabled && "text-surface-ink-neutral-disabled"), children: hasValue && value ? formatDate(value) : placeholder }), 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" }) }) })), isOpen && !isDisabled && (jsxRuntime.jsx("div", { ref: calendarRef, className: cn("absolute z-50 left-0 bg-surface-fill-neutral-intense rounded-large shadow-lg p-4", dropdownPlacement === "bottom"
2254
+ : "text-surface-ink-neutral-muted") }), jsxRuntime.jsx("span", { className: cn("flex-1 text-left truncate", !hasValue && "text-surface-ink-neutral-muted", isDisabled && "text-surface-ink-neutral-disabled"), children: hasValue && value ? formatDate(value) : placeholder }), 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, "aria-label": "Clear date", children: jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" }) })), isOpen && !isDisabled && (jsxRuntime.jsx("div", { ref: calendarRef, className: cn("absolute z-50 left-0 bg-surface-fill-neutral-intense rounded-large shadow-lg p-4", dropdownPlacement === "bottom"
2255
2255
  ? "top-full mt-1"
2256
2256
  : "bottom-full mb-1", calendarClassName), onClick: (e) => e.stopPropagation(), children: jsxRuntime.jsx("div", { className: "react-calendar-wrapper w-fit", children: jsxRuntime.jsx(Calendar, { onChange: handleCalendarChange, value: value ?? null, minDate: minDateParsed ?? undefined, maxDate: maxDateParsed ?? undefined, locale: "en-US", formatShortWeekday: (locale, date) => {
2257
2257
  const weekdayNames = [
@@ -3119,6 +3119,140 @@ const Radio = React__namespace.forwardRef(({ label, errorText, size = "medium",
3119
3119
  });
3120
3120
  Radio.displayName = "Radio";
3121
3121
 
3122
+ const RadioGroup = React__namespace.forwardRef(({ value: controlledValue, defaultValue, onChange, options, children, label, helperText, errorText, successText, validationState = "none", isDisabled = false, isRequired = false, isOptional = false, size = "medium", name: nameProp, orientation = "vertical", spacing = "normal", containerClassName, labelClassName, groupClassName, infoHeading, infoDescription, LinkComponent, linkText, linkHref, onLinkClick, className, id, ...props }, ref) => {
3123
+ const [uncontrolledValue, setUncontrolledValue] = React__namespace.useState(defaultValue);
3124
+ const groupId = React__namespace.useId();
3125
+ const name = nameProp || `radio-group-${groupId}`;
3126
+ const groupRef = React__namespace.useRef(null);
3127
+ const radioRefs = React__namespace.useRef([]);
3128
+ const value = controlledValue !== undefined ? controlledValue : uncontrolledValue;
3129
+ // Determine which helper text to show
3130
+ const displayHelperText = errorText || successText || helperText;
3131
+ const currentValidationState = errorText ? "error" : validationState;
3132
+ const handleChange = (optionValue) => {
3133
+ if (onChange) {
3134
+ onChange(optionValue);
3135
+ }
3136
+ else {
3137
+ setUncontrolledValue(optionValue);
3138
+ }
3139
+ };
3140
+ // Keyboard navigation
3141
+ const handleKeyDown = (e) => {
3142
+ if (isDisabled)
3143
+ return;
3144
+ const currentIndex = radioRefs.current.findIndex((ref) => ref === document.activeElement);
3145
+ if (currentIndex === -1)
3146
+ return;
3147
+ const direction = orientation === "horizontal"
3148
+ ? e.key === "ArrowRight"
3149
+ ? 1
3150
+ : e.key === "ArrowLeft"
3151
+ ? -1
3152
+ : 0
3153
+ : e.key === "ArrowDown"
3154
+ ? 1
3155
+ : e.key === "ArrowUp"
3156
+ ? -1
3157
+ : 0;
3158
+ if (direction === 0)
3159
+ return;
3160
+ e.preventDefault();
3161
+ // Find next enabled radio
3162
+ let nextIndex = currentIndex;
3163
+ const total = radioRefs.current.length;
3164
+ let attempts = 0;
3165
+ while (attempts < total) {
3166
+ nextIndex = (nextIndex + direction + total) % total;
3167
+ const nextRadio = radioRefs.current[nextIndex];
3168
+ if (nextRadio && !nextRadio.disabled) {
3169
+ nextRadio.focus();
3170
+ nextRadio.click();
3171
+ return;
3172
+ }
3173
+ attempts++;
3174
+ }
3175
+ };
3176
+ // Spacing configuration
3177
+ const spacingConfig = {
3178
+ tight: orientation === "horizontal" ? "gap-3" : "gap-2",
3179
+ normal: orientation === "horizontal" ? "gap-4" : "gap-3",
3180
+ loose: orientation === "horizontal" ? "gap-6" : "gap-4",
3181
+ };
3182
+ // Size configuration
3183
+ const sizeConfig = {
3184
+ small: {
3185
+ gap: "gap-2",
3186
+ },
3187
+ medium: {
3188
+ gap: "gap-2",
3189
+ },
3190
+ large: {
3191
+ gap: "gap-3",
3192
+ },
3193
+ };
3194
+ // Render options from array
3195
+ const renderOptions = () => {
3196
+ if (!options)
3197
+ return null;
3198
+ return options.map((option, index) => {
3199
+ const isChecked = value === option.value;
3200
+ const optionDisabled = isDisabled || option.isDisabled;
3201
+ return (jsxRuntime.jsx(Radio, { ref: (el) => {
3202
+ radioRefs.current[index] = el;
3203
+ }, name: name, value: option.value, label: option.label, checked: isChecked, onChange: (e) => {
3204
+ if (e.target.checked) {
3205
+ handleChange(option.value);
3206
+ }
3207
+ }, size: size, validationState: currentValidationState, isDisabled: optionDisabled, showErrorText: false, containerClassName: option.containerClassName, labelClassName: option.labelClassName }, option.value));
3208
+ });
3209
+ };
3210
+ // Clone children and inject props
3211
+ const renderChildren = () => {
3212
+ if (!children)
3213
+ return null;
3214
+ return React__namespace.Children.map(children, (child, index) => {
3215
+ if (!React__namespace.isValidElement(child)) {
3216
+ return child;
3217
+ }
3218
+ const childValue = child.props.value;
3219
+ const isChecked = value === childValue;
3220
+ const childDisabled = isDisabled || child.props.isDisabled;
3221
+ return React__namespace.cloneElement(child, {
3222
+ ...child.props,
3223
+ ref: (el) => {
3224
+ radioRefs.current[index] = el;
3225
+ },
3226
+ name,
3227
+ checked: isChecked,
3228
+ onChange: (e) => {
3229
+ if (e.target.checked) {
3230
+ handleChange(typeof childValue === "string"
3231
+ ? childValue
3232
+ : String(childValue || ""));
3233
+ }
3234
+ // Call original onChange if it exists
3235
+ if (child.props.onChange) {
3236
+ child.props.onChange(e);
3237
+ }
3238
+ },
3239
+ size: child.props.size || size,
3240
+ validationState: child.props.validationState || currentValidationState,
3241
+ isDisabled: childDisabled,
3242
+ showErrorText: false,
3243
+ });
3244
+ });
3245
+ };
3246
+ return (jsxRuntime.jsxs("div", { ref: ref, className: cn("w-full flex flex-col", sizeConfig[size].gap, containerClassName), ...props, children: [label && (jsxRuntime.jsx(FormHeader, { label: label, size: size, isRequired: isRequired, isOptional: isOptional, infoHeading: infoHeading, infoDescription: infoDescription, LinkComponent: LinkComponent, linkText: linkText, linkHref: linkHref, onLinkClick: onLinkClick, htmlFor: id, className: "mb-2", labelClassName: labelClassName })), jsxRuntime.jsx("div", { ref: groupRef, role: "radiogroup", "aria-label": label, "aria-required": isRequired, "aria-invalid": currentValidationState === "error", "aria-disabled": isDisabled, className: cn("flex", orientation === "horizontal"
3247
+ ? "flex-row items-center"
3248
+ : "flex-col items-start", spacingConfig[spacing], groupClassName, className), onKeyDown: handleKeyDown, id: id, children: options ? renderOptions() : renderChildren() }), jsxRuntime.jsx(FormFooter, { helperText: displayHelperText, validationState: currentValidationState === "none"
3249
+ ? "default"
3250
+ : currentValidationState === "error"
3251
+ ? "negative"
3252
+ : "default", size: size, isDisabled: isDisabled, className: "mt-1" })] }));
3253
+ });
3254
+ RadioGroup.displayName = "RadioGroup";
3255
+
3122
3256
  const textFieldVariants = classVarianceAuthority.cva("relative flex items-center gap-2 border rounded-large transition-all font-functional font-size-100 leading-100", {
3123
3257
  variants: {
3124
3258
  size: {
@@ -4737,6 +4871,7 @@ exports.Modal = Modal;
4737
4871
  exports.NumberCell = NumberCell;
4738
4872
  exports.Pagination = Pagination;
4739
4873
  exports.Radio = Radio;
4874
+ exports.RadioGroup = RadioGroup;
4740
4875
  exports.SearchableDropdown = SearchableDropdown;
4741
4876
  exports.Select = Select;
4742
4877
  exports.SelectTextField = SelectTextField;