@amaui/ui-react
Version:
UI for React
414 lines (413 loc) • 25.1 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importDefault(require("react"));
const utils_1 = require("@amaui/utils");
const style_react_1 = require("@amaui/style-react");
const IconMaterialCloseW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialCloseW100"));
const IconMaterialArrowDropDownW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialArrowDropDownW100"));
const ListItem_1 = __importDefault(require("../ListItem"));
const Type_1 = __importDefault(require("../Type"));
const Menu_1 = __importDefault(require("../Menu"));
const Chip_1 = __importDefault(require("../Chip"));
const Chips_1 = __importDefault(require("../Chips"));
const TextField_1 = __importDefault(require("../TextField"));
const IconButton_1 = __importDefault(require("../IconButton"));
const Line_1 = __importDefault(require("../Line"));
const utils_2 = require("../utils");
const useStyle = (0, style_react_1.style)(theme => {
const overflow = {
width: '100%',
overflow: 'hidden',
whiteSpace: 'pre',
textOverflow: 'ellipsis'
};
return {
root: {
flex: 'unset',
minWidth: '184px',
'& .amaui-TextField-input': {
position: 'absolute',
left: '0',
bottom: '0',
pointerEvents: 'none',
opacity: '0'
},
'& .amaui-TextField-input-wrapper': {
cursor: 'pointer'
}
},
wrapper: {
position: 'relative'
},
inputWrapper: {
cursor: 'pointer',
'&.amaui-TextField-input-wrapper': {
cursor: 'pointer'
}
},
inputWrapper_chip_size_small: {
minHeight: '48px'
},
inputWrapper_chip_size_regular: {
minHeight: '56px'
},
inputWrapper_chip_size_large: {
minHeight: '64px'
},
input: Object.assign(Object.assign({ display: 'flex', alignItems: 'center', width: '100%', minHeight: 20, margin: '0', border: '0', color: theme.palette.text.default.primary, background: 'transparent', '-webkit-tap-highlight-color': 'transparent', textAlign: 'start', borderRadius: `${theme.shape.radius.unit / 2}px ${theme.shape.radius.unit / 2}px 0 0`, cursor: 'pointer', pointerEvents: 'none' }, theme.typography.values.b2), overflow),
chip: {
'&.amaui-TextField-input-wrapper': {
height: 'unset'
}
},
chipGroup: {
pointerEvents: 'auto'
},
chipGroup_padding: {
paddingTop: theme.methods.space.value(0.5, 'px')
},
arrow: {
transition: theme.methods.transitions.make('transform')
},
arrow_open: {
transform: 'rotate(-180deg)'
},
open: {
'&.amaui-TextField-root': {
cursor: 'default'
}
},
fullWidth: {
width: '100%'
},
readOnly: {
'&.amaui-TextField-root': {
cursor: 'default'
}
},
disabled: {
'&.amaui-TextField-root': {
cursor: 'default'
}
}
};
}, { name: 'amaui-Select' });
const getValue = (value) => (value === null || value === void 0 ? void 0 : value.value) !== undefined ? value.value : value;
const Select = react_1.default.forwardRef((props_, ref) => {
var _a;
const theme = (0, style_react_1.useAmauiTheme)();
const props = react_1.default.useMemo(() => { var _a, _b, _c, _d, _e, _f, _g, _h; return (Object.assign(Object.assign(Object.assign({}, (_d = (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _a === void 0 ? void 0 : _a.elements) === null || _b === void 0 ? void 0 : _b.all) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.default), (_h = (_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _e === void 0 ? void 0 : _e.elements) === null || _f === void 0 ? void 0 : _f.amauiSelect) === null || _g === void 0 ? void 0 : _g.props) === null || _h === void 0 ? void 0 : _h.default), props_)); }, [props_]);
const Line = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Line) || Line_1.default; }, [theme]);
const ListItem = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.ListItem) || ListItem_1.default; }, [theme]);
const Type = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Type) || Type_1.default; }, [theme]);
const Menu = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Menu) || Menu_1.default; }, [theme]);
const Chip = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Chip) || Chip_1.default; }, [theme]);
const Chips = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Chips) || Chips_1.default; }, [theme]);
const TextField = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.TextField) || TextField_1.default; }, [theme]);
const IconButton = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.IconButton) || IconButton_1.default; }, [theme]);
const { tonal = true, color = 'primary', size = 'regular', version = 'filled', value: value_, valueDefault, onChange: onChange_, options, name, multiple, prefix, sufix, start, end, autoWidth = true, getLabel: getLabel_, fullWidth, chip, clear, readOnly, noSelectText, disabled, renderValues: renderValues_, renderChip, IconClear = IconMaterialCloseW100_1.default, IconDropdown = IconMaterialArrowDropDownW100_1.default, WrapperProps, ChipProps, ChiProps, ListProps = {
style: {
maxHeight: 250,
overflowY: 'auto',
overflowX: 'hidden'
}
}, MenuProps = {
portal: true
}, IconButtonProps, IconProps, className, style, children: children_ } = props, other = __rest(props, ["tonal", "color", "size", "version", "value", "valueDefault", "onChange", "options", "name", "multiple", "prefix", "sufix", "start", "end", "autoWidth", "getLabel", "fullWidth", "chip", "clear", "readOnly", "noSelectText", "disabled", "renderValues", "renderChip", "IconClear", "IconDropdown", "WrapperProps", "ChipProps", "ChiProps", "ListProps", "MenuProps", "IconButtonProps", "IconProps", "className", "style", "children"]);
const children = react_1.default.Children.toArray(children_);
const [value, setValue] = react_1.default.useState(() => {
const values = valueDefault !== undefined ? valueDefault : value_;
return multiple ? ((0, utils_1.is)('array', values) ? values : [values]).filter(Boolean) : values;
});
const [open, setOpen] = react_1.default.useState(false);
const [mouseDown, setMouseDown] = react_1.default.useState(false);
const [focus, setFocus] = react_1.default.useState(false);
const { classes } = useStyle();
const refs = {
root: react_1.default.useRef(undefined),
wrapper: react_1.default.useRef(undefined),
menu: react_1.default.useRef(undefined),
input: react_1.default.useRef(undefined),
ids: {
list: react_1.default.useId()
}
};
const styles = {
root: {},
menu: {}
};
if ((MenuProps === null || MenuProps === void 0 ? void 0 : MenuProps.portal) && autoWidth) {
styles.menu.width = (_a = refs.wrapper.current) === null || _a === void 0 ? void 0 : _a.clientWidth;
}
react_1.default.useEffect(() => {
var _a;
const method = (event) => {
if (event.key === 'Escape')
onClose();
};
const rootDocument = (0, utils_1.isEnvironment)('browser') ? (((_a = refs.root.current) === null || _a === void 0 ? void 0 : _a.ownerDocument) || window.document) : undefined;
rootDocument.addEventListener('keydown', method);
return () => {
// Clean up
rootDocument.removeEventListener('keydown', method);
};
}, []);
react_1.default.useEffect(() => {
if (value_ !== undefined && value_ !== value)
setValue(value_);
}, [value_]);
const onMouseDown = react_1.default.useCallback((event) => {
if (!disabled && !readOnly)
setMouseDown(true);
}, []);
const onMouseUp = react_1.default.useCallback((event) => {
if (!disabled && !readOnly)
setMouseDown(false);
}, []);
const onFocus = react_1.default.useCallback((event) => {
if (!disabled && !readOnly)
setFocus(true);
}, []);
const onBlur = react_1.default.useCallback((event) => {
if (!disabled && !readOnly)
setFocus(false);
}, []);
const onClick = react_1.default.useCallback((event) => {
if (!disabled && !readOnly)
setOpen(open_ => {
if (open_)
setFocus(false);
return !open_;
});
}, []);
const onClickArrowDown = react_1.default.useCallback((event) => {
if (!disabled && !readOnly)
setOpen(open_ => !open_);
}, []);
const onEnterKeyDown = react_1.default.useCallback((event) => {
if (event.key === 'Enter' && !disabled && !readOnly)
setOpen(open_ => {
if (open_)
refs.input.current.focus();
return !open_;
});
}, []);
const onClose = react_1.default.useCallback((refocus = true) => {
if (!disabled && !readOnly) {
setOpen(open_ => {
if (open_ && refocus)
refs.input.current.focus();
return false;
});
}
}, []);
const onChange = (valueNew) => {
// Inner controlled value
if (!props.hasOwnProperty('value'))
setValue(valueNew);
if ((0, utils_1.is)('function', onChange_))
onChange_(valueNew);
};
const onSelect = (newValue) => {
let values = multiple ? (0, utils_1.is)('array', value) ? value : [value] : value;
values = multiple ? (0, utils_1.unique)([...values, newValue]) : newValue;
onChange(values);
};
const onUnselect = (itemValue) => {
if (multiple) {
let values = (0, utils_1.is)('array', value) ? value : [value];
values = values.filter(item => item !== itemValue);
onChange(values);
}
};
const onClear = react_1.default.useCallback((refocus = false) => {
if (!disabled && !readOnly) {
onChange(multiple ? [] : null);
if (refocus)
refs.input.current.focus();
}
}, [multiple, readOnly, disabled]);
const items = react_1.default.useMemo(() => {
return (options || []).map((item) => (Object.assign(Object.assign({}, item), { name: String((item === null || item === void 0 ? void 0 : item.name) !== undefined ? item === null || item === void 0 ? void 0 : item.name : (item === null || item === void 0 ? void 0 : item.value) !== undefined ? item.value : item), value: (item === null || item === void 0 ? void 0 : item.value) !== undefined ? item === null || item === void 0 ? void 0 : item.value : item })));
}, [options]);
const getLabel = (item, propsOther) => {
if ((0, utils_1.is)('function', getLabel_))
return getLabel_(item, propsOther);
const properties = ['name', 'label', 'primary', 'secondary', 'tertiary', 'value', 'children'];
const objects = [item, item === null || item === void 0 ? void 0 : item.props].filter(Boolean);
for (const itemObject of objects) {
if ((0, utils_1.is)('simple', itemObject))
return itemObject;
const valueItem = (0, utils_1.getObjectValue)(itemObject, ...properties);
if (valueItem !== undefined)
return valueItem;
}
return noSelectText || 'Select an option';
};
const renderValue = (itemValue = value) => {
const item = !!(items === null || items === void 0 ? void 0 : items.length) ? items.find((item_) => getValue(item_) === getValue(itemValue)) : children.find((item_) => { var _a; return getValue((_a = item_.props) === null || _a === void 0 ? void 0 : _a.value) === getValue(itemValue); });
return item ? getLabel(item, props) : getLabel(itemValue, props) || '';
};
const renderValues = renderValues_ || ((value__ = value) => {
if (multiple) {
if (chip) {
return ((0, jsx_runtime_1.jsx)(Chips, Object.assign({ wrap: 'wrap', size: size, className: (0, style_react_1.classNames)([
classes.chipGroup,
version !== 'outlined' && classes.chipGroup_padding
]) }, ChiProps, { children: value__.map(item => {
const other_ = {
onClick: (event) => {
event.preventDefault();
event.stopPropagation();
},
onRemove: (event) => {
event.preventDefault();
event.stopPropagation();
onUnselect(item);
},
input: true
};
if ((0, utils_1.is)('function', renderChip))
return renderChip(item, renderValue(item), other_);
return ((0, jsx_runtime_1.jsx)(Chip, Object.assign({ size: 'small' }, other_, ChipProps, { children: renderValue(item) }), item));
}) })));
}
const valuesAll = value.map(item => renderValue(item));
if (valuesAll.every(item => (0, utils_1.is)('simple', item)))
return valuesAll.join(', ');
return (value === null || value === void 0 ? void 0 : value.length) ? valuesAll : noSelectText || name;
}
return renderValue(value);
});
const endIcons = [
end,
clear && !!(multiple ? value.length : ![undefined, null].includes(value)) && ((0, jsx_runtime_1.jsx)(IconButton, Object.assign({ onClick: onClear, size: 'small', "aria-label": 'Input clear' }, IconButtonProps, { children: (0, jsx_runtime_1.jsx)(IconClear, Object.assign({}, IconProps)) }))),
...(!readOnly ? [
(0, jsx_runtime_1.jsx)(IconButton, Object.assign({ size: 'regular', onClick: onClickArrowDown, "aria-expanded": open, "aria-controls": refs.ids.list }, IconButtonProps, { children: (0, jsx_runtime_1.jsx)(IconDropdown, Object.assign({ size: 'large' }, IconProps, { className: (0, style_react_1.classNames)([
IconProps === null || IconProps === void 0 ? void 0 : IconProps.className,
classes.arrow,
open && classes.arrow_open
]) })) }), 1)
] : [])
];
const sizeListItem = (MenuProps === null || MenuProps === void 0 ? void 0 : MenuProps.size) || size;
return ((0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 0, direction: 'column', fullWidth: fullWidth }, WrapperProps, { ref: item => {
if (WrapperProps === null || WrapperProps === void 0 ? void 0 : WrapperProps.ref) {
if ((0, utils_1.is)('function', WrapperProps.ref))
WrapperProps.ref(item);
else
WrapperProps.ref.current = item;
}
refs.wrapper.current = item;
}, className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('Select', theme) && [
'amaui-Select-wrapper',
fullWidth && 'amaui-full-width'
],
WrapperProps === null || WrapperProps === void 0 ? void 0 : WrapperProps.className,
classes.wrapper
]) }, { children: [(0, jsx_runtime_1.jsx)(TextField, Object.assign({ ref: refs.input, rootRef: (item => {
if (ref) {
if ((0, utils_1.is)('function', ref))
ref(item);
else
ref.current = item;
}
refs.root.current = item;
}), onBlur: onBlur, onFocus: onFocus, enabled: open || focus || mouseDown || !!((0, utils_1.is)('array', value) ? value.length : ![undefined, null].includes(value)), focus: open || focus || mouseDown, className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('Select', theme) && [
'amaui-Select-root',
`amaui-Select-version-${version}`,
`amaui-Select-size-${size}`,
open && `amaui-Select-open`,
mouseDown && `amaui-Select-mouse-down`,
focus && `amaui-Select-focus`
],
className,
classes.root,
open && classes.open,
disabled && classes.disabled
]), tonal: tonal, color: color, size: size, version: version, name: name, prefix: prefix, sufix: sufix, start: start, end: endIcons, readOnly: readOnly, endVerticalAlign: 'center', role: 'combobox', "aria-multiselectable": multiple, "aria-controls": refs.ids.list, "aria-expanded": open, "aria-haspopup": 'listbox', "aria-labelledby": name, "aria-disabled": disabled, fullWidth: fullWidth, disabled: disabled, InputWrapperProps: {
className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('Select', theme) && [
'amaui-Select-input-wrapper'
],
classes.inputWrapper,
chip && [
classes.chip,
classes[`inputWrapper_chip_size_${size}`]
],
open && classes.open,
readOnly && classes.readOnly
]),
onMouseDown,
onMouseUp,
onClick,
onKeyDown: onEnterKeyDown
}, inputProps: {
disabled: true,
readOnly: true
}, style: Object.assign(Object.assign({}, style), styles.root) }, other, { children: (0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0, direction: 'row', className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('Select', theme) && [
'amaui-Select-input'
],
classes.input,
chip && classes.chip,
open && classes.open,
readOnly && classes.readOnly
]), justify: other.align }, { children: renderValues(value) })) })), (!!items.length || children) && ((0, jsx_runtime_1.jsx)(Menu, Object.assign({ ref: refs.menu, open: open, portal: false, onClose: () => onClose(false), anchorElement: refs.root.current, transformOrigin: 'center top', transformOriginSwitch: 'center bottom', maxWidth: 'unset', size: size, menuItems: !!items.length ? (items.map((item, index) => ((0, jsx_runtime_1.jsx)(ListItem, Object.assign({ role: 'option', selected: item.selected !== undefined ? item.selected : multiple ? value.includes(item === null || item === void 0 ? void 0 : item.value) : value === (item === null || item === void 0 ? void 0 : item.value), preselected: item.preselected !== undefined ? item.preselected : !(multiple ? value.includes(item === null || item === void 0 ? void 0 : item.value) : value === (item === null || item === void 0 ? void 0 : item.value)), onMouseUp: onMouseUp, onMouseDown: onMouseDown, primary: ((0, jsx_runtime_1.jsx)(Type, Object.assign({ version: sizeListItem === 'large' ? 'b1' : sizeListItem === 'regular' ? 'b2' : 'b3' }, { children: item.name }))), value: item.value, size: (MenuProps === null || MenuProps === void 0 ? void 0 : MenuProps.size) || size, button: true }, item.props, { onClick: (event) => {
var _a, _b;
if (multiple && value.includes(item === null || item === void 0 ? void 0 : item.value))
onUnselect(item === null || item === void 0 ? void 0 : item.value);
else
onSelect(item === null || item === void 0 ? void 0 : item.value);
if ((0, utils_1.is)('function', (_a = item.props) === null || _a === void 0 ? void 0 : _a.onClick))
(_b = item.props) === null || _b === void 0 ? void 0 : _b.onClick(event);
if (!multiple)
setOpen(false);
} }), index)))) : children.map((item, index) => {
var _a, _b, _c, _d;
return (react_1.default.cloneElement(item, {
key: index,
role: 'option',
selected: item.props.selected !== undefined ? item.props.selected : multiple ? value.includes((_a = item.props) === null || _a === void 0 ? void 0 : _a.value) : value === ((_b = item.props) === null || _b === void 0 ? void 0 : _b.value),
preselected: item.props.preselected !== undefined ? item.props.preselected : !(multiple ? value.includes((_c = item.props) === null || _c === void 0 ? void 0 : _c.value) : value === ((_d = item.props) === null || _d === void 0 ? void 0 : _d.value)),
onMouseUp,
onMouseDown,
onClick: (event) => {
var _a, _b, _c, _d, _e;
if (multiple && value.includes((_a = item.props) === null || _a === void 0 ? void 0 : _a.value))
onUnselect((_b = item.props) === null || _b === void 0 ? void 0 : _b.value);
else
onSelect((_c = item.props) === null || _c === void 0 ? void 0 : _c.value);
if ((0, utils_1.is)('function', (_d = item.props) === null || _d === void 0 ? void 0 : _d.onClick))
(_e = item.props) === null || _e === void 0 ? void 0 : _e.onClick(event);
if (!multiple)
setOpen(false);
}
}));
}), AppendProps: {
alignment: 'start'
}, ModalProps: {
// focus: !MenuProps.portal
}, ListProps: Object.assign({ menu: true, size: (ListProps === null || ListProps === void 0 ? void 0 : ListProps.size) || (MenuProps === null || MenuProps === void 0 ? void 0 : MenuProps.size) || size, role: 'listbox', id: refs.ids.list, 'aria-label': name }, ListProps) }, MenuProps, { style: Object.assign(Object.assign({}, styles.menu), MenuProps === null || MenuProps === void 0 ? void 0 : MenuProps.style), className: (0, style_react_1.classNames)([
MenuProps === null || MenuProps === void 0 ? void 0 : MenuProps.className
]) })))] })));
});
Select.displayName = 'amaui-Select';
exports.default = Select;
;