@shopify/polaris
Version:
Shopify’s admin product component library
210 lines (183 loc) • 5.79 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var React = require('react');
var polarisIcons = require('@shopify/polaris-icons');
var css = require('../../utilities/css.js');
var Select$1 = require('./Select.scss.js');
var hooks = require('../../utilities/unique-id/hooks.js');
var Icon = require('../Icon/Icon.js');
var Labelled = require('../Labelled/Labelled.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
const PLACEHOLDER_VALUE = '';
function Select({
options: optionsProp,
label,
labelAction,
labelHidden: labelHiddenProp,
labelInline,
disabled,
helpText,
placeholder,
id: idProp,
name,
value = PLACEHOLDER_VALUE,
error,
onChange,
onFocus,
onBlur,
requiredIndicator
}) {
const id = hooks.useUniqueId('Select', idProp);
const labelHidden = labelInline ? true : labelHiddenProp;
const className = css.classNames(Select$1['default'].Select, error && Select$1['default'].error, disabled && Select$1['default'].disabled);
const handleChange = onChange ? event => onChange(event.currentTarget.value, id) : undefined;
const describedBy = [];
if (helpText) {
describedBy.push(Labelled.helpTextID(id));
}
if (error) {
describedBy.push(`${id}Error`);
}
const options = optionsProp || [];
let normalizedOptions = options.map(normalizeOption);
if (placeholder) {
normalizedOptions = [{
label: placeholder,
value: PLACEHOLDER_VALUE,
disabled: true
}, ...normalizedOptions];
}
const inlineLabelMarkup = labelInline && /*#__PURE__*/React__default['default'].createElement("span", {
className: Select$1['default'].InlineLabel
}, label);
const selectedOption = getSelectedOption(normalizedOptions, value);
const prefixMarkup = selectedOption.prefix && /*#__PURE__*/React__default['default'].createElement("div", {
className: Select$1['default'].Prefix
}, selectedOption.prefix);
const contentMarkup = /*#__PURE__*/React__default['default'].createElement("div", {
className: Select$1['default'].Content,
"aria-hidden": true,
"aria-disabled": disabled
}, inlineLabelMarkup, prefixMarkup, /*#__PURE__*/React__default['default'].createElement("span", {
className: Select$1['default'].SelectedOption
}, selectedOption.label), /*#__PURE__*/React__default['default'].createElement("span", {
className: Select$1['default'].Icon
}, /*#__PURE__*/React__default['default'].createElement(Icon.Icon, {
source: polarisIcons.SelectMinor
})));
const optionsMarkup = normalizedOptions.map(renderOption);
return /*#__PURE__*/React__default['default'].createElement(Labelled.Labelled, {
id: id,
label: label,
error: error,
action: labelAction,
labelHidden: labelHidden,
helpText: helpText,
requiredIndicator: requiredIndicator
}, /*#__PURE__*/React__default['default'].createElement("div", {
className: className
}, /*#__PURE__*/React__default['default'].createElement("select", {
id: id,
name: name,
value: value,
className: Select$1['default'].Input,
disabled: disabled,
onFocus: onFocus,
onBlur: onBlur,
onChange: handleChange,
"aria-invalid": Boolean(error),
"aria-describedby": describedBy.length ? describedBy.join(' ') : undefined,
"aria-required": requiredIndicator
}, optionsMarkup), contentMarkup, /*#__PURE__*/React__default['default'].createElement("div", {
className: Select$1['default'].Backdrop
})));
}
function isString(option) {
return typeof option === 'string';
}
function isGroup(option) {
return typeof option === 'object' && 'options' in option && option.options != null;
}
function normalizeStringOption(option) {
return {
label: option,
value: option
};
}
/**
* Converts a string option (and each string option in a Group) into
* an Option object.
*/
function normalizeOption(option) {
if (isString(option)) {
return normalizeStringOption(option);
} else if (isGroup(option)) {
const {
title,
options
} = option;
return {
title,
options: options.map(option => {
return isString(option) ? normalizeStringOption(option) : option;
})
};
}
return option;
}
/**
* Gets the text to display in the UI, for the currently selected option
*/
function getSelectedOption(options, value) {
const flatOptions = flattenOptions(options);
let selectedOption = flatOptions.find(option => value === option.value);
if (selectedOption === undefined) {
// Get the first visible option (not the hidden placeholder)
selectedOption = flatOptions.find(option => !option.hidden);
}
return selectedOption || {
value: '',
label: ''
};
}
/**
* Ungroups an options array
*/
function flattenOptions(options) {
let flatOptions = [];
options.forEach(optionOrGroup => {
if (isGroup(optionOrGroup)) {
flatOptions = flatOptions.concat(optionOrGroup.options);
} else {
flatOptions.push(optionOrGroup);
}
});
return flatOptions;
}
function renderSingleOption(option) {
const {
value,
label,
prefix: _prefix,
...rest
} = option;
return /*#__PURE__*/React__default['default'].createElement("option", Object.assign({
key: value,
value: value
}, rest), label);
}
function renderOption(optionOrGroup) {
if (isGroup(optionOrGroup)) {
const {
title,
options
} = optionOrGroup;
return /*#__PURE__*/React__default['default'].createElement("optgroup", {
label: title,
key: title
}, options.map(renderSingleOption));
}
return renderSingleOption(optionOrGroup);
}
exports.Select = Select;