@limetech/lime-elements
Version:
193 lines (192 loc) • 7.35 kB
JavaScript
import { h } from '@stencil/core';
import { isMultiple } from '../../util/multiple';
import { getIconColor, getIconName } from '../icon/get-icon-props';
export const SelectTemplate = (props) => {
const value = props.value;
let hasValue = !!props.value;
let hasEmptyText = true;
if (isMultiple(value)) {
hasValue = value.length > 0;
}
else if (hasValue) {
hasValue = !!value.value;
hasEmptyText = value.text === '';
}
let isValid = !props.invalid;
if (props.checkValid && props.required && !hasValue) {
isValid = false;
}
const classList = {
'limel-select': true,
'mdc-select': true,
'mdc-select--disabled': props.disabled,
'limel-select--readonly': props.readonly,
'limel-select--invalid': !isValid,
'limel-select--with-helper-text': typeof props.helperText === 'string',
};
return [
h("limel-notched-outline", { class: classList, labelId: "s-label", label: props.label, required: props.required, invalid: !isValid, disabled: props.disabled, readonly: props.readonly, hasValue: hasValue, hasFloatingLabel: floatLabelAbove(props) }, h(SelectValue, Object.assign({}, props, { hasValue: hasValue, isValid: isValid, hasEmptyText: hasEmptyText }))),
h(HelperText, { text: props.helperText, isValid: !props.invalid }),
h(SelectDropdown, Object.assign({}, props)),
];
};
const floatLabelAbove = (props) => {
if (props.isOpen) {
return true;
}
const value = props.value;
if (value) {
if (isMultiple(value)) {
return value.length > 0;
}
else {
return value.text !== '';
}
}
return false;
};
const SelectValue = (props) => {
const anchorClassList = {
'mdc-select__anchor': true,
'limel-select-trigger': true,
'limel-select--focused': props.isOpen,
};
return (h("button", { slot: "content", class: anchorClassList, onClick: props.open, onKeyPress: props.onTriggerPress, "aria-haspopup": "listbox", "aria-expanded": props.isOpen, "aria-controls": props.id, "aria-labelledby": "s-label s-selected-text", "aria-required": props.required, disabled: props.disabled || props.readonly }, h("span", { class: "mdc-select__selected-text-container limel-select__selected-option" }, getSelectedIcon(props.value), h("span", { id: "s-selected-text", class: "mdc-select__selected-text limel-select__selected-option__text" }, getSelectedText(props.value))), h(ShowIcon, Object.assign({}, props, { isValid: props.isValid })), h("span", { class: "mdc-select__dropdown-icon" }, h("svg", { class: "mdc-select__dropdown-icon-graphic", viewBox: "7 10 10 5", focusable: "false" }, h("polygon", { stroke: "none", "fill-rule": "evenodd", points: "7 10 12 15 17 10" })))));
};
const ShowIcon = (props) => {
if (props.isValid) {
return;
}
return (h("limel-icon", { name: "high_importance", size: "medium", class: "invalid-icon" }));
};
const HelperText = (props) => {
if (typeof props.text !== 'string') {
return;
}
return (h("limel-helper-line", { helperText: props.text.trim(), invalid: !props.isValid }));
};
const SelectDropdown = (props) => {
if (props.native) {
return h(NativeDropdown, Object.assign({}, props));
}
return h(MenuDropdown, Object.assign({}, props));
};
const MenuDropdown = (props) => {
const items = createMenuItems(props.options, props.value, props.required);
return (h("limel-portal", { containerId: props.id, visible: props.isOpen, inheritParentWidth: true, containerStyle: { 'z-index': props.dropdownZIndex } }, h("limel-menu-surface", { open: props.isOpen, onDismiss: props.close, style: {
'--menu-surface-width': '100%',
'max-height': 'inherit',
display: 'flex',
'min-width': '100%',
width: 'fit-content',
} }, h("limel-list", { items: items, type: props.multiple ? 'checkbox' : 'selectable', onChange: props.onMenuChange }))));
};
const NativeDropdown = (props) => {
const options = props.options
.filter((option) => !('separator' in option))
.map(renderOption(props.value));
return (h("select", { required: props.required, "aria-disabled": props.disabled, "aria-required": props.required, onChange: props.onNativeChange, onFocus: props.open, onBlur: props.close, class: "limel-select__native-control", disabled: props.disabled, multiple: props.multiple }, options));
};
const renderOption = (selectedOption) => {
return (option) => {
const { value, disabled, text } = option;
return (h("option", { key: value, value: value, selected: isSelected(option, selectedOption), disabled: disabled }, text));
};
};
function isSelected(option, value) {
if (!value) {
return false;
}
if (isMultiple(value)) {
return value.some((o) => option.value === o.value);
}
return option.value === value.value;
}
function createMenuItems(options, value, selectIsRequired = false) {
const menuOptionFilter = getMenuOptionFilter(selectIsRequired);
return options.filter(menuOptionFilter).map((option) => {
if ('separator' in option) {
return {
text: option.text,
separator: true,
};
}
const selected = isSelected(option, value);
const { text, secondaryText, disabled } = option;
const name = getIconName(option.icon);
const color = getIconColor(option.icon, option.iconColor);
if (!name) {
return {
text: text,
secondaryText: secondaryText,
selected: selected,
disabled: disabled,
value: option,
};
}
return {
text: text,
secondaryText: secondaryText,
selected: selected,
disabled: disabled,
value: option,
icon: {
name: name,
color: color,
},
};
});
}
function getMenuOptionFilter(selectIsRequired) {
return (option) => {
if (!selectIsRequired) {
// If the select component is NOT required, we keep all options.
return true;
}
if (option.text) {
// If the select component IS required, we keep only options
// that are not "empty". We only check the text property, because
// some systems use an "empty option" that will have a value for
// the `value` property, to signify "no option selected". Such
// an option should be treated as "empty".
return true;
}
if ('separator' in option) {
return true;
}
};
}
function getSelectedText(value) {
const isEmptyValue = !value || (isMultiple(value) && value.length === 0);
if (isEmptyValue) {
return '';
}
if (isMultiple(value)) {
return value.map((option) => option.text).join(', ');
}
return value.text;
}
function getSelectedIcon(value) {
if (!(value === null || value === void 0 ? void 0 : value.icon)) {
return '';
}
const name = getIconName(value.icon);
const color = getIconColor(value.icon, value.iconColor);
const style = {};
if (color) {
style.color = color;
}
return (h("limel-icon", { class: "limel-select__selected-option__icon", name: name, size: "medium", style: style }));
}
/**
*
* @param options
*/
export function triggerIconColorWarning(options) {
for (const option of options) {
if (option.iconColor) {
console.warn("The `iconColor` prop is deprecated now! Use the new `Icon` interface and instead of `iconColor: 'color-name'` write `icon {name: 'icon-name', color: 'color-name'}`.");
}
}
}
//# sourceMappingURL=select.template.js.map