@codecademy/gamut
72.2.472.2.5-alpha.619ec9.0
dist/Form/SelectDropdown/SelectDropdown.js~
dist/Form/SelectDropdown/SelectDropdown.jsModified+71−103
Index: package/dist/Form/SelectDropdown/SelectDropdown.js
===================================================================
--- package/dist/Form/SelectDropdown/SelectDropdown.js
+++ package/dist/Form/SelectDropdown/SelectDropdown.js
@@ -1,28 +1,23 @@
+import _styled from "@emotion/styled/base";
+import { screenReaderOnly } from '@codecademy/gamut-styles';
import { useTheme } from '@emotion/react';
-import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
+import { useId, useMemo, useRef, useState } from 'react';
import * as React from 'react';
-import { parseOptions } from '../utils';
-import { AbbreviatedSingleValue, CustomContainer, CustomInput, CustomValueContainer, DropdownButton, formatGroupLabel, formatOptionLabel, IconOption, MultiValueRemoveButton, MultiValueWithColorMode, onFocus, RemoveAllButton, SelectDropdownContext, TypedReactSelect } from './elements';
-import { getMemoizedStyles } from './styles';
-import { filterValueFromOptions, isMultipleSelectProps, isOptionsGrouped, isSingleSelectProps, removeValueFromSelectedOptions } from './utils';
-import { jsx as _jsx } from "react/jsx-runtime";
-const defaultProps = {
- name: undefined,
- components: {
- DropdownIndicator: DropdownButton,
- IndicatorSeparator: () => null,
- ClearIndicator: RemoveAllButton,
- SelectContainer: CustomContainer,
- ValueContainer: CustomValueContainer,
- MultiValue: MultiValueWithColorMode,
- MultiValueRemove: MultiValueRemoveButton,
- Option: IconOption,
- SingleValue: AbbreviatedSingleValue,
- Input: CustomInput
- }
-};
-const onChangeAction = 'select-option';
+import { onFocus } from './core/accessibility';
+import { getDefaultComponents } from './core/constants';
+import { getMemoizedStyles } from './core/styles';
+import { resolveNoOptionsMessage } from './core/utils';
+import { formatGroupLabel, formatOptionLabel, SelectDropdownContext, TypedReactSelect } from './elements';
+import { useNoOptionsAnnouncement } from './hooks/useNoOptionsAnnouncement';
+import { useSelectHandlers } from './hooks/useSelectHandlers';
+import { useSelectOptions } from './hooks/useSelectOptions';
+import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
+/** Announces the custom `validationMessage` menu text - see `useNoOptionsAnnouncement`. */
+const NoOptionsLiveRegion = /*#__PURE__*/_styled("div", {
+ target: "e2dtq0m0",
+ label: "NoOptionsLiveRegion"
+})(screenReaderOnly, process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9Gb3JtL1NlbGVjdERyb3Bkb3duL1NlbGVjdERyb3Bkb3duLnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUF1QjRCIiwiZmlsZSI6Ii4uLy4uLy4uL3NyYy9Gb3JtL1NlbGVjdERyb3Bkb3duL1NlbGVjdERyb3Bkb3duLnRzeCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNjcmVlblJlYWRlck9ubHkgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHsgdXNlVGhlbWUgfSBmcm9tICdAZW1vdGlvbi9yZWFjdCc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCc7XG5pbXBvcnQgeyB1c2VJZCwgdXNlTWVtbywgdXNlUmVmLCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0JztcbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7IFN0eWxlc0NvbmZpZyB9IGZyb20gJ3JlYWN0LXNlbGVjdCc7XG5cbmltcG9ydCB7IG9uRm9jdXMgfSBmcm9tICcuL2NvcmUvYWNjZXNzaWJpbGl0eSc7XG5pbXBvcnQgeyBnZXREZWZhdWx0Q29tcG9uZW50cyB9IGZyb20gJy4vY29yZS9jb25zdGFudHMnO1xuaW1wb3J0IHsgZ2V0TWVtb2l6ZWRTdHlsZXMgfSBmcm9tICcuL2NvcmUvc3R5bGVzJztcbmltcG9ydCB7IHJlc29sdmVOb09wdGlvbnNNZXNzYWdlIH0gZnJvbSAnLi9jb3JlL3V0aWxzJztcbmltcG9ydCB7XG4gIGZvcm1hdEdyb3VwTGFiZWwsXG4gIGZvcm1hdE9wdGlvbkxhYmVsLFxuICBTZWxlY3REcm9wZG93bkNvbnRleHQsXG4gIFR5cGVkUmVhY3RTZWxlY3QsXG59IGZyb20gJy4vZWxlbWVudHMnO1xuaW1wb3J0IHsgdXNlTm9PcHRpb25zQW5ub3VuY2VtZW50IH0gZnJvbSAnLi9ob29rcy91c2VOb09wdGlvbnNBbm5vdW5jZW1lbnQnO1xuaW1wb3J0IHsgdXNlU2VsZWN0SGFuZGxlcnMgfSBmcm9tICcuL2hvb2tzL3VzZVNlbGVjdEhhbmRsZXJzJztcbmltcG9ydCB7IHVzZVNlbGVjdE9wdGlvbnMgfSBmcm9tICcuL2hvb2tzL3VzZVNlbGVjdE9wdGlvbnMnO1xuaW1wb3J0IHsgU2VsZWN0RHJvcGRvd25Qcm9wcyB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKiogQW5ub3VuY2VzIHRoZSBjdXN0b20gYHZhbGlkYXRpb25NZXNzYWdlYCBtZW51IHRleHQgLSBzZWUgYHVzZU5vT3B0aW9uc0Fubm91bmNlbWVudGAuICovXG5jb25zdCBOb09wdGlvbnNMaXZlUmVnaW9uID0gc3R5bGVkLmRpdihzY3JlZW5SZWFkZXJPbmx5KTtcblxuLyoqXG4gKiBBIGZsZXhpYmxlIGRyb3Bkb3duIHNlbGVjdCBjb21wb25lbnQgYnVpbHQgb24gdG9wIG9mIHJlYWN0LXNlbGVjdC5cbiAqXG4gKiBTdXBwb3J0cyBib3RoIHNpbmdsZSBhbmQgbXVsdGktc2VsZWN0IG1vZGVzIHdpdGggY3VzdG9taXphYmxlIG9wdGlvbnMgaW5jbHVkaW5nXG4gKiBpY29ucywgc3VidGl0bGVzLCByaWdodCBsYWJlbHMsIGFuZCBhYmJyZXZpYXRpb25zLiBUaGUgY29tcG9uZW50IHByb3ZpZGVzXG4gKiBhY2Nlc3NpYmlsaXR5IGZlYXR1cmVzLCBrZXlib2FyZCBuYXZpZ2F0aW9uLCBhbmQgcmVzcG9uc2l2ZSBzdHlsaW5nLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c3hcbiAqIC8vIEJhc2ljIHNpbmdsZSBzZWxlY3RcbiAqIDxTZWxlY3REcm9wZG93blxuICogICBuYW1lPVwiY291bnRyeVwiXG4gKiAgIG9wdGlvbnM9e1tcbiAqICAgICB7IGxhYmVsOiAnVW5pdGVkIFN0YXRlcycsIHZhbHVlOiAndXMnIH0sXG4gKiAgICAgeyBsYWJlbDogJ0NhbmFkYScsIHZhbHVlOiAnY2EnIH1cbiAqICAgXX1cbiAqICAgb25DaGFuZ2U9eyhvcHRpb24pID0+IGNvbnNvbGUubG9nKG9wdGlvbil9XG4gKiAvPlxuICpcbiAqIC8vIE11bHRpLXNlbGVjdCB3aXRoIGljb25zXG4gKiA8U2VsZWN0RHJvcGRvd25cbiAqICAgbmFtZT1cInNraWxsc1wiXG4gKiAgIG11bHRpcGxlXG4gKiAgIG9wdGlvbnM9e1tcbiAqICAgICB7IGxhYmVsOiAnUmVhY3QnLCB2YWx1ZTogJ3JlYWN0JywgaWNvbjogUmVhY3RJY29uIH0sXG4gKiAgICAgeyBsYWJlbDogJ1R5cGVTY3JpcHQnLCB2YWx1ZTogJ3RzJywgaWNvbjogVHlwZVNjcmlwdEljb24gfVxuICogICBdfVxuICogICBvbkNoYW5nZT17KG9wdGlvbnMpID0+IGNvbnNvbGUubG9nKG9wdGlvbnMpfVxuICogLz5cbiAqXG4gKiAvLyBHcm91cGVkIG9wdGlvbnMgd2l0aCBleHRlbmRlZCBmZWF0dXJlc1xuICogPFNlbGVjdERyb3Bkb3duXG4gKiAgIG5hbWU9XCJjYXRlZ29yeVwiXG4gKiAgIHBsYWNlaG9sZGVyPVwiRGVmYXVsdCBwbGFjZWhvbGRlciB0ZXh0XCJcbiAqICAgb3B0aW9ucz17W1xuICogICAgIHtcbiAqICAgICAgIGxhYmVsOiAnRnJvbnRlbmQnLFxuICogICAgICAgb3B0aW9uczogW1xuICogICAgICAgICB7IGxhYmVsOiAnUmVhY3QnLCB2YWx1ZTogJ3JlYWN0Jywgc3VidGl0bGU6ICdVSSBMaWJyYXJ5JyB9LFxuICogICAgICAgICB7IGxhYmVsOiAnVnVlJywgdmFsdWU6ICd2dWUnLCBzdWJ0aXRsZTogJ1Byb2dyZXNzaXZlIEZyYW1ld29yaycgfVxuICogICAgICAgXVxuICogICAgIH1cbiAqICAgXX1cbiAqIC8+XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNvbnN0IFNlbGVjdERyb3Bkb3duOiBSZWFjdC5GQzxTZWxlY3REcm9wZG93blByb3BzPiA9ICh7XG4gIGRpc2FibGVkLFxuICBkcm9wZG93bldpZHRoLFxuICBlcnJvcixcbiAgZm9ybWF0Q3JlYXRlTGFiZWwgPSAoaW5wdXRWYWx1ZTogc3RyaW5nKSA9PiBgQWRkIFwiJHtpbnB1dFZhbHVlfVwiYCxcbiAgaWQsXG4gIGlucHV0UHJvcHMsXG4gIGlucHV0V2lkdGgsXG4gIGlzQ3JlYXRhYmxlID0gZmFsc2UsXG4gIGlzU2VhcmNoYWJsZTogaXNTZWFyY2hhYmxlUHJvcCA9IGZhbHNlLFxuICBpc1ZhbGlkTmV3T3B0aW9uLFxuICBtZW51QWxpZ25tZW50ID0gJ2xlZnQnLFxuICBtdWx0aXBsZSxcbiAgbmFtZSxcbiAgb25DaGFuZ2UsXG4gIG9uQ3JlYXRlT3B0aW9uLFxuICBvbklucHV0Q2hhbmdlLFxuICBvcHRpb25zLFxuICBwbGFjZWhvbGRlciA9ICdTZWxlY3QgYW4gb3B0aW9uJyxcbiAgc2hvd25PcHRpb25zTGltaXQgPSA2LFxuICBzaXplLFxuICB2YWxpZGF0aW9uTWVzc2FnZSxcbiAgdmFsdWUsXG4gIHpJbmRleCxcbiAgLi4ucmVzdFxufSkgPT4ge1xuICAvLyBpc1NlYXJjaGFibGUgaXMgZm9yY2VkIHRydWUgd2hlbiBpc0NyZWF0YWJsZSBpcyB0cnVlIChDcmVhdGFibGVTZWxlY3QgcmVxdWlyZXMgYSB0ZXh0IGlucHV0KVxuICBjb25zdCBpc1NlYXJjaGFibGUgPSBpc0NyZWF0YWJsZSB8fCBpc1NlYXJjaGFibGVQcm9wO1xuICBjb25zdCByYXdJbnB1dElkID0gdXNlSWQoKTtcbiAgY29uc3QgaW5wdXRJZCA9IG5hbWUgPz8gYCR7aWR9LXNlbGVjdC1kcm9wZG93bi0ke3Jhd0lucHV0SWR9YDtcblxuICBjb25zdCByZW1vdmVBbGxCdXR0b25SZWYgPSB1c2VSZWY8SFRNTERpdkVsZW1lbnQ+KG51bGwpO1xuICBjb25zdCBzZWxlY3RJbnB1dFJlZiA9IHVzZVJlZjxIVE1MRGl2RWxlbWVudD4obnVsbCk7XG5cbiAgY29uc3QgW2N1cnJlbnRGb2N1c2VkVmFsdWUsIHNldEN1cnJlbnRGb2N1c2VkVmFsdWVdID0gdXNlU3RhdGUodW5kZWZpbmVkKTtcblxuICBjb25zdCB7IHNlbGVjdE9wdGlvbnMsIHBhcnNlZFZhbHVlIH0gPSB1c2VTZWxlY3RPcHRpb25zKHtcbiAgICBvcHRpb25zLFxuICAgIGlkLFxuICAgIHNpemUsXG4gICAgdmFsdWU6IHZhbHVlIGFzIHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkLFxuICB9KTtcblxuICBjb25zdCBub09wdGlvbnNNZXNzYWdlID0gcmVzb2x2ZU5vT3B0aW9uc01lc3NhZ2UodmFsaWRhdGlvbk1lc3NhZ2UpO1xuICBjb25zdCB7IG5vT3B0aW9uc01lc3NhZ2VDb21wb25lbnQsIGFubm91bmNlbWVudCwgYW5ub3VuY2VtZW50S2V5IH0gPVxuICAgIHVzZU5vT3B0aW9uc0Fubm91bmNlbWVudCgpO1xuICBjb25zdCBjb21wb25lbnRzID0gdXNlTWVtbyhcbiAgICAoKSA9PiBnZXREZWZhdWx0Q29tcG9uZW50cyhub09wdGlvbnNNZXNzYWdlQ29tcG9uZW50KSxcbiAgICBbbm9PcHRpb25zTWVzc2FnZUNvbXBvbmVudF1cbiAgKTtcblxuICBjb25zdCB7IGFjdGl2YXRlZCwgbXVsdGlWYWx1ZXMsIGNoYW5nZUhhbmRsZXIsIGtleVByZXNzSGFuZGxlciB9ID1cbiAgICB1c2VTZWxlY3RIYW5kbGVycyh7XG4gICAgICBvbkNoYW5nZSxcbiAgICAgIG11bHRpcGxlLFxuICAgICAgb25DcmVhdGVPcHRpb24sXG4gICAgICBzZWxlY3RPcHRpb25zLFxuICAgICAgdmFsdWUsXG4gICAgICBjdXJyZW50Rm9jdXNlZFZhbHVlLFxuICAgICAgcmVtb3ZlQWxsQnV0dG9uUmVmLFxuICAgIH0pO1xuXG4gIGNvbnN0IHRoZW1lID0gdXNlVGhlbWUoKTtcbiAgY29uc3QgbWVtb2l6ZWRTdHlsZXMgPSB1c2VNZW1vKCgpOiBTdHlsZXNDb25maWc8YW55LCBmYWxzZT4gPT4ge1xuICAgIHJldHVybiBnZXRNZW1vaXplZFN0eWxlcyh0aGVtZSwgekluZGV4KTtcbiAgfSwgW3RoZW1lLCB6SW5kZXhdKTtcblxuICByZXR1cm4gKFxuICAgIDxTZWxlY3REcm9wZG93bkNvbnRleHQuUHJvdmlkZXJcbiAgICAgIHZhbHVlPXt7XG4gICAgICAgIGN1cnJlbnRGb2N1c2VkVmFsdWUsXG4gICAgICAgIHNldEN1cnJlbnRGb2N1c2VkVmFsdWUsXG4gICAgICAgIHJlbW92ZUFsbEJ1dHRvblJlZixcbiAgICAgICAgc2VsZWN0SW5wdXRSZWYsXG4gICAgICB9fVxuICAgID5cbiAgICAgIDxUeXBlZFJlYWN0U2VsZWN0XG4gICAgICAgIGFjdGl2YXRlZD17YWN0aXZhdGVkfVxuICAgICAgICBhcmlhLWxpdmU9XCJhc3NlcnRpdmVcIlxuICAgICAgICBhcmlhTGl2ZU1lc3NhZ2VzPXt7IG9uRm9jdXMgfX1cbiAgICAgICAgY29tcG9uZW50cz17Y29tcG9uZW50c31cbiAgICAgICAgZHJvcGRvd25XaWR0aD17ZHJvcGRvd25XaWR0aH1cbiAgICAgICAgZXJyb3I9e0Jvb2xlYW4oZXJyb3IpfVxuICAgICAgICBmb3JtYXRDcmVhdGVMYWJlbD17Zm9ybWF0Q3JlYXRlTGFiZWx9XG4gICAgICAgIGZvcm1hdEdyb3VwTGFiZWw9e2Zvcm1hdEdyb3VwTGFiZWx9XG4gICAgICAgIGZvcm1hdE9wdGlvbkxhYmVsPXtmb3JtYXRPcHRpb25MYWJlbH1cbiAgICAgICAgaWQ9e2lkIHx8IHJlc3QuaHRtbEZvciB8fCByYXdJbnB1dElkfVxuICAgICAgICBpbnB1dElkPXtpbnB1dElkfVxuICAgICAgICBpbnB1dFByb3BzPXt7IC4uLmlucHV0UHJvcHMgfX1cbiAgICAgICAgaW5wdXRXaWR0aD17aW5wdXRXaWR0aH1cbiAgICAgICAgaXNDcmVhdGFibGU9e2lzQ3JlYXRhYmxlfVxuICAgICAgICBpc0Rpc2FibGVkPXtkaXNhYmxlZH1cbiAgICAgICAgaXNNdWx0aT17bXVsdGlwbGV9XG4gICAgICAgIGlzT3B0aW9uRGlzYWJsZWQ9eyhvcHRpb24pID0+IG9wdGlvbi5kaXNhYmxlZH1cbiAgICAgICAgaXNTZWFyY2hhYmxlPXtpc1NlYXJjaGFibGV9XG4gICAgICAgIGlzVmFsaWROZXdPcHRpb249e2lzVmFsaWROZXdPcHRpb259XG4gICAgICAgIG1lbnVBbGlnbm1lbnQ9e21lbnVBbGlnbm1lbnR9XG4gICAgICAgIG5hbWU9e25hbWV9XG4gICAgICAgIG5vT3B0aW9uc01lc3NhZ2U9e25vT3B0aW9uc01lc3NhZ2V9XG4gICAgICAgIG9wdGlvbnM9e3NlbGVjdE9wdGlvbnN9XG4gICAgICAgIHBsYWNlaG9sZGVyPXtwbGFjZWhvbGRlcn1cbiAgICAgICAgc2VsZWN0UmVmPXtzZWxlY3RJbnB1dFJlZn1cbiAgICAgICAgc2hvd25PcHRpb25zTGltaXQ9e3Nob3duT3B0aW9uc0xpbWl0fVxuICAgICAgICBzaXplPXtzaXplfVxuICAgICAgICBzdHlsZXM9e21lbW9pemVkU3R5bGVzfVxuICAgICAgICB2YWx1ZT17bXVsdGlwbGUgPyBtdWx0aVZhbHVlcyA6IHBhcnNlZFZhbHVlfVxuICAgICAgICBvbkNoYW5nZT17Y2hhbmdlSGFuZGxlcn1cbiAgICAgICAgb25JbnB1dENoYW5nZT17b25JbnB1dENoYW5nZX1cbiAgICAgICAgb25LZXlEb3duPXttdWx0aXBsZSA/IGtleVByZXNzSGFuZGxlciA6IHVuZGVmaW5lZH1cbiAgICAgICAgey4uLnJlc3R9XG4gICAgICAvPlxuICAgICAgPE5vT3B0aW9uc0xpdmVSZWdpb25cbiAgICAgICAgYXJpYS1saXZlPVwicG9saXRlXCJcbiAgICAgICAga2V5PXthbm5vdW5jZW1lbnRLZXl9XG4gICAgICAgIHJvbGU9XCJzdGF0dXNcIlxuICAgICAgPlxuICAgICAgICB7YW5ub3VuY2VtZW50fVxuICAgICAgPC9Ob09wdGlvbnNMaXZlUmVnaW9uPlxuICAgIDwvU2VsZWN0RHJvcGRvd25Db250ZXh0LlByb3ZpZGVyPlxuICApO1xufTtcbiJdfQ== */");
/**
* A flexible dropdown select component built on top of react-select.
*
@@ -72,146 +67,119 @@
export const SelectDropdown = ({
disabled,
dropdownWidth,
error,
+ formatCreateLabel = inputValue => `Add "${inputValue}"`,
id,
inputProps,
inputWidth,
- isSearchable = false,
+ isCreatable = false,
+ isSearchable: isSearchableProp = false,
+ isValidNewOption,
menuAlignment = 'left',
multiple,
name,
onChange,
+ onCreateOption,
+ onInputChange,
options,
placeholder = 'Select an option',
shownOptionsLimit = 6,
size,
+ validationMessage,
value,
zIndex,
...rest
}) => {
+ // isSearchable is forced true when isCreatable is true (CreatableSelect requires a text input)
+ const isSearchable = isCreatable || isSearchableProp;
const rawInputId = useId();
const inputId = name ?? `${id}-select-dropdown-${rawInputId}`;
- const [activated, setActivated] = useState(false);
- const [currentFocusedValue, setCurrentFocusedValue] = useState(undefined);
-
- // these are used to programatically manage the focus state of our multi-select options + 'Remove all' button
const removeAllButtonRef = useRef(null);
const selectInputRef = useRef(null);
- const selectOptions = useMemo(() => {
- if (!options || Array.isArray(options) && !options.length || typeof options === 'object' && !Array.isArray(options) && Object.keys(options).length === 0) {
- return [];
- }
- if (isOptionsGrouped(options)) {
- return options;
- }
- return parseOptions({
- options,
- id,
- size
- });
- }, [options, id, size]);
- const parsedValue = useMemo(() => {
- if (isOptionsGrouped(selectOptions)) {
- for (const group of selectOptions) {
- if (group.options) {
- const foundOption = group.options.find(option => option.value === value);
- if (foundOption) return foundOption;
- }
- }
- return undefined;
- }
- return selectOptions.find(option => option.value === value);
- }, [selectOptions, value]);
- const [multiValues, setMultiValues] = useState(multiple &&
- // To keep this efficient for non-multiSelect
- filterValueFromOptions(selectOptions, value, isOptionsGrouped(selectOptions)));
-
- // If the caller changes the initial value, let's update our value to match.
- useEffect(() => {
- const newMultiValues = filterValueFromOptions(selectOptions, value, isOptionsGrouped(selectOptions));
- if (newMultiValues !== multiValues) setMultiValues(newMultiValues);
-
- //
- // We only update this when our passed in options or value changes, not multiValues.
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [options, value]);
- const changeHandler = useCallback(optionEvent => {
- setActivated(true);
-
- // We have to do this because the version of typescript we have doesn't have the transitivity of these type guards yet. But, we will soon!
- // Should probably come with: https://codecademy.atlassian.net/browse/GM-354
- const onChangeProps = {
- onChange,
- multiple
- };
- if (isSingleSelectProps(onChangeProps)) {
- const singleOptionEvent = optionEvent;
- onChangeProps.onChange?.(singleOptionEvent, {
- action: onChangeAction,
- option: singleOptionEvent
- });
- }
- if (isMultipleSelectProps(onChangeProps)) {
- setMultiValues(optionEvent);
- onChangeProps.onChange?.(optionEvent, {
- action: onChangeAction,
- option: undefined // At the moment this isn't used, but when multi select is built for real, boom (https://codecademy.atlassian.net/browse/GM-354)
- });
- }
- }, [onChange, multiple]);
- const keyPressHandler = e => {
- if (multiple && e.key === 'Enter' && currentFocusedValue && multiValues) {
- const newMultiValues = removeValueFromSelectedOptions(multiValues, currentFocusedValue);
- if (newMultiValues !== multiValues) setMultiValues(newMultiValues);
- }
- if (removeAllButtonRef.current !== null && e.key === 'ArrowRight' && multiValues && currentFocusedValue === multiValues[multiValues.length - 1].value) {
- removeAllButtonRef.current.focus();
- }
- };
+ const [currentFocusedValue, setCurrentFocusedValue] = useState(undefined);
+ const {
+ selectOptions,
+ parsedValue
+ } = useSelectOptions({
+ options,
+ id,
+ size,
+ value: value
+ });
+ const noOptionsMessage = resolveNoOptionsMessage(validationMessage);
+ const {
+ noOptionsMessageComponent,
+ announcement,
+ announcementKey
+ } = useNoOptionsAnnouncement();
+ const components = useMemo(() => getDefaultComponents(noOptionsMessageComponent), [noOptionsMessageComponent]);
+ const {
+ activated,
+ multiValues,
+ changeHandler,
+ keyPressHandler
+ } = useSelectHandlers({
+ onChange,
+ multiple,
+ onCreateOption,
+ selectOptions,
+ value,
+ currentFocusedValue,
+ removeAllButtonRef
+ });
const theme = useTheme();
const memoizedStyles = useMemo(() => {
return getMemoizedStyles(theme, zIndex);
}, [theme, zIndex]);
- return /*#__PURE__*/_jsx(SelectDropdownContext.Provider, {
+ return /*#__PURE__*/_jsxs(SelectDropdownContext.Provider, {
value: {
currentFocusedValue,
setCurrentFocusedValue,
removeAllButtonRef,
selectInputRef
},
- children: /*#__PURE__*/_jsx(TypedReactSelect, {
- ...defaultProps,
+ children: [/*#__PURE__*/_jsx(TypedReactSelect, {
activated: activated,
"aria-live": "assertive",
ariaLiveMessages: {
onFocus
},
+ components: components,
dropdownWidth: dropdownWidth,
error: Boolean(error),
+ formatCreateLabel: formatCreateLabel,
formatGroupLabel: formatGroupLabel,
formatOptionLabel: formatOptionLabel,
id: id || rest.htmlFor || rawInputId,
inputId: inputId,
inputProps: {
...inputProps
},
inputWidth: inputWidth,
+ isCreatable: isCreatable,
isDisabled: disabled,
isMulti: multiple,
isOptionDisabled: option => option.disabled,
isSearchable: isSearchable,
+ isValidNewOption: isValidNewOption,
menuAlignment: menuAlignment,
name: name,
+ noOptionsMessage: noOptionsMessage,
options: selectOptions,
placeholder: placeholder,
selectRef: selectInputRef,
shownOptionsLimit: shownOptionsLimit,
size: size,
styles: memoizedStyles,
value: multiple ? multiValues : parsedValue,
onChange: changeHandler,
- onKeyDown: multiple ? e => keyPressHandler(e) : undefined,
+ onInputChange: onInputChange,
+ onKeyDown: multiple ? keyPressHandler : undefined,
...rest
- })
+ }), /*#__PURE__*/_jsx(NoOptionsLiveRegion, {
+ "aria-live": "polite",
+ role: "status",
+ children: announcement
+ }, announcementKey)]
});
};
\ No newline at end of file