@veracity/vui
Version:
Veracity UI is a React component library crafted for use within Veracity applications and pages. Based on Styled Components and @xstyled.
114 lines (112 loc) • 3.65 kB
JavaScript
import { filterUndefined } from "../utils/object.js";
import { cs } from "../utils/styles.js";
import { selectionControlGroupGap, selectionControlLabelSize, selectionControlStackGap } from "../selectionControl/theme.js";
import { selectionControlColors } from "../selectionControl/consts.js";
import styled from "../core/styled.js";
import vui from "../core/vui.js";
import { Box } from "../box/box.js";
import { T } from "../t/t.js";
import { RadioGroupProvider } from "./context.js";
import { useCallback, useId, useMemo, useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
//#region src/radio/radioGroup.tsx
const RadioGroupBase = styled.divBox`
display: flex;
flex-direction: column;
`;
/**
* Organizes layout and display of multiple radio buttons as a row or column.
* Exposes some props to the children via context. `label`/`helpText`/`errorText` render an optional
* group heading/description around the stack; `errorText` overrides `helpText` and marks the group invalid.
*/
const RadioGroup = vui((props, ref) => {
const { children, className, defaultValue, disabled, errorText, gap, groupGap, helpText, isRow, label, name, onBlur, onChange, onFocus, size, value, variant, ...rest } = props;
const description = errorText ?? helpText;
const [isChecked, setIsChecked] = useState(value ?? defaultValue);
const handleOnChange = useCallback((e) => {
setIsChecked(e.target.value);
onChange?.(e);
}, [onChange]);
const context = useMemo(() => filterUndefined({
defaultValue,
disabled,
isChecked,
name,
onBlur,
onChange: handleOnChange,
onFocus,
size,
value,
variant
}), [
defaultValue,
disabled,
handleOnChange,
isChecked,
name,
onBlur,
onFocus,
size,
value,
variant
]);
const groupSize = size ?? "md";
const aliasedProps = filterUndefined({
flexDirection: isRow ? "row" : void 0,
gap: gap ?? selectionControlStackGap[groupSize] ?? selectionControlStackGap.md
});
const generatedId = useId();
const labelId = label ? `${generatedId}-label` : void 0;
const descriptionId = description ? `${generatedId}-help-text` : void 0;
if (!label && !description) return /* @__PURE__ */ jsx(RadioGroupProvider, {
value: context,
children: /* @__PURE__ */ jsx(RadioGroupBase, {
className: cs("vui-radioGroup", className),
ref,
...aliasedProps,
...rest,
children
})
});
return /* @__PURE__ */ jsx(RadioGroupProvider, {
value: context,
children: /* @__PURE__ */ jsxs(Box, {
className: cs("vui-radioGroup", className),
column: true,
gap: groupGap ?? selectionControlGroupGap[groupSize] ?? selectionControlGroupGap.md,
ref,
...rest,
children: [
label && /* @__PURE__ */ jsx(T, {
className: "vui-radioGroupLabel",
color: selectionControlColors.label,
fontWeight: "demi",
id: labelId,
size: selectionControlLabelSize[groupSize] ?? selectionControlLabelSize.md,
children: label
}),
/* @__PURE__ */ jsx(RadioGroupBase, {
"aria-describedby": descriptionId,
"aria-invalid": !!errorText || void 0,
"aria-labelledby": labelId,
className: "vui-radioGroupStack",
role: "group",
...aliasedProps,
children
}),
description && /* @__PURE__ */ jsx(T, {
className: "vui-radioGroupHelpText",
color: errorText ? selectionControlColors.error : selectionControlColors.helper,
id: descriptionId,
size: "xs",
children: description
})
]
})
});
});
RadioGroup.displayName = "RadioGroup";
//#endregion
export { RadioGroup, RadioGroup as default, RadioGroupBase };
globalThis.__vuiVersion__ = "5.4.0"
//# sourceMappingURL=radioGroup.js.map