UNPKG

@shopify/polaris

Version:

Shopify’s product component library

127 lines (115 loc) 4.12 kB
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 };