@hypothesis/frontend-shared
Version:
Shared components, styles and utilities for Hypothesis projects
136 lines • 3.9 kB
JavaScript
var _jsxFileName = "/home/runner/work/frontend-shared/frontend-shared/src/components/input/RadioGroup.tsx";
import classnames from 'classnames';
import { useContext, useRef } from 'preact/hooks';
import { useArrowKeyNavigation } from '../../hooks/use-arrow-key-navigation';
import { RadioCheckedIcon, RadioIcon } from '../icons';
import RadioGroupContext from './RadioGroupContext';
import { jsxDEV as _jsxDEV } from "preact/jsx-dev-runtime";
function Radio({
value,
children,
subtitle,
disabled: radioDisabled
}) {
const radioGroupContext = useContext(RadioGroupContext);
if (!radioGroupContext) {
throw new Error('RadioGroup.Radio can only be used as RadioGroup child');
}
const {
selected,
disabled = radioDisabled,
onChange
} = radioGroupContext;
const isSelected = !disabled && selected === value;
return _jsxDEV("div", {
role: "radio",
"aria-checked": isSelected,
"aria-disabled": disabled,
className: classnames('focus-visible-ring rounded-lg px-3 py-2 flex-1 group', {
'bg-grey-3/50': isSelected,
'hover:bg-grey-3/25': !isSelected && !disabled,
'opacity-70': disabled,
'cursor-pointer': !disabled
}),
"data-value": value,
onClick: !disabled ? () => onChange(value) : undefined,
onKeyDown: disabled ? undefined : e => {
if (['Enter', ' '].includes(e.key)) {
e.preventDefault();
onChange(value);
}
},
tabIndex: -1,
children: [_jsxDEV("div", {
className: "flex items-center gap-x-1.5",
children: [isSelected ? _jsxDEV(RadioCheckedIcon, {}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 68,
columnNumber: 23
}, this) : _jsxDEV(RadioIcon, {}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 68,
columnNumber: 46
}, this), children]
}, void 0, true, {
fileName: _jsxFileName,
lineNumber: 67,
columnNumber: 7
}, this), subtitle && _jsxDEV("div", {
className: classnames('pl-4 ml-1.5 mt-1 text-sm', {
'text-grey-7': isSelected,
'text-grey-6 group-hover:text-grey-7': !isSelected && !disabled
}),
children: subtitle
}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 72,
columnNumber: 9
}, this)]
}, void 0, true, {
fileName: _jsxFileName,
lineNumber: 40,
columnNumber: 5
}, this);
}
Radio.displayName = 'RadioGroup.Radio';
function RadioGroupMain({
direction = 'horizontal',
children,
selected,
onChange,
disabled,
'aria-label': label,
'aria-labelledby': labelledBy,
name
}) {
const containerRef = useRef(null);
useArrowKeyNavigation(containerRef, {
loop: false,
selector: '[role="radio"]:not([aria-disabled="true"])',
focusElement: el => {
onChange(el.dataset.value);
el.focus();
}
});
return _jsxDEV(RadioGroupContext.Provider, {
value: {
selected,
disabled,
onChange: onChange
},
children: [_jsxDEV("div", {
"aria-label": label,
"aria-labelledby": labelledBy,
ref: containerRef,
role: "radiogroup",
className: classnames('w-full flex gap-1.5', {
'flex-col': direction === 'vertical'
}),
children: children
}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 134,
columnNumber: 7
}, this), name && _jsxDEV("input", {
type: "hidden",
"data-testid": "hidden-input",
name: name,
value: selected,
disabled: disabled
}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 146,
columnNumber: 9
}, this)]
}, void 0, true, {
fileName: _jsxFileName,
lineNumber: 131,
columnNumber: 5
}, this);
}
const RadioGroup = Object.assign(RadioGroupMain, {
Radio,
displayName: 'RadioGroup'
});
export default RadioGroup;
//# sourceMappingURL=RadioGroup.js.map