@shopify/polaris
Version:
Shopify’s product component library
127 lines (115 loc) • 4.12 kB
JavaScript
import React$1, { useState, useCallback } from 'react';
import { useFeatures } from '../../utilities/features/hooks.js';
import { useUniqueId } from '../../utilities/unique-id/hooks.js';
import { classNames } from '../../utilities/css.js';
import { arraysAreEqual } from '../../utilities/arrays.js';
import { useDeepEffect as useDeepEffect$1 } from '../../utilities/use-deep-effect.js';
import { Option as Option$1 } from './components/Option/Option.js';
import styles from './OptionList.scss.js';
function OptionList({
options,
sections,
title,
selected,
allowMultiple,
role,
optionRole,
onChange,
id: idProp
}) {
var [normalizedOptions, setNormalizedOptions] = useState(createNormalizedOptions(options, sections, title));
var id = useUniqueId('OptionList', idProp);
var {
newDesignLanguage
} = useFeatures();
useDeepEffect$1(() => {
setNormalizedOptions(createNormalizedOptions(options || [], sections || [], title));
}, [options, sections, title], optionArraysAreEqual);
var handleClick = useCallback((sectionIndex, optionIndex) => {
var selectedValue = normalizedOptions[sectionIndex].options[optionIndex].value;
var foundIndex = selected.indexOf(selectedValue);
if (allowMultiple) {
var newSelection = foundIndex === -1 ? [selectedValue, ...selected] : [...selected.slice(0, foundIndex), ...selected.slice(foundIndex + 1, selected.length)];
onChange(newSelection);
return;
}
onChange([selectedValue]);
}, [normalizedOptions, selected, allowMultiple, onChange]);
var optionsExist = normalizedOptions.length > 0;
var optionsMarkup = optionsExist ? normalizedOptions.map(({
title,
options
}, sectionIndex) => {
var titleMarkup = title ? /*#__PURE__*/React$1.createElement("p", {
className: styles.Title,
role: role
}, title) : null;
var optionsMarkup = options && options.map((option, optionIndex) => {
var isSelected = selected.includes(option.value);
var optionId = option.id || "".concat(id, "-").concat(sectionIndex, "-").concat(optionIndex);
return /*#__PURE__*/React$1.createElement(Option$1, Object.assign({}, option, {
key: optionId,
id: optionId,
section: sectionIndex,
index: optionIndex,
onClick: handleClick,
select: isSelected,
allowMultiple: allowMultiple,
role: optionRole
}));
});
return /*#__PURE__*/React$1.createElement("li", {
key: title || "noTitle-".concat(sectionIndex)
}, titleMarkup, /*#__PURE__*/React$1.createElement("ul", {
className: styles.Options,
id: "".concat(id, "-").concat(sectionIndex),
role: role,
"aria-multiselectable": allowMultiple
}, optionsMarkup));
}) : null;
var optionListClassName = classNames(styles.OptionList, newDesignLanguage && styles.newDesignLanguage);
return /*#__PURE__*/React$1.createElement("ul", {
className: optionListClassName,
role: role
}, optionsMarkup);
}
function createNormalizedOptions(options, sections, title) {
if (options == null) {
var section = {
options: [],
title
};
return sections == null ? [] : [section, ...sections];
}
if (sections == null) {
return [{
title,
options
}];
}
return [{
title,
options
}, ...sections];
}
function isSection(arr) {
return typeof arr[0] === 'object' && Object.prototype.hasOwnProperty.call(arr[0], 'options');
}
function optionArraysAreEqual(firstArray, secondArray) {
if (isSection(firstArray) && isSection(secondArray)) {
return arraysAreEqual(firstArray, secondArray, testSectionsPropEquality);
}
return arraysAreEqual(firstArray, secondArray);
}
function testSectionsPropEquality(previousSection, currentSection) {
var {
options: previousOptions
} = previousSection;
var {
options: currentOptions
} = currentSection;
var optionsAreEqual = arraysAreEqual(previousOptions, currentOptions);
var titlesAreEqual = previousSection.title === currentSection.title;
return optionsAreEqual && titlesAreEqual;
}
export { OptionList };