@transferwise/components 45.27.0 → 45.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/build/i18n/cs.json +2 -0
  2. package/build/i18n/de.json +2 -0
  3. package/build/i18n/es.json +2 -0
  4. package/build/i18n/fr.json +2 -0
  5. package/build/i18n/hu.json +2 -0
  6. package/build/i18n/id.json +2 -0
  7. package/build/i18n/it.json +2 -0
  8. package/build/i18n/ja.json +2 -0
  9. package/build/i18n/pl.json +2 -0
  10. package/build/i18n/pt.json +5 -3
  11. package/build/i18n/ro.json +5 -3
  12. package/build/i18n/ru.json +3 -1
  13. package/build/i18n/th.json +2 -0
  14. package/build/i18n/tr.json +2 -0
  15. package/build/i18n/uk.json +2 -0
  16. package/build/i18n/zh-CN.json +8 -6
  17. package/build/i18n/zh-HK.json +2 -0
  18. package/build/index.esm.js +1344 -1253
  19. package/build/index.esm.js.map +1 -1
  20. package/build/index.js +1343 -1252
  21. package/build/index.js.map +1 -1
  22. package/build/main.css +1 -1
  23. package/build/styles/main.css +1 -1
  24. package/build/styles/moneyInput/MoneyInput.css +1 -1
  25. package/build/types/inputs/SelectInput.d.ts +2 -1
  26. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  27. package/build/types/moneyInput/MoneyInput.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/src/i18n/cs.json +2 -0
  30. package/src/i18n/de.json +2 -0
  31. package/src/i18n/es.json +2 -0
  32. package/src/i18n/fr.json +2 -0
  33. package/src/i18n/hu.json +2 -0
  34. package/src/i18n/id.json +2 -0
  35. package/src/i18n/it.json +2 -0
  36. package/src/i18n/ja.json +2 -0
  37. package/src/i18n/pl.json +2 -0
  38. package/src/i18n/pt.json +5 -3
  39. package/src/i18n/ro.json +5 -3
  40. package/src/i18n/ru.json +3 -1
  41. package/src/i18n/th.json +2 -0
  42. package/src/i18n/tr.json +2 -0
  43. package/src/i18n/uk.json +2 -0
  44. package/src/i18n/zh-CN.json +8 -6
  45. package/src/i18n/zh-HK.json +2 -0
  46. package/src/inputs/SelectInput.spec.tsx +5 -5
  47. package/src/inputs/SelectInput.tsx +24 -3
  48. package/src/main.css +1 -1
  49. package/src/moneyInput/MoneyInput.css +1 -1
  50. package/src/moneyInput/MoneyInput.js +85 -42
  51. package/src/moneyInput/MoneyInput.less +40 -159
  52. package/src/moneyInput/MoneyInput.rtl.spec.js +71 -0
  53. package/src/moneyInput/MoneyInput.spec.js +247 -116
  54. package/src/moneyInput/MoneyInput.story.tsx +54 -1
package/build/index.js CHANGED
@@ -6894,6 +6894,7 @@ function SelectInput({
6894
6894
  size = 'md',
6895
6895
  className,
6896
6896
  onChange,
6897
+ onSearchChange,
6897
6898
  onClear
6898
6899
  }) {
6899
6900
  const [open, setOpen] = React.useState(false);
@@ -6932,6 +6933,11 @@ function SelectInput({
6932
6933
  ...mergeProps__default.default({
6933
6934
  onClick: () => {
6934
6935
  setOpen(prev => !prev);
6936
+ },
6937
+ onKeyDown: event => {
6938
+ if (event.key === ' ' || event.key === 'Enter' || event.key === 'ArrowDown' || event.key === 'ArrowUp') {
6939
+ setOpen(prev => !prev);
6940
+ }
6935
6941
  }
6936
6942
  }, getInteractionProps())
6937
6943
  },
@@ -6964,7 +6970,8 @@ function SelectInput({
6964
6970
  filterable: filterable,
6965
6971
  filterPlaceholder: filterPlaceholder,
6966
6972
  searchInputRef: searchInputRef,
6967
- listboxRef: listboxRef
6973
+ listboxRef: listboxRef,
6974
+ onSearchChange: onSearchChange
6968
6975
  })
6969
6976
  })
6970
6977
  });
@@ -6976,6 +6983,7 @@ function SelectInputTriggerButton({
6976
6983
  const {
6977
6984
  ref,
6978
6985
  onClick,
6986
+ onKeyDown,
6979
6987
  ...interactionProps
6980
6988
  } = React.useContext(SelectInputTriggerButtonPropsContext);
6981
6989
  return /*#__PURE__*/jsxRuntime.jsx(react$1.Listbox.Button, {
@@ -6986,7 +6994,8 @@ function SelectInputTriggerButton({
6986
6994
  ...interactionProps
6987
6995
  },
6988
6996
  ...mergeProps__default.default({
6989
- onClick
6997
+ onClick,
6998
+ onKeyDown
6990
6999
  }, restProps)
6991
7000
  });
6992
7001
  }
@@ -7032,7 +7041,8 @@ function SelectInputOptions({
7032
7041
  filterable = false,
7033
7042
  filterPlaceholder,
7034
7043
  searchInputRef,
7035
- listboxRef
7044
+ listboxRef,
7045
+ onSearchChange
7036
7046
  }) {
7037
7047
  const intl = reactIntl.useIntl();
7038
7048
  const controllerRef = filterable ? searchInputRef : listboxRef;
@@ -7084,6 +7094,9 @@ function SelectInputOptions({
7084
7094
  },
7085
7095
  onChange: event => {
7086
7096
  setQuery(event.currentTarget.value);
7097
+ if (onSearchChange) {
7098
+ onSearchChange(event.currentTarget.value);
7099
+ }
7087
7100
  }
7088
7101
  })
7089
7102
  }) : null, /*#__PURE__*/jsxRuntime.jsxs("section", {
@@ -7813,1139 +7826,526 @@ Money.propTypes = {
7813
7826
  var Money$1 = Money;
7814
7827
 
7815
7828
  var messages$3 = reactIntl.defineMessages({
7816
- searchPlaceholder: {
7817
- id: "neptune.Select.searchPlaceholder"
7829
+ selectPlaceholder: {
7830
+ id: "neptune.MoneyInput.Select.placeholder"
7818
7831
  }
7819
7832
  });
7820
7833
 
7821
- // Option.tsx NEW
7822
- function Option$1({
7823
- label,
7824
- currency = '',
7825
- note = '',
7826
- secondary = '',
7827
- icon,
7828
- classNames = {},
7829
- selected = false
7830
- }) {
7831
- const {
7832
- isModern
7833
- } = componentsTheming.useTheme();
7834
- const style = classes => classes.map(className => classNames[className] || className).join(' ');
7835
- const currencyClassNames = currency ? style(['currency-flag', `currency-flag-${currency.toLowerCase()}`]) : undefined;
7836
- const iconElement = icon ? /*#__PURE__*/React.cloneElement(icon, {
7837
- size: 24,
7838
- className: 'tw-icon'
7839
- }) : currency && /*#__PURE__*/jsxRuntime.jsx("i", {
7840
- className: currencyClassNames
7841
- });
7842
- const titleAndNoteElement = /*#__PURE__*/jsxRuntime.jsxs(Body, {
7843
- as: "span",
7844
- type: exports.Typography.BODY_LARGE,
7845
- className: selected ? 'text-ellipsis' : undefined,
7846
- children: [label, note && /*#__PURE__*/jsxRuntime.jsx(Body, {
7847
- as: "span",
7848
- className: isModern ? 'm-l-1' : 'm-l-1 body-2',
7849
- children: note
7850
- })]
7851
- });
7852
- const secondaryElementClassNames = () => {
7853
- let classes = undefined;
7854
- if (selected) {
7855
- classes = 'text-ellipsis';
7856
- }
7857
- if (isModern) {
7858
- return classes;
7859
- }
7860
- return `${classes ? classes + ' ' : ''}body-2`;
7861
- };
7862
- const secondaryElement = secondary && /*#__PURE__*/jsxRuntime.jsx(Body, {
7863
- className: secondaryElementClassNames(),
7864
- children: secondary
7865
- });
7866
- return iconElement ? /*#__PURE__*/jsxRuntime.jsxs("div", {
7867
- className: "d-flex np-option-content",
7868
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
7869
- className: `d-flex flex-column${selected ? ' justify-content-center' : ''}`,
7870
- children: iconElement
7871
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
7872
- className: "d-flex flex-column justify-content-center",
7873
- children: [titleAndNoteElement, secondaryElement]
7874
- })]
7875
- }) : /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
7876
- children: [iconElement, titleAndNoteElement, secondaryElement]
7877
- });
7834
+ // TODO: do not duplicate this between formatting and components
7835
+ const currencyDecimals = {
7836
+ BIF: 0,
7837
+ BYR: 0,
7838
+ CLP: 0,
7839
+ DJF: 0,
7840
+ GNF: 0,
7841
+ JPY: 0,
7842
+ KMF: 0,
7843
+ KRW: 0,
7844
+ MGA: 0,
7845
+ PYG: 0,
7846
+ RWF: 0,
7847
+ VND: 0,
7848
+ VUV: 0,
7849
+ XAF: 0,
7850
+ XOF: 0,
7851
+ XPF: 0,
7852
+ // technically HUF does have decimals, but due to the exchange rate banks
7853
+ // do not accept decimal amounts
7854
+ HUF: 0,
7855
+ BHD: 3,
7856
+ JOD: 3,
7857
+ KWD: 3,
7858
+ OMR: 3,
7859
+ TND: 3
7860
+ };
7861
+ const DEFAULT_CURRENCY_DECIMALS = 2;
7862
+ function isNumberLocaleSupported() {
7863
+ const number = 1234;
7864
+ const numberString = number.toLocaleString && number.toLocaleString(DEFAULT_LOCALE);
7865
+ return numberString === '1,234';
7878
7866
  }
7879
-
7880
- const SearchBox = /*#__PURE__*/React.forwardRef(({
7881
- id,
7882
- classNames = {},
7883
- focusedOptionId,
7884
- onChange,
7885
- onClick,
7886
- placeholder = undefined,
7887
- value = ''
7888
- }, reference) => {
7889
- const style = className => classNames[className] || className;
7890
- return /*#__PURE__*/jsxRuntime.jsx("li", {
7891
- className: style('border-bottom'),
7892
- children: /*#__PURE__*/jsxRuntime.jsx("a", {
7893
- className: `${style('np-select-filter-link')} ${style('p-a-0')}`,
7894
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
7895
- className: style('input-group'),
7896
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
7897
- className: classNames__default.default('input-group-addon', 'input-group-addon--search'),
7898
- children: /*#__PURE__*/jsxRuntime.jsx(icons.Search, {
7899
- className: classNames__default.default(style('tw-icon'), style('tw-icon-search')),
7900
- size: 24
7901
- })
7902
- }), /*#__PURE__*/jsxRuntime.jsx(Input, {
7903
- ref: reference,
7904
- id: id,
7905
- role: "searchbox",
7906
- inputMode: "search",
7907
- className: classNames__default.default(style('np-select-filter')),
7908
- placeholder: placeholder,
7909
- value: value,
7910
- spellCheck: "false",
7911
- "aria-activedescendant": focusedOptionId,
7912
- onChange: onChange,
7913
- onClick: onClick
7914
- })]
7915
- })
7916
- })
7917
- });
7918
- });
7919
- var SearchBox$1 = SearchBox;
7920
-
7921
- const DEFAULT_SEARCH_VALUE = '';
7922
- const DEFAULT_OPTIONS_PAGE_SIZE = 1000;
7923
- const includesString = (string1, string2) => string1.toLowerCase().includes(string2.toLowerCase());
7924
- function defaultFilterFunction(option, searchValue) {
7925
- if (isPlaceholderOption(option)) {
7926
- return true;
7867
+ function getValidLocale(locale) {
7868
+ try {
7869
+ const noUnderscoreLocale = locale.replace(/_/, '-');
7870
+ Intl.NumberFormat(noUnderscoreLocale);
7871
+ return noUnderscoreLocale;
7872
+ } catch {
7873
+ return 'en-GB';
7927
7874
  }
7928
- const {
7929
- label,
7930
- note,
7931
- secondary,
7932
- currency,
7933
- searchStrings
7934
- } = option;
7935
- return !!label && includesString(label, searchValue) || !!note && includesString(note, searchValue) || !!secondary && includesString(secondary, searchValue) || !!currency && includesString(currency, searchValue) || !!searchStrings && searchStrings.some(string => includesString(string, searchValue));
7936
- }
7937
- function isActionableOption(option) {
7938
- return !option.header && !option.separator && !option.disabled;
7939
7875
  }
7940
- function isHeaderOption(option) {
7941
- return option != null && 'header' in option;
7876
+ function getCurrencyDecimals(currency = '') {
7877
+ const upperCaseCurrency = currency.toUpperCase();
7878
+ if (Object.prototype.hasOwnProperty.call(currencyDecimals, upperCaseCurrency)) {
7879
+ return currencyDecimals[upperCaseCurrency];
7880
+ }
7881
+ return DEFAULT_CURRENCY_DECIMALS;
7942
7882
  }
7943
- function isSeparatorOption(option) {
7944
- return option != null && 'separator' in option;
7883
+ function getDecimalSeparator(locale) {
7884
+ return isNumberLocaleSupported() ? 1.1.toLocaleString(locale)[1] : '.';
7945
7885
  }
7946
- function clamp(from, to, value) {
7947
- return Math.max(Math.min(to, value), from);
7886
+ function parseAmount(number, currency, locale) {
7887
+ const validLocale = getValidLocale(locale);
7888
+ const precision = getCurrencyDecimals(currency);
7889
+ const groupSeparator = isNumberLocaleSupported() ? 10000 .toLocaleString(validLocale)[2] : ',';
7890
+ const decimalSeparator = getDecimalSeparator(validLocale);
7891
+ const numberWithStandardDecimalSeparator = (number ? `${number}` : '').replace(new RegExp(`\\${groupSeparator}`, 'g'), '').replace(new RegExp(`\\${decimalSeparator}`, 'g'), '.').replace(/[^0-9.]/g, '');
7892
+ const parsedAmount = parseFloat(parseFloat(numberWithStandardDecimalSeparator).toFixed(precision));
7893
+ return Math.abs(parsedAmount);
7948
7894
  }
7949
7895
 
7950
- /**
7951
- * No option or placeholder option is selected
7952
- */
7953
- const DEFAULT_SELECTED_OPTION = null;
7954
- function isPlaceholderOption(option) {
7955
- return option === DEFAULT_SELECTED_OPTION || 'placeholder' in option;
7956
- }
7957
- function isSearchableOption(option) {
7958
- return !isHeaderOption(option) && !isSeparatorOption(option) && !isPlaceholderOption(option);
7959
- }
7960
- const getUniqueIdForOption = (parentId = '', option) => {
7961
- if (option == null) {
7962
- return undefined;
7896
+ const Currency = PropTypes__default.default.shape({
7897
+ header: PropTypes__default.default.string,
7898
+ value: PropTypes__default.default.string,
7899
+ label: PropTypes__default.default.string,
7900
+ currency: PropTypes__default.default.string,
7901
+ note: PropTypes__default.default.string,
7902
+ searchable: PropTypes__default.default.string
7903
+ });
7904
+ const isNumberOrNull = v => neptuneValidation.isNumber(v) || neptuneValidation.isNull(v);
7905
+ const formatAmountIfSet = (amount, currency, locale, maxLengthOverride) => {
7906
+ if (maxLengthOverride) {
7907
+ return amount || '';
7908
+ } else {
7909
+ return typeof amount === 'number' ? formatting.formatAmount(amount, currency, locale) : '';
7963
7910
  }
7964
- const uniqueOptionId = option.value || (option.label?.replace(/\s/g, '') ?? '');
7965
- return `option-${parentId}-${uniqueOptionId}`;
7966
7911
  };
7967
-
7968
- /**
7969
- * @deprecated Use `SelectInput` instead (https://neptune.wise.design/blog/2023-11-28-adopting-our-new-selectinput)
7970
- */
7971
- function Select({
7972
- placeholder,
7973
- id,
7974
- required,
7975
- disabled,
7976
- inverse,
7977
- dropdownWidth,
7978
- size,
7979
- block,
7980
- selected,
7981
- search,
7982
- onChange,
7983
- onFocus,
7984
- onBlur,
7985
- options: defaultOptions,
7986
- onSearchChange,
7987
- searchValue: initSearchValue,
7988
- searchPlaceholder,
7989
- // eslint-disable-next-line unicorn/prevent-abbreviations
7990
- classNames: classNamesProp,
7991
- dropdownUp,
7992
- dropdownProps,
7993
- buttonProps
7994
- }) {
7995
- const {
7996
- formatMessage
7997
- } = reactIntl.useIntl();
7998
- const {
7999
- isModern
8000
- } = componentsTheming.useTheme();
8001
- const s = className => classNamesProp[className] || className;
8002
- const [open, setOpen] = React.useState(false);
8003
- const [searchValue, setSearchValue] = React.useState(DEFAULT_SEARCH_VALUE);
8004
- const [keyboardFocusedOptionIndex, setKeyboardFocusedOptionIndex] = React.useState(null);
8005
- const keyboardFocusedReference = React.useRef();
8006
- const previousKeyboardFocusedOptionIndex = React.useRef();
8007
- const [numberOfOptionsShown, setNumberOfOptionsShown] = React.useState(DEFAULT_OPTIONS_PAGE_SIZE);
8008
- const searchBoxReference = React.useRef(null);
8009
- const selectReference = React.useRef(null);
8010
- const dropdownButtonReference = React.useRef(null);
8011
- const optionsListReference = React.useRef(null);
8012
- const isSearchEnabled = !!onSearchChange || !!search;
8013
- const isDropdownAutoWidth = dropdownWidth == null;
8014
- const fallbackButtonId = React.useMemo(() => getSimpleRandomId('np-select-'), []);
8015
- const options = React.useMemo(() => {
8016
- if (!search || !searchValue) {
8017
- return defaultOptions;
8018
- }
8019
- return defaultOptions.filter(isSearchableOption).filter(option => {
8020
- if (typeof search === 'function') {
8021
- return search(option, searchValue);
8022
- } else {
8023
- return defaultFilterFunction(option, searchValue);
8024
- }
7912
+ const parseNumber = (amount, currency, locale, maxLengthOverride) => {
7913
+ if (!maxLengthOverride) {
7914
+ return parseAmount(amount, currency, locale);
7915
+ }
7916
+ if (maxLengthOverride && amount.length > maxLengthOverride) {
7917
+ return 0;
7918
+ }
7919
+ return +amount;
7920
+ };
7921
+ const inputKeyCodeAllowlist = new Set([KeyCodes.BACKSPACE, KeyCodes.DELETE, KeyCodes.COMMA, KeyCodes.PERIOD, KeyCodes.DOWN, KeyCodes.UP, KeyCodes.LEFT, KeyCodes.RIGHT, KeyCodes.ENTER, KeyCodes.ESCAPE, KeyCodes.TAB]);
7922
+ const inputKeyAllowlist = new Set([Key.PERIOD, Key.COMMA]);
7923
+ class MoneyInput extends React.Component {
7924
+ constructor(props) {
7925
+ super(props);
7926
+ const {
7927
+ locale
7928
+ } = this.props.intl;
7929
+ this.formatMessage = this.props.intl.formatMessage;
7930
+ this.state = {
7931
+ searchQuery: '',
7932
+ selectedOption: this.props.selectedCurrency,
7933
+ formattedAmount: formatAmountIfSet(props.amount, props.selectedCurrency.currency, locale, props.maxLengthOverride),
7934
+ locale
7935
+ };
7936
+ }
7937
+ UNSAFE_componentWillReceiveProps(nextProps) {
7938
+ this.setState({
7939
+ locale: nextProps?.intl?.locale
8025
7940
  });
8026
- }, [defaultOptions, search, searchValue]);
8027
- const selectableOptions = React.useMemo(() => options.filter(isActionableOption), [options]);
8028
- const focusedOption = selectableOptions[keyboardFocusedOptionIndex];
8029
- const computedId = id || fallbackButtonId;
8030
- const listboxId = `${computedId}-listbox`;
8031
- const searchBoxId = `${computedId}-searchbox`;
8032
- const {
8033
- isMobile
8034
- } = useLayout();
8035
- React.useEffect(() => {
8036
- let cancelled;
8037
- if (keyboardFocusedOptionIndex >= 0) {
8038
- requestAnimationFrame(() => {
8039
- if (!cancelled) {
8040
- if (isSearchEnabled) {
8041
- keyboardFocusedReference.current?.scrollIntoView?.({
8042
- block: 'center'
8043
- });
8044
- } else {
8045
- keyboardFocusedReference.current?.focus();
8046
- }
8047
- }
7941
+ if (!this.amountFocused) {
7942
+ this.setState({
7943
+ formattedAmount: formatAmountIfSet(nextProps.amount, nextProps.selectedCurrency.currency, nextProps?.intl?.locale, nextProps.maxLengthOverride)
8048
7944
  });
8049
- return () => {
8050
- cancelled = true;
8051
- };
8052
7945
  }
8053
- }, [keyboardFocusedOptionIndex, isSearchEnabled]);
8054
- const handleOnClick = () => {
8055
- setOpen(true);
7946
+ }
7947
+ isInputAllowedForKeyEvent = event => {
7948
+ const {
7949
+ keyCode,
7950
+ metaKey,
7951
+ key,
7952
+ ctrlKey
7953
+ } = event;
7954
+ const isNumberKey = neptuneValidation.isNumber(parseInt(key, 10));
7955
+ return isNumberKey || metaKey || ctrlKey || inputKeyCodeAllowlist.has(keyCode) || inputKeyAllowlist.has(key);
8056
7956
  };
8057
- const handleTouchStart = event => {
8058
- if (event.currentTarget === event.target && open) {
8059
- handleCloseOptions();
7957
+ handleKeyDown = event => {
7958
+ if (!this.isInputAllowedForKeyEvent(event)) {
7959
+ event.preventDefault();
8060
7960
  }
8061
7961
  };
8062
- const handleOnFocus = event => {
8063
- if (onFocus) {
8064
- onFocus(event);
7962
+ handlePaste = event => {
7963
+ const paste = (event.clipboardData || window.clipboardData).getData('text');
7964
+ const {
7965
+ locale
7966
+ } = this.state;
7967
+ const parsed = neptuneValidation.isEmpty(paste) ? null : parseNumber(paste, this.props.selectedCurrency.currency, locale, this.props.maxLengthOverride);
7968
+ if (isNumberOrNull(parsed)) {
7969
+ this.setState({
7970
+ formattedAmount: formatAmountIfSet(parsed, this.props.selectedCurrency.currency, locale, this.props.maxLengthOverride)
7971
+ });
7972
+ this.props.onAmountChange(parsed);
8065
7973
  }
7974
+ event.preventDefault();
8066
7975
  };
8067
- const handleOnBlur = event => {
7976
+ onAmountChange = event => {
8068
7977
  const {
8069
- nativeEvent
8070
- } = event;
8071
- if (nativeEvent) {
8072
- const elementReceivingFocus = nativeEvent.relatedTarget;
8073
- const select = event.currentTarget;
8074
- if (select && elementReceivingFocus && select.contains(elementReceivingFocus)) {
8075
- return;
8076
- }
8077
- }
8078
- if (onBlur) {
8079
- onBlur(event);
7978
+ value
7979
+ } = event.target;
7980
+ this.setState({
7981
+ formattedAmount: value
7982
+ });
7983
+ const parsed = neptuneValidation.isEmpty(value) ? null : parseNumber(value, this.props.selectedCurrency.currency, this.state.locale, this.props.maxLengthOverride);
7984
+ if (isNumberOrNull(parsed)) {
7985
+ this.props.onAmountChange(parsed);
8080
7986
  }
8081
7987
  };
8082
- const handleSearchChange = event => {
8083
- setNumberOfOptionsShown(DEFAULT_OPTIONS_PAGE_SIZE);
8084
- setSearchValue(event.target.value);
8085
- if (onSearchChange) {
8086
- onSearchChange(event.target.value);
8087
- }
7988
+ onAmountBlur = () => {
7989
+ this.amountFocused = false;
7990
+ this.setAmount();
8088
7991
  };
8089
- const handleKeyDown = event => {
8090
- switch (event.keyCode) {
8091
- case KeyCodes.UP:
8092
- case KeyCodes.DOWN:
8093
- if (open) {
8094
- moveFocusWithDifference(event.keyCode === KeyCodes.UP ? -1 : 1);
8095
- } else {
8096
- setOpen(true);
8097
- }
8098
- stopPropagation$1(event);
8099
- break;
8100
- case KeyCodes.SPACE:
8101
- if (event.target !== searchBoxReference.current) {
8102
- if (open) {
8103
- selectKeyboardFocusedOption();
8104
- } else {
8105
- setOpen(true);
8106
- }
8107
- stopPropagation$1(event);
8108
- }
8109
- break;
8110
- case KeyCodes.ENTER:
8111
- if (open) {
8112
- selectKeyboardFocusedOption();
8113
- } else {
8114
- setOpen(true);
8115
- }
8116
- stopPropagation$1(event);
8117
- break;
8118
- case KeyCodes.ESCAPE:
8119
- handleCloseOptions();
8120
- stopPropagation$1(event);
8121
- break;
8122
- case KeyCodes.TAB:
8123
- if (open) {
8124
- selectKeyboardFocusedOption();
8125
- }
8126
- break;
8127
- }
7992
+ onAmountFocus = () => {
7993
+ this.amountFocused = true;
8128
7994
  };
8129
- function selectKeyboardFocusedOption() {
8130
- if (keyboardFocusedOptionIndex != null) {
8131
- selectableOptions.length > 0 && selectOption(selectableOptions[keyboardFocusedOptionIndex]);
8132
- }
8133
- }
8134
- function moveFocusWithDifference(difference) {
8135
- const selectedOptionIndex = selectableOptions.reduce((optionIndex, current, index) => {
8136
- if (optionIndex != null) {
8137
- return optionIndex;
8138
- }
8139
- if (isOptionSelected(selected, current)) {
8140
- return index;
8141
- }
8142
- return null;
8143
- }, null);
8144
- const previousFocusedIndex = previousKeyboardFocusedOptionIndex.current ?? -1;
8145
- let indexToStartMovingFrom = previousFocusedIndex;
8146
- if (previousFocusedIndex === -1) {
8147
- if (selectedOptionIndex == null) {
8148
- setKeyboardFocusedOptionIndex(0);
7995
+ mapOption = item => {
7996
+ return {
7997
+ type: 'option',
7998
+ value: item,
7999
+ filterMatchers: [item.value, item.label, item.note, item.searchable]
8000
+ };
8001
+ };
8002
+ getSelectOptions() {
8003
+ const selectOptions = [...filterOptionsForQuery(this.props.currencies, this.state.searchQuery)];
8004
+ let formattedOptions = [];
8005
+ let groupIndex = null;
8006
+ selectOptions.forEach(item => {
8007
+ if (item.header) {
8008
+ formattedOptions.push({
8009
+ type: 'group',
8010
+ label: item.header,
8011
+ options: []
8012
+ });
8013
+ groupIndex = formattedOptions.length - 1;
8149
8014
  } else {
8150
- indexToStartMovingFrom = selectedOptionIndex;
8015
+ if (groupIndex === null) {
8016
+ formattedOptions.push(this.mapOption(item));
8017
+ } else {
8018
+ formattedOptions[groupIndex]?.options.push(this.mapOption(item));
8019
+ }
8151
8020
  }
8152
- }
8153
- const unClampedNewIndex = indexToStartMovingFrom + difference;
8154
- const newIndex = clamp(0, selectableOptions.length - 1, unClampedNewIndex);
8155
- setKeyboardFocusedOptionIndex(newIndex);
8021
+ });
8022
+ return formattedOptions;
8156
8023
  }
8157
- React.useEffect(() => {
8158
- if (open) {
8159
- if (!isMobile || searchValue) {
8160
- if (isSearchEnabled && !!searchBoxReference.current) {
8161
- searchBoxReference.current.focus();
8162
- }
8163
- if (!isSearchEnabled && optionsListReference.current && (previousKeyboardFocusedOptionIndex.current == null || Number.isNaN(previousKeyboardFocusedOptionIndex.current))) {
8164
- optionsListReference.current.focus();
8165
- }
8024
+ setAmount() {
8025
+ this.setState(previousState => {
8026
+ const parsed = parseNumber(previousState.formattedAmount, this.props.selectedCurrency.currency, previousState.locale, this.props.maxLengthOverride);
8027
+ if (!isNumberOrNull(parsed)) {
8028
+ return {
8029
+ formattedAmount: previousState.formattedAmount
8030
+ };
8166
8031
  }
8167
- previousKeyboardFocusedOptionIndex.current = keyboardFocusedOptionIndex;
8168
- } else {
8169
- previousKeyboardFocusedOptionIndex.current = null;
8170
- }
8171
- }, [open, searchValue, isSearchEnabled, isMobile, keyboardFocusedOptionIndex]);
8172
- const handleCloseOptions = () => {
8173
- setOpen(false);
8174
- setKeyboardFocusedOptionIndex(null);
8175
- if (dropdownButtonReference.current) {
8176
- dropdownButtonReference.current.focus();
8032
+ return {
8033
+ formattedAmount: formatAmountIfSet(parsed, this.props.selectedCurrency.currency, previousState.locale, this.props.maxLengthOverride)
8034
+ };
8035
+ });
8036
+ }
8037
+ handleSelectChange = value => {
8038
+ this.handleSearchChange('');
8039
+ this.setState({
8040
+ selectedOption: value
8041
+ });
8042
+ this.props.onCurrencyChange(value);
8043
+ };
8044
+ handleCustomAction = () => {
8045
+ this.handleSearchChange('');
8046
+ if (this.props.onCustomAction) {
8047
+ this.props.onCustomAction();
8177
8048
  }
8178
8049
  };
8179
- function createSelectHandlerForOption(option) {
8180
- return event => {
8181
- stopPropagation$1(event);
8182
- selectOption(option);
8183
- };
8184
- }
8185
- function selectOption(option) {
8186
- onChange(isPlaceholderOption(option) ? DEFAULT_SELECTED_OPTION : option);
8187
- handleCloseOptions();
8188
- }
8189
- function renderOptionsList({
8190
- className
8191
- } = {}) {
8192
- const dropdownClass = classNames__default.default(s('np-dropdown-menu'), {
8193
- [s('np-dropdown-menu-desktop')]: !isMobile,
8194
- [s(`np-dropdown-menu-${dropdownWidth}`)]: !isMobile && !isDropdownAutoWidth
8195
- }, s(className));
8196
- const showPlaceholder = !required && !isSearchEnabled && Boolean(placeholder);
8197
- return /*#__PURE__*/jsxRuntime.jsxs("ul", {
8198
- ref: optionsListReference,
8199
- id: listboxId,
8200
- role: "listbox",
8201
- "aria-orientation": "vertical",
8202
- "aria-activedescendant": getUniqueIdForOption(id, selected),
8203
- tabIndex: "-1",
8204
- className: dropdownClass,
8205
- ...dropdownProps,
8206
- children: [showPlaceholder && /*#__PURE__*/jsxRuntime.jsx(PlaceHolderOption, {}), isSearchEnabled && /*#__PURE__*/jsxRuntime.jsx(SearchBox$1, {
8207
- ref: searchBoxReference,
8208
- id: searchBoxId,
8209
- classNames: classNamesProp,
8210
- value: initSearchValue || searchValue,
8211
- placeholder: searchPlaceholder || formatMessage(messages$3.searchPlaceholder),
8212
- focusedOptionId: getUniqueIdForOption(id, focusedOption),
8213
- onChange: handleSearchChange,
8214
- onClick: stopPropagation$1
8215
- }), options.slice(0, numberOfOptionsShown).map(renderOption), numberOfOptionsShown < options.length && /*#__PURE__*/jsxRuntime.jsx(ShowMoreOption, {})]
8050
+ handleSearchChange = searchQuery => {
8051
+ this.setState({
8052
+ searchQuery
8216
8053
  });
8217
- }
8218
- function ShowMoreOption() {
8219
- function handleOnClick(event) {
8220
- stopPropagation$1(event);
8221
- setNumberOfOptionsShown(numberOfOptionsShown + DEFAULT_OPTIONS_PAGE_SIZE);
8054
+ if (this.props.onSearchChange) {
8055
+ this.props.onSearchChange({
8056
+ searchQuery,
8057
+ filteredOptions: filterOptionsForQuery(this.props.currencies, searchQuery)
8058
+ });
8222
8059
  }
8223
- return (
8224
- /*#__PURE__*/
8225
- /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */
8226
- jsxRuntime.jsx("li", {
8227
- className: classNames__default.default(s('clickable'), s('border-bottom'), s('show-more')),
8228
- onClick: handleOnClick,
8229
- onKeyPress: handleOnClick,
8230
- children: /*#__PURE__*/jsxRuntime.jsx("a", {
8231
- children: "..."
8232
- })
8233
- })
8234
- );
8235
- }
8236
- function PlaceHolderOption() {
8237
- const placeholderOption = {
8238
- placeholder
8060
+ };
8061
+ style = className => this.props.classNames[className] || className;
8062
+ render() {
8063
+ const {
8064
+ selectedCurrency,
8065
+ onCurrencyChange,
8066
+ size,
8067
+ addon,
8068
+ id,
8069
+ selectProps,
8070
+ maxLengthOverride
8071
+ } = this.props;
8072
+ const selectOptions = this.getSelectOptions();
8073
+ const getFirstOption = () => {
8074
+ if (selectOptions.length !== 0) {
8075
+ const firstOption = selectOptions[0];
8076
+ if (firstOption.type === 'option') {
8077
+ return firstOption.value;
8078
+ }
8079
+ if (firstOption.type === 'group' && firstOption.options.length !== 0) {
8080
+ return firstOption.options[0].value;
8081
+ }
8082
+ }
8083
+ return null;
8239
8084
  };
8240
- return (
8241
- /*#__PURE__*/
8242
- /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */
8243
- jsxRuntime.jsx("li", {
8244
- className: classNames__default.default(s('clickable'), s('border-bottom')),
8245
- onClick: createSelectHandlerForOption(placeholderOption),
8246
- onKeyPress: createSelectHandlerForOption(placeholderOption),
8247
- children: /*#__PURE__*/jsxRuntime.jsx("a", {
8248
- children: placeholder
8085
+ const firstOption = getFirstOption();
8086
+ const isFixedCurrency = !this.state.searchQuery && (selectOptions.length === 1 && firstOption.currency === selectedCurrency.currency || !onCurrencyChange);
8087
+ const disabled = !this.props.onAmountChange;
8088
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
8089
+ className: classNames__default.default(this.style('tw-money-input'), this.style('input-group'), this.style(`input-group-${size}`)),
8090
+ children: [/*#__PURE__*/jsxRuntime.jsx(Input, {
8091
+ id: id,
8092
+ value: this.state.formattedAmount,
8093
+ inputMode: "decimal",
8094
+ disabled: disabled,
8095
+ maxLength: maxLengthOverride,
8096
+ placeholder: formatAmountIfSet(this.props.placeholder, this.props.selectedCurrency.currency, this.state.locale, this.props.maxLengthOverride),
8097
+ autoComplete: "off",
8098
+ onKeyDown: this.handleKeyDown,
8099
+ onChange: this.onAmountChange,
8100
+ onFocus: this.onAmountFocus,
8101
+ onBlur: this.onAmountBlur,
8102
+ onPaste: this.handlePaste
8103
+ }), addon && /*#__PURE__*/jsxRuntime.jsx("span", {
8104
+ className: classNames__default.default(this.style('input-group-addon'), this.style(`input-${size}`), disabled ? this.style('disabled') : ''),
8105
+ children: addon
8106
+ }), isFixedCurrency ? /*#__PURE__*/jsxRuntime.jsxs("div", {
8107
+ className: classNames__default.default(this.style('input-group-addon'), this.style(`input-${size}`), this.style('tw-money-input__fixed-currency'), disabled ? this.style('disabled') : ''),
8108
+ children: [(size === 'lg' || size === 'md') && /*#__PURE__*/jsxRuntime.jsx("span", {
8109
+ className: classNames__default.default(this.style('money-input-currency-flag'), this.style('m-r-2')),
8110
+ children: /*#__PURE__*/jsxRuntime.jsx(art.Flag, {
8111
+ code: selectedCurrency.currency.toLowerCase(),
8112
+ intrinsicSize: 24
8113
+ })
8114
+ }), /*#__PURE__*/jsxRuntime.jsx(Title, {
8115
+ as: "span",
8116
+ type: exports.Typography.TITLE_SUBSECTION,
8117
+ className: size === 'lg' ? this.style('m-r-1') : '',
8118
+ children: selectedCurrency.currency.toUpperCase()
8119
+ })]
8120
+ }) : /*#__PURE__*/jsxRuntime.jsx("div", {
8121
+ className: classNames__default.default(this.style('input-group-btn'), this.style('amount-currency-select-btn')),
8122
+ children: /*#__PURE__*/jsxRuntime.jsx(SelectInput, {
8123
+ items: selectOptions,
8124
+ value: this.state.selectedOption,
8125
+ compareValues: "currency",
8126
+ renderValue: (currency, withinTrigger) => {
8127
+ return /*#__PURE__*/jsxRuntime.jsx(SelectInputOptionContent, {
8128
+ title: currency.label,
8129
+ note: withinTrigger ? undefined : currency.note,
8130
+ icon: /*#__PURE__*/jsxRuntime.jsx(art.Flag, {
8131
+ code: currency.currency,
8132
+ intrinsicSize: 24
8133
+ })
8134
+ });
8135
+ },
8136
+ renderFooter: this.props.onCustomAction ? () =>
8137
+ /*#__PURE__*/
8138
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events
8139
+ jsxRuntime.jsx("div", {
8140
+ role: "button",
8141
+ tabIndex: "0",
8142
+ onClick: this.handleCustomAction,
8143
+ children: this.props.customActionLabel
8144
+ }) : null,
8145
+ placeholder: this.formatMessage(messages$3.selectPlaceholder),
8146
+ filterable: true,
8147
+ filterPlaceholder: this.props.searchPlaceholder,
8148
+ disabled: disabled,
8149
+ size: size,
8150
+ onChange: this.handleSelectChange,
8151
+ onSearchChange: this.handleSearchChange,
8152
+ ...selectProps
8249
8153
  })
8250
- })
8251
- );
8252
- }
8253
-
8254
- // eslint-disable-next-line react/prop-types
8255
- function SeparatorOption() {
8256
- return /*#__PURE__*/jsxRuntime.jsx("li", {
8257
- className: s('np-separator'),
8258
- "aria-hidden": true
8259
- });
8260
- }
8261
-
8262
- // eslint-disable-next-line react/prop-types
8263
- function HeaderOption({
8264
- children
8265
- }) {
8266
- return /*#__PURE__*/jsxRuntime.jsx("li", {
8267
- // eslint-disable-line jsx-a11y/no-noninteractive-element-interactions
8268
- className: classNames__default.default(s('np-dropdown-header'), s('np-text-title-group')),
8269
- onClick: stopPropagation$1,
8270
- onKeyPress: stopPropagation$1,
8271
- children: children
8154
+ })]
8272
8155
  });
8273
8156
  }
8274
- function isOptionSelected(selected, option) {
8275
- return selected?.value === option?.value;
8157
+ }
8158
+ function filterOptionsForQuery(options, query) {
8159
+ if (!query) {
8160
+ return options;
8276
8161
  }
8277
- const renderOption = (option, index) => {
8278
- const separatorOption = option;
8279
- if (isSeparatorOption(separatorOption) && separatorOption?.separator) {
8280
- return /*#__PURE__*/jsxRuntime.jsx(SeparatorOption, {}, index);
8281
- }
8282
- const headerOption = option;
8283
- if (isHeaderOption(headerOption) && headerOption.header) {
8284
- return /*#__PURE__*/jsxRuntime.jsx(HeaderOption, {
8285
- children: headerOption.header
8286
- }, index);
8162
+ const filteredOptions = removeDuplicateValueOptions(options).filter(option => isCurrencyOptionAndFitsQuery(option, query));
8163
+ return sortOptionsLabelsToFirst(filteredOptions, query);
8164
+ }
8165
+ function removeDuplicateValueOptions(options) {
8166
+ const result = [];
8167
+ const resultValues = [];
8168
+ options.forEach(option => {
8169
+ if (option.value && !resultValues.includes(option.value)) {
8170
+ result.push(option);
8171
+ resultValues.push(option.value);
8287
8172
  }
8288
- const isActive = isOptionSelected(selected, option);
8289
- const selectOption = option;
8290
- const isFocusedWithKeyboard = !selectOption.disabled && keyboardFocusedOptionIndex === getIndexWithoutHeadersForIndexWithHeaders(index);
8291
- const className = classNames__default.default(s('np-dropdown-item'), selectOption.disabled ? [s('disabled')] : s('clickable'), {
8292
- [s('active')]: isActive,
8293
- [s('np-dropdown-item--focused')]: isFocusedWithKeyboard
8294
- });
8295
- const handleOnClick = selectOption.disabled ? stopPropagation$1 : createSelectHandlerForOption(selectOption);
8296
- return (
8297
- /*#__PURE__*/
8298
- /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */
8299
- jsxRuntime.jsx("li", {
8300
- ref: isFocusedWithKeyboard ? keyboardFocusedReference : undefined,
8301
- id: getUniqueIdForOption(id, option),
8302
- "aria-selected": isActive,
8303
- "aria-disabled": option.disabled,
8304
- role: "option",
8305
- tabIndex: "-1",
8306
- className: className,
8307
- onClick: handleOnClick,
8308
- onKeyPress: handleOnClick,
8309
- children: /*#__PURE__*/jsxRuntime.jsx("a", {
8310
- disabled: selectOption.disabled,
8311
- children: /*#__PURE__*/jsxRuntime.jsx(Option$1, {
8312
- ...selectOption,
8313
- classNames: classNamesProp
8314
- })
8315
- })
8316
- }, index)
8317
- );
8318
- };
8319
- function getIndexWithoutHeadersForIndexWithHeaders(index) {
8320
- return options.reduce((sum, option, currentIndex) => {
8321
- if (currentIndex < index && isActionableOption(option)) {
8322
- return sum + 1;
8323
- }
8324
- return sum;
8325
- }, 0);
8173
+ });
8174
+ return result;
8175
+ }
8176
+ function isCurrencyOptionAndFitsQuery(option, query) {
8177
+ if (!option.value) {
8178
+ return false;
8326
8179
  }
8327
- const hasActiveOptions = !!defaultOptions.length;
8328
- if (open && (initSearchValue || searchValue)) {
8329
- if (hasActiveOptions && keyboardFocusedOptionIndex == null) {
8330
- setKeyboardFocusedOptionIndex(0);
8180
+ return contains(option.label, query) || contains(option.searchable, query) || contains(option.note, query);
8181
+ }
8182
+ function contains(property, query) {
8183
+ return property && property.toLowerCase().includes(query.toLowerCase());
8184
+ }
8185
+ function sortOptionsLabelsToFirst(options, query) {
8186
+ return options.sort((first, second) => {
8187
+ const firstContains = contains(first.label, query);
8188
+ const secondContains = contains(second.label, query);
8189
+ if (firstContains && secondContains) {
8190
+ return 0;
8331
8191
  }
8332
- if (!hasActiveOptions && keyboardFocusedOptionIndex != null) {
8333
- setKeyboardFocusedOptionIndex(null);
8192
+ if (firstContains) {
8193
+ return -1;
8334
8194
  }
8335
- }
8336
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
8337
- // eslint-disable-line jsx-a11y/no-static-element-interactions
8338
- ref: selectReference,
8339
- className: classNames__default.default(s('np-select'), block ? s('btn-block') : null, s('btn-group')),
8340
- onKeyDown: handleKeyDown,
8341
- onTouchMove: handleTouchStart,
8342
- onFocus: handleOnFocus,
8343
- onBlur: handleOnBlur,
8344
- children: [/*#__PURE__*/jsxRuntime.jsxs(Button, {
8345
- ref: dropdownButtonReference,
8346
- id: computedId,
8347
- block: block,
8348
- size: size,
8349
- htmlType: "button",
8350
- className: classNames__default.default(s('np-dropdown-toggle'), s('np-text-body-large'), inverse ? s('np-dropdown-toggle-navy') : null)
8351
- // reset Button's styles
8352
- ,
8353
- type: null,
8354
- priority: null,
8355
- disabled: disabled,
8356
- "aria-controls": listboxId,
8357
- "aria-expanded": open,
8358
- "aria-autocomplete": "none",
8359
- onClick: handleOnClick,
8360
- ...buttonProps,
8361
- children: [selected ? /*#__PURE__*/jsxRuntime.jsx(Option$1, {
8362
- ...selected,
8363
- classNames: classNamesProp,
8364
- selected: true
8365
- }) : /*#__PURE__*/jsxRuntime.jsx("span", {
8366
- className: s('form-control-placeholder'),
8367
- children: placeholder
8368
- }), /*#__PURE__*/jsxRuntime.jsx(Chevron$1
8369
- // disabled={disabled}
8370
- , {
8371
- className: classNames__default.default(s('tw-icon'), s('tw-chevron-up-icon'), s('tw-chevron'), s('bottom'), s('np-select-chevron'))
8372
- })]
8373
- }), isMobile ? isSearchEnabled ? /*#__PURE__*/jsxRuntime.jsx(Drawer$1, {
8374
- open: open,
8375
- headerTitle: searchPlaceholder || formatMessage(messages$3.searchPlaceholder),
8376
- onClose: handleCloseOptions,
8377
- children: renderOptionsList()
8378
- }) : /*#__PURE__*/jsxRuntime.jsx(BottomSheet$2, {
8379
- open: open,
8380
- onClose: handleCloseOptions,
8381
- children: renderOptionsList({
8382
- className: isModern ? '' : 'p-a-1'
8383
- })
8384
- }) : /*#__PURE__*/jsxRuntime.jsx(Panel$1, {
8385
- open: open,
8386
- flip: false,
8387
- altAxis: true,
8388
- anchorRef: selectReference,
8389
- anchorWidth: isDropdownAutoWidth,
8390
- position: dropdownUp ? exports.Position.TOP : exports.Position.BOTTOM,
8391
- onClose: handleCloseOptions,
8392
- children: renderOptionsList({
8393
- className: 'p-a-1'
8394
- })
8395
- })]
8195
+ if (secondContains) {
8196
+ return 1;
8197
+ }
8198
+ return 0;
8396
8199
  });
8397
8200
  }
8398
- Select.propTypes = {
8399
- placeholder: PropTypes__default.default.string,
8201
+ MoneyInput.propTypes = {
8400
8202
  id: PropTypes__default.default.string,
8401
- required: PropTypes__default.default.bool,
8402
- disabled: PropTypes__default.default.bool,
8403
- inverse: PropTypes__default.default.bool,
8404
- dropdownRight: PropTypes__default.default.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
8405
- dropdownWidth: PropTypes__default.default.oneOf(['sm', 'md', 'lg']),
8203
+ currencies: PropTypes__default.default.arrayOf(Currency).isRequired,
8204
+ selectedCurrency: Currency.isRequired,
8205
+ onCurrencyChange: PropTypes__default.default.func,
8206
+ placeholder: PropTypes__default.default.number,
8207
+ amount: PropTypes__default.default.number,
8406
8208
  size: PropTypes__default.default.oneOf(['sm', 'md', 'lg']),
8407
- block: PropTypes__default.default.bool,
8408
- selected: PropTypes__default.default.shape({
8409
- value: PropTypes__default.default.any.isRequired,
8410
- label: PropTypes__default.default.node,
8411
- icon: PropTypes__default.default.node,
8412
- currency: PropTypes__default.default.string,
8413
- note: PropTypes__default.default.node,
8414
- secondary: PropTypes__default.default.node
8415
- }),
8416
- /**
8417
- * Search toggle
8418
- * if `true` default search functionality being enabled (not case sensitive search in option labels & currency props)
8419
- * if `function` you can define your own search function to implement custom search experience. This search function used while filtering the options array. The custom search function takes two parameters. First is the option the second is the keyword.
8420
- */
8421
- search: PropTypes__default.default.oneOfType([PropTypes__default.default.bool, PropTypes__default.default.func]),
8422
- onChange: PropTypes__default.default.func.isRequired,
8423
- onFocus: PropTypes__default.default.func,
8424
- onBlur: PropTypes__default.default.func,
8425
- options: PropTypes__default.default.arrayOf(PropTypes__default.default.shape({
8426
- value: PropTypes__default.default.any,
8427
- label: PropTypes__default.default.node,
8428
- header: PropTypes__default.default.node,
8429
- icon: PropTypes__default.default.node,
8430
- currency: PropTypes__default.default.string,
8431
- note: PropTypes__default.default.node,
8432
- secondary: PropTypes__default.default.node,
8433
- separator: PropTypes__default.default.bool,
8434
- disabled: PropTypes__default.default.bool,
8435
- searchStrings: PropTypes__default.default.arrayOf(PropTypes__default.default.string)
8436
- })).isRequired,
8209
+ onAmountChange: PropTypes__default.default.func,
8210
+ addon: PropTypes__default.default.node,
8211
+ searchPlaceholder: PropTypes__default.default.string,
8437
8212
  /**
8438
- * To have full control of your search value and response use `onSearchChange` function combined with `searchValue` and custom filtering on the options array.
8439
- * DO NOT USE TOGETHER WITH `search` PROPERTY
8213
+ * Allows the consumer to react to searching, while the search itself is handled internally. Called with `{ searchQuery: string, filteredOptions: Currency[] }`
8440
8214
  */
8441
8215
  onSearchChange: PropTypes__default.default.func,
8442
- searchValue: PropTypes__default.default.string,
8443
- searchPlaceholder: PropTypes__default.default.string,
8216
+ customActionLabel: PropTypes__default.default.node,
8217
+ onCustomAction: PropTypes__default.default.func,
8444
8218
  classNames: PropTypes__default.default.objectOf(PropTypes__default.default.string),
8445
- dropdownUp: PropTypes__default.default.bool,
8446
- buttonProps: PropTypes__default.default.object,
8447
- dropdownProps: PropTypes__default.default.object
8219
+ selectProps: PropTypes__default.default.object,
8220
+ maxLengthOverride: PropTypes__default.default.number
8448
8221
  };
8449
- Select.defaultProps = {
8450
- id: undefined,
8451
- placeholder: undefined,
8452
- size: 'md',
8453
- dropdownRight: null,
8454
- dropdownWidth: null,
8455
- inverse: false,
8456
- required: false,
8457
- disabled: false,
8458
- block: true,
8459
- selected: null,
8460
- onFocus: null,
8461
- onBlur: null,
8222
+ MoneyInput.defaultProps = {
8223
+ id: null,
8224
+ size: exports.Size.LARGE,
8225
+ addon: null,
8226
+ searchPlaceholder: '',
8462
8227
  onSearchChange: undefined,
8463
- search: false,
8464
- searchValue: '',
8465
- searchPlaceholder: undefined,
8228
+ onCurrencyChange: null,
8229
+ placeholder: null,
8230
+ amount: null,
8231
+ onAmountChange: null,
8232
+ customActionLabel: '',
8233
+ onCustomAction: null,
8466
8234
  classNames: {},
8467
- dropdownUp: false,
8468
- buttonProps: {},
8469
- dropdownProps: {}
8235
+ selectProps: {},
8236
+ maxLengthOverride: null
8470
8237
  };
8238
+ var MoneyInput$1 = reactIntl.injectIntl(MoneyInput);
8471
8239
 
8472
- var messages$2 = reactIntl.defineMessages({
8473
- selectPlaceholder: {
8474
- id: "neptune.MoneyInput.Select.placeholder"
8475
- }
8476
- });
8477
-
8478
- // TODO: do not duplicate this between formatting and components
8479
- const currencyDecimals = {
8480
- BIF: 0,
8481
- BYR: 0,
8482
- CLP: 0,
8483
- DJF: 0,
8484
- GNF: 0,
8485
- JPY: 0,
8486
- KMF: 0,
8487
- KRW: 0,
8488
- MGA: 0,
8489
- PYG: 0,
8490
- RWF: 0,
8491
- VND: 0,
8492
- VUV: 0,
8493
- XAF: 0,
8494
- XOF: 0,
8495
- XPF: 0,
8496
- // technically HUF does have decimals, but due to the exchange rate banks
8497
- // do not accept decimal amounts
8498
- HUF: 0,
8499
- BHD: 3,
8500
- JOD: 3,
8501
- KWD: 3,
8502
- OMR: 3,
8503
- TND: 3
8240
+ const NavigationOptionList = ({
8241
+ children
8242
+ }) => {
8243
+ return /*#__PURE__*/jsxRuntime.jsx("ul", {
8244
+ className: "np-navigation-options-list",
8245
+ children: React.Children.map(children, child => /*#__PURE__*/jsxRuntime.jsx("li", {
8246
+ className: "np-navigation-options-list__item",
8247
+ children: child
8248
+ }, child.key))
8249
+ });
8504
8250
  };
8505
- const DEFAULT_CURRENCY_DECIMALS = 2;
8506
- function isNumberLocaleSupported() {
8507
- const number = 1234;
8508
- const numberString = number.toLocaleString && number.toLocaleString(DEFAULT_LOCALE);
8509
- return numberString === '1,234';
8510
- }
8511
- function getValidLocale(locale) {
8512
- try {
8513
- const noUnderscoreLocale = locale.replace(/_/, '-');
8514
- Intl.NumberFormat(noUnderscoreLocale);
8515
- return noUnderscoreLocale;
8516
- } catch {
8517
- return 'en-GB';
8518
- }
8519
- }
8520
- function getCurrencyDecimals(currency = '') {
8521
- const upperCaseCurrency = currency.toUpperCase();
8522
- if (Object.prototype.hasOwnProperty.call(currencyDecimals, upperCaseCurrency)) {
8523
- return currencyDecimals[upperCaseCurrency];
8524
- }
8525
- return DEFAULT_CURRENCY_DECIMALS;
8526
- }
8527
- function getDecimalSeparator(locale) {
8528
- return isNumberLocaleSupported() ? 1.1.toLocaleString(locale)[1] : '.';
8529
- }
8530
- function parseAmount(number, currency, locale) {
8531
- const validLocale = getValidLocale(locale);
8532
- const precision = getCurrencyDecimals(currency);
8533
- const groupSeparator = isNumberLocaleSupported() ? 10000 .toLocaleString(validLocale)[2] : ',';
8534
- const decimalSeparator = getDecimalSeparator(validLocale);
8535
- const numberWithStandardDecimalSeparator = (number ? `${number}` : '').replace(new RegExp(`\\${groupSeparator}`, 'g'), '').replace(new RegExp(`\\${decimalSeparator}`, 'g'), '.').replace(/[^0-9.]/g, '');
8536
- const parsedAmount = parseFloat(parseFloat(numberWithStandardDecimalSeparator).toFixed(precision));
8537
- return Math.abs(parsedAmount);
8538
- }
8539
-
8540
- const Currency = PropTypes__default.default.shape({
8541
- header: PropTypes__default.default.string,
8542
- value: PropTypes__default.default.string,
8543
- label: PropTypes__default.default.string,
8544
- currency: PropTypes__default.default.string,
8545
- note: PropTypes__default.default.string,
8546
- searchable: PropTypes__default.default.string
8547
- });
8548
- const CUSTOM_ACTION = 'CUSTOM_ACTION';
8549
- const isNumberOrNull = v => neptuneValidation.isNumber(v) || neptuneValidation.isNull(v);
8550
- const formatAmountIfSet = (amount, currency, locale, maxLengthOverride) => {
8551
- if (maxLengthOverride) {
8552
- return amount || '';
8553
- } else {
8554
- return typeof amount === 'number' ? formatting.formatAmount(amount, currency, locale) : '';
8555
- }
8251
+ NavigationOptionList.propTypes = {
8252
+ children: PropTypes__default.default.node.isRequired
8556
8253
  };
8557
- const parseNumber = (amount, currency, locale, maxLengthOverride) => {
8558
- if (!maxLengthOverride) {
8559
- return parseAmount(amount, currency, locale);
8560
- }
8561
- if (maxLengthOverride && amount.length > maxLengthOverride) {
8562
- return 0;
8563
- }
8564
- return +amount;
8254
+ var NavigationOptionList$1 = NavigationOptionList;
8255
+
8256
+ const STORAGE_NAME = 'dismissedNudges';
8257
+ const getLocalStorage = () => {
8258
+ try {
8259
+ const storageItem = localStorage.getItem(STORAGE_NAME);
8260
+ if (storageItem) {
8261
+ const storage = JSON.parse(storageItem);
8262
+ if (Array.isArray(storage)) {
8263
+ return storage;
8264
+ }
8265
+ }
8266
+ // eslint-disable-next-line unicorn/prefer-optional-catch-binding, no-empty
8267
+ } catch (error) {}
8268
+ return [];
8565
8269
  };
8566
- const inputKeyCodeAllowlist = new Set([KeyCodes.BACKSPACE, KeyCodes.DELETE, KeyCodes.COMMA, KeyCodes.PERIOD, KeyCodes.DOWN, KeyCodes.UP, KeyCodes.LEFT, KeyCodes.RIGHT, KeyCodes.ENTER, KeyCodes.ESCAPE, KeyCodes.TAB]);
8567
- const inputKeyAllowlist = new Set([Key.PERIOD, Key.COMMA]);
8568
- class MoneyInput extends React.Component {
8569
- constructor(props) {
8570
- super(props);
8571
- const {
8572
- locale
8573
- } = this.props.intl;
8574
- this.formatMessage = this.props.intl.formatMessage;
8575
- this.state = {
8576
- searchQuery: '',
8577
- formattedAmount: formatAmountIfSet(props.amount, props.selectedCurrency.currency, locale, props.maxLengthOverride),
8578
- locale
8579
- };
8580
- }
8581
- UNSAFE_componentWillReceiveProps(nextProps) {
8582
- this.setState({
8583
- locale: nextProps?.intl?.locale
8584
- });
8585
- if (!this.amountFocused) {
8586
- this.setState({
8587
- formattedAmount: formatAmountIfSet(nextProps.amount, nextProps.selectedCurrency.currency, nextProps?.intl?.locale, nextProps.maxLengthOverride)
8588
- });
8589
- }
8590
- }
8591
- isInputAllowedForKeyEvent = event => {
8592
- const {
8593
- keyCode,
8594
- metaKey,
8595
- key,
8596
- ctrlKey
8597
- } = event;
8598
- const isNumberKey = neptuneValidation.isNumber(parseInt(key, 10));
8599
- return isNumberKey || metaKey || ctrlKey || inputKeyCodeAllowlist.has(keyCode) || inputKeyAllowlist.has(key);
8600
- };
8601
- handleKeyDown = event => {
8602
- if (!this.isInputAllowedForKeyEvent(event)) {
8603
- event.preventDefault();
8604
- }
8605
- };
8606
- handlePaste = event => {
8607
- const paste = (event.clipboardData || window.clipboardData).getData('text');
8608
- const {
8609
- locale
8610
- } = this.state;
8611
- const parsed = neptuneValidation.isEmpty(paste) ? null : parseNumber(paste, this.props.selectedCurrency.currency, locale, this.props.maxLengthOverride);
8612
- if (isNumberOrNull(parsed)) {
8613
- this.setState({
8614
- formattedAmount: formatAmountIfSet(parsed, this.props.selectedCurrency.currency, locale, this.props.maxLengthOverride)
8615
- });
8616
- this.props.onAmountChange(parsed);
8270
+ const Nudge = ({
8271
+ media,
8272
+ mediaName,
8273
+ title,
8274
+ link,
8275
+ href,
8276
+ onClick,
8277
+ onDismiss,
8278
+ persistDismissal,
8279
+ isPreviouslyDismissed,
8280
+ id,
8281
+ className
8282
+ }) => {
8283
+ const [isDismissed, setIsDismissed] = React.useState(false);
8284
+ const [isMounted, setIsMounted] = React.useState(false);
8285
+ const handleOnDismiss = () => {
8286
+ const dismissedNudgesStorage = getLocalStorage();
8287
+ if (persistDismissal && id) {
8288
+ try {
8289
+ localStorage.setItem(STORAGE_NAME, JSON.stringify([...(dismissedNudgesStorage ? dismissedNudgesStorage : []), id]));
8290
+ // eslint-disable-next-line unicorn/prefer-optional-catch-binding, no-empty
8291
+ } catch (error) {}
8292
+ setIsDismissed(true);
8617
8293
  }
8618
- event.preventDefault();
8619
- };
8620
- onAmountChange = event => {
8621
- const {
8622
- value
8623
- } = event.target;
8624
- this.setState({
8625
- formattedAmount: value
8626
- });
8627
- const parsed = neptuneValidation.isEmpty(value) ? null : parseNumber(value, this.props.selectedCurrency.currency, this.state.locale, this.props.maxLengthOverride);
8628
- if (isNumberOrNull(parsed)) {
8629
- this.props.onAmountChange(parsed);
8294
+ if (onDismiss) {
8295
+ onDismiss();
8630
8296
  }
8631
8297
  };
8632
- onAmountBlur = () => {
8633
- this.amountFocused = false;
8634
- this.setAmount();
8635
- };
8636
- onAmountFocus = () => {
8637
- this.amountFocused = true;
8638
- };
8639
- getSelectOptions() {
8640
- const selectOptions = [...filterOptionsForQuery(this.props.currencies, this.state.searchQuery)];
8641
- if (this.props.onCustomAction) {
8642
- selectOptions.push({
8643
- value: CUSTOM_ACTION,
8644
- label: this.props.customActionLabel
8645
- });
8646
- }
8647
- return selectOptions;
8648
- }
8649
- setAmount() {
8650
- this.setState(previousState => {
8651
- const parsed = parseNumber(previousState.formattedAmount, this.props.selectedCurrency.currency, previousState.locale, this.props.maxLengthOverride);
8652
- if (!isNumberOrNull(parsed)) {
8653
- return {
8654
- formattedAmount: previousState.formattedAmount
8655
- };
8298
+ React.useEffect(() => {
8299
+ if (persistDismissal && id) {
8300
+ const dismissedNudgesStorage = getLocalStorage();
8301
+ let isDismissed = false;
8302
+ if (dismissedNudgesStorage && dismissedNudgesStorage.find(item => item === id)) {
8303
+ setIsDismissed(true);
8304
+ isDismissed = true;
8305
+ }
8306
+ if (isPreviouslyDismissed) {
8307
+ isPreviouslyDismissed(isDismissed);
8656
8308
  }
8657
- return {
8658
- formattedAmount: formatAmountIfSet(parsed, this.props.selectedCurrency.currency, previousState.locale, this.props.maxLengthOverride)
8659
- };
8660
- });
8661
- }
8662
- handleSelectChange = value => {
8663
- this.handleSearchChange('');
8664
- if (this.props.onCustomAction && value.value === CUSTOM_ACTION) {
8665
- this.props.onCustomAction();
8666
- } else {
8667
- this.props.onCurrencyChange(value);
8668
- }
8669
- };
8670
- handleSearchChange = searchQuery => {
8671
- this.setState({
8672
- searchQuery
8673
- });
8674
- if (this.props.onSearchChange) {
8675
- this.props.onSearchChange({
8676
- searchQuery,
8677
- filteredOptions: filterOptionsForQuery(this.props.currencies, searchQuery)
8678
- });
8679
8309
  }
8680
- };
8681
- style = className => this.props.classNames[className] || className;
8682
- render() {
8683
- const {
8684
- selectedCurrency,
8685
- onCurrencyChange,
8686
- size,
8687
- addon,
8688
- id,
8689
- selectProps,
8690
- maxLengthOverride
8691
- } = this.props;
8692
- const selectOptions = this.getSelectOptions();
8693
- const isFixedCurrency = !this.state.searchQuery && (selectOptions.length === 1 && selectOptions[0].currency === selectedCurrency.currency || !onCurrencyChange);
8694
- const disabled = !this.props.onAmountChange;
8695
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
8696
- className: classNames__default.default(this.style('tw-money-input'), this.style('input-group'), this.style(`input-group-${size}`)),
8697
- children: [/*#__PURE__*/jsxRuntime.jsx(Input, {
8698
- id: id,
8699
- value: this.state.formattedAmount,
8700
- inputMode: "decimal",
8701
- disabled: disabled,
8702
- maxLength: maxLengthOverride,
8703
- placeholder: formatAmountIfSet(this.props.placeholder, this.props.selectedCurrency.currency, this.state.locale, this.props.maxLengthOverride),
8704
- autoComplete: "off",
8705
- onKeyDown: this.handleKeyDown,
8706
- onChange: this.onAmountChange,
8707
- onFocus: this.onAmountFocus,
8708
- onBlur: this.onAmountBlur,
8709
- onPaste: this.handlePaste
8710
- }), addon && /*#__PURE__*/jsxRuntime.jsx("span", {
8711
- className: classNames__default.default(this.style('input-group-addon'), this.style(`input-${size}`), disabled ? this.style('disabled') : ''),
8712
- children: addon
8713
- }), isFixedCurrency ? /*#__PURE__*/jsxRuntime.jsxs("div", {
8714
- className: classNames__default.default(this.style('input-group-addon'), this.style(`input-${size}`), this.style('tw-money-input__fixed-currency'), disabled ? this.style('disabled') : ''),
8715
- children: [(size === 'lg' || size === 'md') && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
8716
- children: [/*#__PURE__*/jsxRuntime.jsx("i", {
8717
- className: classNames__default.default(this.style('tw-money-input__keyline'))
8718
- }), /*#__PURE__*/jsxRuntime.jsx("i", {
8719
- className: classNames__default.default(this.style('currency-flag'), this.style(`currency-flag-${selectedCurrency.currency.toLowerCase()}`), this.style('m-r-2'))
8720
- })]
8721
- }), /*#__PURE__*/jsxRuntime.jsx(Title, {
8722
- as: "span",
8723
- type: exports.Typography.TITLE_SUBSECTION,
8724
- className: size === 'lg' ? this.style('m-r-1') : '',
8725
- children: selectedCurrency.currency.toUpperCase()
8726
- })]
8727
- }) : /*#__PURE__*/jsxRuntime.jsx("div", {
8728
- className: classNames__default.default(this.style('input-group-btn'), this.style('amount-currency-select-btn')),
8729
- children: /*#__PURE__*/jsxRuntime.jsx(Select, {
8730
- id: id ? `${id}-select` : undefined,
8731
- classNames: this.props.classNames,
8732
- options: selectOptions,
8733
- selected: {
8734
- ...selectedCurrency,
8735
- label: /*#__PURE__*/jsxRuntime.jsx(Title, {
8736
- as: "span",
8737
- type: exports.Typography.TITLE_SUBSECTION,
8738
- className: "tw-money-input__text",
8739
- children: selectedCurrency.label
8740
- }),
8741
- note: null
8742
- },
8743
- placeholder: this.formatMessage(messages$2.selectPlaceholder),
8744
- searchPlaceholder: this.props.searchPlaceholder,
8745
- searchValue: this.state.searchQuery,
8746
- size: size,
8747
- required: true,
8748
- dropdownWidth: exports.Size.LARGE,
8749
- inverse: true,
8750
- onChange: this.handleSelectChange,
8751
- onSearchChange: this.handleSearchChange,
8752
- ...selectProps
8753
- })
8754
- })]
8755
- });
8756
- }
8757
- }
8758
- function filterOptionsForQuery(options, query) {
8759
- if (!query) {
8760
- return options;
8310
+ setIsMounted(true);
8311
+ // eslint-disable-next-line react-hooks/exhaustive-deps
8312
+ }, [id, persistDismissal]);
8313
+ if (persistDismissal && (isDismissed || !isMounted)) {
8314
+ return null;
8761
8315
  }
8762
- const filteredOptions = removeDuplicateValueOptions(options).filter(option => isCurrencyOptionAndFitsQuery(option, query));
8763
- return sortOptionsLabelsToFirst(filteredOptions, query);
8764
- }
8765
- function removeDuplicateValueOptions(options) {
8766
- const result = [];
8767
- const resultValues = [];
8768
- options.forEach(option => {
8769
- if (option.value && !resultValues.includes(option.value)) {
8770
- result.push(option);
8771
- resultValues.push(option.value);
8772
- }
8773
- });
8774
- return result;
8775
- }
8776
- function isCurrencyOptionAndFitsQuery(option, query) {
8777
- if (!option.value) {
8778
- return false;
8779
- }
8780
- return contains(option.label, query) || contains(option.searchable, query) || contains(option.note, query);
8781
- }
8782
- function contains(property, query) {
8783
- return property && property.toLowerCase().includes(query.toLowerCase());
8784
- }
8785
- function sortOptionsLabelsToFirst(options, query) {
8786
- return options.sort((first, second) => {
8787
- const firstContains = contains(first.label, query);
8788
- const secondContains = contains(second.label, query);
8789
- if (firstContains && secondContains) {
8790
- return 0;
8791
- }
8792
- if (firstContains) {
8793
- return -1;
8794
- }
8795
- if (secondContains) {
8796
- return 1;
8797
- }
8798
- return 0;
8799
- });
8800
- }
8801
- MoneyInput.propTypes = {
8802
- id: PropTypes__default.default.string,
8803
- currencies: PropTypes__default.default.arrayOf(Currency).isRequired,
8804
- selectedCurrency: Currency.isRequired,
8805
- onCurrencyChange: PropTypes__default.default.func,
8806
- placeholder: PropTypes__default.default.number,
8807
- amount: PropTypes__default.default.number,
8808
- size: PropTypes__default.default.oneOf(['sm', 'md', 'lg']),
8809
- onAmountChange: PropTypes__default.default.func,
8810
- addon: PropTypes__default.default.node,
8811
- searchPlaceholder: PropTypes__default.default.string,
8812
- /**
8813
- * Allows the consumer to react to searching, while the search itself is handled internally. Called with `{ searchQuery: string, filteredOptions: Currency[] }`
8814
- */
8815
- onSearchChange: PropTypes__default.default.func,
8816
- customActionLabel: PropTypes__default.default.node,
8817
- onCustomAction: PropTypes__default.default.func,
8818
- classNames: PropTypes__default.default.objectOf(PropTypes__default.default.string),
8819
- selectProps: PropTypes__default.default.object,
8820
- maxLengthOverride: PropTypes__default.default.number
8821
- };
8822
- MoneyInput.defaultProps = {
8823
- id: null,
8824
- size: exports.Size.LARGE,
8825
- addon: null,
8826
- searchPlaceholder: '',
8827
- onSearchChange: undefined,
8828
- onCurrencyChange: null,
8829
- placeholder: null,
8830
- amount: null,
8831
- onAmountChange: null,
8832
- customActionLabel: '',
8833
- onCustomAction: null,
8834
- classNames: {},
8835
- selectProps: {},
8836
- maxLengthOverride: null
8837
- };
8838
- var MoneyInput$1 = reactIntl.injectIntl(MoneyInput);
8839
-
8840
- const NavigationOptionList = ({
8841
- children
8842
- }) => {
8843
- return /*#__PURE__*/jsxRuntime.jsx("ul", {
8844
- className: "np-navigation-options-list",
8845
- children: React.Children.map(children, child => /*#__PURE__*/jsxRuntime.jsx("li", {
8846
- className: "np-navigation-options-list__item",
8847
- children: child
8848
- }, child.key))
8849
- });
8850
- };
8851
- NavigationOptionList.propTypes = {
8852
- children: PropTypes__default.default.node.isRequired
8853
- };
8854
- var NavigationOptionList$1 = NavigationOptionList;
8855
-
8856
- const STORAGE_NAME = 'dismissedNudges';
8857
- const getLocalStorage = () => {
8858
- try {
8859
- const storageItem = localStorage.getItem(STORAGE_NAME);
8860
- if (storageItem) {
8861
- const storage = JSON.parse(storageItem);
8862
- if (Array.isArray(storage)) {
8863
- return storage;
8864
- }
8865
- }
8866
- // eslint-disable-next-line unicorn/prefer-optional-catch-binding, no-empty
8867
- } catch (error) {}
8868
- return [];
8869
- };
8870
- const Nudge = ({
8871
- media,
8872
- mediaName,
8873
- title,
8874
- link,
8875
- href,
8876
- onClick,
8877
- onDismiss,
8878
- persistDismissal,
8879
- isPreviouslyDismissed,
8880
- id,
8881
- className
8882
- }) => {
8883
- const [isDismissed, setIsDismissed] = React.useState(false);
8884
- const [isMounted, setIsMounted] = React.useState(false);
8885
- const handleOnDismiss = () => {
8886
- const dismissedNudgesStorage = getLocalStorage();
8887
- if (persistDismissal && id) {
8888
- try {
8889
- localStorage.setItem(STORAGE_NAME, JSON.stringify([...(dismissedNudgesStorage ? dismissedNudgesStorage : []), id]));
8890
- // eslint-disable-next-line unicorn/prefer-optional-catch-binding, no-empty
8891
- } catch (error) {}
8892
- setIsDismissed(true);
8893
- }
8894
- if (onDismiss) {
8895
- onDismiss();
8896
- }
8897
- };
8898
- React.useEffect(() => {
8899
- if (persistDismissal && id) {
8900
- const dismissedNudgesStorage = getLocalStorage();
8901
- let isDismissed = false;
8902
- if (dismissedNudgesStorage && dismissedNudgesStorage.find(item => item === id)) {
8903
- setIsDismissed(true);
8904
- isDismissed = true;
8905
- }
8906
- if (isPreviouslyDismissed) {
8907
- isPreviouslyDismissed(isDismissed);
8908
- }
8909
- }
8910
- setIsMounted(true);
8911
- // eslint-disable-next-line react-hooks/exhaustive-deps
8912
- }, [id, persistDismissal]);
8913
- if (persistDismissal && (isDismissed || !isMounted)) {
8914
- return null;
8915
- }
8916
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
8917
- className: classNames__default.default('wds-nudge', className),
8918
- id: id,
8919
- children: [!!mediaName && /*#__PURE__*/jsxRuntime.jsx("div", {
8920
- className: "wds-nudge-media",
8921
- children: /*#__PURE__*/jsxRuntime.jsx(art.Illustration, {
8922
- name: mediaName,
8923
- className: classNames__default.default(`wds-nudge-media-${mediaName}`),
8924
- size: "small",
8925
- disablePadding: true,
8926
- alt: ""
8927
- })
8928
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
8929
- className: "wds-nudge-container",
8930
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
8931
- className: "wds-nudge-content",
8932
- children: [/*#__PURE__*/jsxRuntime.jsx(Body, {
8933
- type: exports.Typography.BODY_LARGE,
8934
- className: classNames__default.default('wds-nudge-body'),
8935
- children: title
8936
- }), link && /*#__PURE__*/jsxRuntime.jsx(Link, {
8937
- href: href,
8938
- type: exports.Typography.LINK_LARGE,
8939
- className: "wds-nudge-link",
8940
- onClick: onClick,
8941
- children: link
8942
- })]
8943
- }), onDismiss || persistDismissal ? /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
8944
- className: "wds-nudge-control",
8945
- size: "sm",
8946
- onClick: handleOnDismiss
8947
- }) : null]
8948
- })]
8316
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
8317
+ className: classNames__default.default('wds-nudge', className),
8318
+ id: id,
8319
+ children: [!!mediaName && /*#__PURE__*/jsxRuntime.jsx("div", {
8320
+ className: "wds-nudge-media",
8321
+ children: /*#__PURE__*/jsxRuntime.jsx(art.Illustration, {
8322
+ name: mediaName,
8323
+ className: classNames__default.default(`wds-nudge-media-${mediaName}`),
8324
+ size: "small",
8325
+ disablePadding: true,
8326
+ alt: ""
8327
+ })
8328
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
8329
+ className: "wds-nudge-container",
8330
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
8331
+ className: "wds-nudge-content",
8332
+ children: [/*#__PURE__*/jsxRuntime.jsx(Body, {
8333
+ type: exports.Typography.BODY_LARGE,
8334
+ className: classNames__default.default('wds-nudge-body'),
8335
+ children: title
8336
+ }), link && /*#__PURE__*/jsxRuntime.jsx(Link, {
8337
+ href: href,
8338
+ type: exports.Typography.LINK_LARGE,
8339
+ className: "wds-nudge-link",
8340
+ onClick: onClick,
8341
+ children: link
8342
+ })]
8343
+ }), onDismiss || persistDismissal ? /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
8344
+ className: "wds-nudge-control",
8345
+ size: "sm",
8346
+ onClick: handleOnDismiss
8347
+ }) : null]
8348
+ })]
8949
8349
  });
8950
8350
  };
8951
8351
 
@@ -11058,179 +10458,836 @@ const Radio = ({
11058
10458
  })]
11059
10459
  })
11060
10460
  });
11061
- };
11062
- Radio.propTypes = {
11063
- avatar: PropTypes__default.default.element,
11064
- checked: PropTypes__default.default.bool,
11065
- disabled: PropTypes__default.default.bool,
10461
+ };
10462
+ Radio.propTypes = {
10463
+ avatar: PropTypes__default.default.element,
10464
+ checked: PropTypes__default.default.bool,
10465
+ disabled: PropTypes__default.default.bool,
10466
+ id: PropTypes__default.default.string,
10467
+ label: PropTypes__default.default.string.isRequired,
10468
+ name: PropTypes__default.default.string.isRequired,
10469
+ onChange: PropTypes__default.default.func.isRequired,
10470
+ secondary: PropTypes__default.default.string,
10471
+ value: PropTypes__default.default.oneOfType([PropTypes__default.default.number, PropTypes__default.default.string]),
10472
+ className: PropTypes__default.default.string
10473
+ };
10474
+ Radio.defaultProps = {
10475
+ avatar: undefined,
10476
+ checked: false,
10477
+ disabled: false,
10478
+ id: null,
10479
+ secondary: null,
10480
+ value: '',
10481
+ className: undefined
10482
+ };
10483
+ var Radio$1 = Radio;
10484
+
10485
+ class RadioGroup extends React.Component {
10486
+ constructor(props) {
10487
+ super(props);
10488
+ this.state = {
10489
+ selectedValue: props.selectedValue
10490
+ };
10491
+ }
10492
+ handleOnChange = selectedValue => {
10493
+ const {
10494
+ onChange
10495
+ } = this.props;
10496
+ this.setState({
10497
+ selectedValue
10498
+ }, onChange && onChange(selectedValue));
10499
+ };
10500
+ render() {
10501
+ const {
10502
+ radios,
10503
+ name
10504
+ } = this.props;
10505
+ const {
10506
+ selectedValue
10507
+ } = this.state;
10508
+ return radios && radios.length > 0 ? /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
10509
+ children: radios.map(({
10510
+ id,
10511
+ avatar,
10512
+ value,
10513
+ label,
10514
+ disabled,
10515
+ secondary,
10516
+ readOnly
10517
+ }, index) => /*#__PURE__*/jsxRuntime.jsx(Radio$1
10518
+ // eslint-disable-next-line react/no-array-index-key
10519
+ , {
10520
+ id: id,
10521
+ value: value,
10522
+ label: label,
10523
+ name: name,
10524
+ disabled: disabled,
10525
+ checked: selectedValue === value,
10526
+ secondary: secondary,
10527
+ readOnly: readOnly,
10528
+ avatar: avatar,
10529
+ onChange: value_ => this.handleOnChange(value_)
10530
+ }, index))
10531
+ }) : null;
10532
+ }
10533
+ }
10534
+ RadioGroup.propTypes = {
10535
+ radios: PropTypes__default.default.arrayOf(PropTypes__default.default.shape({
10536
+ id: PropTypes__default.default.string,
10537
+ avatar: PropTypes__default.default.element,
10538
+ value: PropTypes__default.default.oneOfType([PropTypes__default.default.number, PropTypes__default.default.string]),
10539
+ secondary: PropTypes__default.default.string,
10540
+ label: PropTypes__default.default.string.isRequired,
10541
+ disabled: PropTypes__default.default.bool,
10542
+ readOnly: PropTypes__default.default.bool
10543
+ })).isRequired,
10544
+ onChange: PropTypes__default.default.func.isRequired,
10545
+ selectedValue: PropTypes__default.default.oneOfType([PropTypes__default.default.number, PropTypes__default.default.string]),
10546
+ name: PropTypes__default.default.string.isRequired
10547
+ };
10548
+ RadioGroup.defaultProps = {
10549
+ selectedValue: null
10550
+ };
10551
+ var RadioGroup$1 = RadioGroup;
10552
+
10553
+ const RadioOption = ({
10554
+ 'aria-label': ariaLabel,
10555
+ media,
10556
+ title,
10557
+ content,
10558
+ id,
10559
+ name,
10560
+ checked,
10561
+ onChange,
10562
+ complex,
10563
+ disabled,
10564
+ value,
10565
+ showMediaCircle,
10566
+ showMediaAtAllSizes,
10567
+ isContainerAligned
10568
+ }) => {
10569
+ const sharedProps = {
10570
+ 'aria-label': ariaLabel,
10571
+ media,
10572
+ title,
10573
+ content,
10574
+ name,
10575
+ complex,
10576
+ disabled,
10577
+ showMediaCircle,
10578
+ showMediaAtAllSizes,
10579
+ isContainerAligned
10580
+ };
10581
+ return /*#__PURE__*/jsxRuntime.jsx(Option$2, {
10582
+ ...sharedProps,
10583
+ button: /*#__PURE__*/jsxRuntime.jsx(RadioButton$1, {
10584
+ id: id,
10585
+ name: name,
10586
+ checked: checked,
10587
+ disabled: disabled,
10588
+ value: value,
10589
+ onChange: onChange
10590
+ })
10591
+ });
10592
+ };
10593
+ RadioOption.propTypes = {
10594
+ 'aria-label': PropTypes__default.default.string,
10595
+ media: PropTypes__default.default.node,
10596
+ id: PropTypes__default.default.string.isRequired,
10597
+ name: PropTypes__default.default.string.isRequired,
10598
+ title: PropTypes__default.default.node.isRequired,
10599
+ content: PropTypes__default.default.node,
10600
+ checked: PropTypes__default.default.bool,
10601
+ onChange: PropTypes__default.default.func.isRequired,
10602
+ complex: PropTypes__default.default.bool,
10603
+ disabled: PropTypes__default.default.bool,
10604
+ value: PropTypes__default.default.string,
10605
+ showMediaCircle: PropTypes__default.default.bool,
10606
+ showMediaAtAllSizes: PropTypes__default.default.bool,
10607
+ isContainerAligned: PropTypes__default.default.bool
10608
+ };
10609
+ RadioOption.defaultProps = {
10610
+ 'aria-label': undefined,
10611
+ media: null,
10612
+ content: null,
10613
+ checked: false,
10614
+ complex: false,
10615
+ disabled: false,
10616
+ showMediaCircle: true,
10617
+ showMediaAtAllSizes: false,
10618
+ isContainerAligned: false,
10619
+ value: ''
10620
+ };
10621
+ var RadioOption$1 = RadioOption;
10622
+
10623
+ const Section = ({
10624
+ children,
10625
+ className,
10626
+ withHorizontalPadding = false
10627
+ }) => {
10628
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
10629
+ className: classNames__default.default('np-section', className, {
10630
+ 'np-section--with-horizontal-padding': withHorizontalPadding
10631
+ }),
10632
+ children: children
10633
+ });
10634
+ };
10635
+
10636
+ var messages$2 = reactIntl.defineMessages({
10637
+ searchPlaceholder: {
10638
+ id: "neptune.Select.searchPlaceholder"
10639
+ }
10640
+ });
10641
+
10642
+ // Option.tsx NEW
10643
+ function Option$1({
10644
+ label,
10645
+ currency = '',
10646
+ note = '',
10647
+ secondary = '',
10648
+ icon,
10649
+ classNames = {},
10650
+ selected = false
10651
+ }) {
10652
+ const {
10653
+ isModern
10654
+ } = componentsTheming.useTheme();
10655
+ const style = classes => classes.map(className => classNames[className] || className).join(' ');
10656
+ const currencyClassNames = currency ? style(['currency-flag', `currency-flag-${currency.toLowerCase()}`]) : undefined;
10657
+ const iconElement = icon ? /*#__PURE__*/React.cloneElement(icon, {
10658
+ size: 24,
10659
+ className: 'tw-icon'
10660
+ }) : currency && /*#__PURE__*/jsxRuntime.jsx("i", {
10661
+ className: currencyClassNames
10662
+ });
10663
+ const titleAndNoteElement = /*#__PURE__*/jsxRuntime.jsxs(Body, {
10664
+ as: "span",
10665
+ type: exports.Typography.BODY_LARGE,
10666
+ className: selected ? 'text-ellipsis' : undefined,
10667
+ children: [label, note && /*#__PURE__*/jsxRuntime.jsx(Body, {
10668
+ as: "span",
10669
+ className: isModern ? 'm-l-1' : 'm-l-1 body-2',
10670
+ children: note
10671
+ })]
10672
+ });
10673
+ const secondaryElementClassNames = () => {
10674
+ let classes = undefined;
10675
+ if (selected) {
10676
+ classes = 'text-ellipsis';
10677
+ }
10678
+ if (isModern) {
10679
+ return classes;
10680
+ }
10681
+ return `${classes ? classes + ' ' : ''}body-2`;
10682
+ };
10683
+ const secondaryElement = secondary && /*#__PURE__*/jsxRuntime.jsx(Body, {
10684
+ className: secondaryElementClassNames(),
10685
+ children: secondary
10686
+ });
10687
+ return iconElement ? /*#__PURE__*/jsxRuntime.jsxs("div", {
10688
+ className: "d-flex np-option-content",
10689
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
10690
+ className: `d-flex flex-column${selected ? ' justify-content-center' : ''}`,
10691
+ children: iconElement
10692
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
10693
+ className: "d-flex flex-column justify-content-center",
10694
+ children: [titleAndNoteElement, secondaryElement]
10695
+ })]
10696
+ }) : /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
10697
+ children: [iconElement, titleAndNoteElement, secondaryElement]
10698
+ });
10699
+ }
10700
+
10701
+ const SearchBox = /*#__PURE__*/React.forwardRef(({
10702
+ id,
10703
+ classNames = {},
10704
+ focusedOptionId,
10705
+ onChange,
10706
+ onClick,
10707
+ placeholder = undefined,
10708
+ value = ''
10709
+ }, reference) => {
10710
+ const style = className => classNames[className] || className;
10711
+ return /*#__PURE__*/jsxRuntime.jsx("li", {
10712
+ className: style('border-bottom'),
10713
+ children: /*#__PURE__*/jsxRuntime.jsx("a", {
10714
+ className: `${style('np-select-filter-link')} ${style('p-a-0')}`,
10715
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
10716
+ className: style('input-group'),
10717
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
10718
+ className: classNames__default.default('input-group-addon', 'input-group-addon--search'),
10719
+ children: /*#__PURE__*/jsxRuntime.jsx(icons.Search, {
10720
+ className: classNames__default.default(style('tw-icon'), style('tw-icon-search')),
10721
+ size: 24
10722
+ })
10723
+ }), /*#__PURE__*/jsxRuntime.jsx(Input, {
10724
+ ref: reference,
10725
+ id: id,
10726
+ role: "searchbox",
10727
+ inputMode: "search",
10728
+ className: classNames__default.default(style('np-select-filter')),
10729
+ placeholder: placeholder,
10730
+ value: value,
10731
+ spellCheck: "false",
10732
+ "aria-activedescendant": focusedOptionId,
10733
+ onChange: onChange,
10734
+ onClick: onClick
10735
+ })]
10736
+ })
10737
+ })
10738
+ });
10739
+ });
10740
+ var SearchBox$1 = SearchBox;
10741
+
10742
+ const DEFAULT_SEARCH_VALUE = '';
10743
+ const DEFAULT_OPTIONS_PAGE_SIZE = 1000;
10744
+ const includesString = (string1, string2) => string1.toLowerCase().includes(string2.toLowerCase());
10745
+ function defaultFilterFunction(option, searchValue) {
10746
+ if (isPlaceholderOption(option)) {
10747
+ return true;
10748
+ }
10749
+ const {
10750
+ label,
10751
+ note,
10752
+ secondary,
10753
+ currency,
10754
+ searchStrings
10755
+ } = option;
10756
+ return !!label && includesString(label, searchValue) || !!note && includesString(note, searchValue) || !!secondary && includesString(secondary, searchValue) || !!currency && includesString(currency, searchValue) || !!searchStrings && searchStrings.some(string => includesString(string, searchValue));
10757
+ }
10758
+ function isActionableOption(option) {
10759
+ return !option.header && !option.separator && !option.disabled;
10760
+ }
10761
+ function isHeaderOption(option) {
10762
+ return option != null && 'header' in option;
10763
+ }
10764
+ function isSeparatorOption(option) {
10765
+ return option != null && 'separator' in option;
10766
+ }
10767
+ function clamp(from, to, value) {
10768
+ return Math.max(Math.min(to, value), from);
10769
+ }
10770
+
10771
+ /**
10772
+ * No option or placeholder option is selected
10773
+ */
10774
+ const DEFAULT_SELECTED_OPTION = null;
10775
+ function isPlaceholderOption(option) {
10776
+ return option === DEFAULT_SELECTED_OPTION || 'placeholder' in option;
10777
+ }
10778
+ function isSearchableOption(option) {
10779
+ return !isHeaderOption(option) && !isSeparatorOption(option) && !isPlaceholderOption(option);
10780
+ }
10781
+ const getUniqueIdForOption = (parentId = '', option) => {
10782
+ if (option == null) {
10783
+ return undefined;
10784
+ }
10785
+ const uniqueOptionId = option.value || (option.label?.replace(/\s/g, '') ?? '');
10786
+ return `option-${parentId}-${uniqueOptionId}`;
10787
+ };
10788
+
10789
+ /**
10790
+ * @deprecated Use `SelectInput` instead (https://neptune.wise.design/blog/2023-11-28-adopting-our-new-selectinput)
10791
+ */
10792
+ function Select({
10793
+ placeholder,
10794
+ id,
10795
+ required,
10796
+ disabled,
10797
+ inverse,
10798
+ dropdownWidth,
10799
+ size,
10800
+ block,
10801
+ selected,
10802
+ search,
10803
+ onChange,
10804
+ onFocus,
10805
+ onBlur,
10806
+ options: defaultOptions,
10807
+ onSearchChange,
10808
+ searchValue: initSearchValue,
10809
+ searchPlaceholder,
10810
+ // eslint-disable-next-line unicorn/prevent-abbreviations
10811
+ classNames: classNamesProp,
10812
+ dropdownUp,
10813
+ dropdownProps,
10814
+ buttonProps
10815
+ }) {
10816
+ const {
10817
+ formatMessage
10818
+ } = reactIntl.useIntl();
10819
+ const {
10820
+ isModern
10821
+ } = componentsTheming.useTheme();
10822
+ const s = className => classNamesProp[className] || className;
10823
+ const [open, setOpen] = React.useState(false);
10824
+ const [searchValue, setSearchValue] = React.useState(DEFAULT_SEARCH_VALUE);
10825
+ const [keyboardFocusedOptionIndex, setKeyboardFocusedOptionIndex] = React.useState(null);
10826
+ const keyboardFocusedReference = React.useRef();
10827
+ const previousKeyboardFocusedOptionIndex = React.useRef();
10828
+ const [numberOfOptionsShown, setNumberOfOptionsShown] = React.useState(DEFAULT_OPTIONS_PAGE_SIZE);
10829
+ const searchBoxReference = React.useRef(null);
10830
+ const selectReference = React.useRef(null);
10831
+ const dropdownButtonReference = React.useRef(null);
10832
+ const optionsListReference = React.useRef(null);
10833
+ const isSearchEnabled = !!onSearchChange || !!search;
10834
+ const isDropdownAutoWidth = dropdownWidth == null;
10835
+ const fallbackButtonId = React.useMemo(() => getSimpleRandomId('np-select-'), []);
10836
+ const options = React.useMemo(() => {
10837
+ if (!search || !searchValue) {
10838
+ return defaultOptions;
10839
+ }
10840
+ return defaultOptions.filter(isSearchableOption).filter(option => {
10841
+ if (typeof search === 'function') {
10842
+ return search(option, searchValue);
10843
+ } else {
10844
+ return defaultFilterFunction(option, searchValue);
10845
+ }
10846
+ });
10847
+ }, [defaultOptions, search, searchValue]);
10848
+ const selectableOptions = React.useMemo(() => options.filter(isActionableOption), [options]);
10849
+ const focusedOption = selectableOptions[keyboardFocusedOptionIndex];
10850
+ const computedId = id || fallbackButtonId;
10851
+ const listboxId = `${computedId}-listbox`;
10852
+ const searchBoxId = `${computedId}-searchbox`;
10853
+ const {
10854
+ isMobile
10855
+ } = useLayout();
10856
+ React.useEffect(() => {
10857
+ let cancelled;
10858
+ if (keyboardFocusedOptionIndex >= 0) {
10859
+ requestAnimationFrame(() => {
10860
+ if (!cancelled) {
10861
+ if (isSearchEnabled) {
10862
+ keyboardFocusedReference.current?.scrollIntoView?.({
10863
+ block: 'center'
10864
+ });
10865
+ } else {
10866
+ keyboardFocusedReference.current?.focus();
10867
+ }
10868
+ }
10869
+ });
10870
+ return () => {
10871
+ cancelled = true;
10872
+ };
10873
+ }
10874
+ }, [keyboardFocusedOptionIndex, isSearchEnabled]);
10875
+ const handleOnClick = () => {
10876
+ setOpen(true);
10877
+ };
10878
+ const handleTouchStart = event => {
10879
+ if (event.currentTarget === event.target && open) {
10880
+ handleCloseOptions();
10881
+ }
10882
+ };
10883
+ const handleOnFocus = event => {
10884
+ if (onFocus) {
10885
+ onFocus(event);
10886
+ }
10887
+ };
10888
+ const handleOnBlur = event => {
10889
+ const {
10890
+ nativeEvent
10891
+ } = event;
10892
+ if (nativeEvent) {
10893
+ const elementReceivingFocus = nativeEvent.relatedTarget;
10894
+ const select = event.currentTarget;
10895
+ if (select && elementReceivingFocus && select.contains(elementReceivingFocus)) {
10896
+ return;
10897
+ }
10898
+ }
10899
+ if (onBlur) {
10900
+ onBlur(event);
10901
+ }
10902
+ };
10903
+ const handleSearchChange = event => {
10904
+ setNumberOfOptionsShown(DEFAULT_OPTIONS_PAGE_SIZE);
10905
+ setSearchValue(event.target.value);
10906
+ if (onSearchChange) {
10907
+ onSearchChange(event.target.value);
10908
+ }
10909
+ };
10910
+ const handleKeyDown = event => {
10911
+ switch (event.keyCode) {
10912
+ case KeyCodes.UP:
10913
+ case KeyCodes.DOWN:
10914
+ if (open) {
10915
+ moveFocusWithDifference(event.keyCode === KeyCodes.UP ? -1 : 1);
10916
+ } else {
10917
+ setOpen(true);
10918
+ }
10919
+ stopPropagation$1(event);
10920
+ break;
10921
+ case KeyCodes.SPACE:
10922
+ if (event.target !== searchBoxReference.current) {
10923
+ if (open) {
10924
+ selectKeyboardFocusedOption();
10925
+ } else {
10926
+ setOpen(true);
10927
+ }
10928
+ stopPropagation$1(event);
10929
+ }
10930
+ break;
10931
+ case KeyCodes.ENTER:
10932
+ if (open) {
10933
+ selectKeyboardFocusedOption();
10934
+ } else {
10935
+ setOpen(true);
10936
+ }
10937
+ stopPropagation$1(event);
10938
+ break;
10939
+ case KeyCodes.ESCAPE:
10940
+ handleCloseOptions();
10941
+ stopPropagation$1(event);
10942
+ break;
10943
+ case KeyCodes.TAB:
10944
+ if (open) {
10945
+ selectKeyboardFocusedOption();
10946
+ }
10947
+ break;
10948
+ }
10949
+ };
10950
+ function selectKeyboardFocusedOption() {
10951
+ if (keyboardFocusedOptionIndex != null) {
10952
+ selectableOptions.length > 0 && selectOption(selectableOptions[keyboardFocusedOptionIndex]);
10953
+ }
10954
+ }
10955
+ function moveFocusWithDifference(difference) {
10956
+ const selectedOptionIndex = selectableOptions.reduce((optionIndex, current, index) => {
10957
+ if (optionIndex != null) {
10958
+ return optionIndex;
10959
+ }
10960
+ if (isOptionSelected(selected, current)) {
10961
+ return index;
10962
+ }
10963
+ return null;
10964
+ }, null);
10965
+ const previousFocusedIndex = previousKeyboardFocusedOptionIndex.current ?? -1;
10966
+ let indexToStartMovingFrom = previousFocusedIndex;
10967
+ if (previousFocusedIndex === -1) {
10968
+ if (selectedOptionIndex == null) {
10969
+ setKeyboardFocusedOptionIndex(0);
10970
+ } else {
10971
+ indexToStartMovingFrom = selectedOptionIndex;
10972
+ }
10973
+ }
10974
+ const unClampedNewIndex = indexToStartMovingFrom + difference;
10975
+ const newIndex = clamp(0, selectableOptions.length - 1, unClampedNewIndex);
10976
+ setKeyboardFocusedOptionIndex(newIndex);
10977
+ }
10978
+ React.useEffect(() => {
10979
+ if (open) {
10980
+ if (!isMobile || searchValue) {
10981
+ if (isSearchEnabled && !!searchBoxReference.current) {
10982
+ searchBoxReference.current.focus();
10983
+ }
10984
+ if (!isSearchEnabled && optionsListReference.current && (previousKeyboardFocusedOptionIndex.current == null || Number.isNaN(previousKeyboardFocusedOptionIndex.current))) {
10985
+ optionsListReference.current.focus();
10986
+ }
10987
+ }
10988
+ previousKeyboardFocusedOptionIndex.current = keyboardFocusedOptionIndex;
10989
+ } else {
10990
+ previousKeyboardFocusedOptionIndex.current = null;
10991
+ }
10992
+ }, [open, searchValue, isSearchEnabled, isMobile, keyboardFocusedOptionIndex]);
10993
+ const handleCloseOptions = () => {
10994
+ setOpen(false);
10995
+ setKeyboardFocusedOptionIndex(null);
10996
+ if (dropdownButtonReference.current) {
10997
+ dropdownButtonReference.current.focus();
10998
+ }
10999
+ };
11000
+ function createSelectHandlerForOption(option) {
11001
+ return event => {
11002
+ stopPropagation$1(event);
11003
+ selectOption(option);
11004
+ };
11005
+ }
11006
+ function selectOption(option) {
11007
+ onChange(isPlaceholderOption(option) ? DEFAULT_SELECTED_OPTION : option);
11008
+ handleCloseOptions();
11009
+ }
11010
+ function renderOptionsList({
11011
+ className
11012
+ } = {}) {
11013
+ const dropdownClass = classNames__default.default(s('np-dropdown-menu'), {
11014
+ [s('np-dropdown-menu-desktop')]: !isMobile,
11015
+ [s(`np-dropdown-menu-${dropdownWidth}`)]: !isMobile && !isDropdownAutoWidth
11016
+ }, s(className));
11017
+ const showPlaceholder = !required && !isSearchEnabled && Boolean(placeholder);
11018
+ return /*#__PURE__*/jsxRuntime.jsxs("ul", {
11019
+ ref: optionsListReference,
11020
+ id: listboxId,
11021
+ role: "listbox",
11022
+ "aria-orientation": "vertical",
11023
+ "aria-activedescendant": getUniqueIdForOption(id, selected),
11024
+ tabIndex: "-1",
11025
+ className: dropdownClass,
11026
+ ...dropdownProps,
11027
+ children: [showPlaceholder && /*#__PURE__*/jsxRuntime.jsx(PlaceHolderOption, {}), isSearchEnabled && /*#__PURE__*/jsxRuntime.jsx(SearchBox$1, {
11028
+ ref: searchBoxReference,
11029
+ id: searchBoxId,
11030
+ classNames: classNamesProp,
11031
+ value: initSearchValue || searchValue,
11032
+ placeholder: searchPlaceholder || formatMessage(messages$2.searchPlaceholder),
11033
+ focusedOptionId: getUniqueIdForOption(id, focusedOption),
11034
+ onChange: handleSearchChange,
11035
+ onClick: stopPropagation$1
11036
+ }), options.slice(0, numberOfOptionsShown).map(renderOption), numberOfOptionsShown < options.length && /*#__PURE__*/jsxRuntime.jsx(ShowMoreOption, {})]
11037
+ });
11038
+ }
11039
+ function ShowMoreOption() {
11040
+ function handleOnClick(event) {
11041
+ stopPropagation$1(event);
11042
+ setNumberOfOptionsShown(numberOfOptionsShown + DEFAULT_OPTIONS_PAGE_SIZE);
11043
+ }
11044
+ return (
11045
+ /*#__PURE__*/
11046
+ /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */
11047
+ jsxRuntime.jsx("li", {
11048
+ className: classNames__default.default(s('clickable'), s('border-bottom'), s('show-more')),
11049
+ onClick: handleOnClick,
11050
+ onKeyPress: handleOnClick,
11051
+ children: /*#__PURE__*/jsxRuntime.jsx("a", {
11052
+ children: "..."
11053
+ })
11054
+ })
11055
+ );
11056
+ }
11057
+ function PlaceHolderOption() {
11058
+ const placeholderOption = {
11059
+ placeholder
11060
+ };
11061
+ return (
11062
+ /*#__PURE__*/
11063
+ /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */
11064
+ jsxRuntime.jsx("li", {
11065
+ className: classNames__default.default(s('clickable'), s('border-bottom')),
11066
+ onClick: createSelectHandlerForOption(placeholderOption),
11067
+ onKeyPress: createSelectHandlerForOption(placeholderOption),
11068
+ children: /*#__PURE__*/jsxRuntime.jsx("a", {
11069
+ children: placeholder
11070
+ })
11071
+ })
11072
+ );
11073
+ }
11074
+
11075
+ // eslint-disable-next-line react/prop-types
11076
+ function SeparatorOption() {
11077
+ return /*#__PURE__*/jsxRuntime.jsx("li", {
11078
+ className: s('np-separator'),
11079
+ "aria-hidden": true
11080
+ });
11081
+ }
11082
+
11083
+ // eslint-disable-next-line react/prop-types
11084
+ function HeaderOption({
11085
+ children
11086
+ }) {
11087
+ return /*#__PURE__*/jsxRuntime.jsx("li", {
11088
+ // eslint-disable-line jsx-a11y/no-noninteractive-element-interactions
11089
+ className: classNames__default.default(s('np-dropdown-header'), s('np-text-title-group')),
11090
+ onClick: stopPropagation$1,
11091
+ onKeyPress: stopPropagation$1,
11092
+ children: children
11093
+ });
11094
+ }
11095
+ function isOptionSelected(selected, option) {
11096
+ return selected?.value === option?.value;
11097
+ }
11098
+ const renderOption = (option, index) => {
11099
+ const separatorOption = option;
11100
+ if (isSeparatorOption(separatorOption) && separatorOption?.separator) {
11101
+ return /*#__PURE__*/jsxRuntime.jsx(SeparatorOption, {}, index);
11102
+ }
11103
+ const headerOption = option;
11104
+ if (isHeaderOption(headerOption) && headerOption.header) {
11105
+ return /*#__PURE__*/jsxRuntime.jsx(HeaderOption, {
11106
+ children: headerOption.header
11107
+ }, index);
11108
+ }
11109
+ const isActive = isOptionSelected(selected, option);
11110
+ const selectOption = option;
11111
+ const isFocusedWithKeyboard = !selectOption.disabled && keyboardFocusedOptionIndex === getIndexWithoutHeadersForIndexWithHeaders(index);
11112
+ const className = classNames__default.default(s('np-dropdown-item'), selectOption.disabled ? [s('disabled')] : s('clickable'), {
11113
+ [s('active')]: isActive,
11114
+ [s('np-dropdown-item--focused')]: isFocusedWithKeyboard
11115
+ });
11116
+ const handleOnClick = selectOption.disabled ? stopPropagation$1 : createSelectHandlerForOption(selectOption);
11117
+ return (
11118
+ /*#__PURE__*/
11119
+ /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */
11120
+ jsxRuntime.jsx("li", {
11121
+ ref: isFocusedWithKeyboard ? keyboardFocusedReference : undefined,
11122
+ id: getUniqueIdForOption(id, option),
11123
+ "aria-selected": isActive,
11124
+ "aria-disabled": option.disabled,
11125
+ role: "option",
11126
+ tabIndex: "-1",
11127
+ className: className,
11128
+ onClick: handleOnClick,
11129
+ onKeyPress: handleOnClick,
11130
+ children: /*#__PURE__*/jsxRuntime.jsx("a", {
11131
+ disabled: selectOption.disabled,
11132
+ children: /*#__PURE__*/jsxRuntime.jsx(Option$1, {
11133
+ ...selectOption,
11134
+ classNames: classNamesProp
11135
+ })
11136
+ })
11137
+ }, index)
11138
+ );
11139
+ };
11140
+ function getIndexWithoutHeadersForIndexWithHeaders(index) {
11141
+ return options.reduce((sum, option, currentIndex) => {
11142
+ if (currentIndex < index && isActionableOption(option)) {
11143
+ return sum + 1;
11144
+ }
11145
+ return sum;
11146
+ }, 0);
11147
+ }
11148
+ const hasActiveOptions = !!defaultOptions.length;
11149
+ if (open && (initSearchValue || searchValue)) {
11150
+ if (hasActiveOptions && keyboardFocusedOptionIndex == null) {
11151
+ setKeyboardFocusedOptionIndex(0);
11152
+ }
11153
+ if (!hasActiveOptions && keyboardFocusedOptionIndex != null) {
11154
+ setKeyboardFocusedOptionIndex(null);
11155
+ }
11156
+ }
11157
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
11158
+ // eslint-disable-line jsx-a11y/no-static-element-interactions
11159
+ ref: selectReference,
11160
+ className: classNames__default.default(s('np-select'), block ? s('btn-block') : null, s('btn-group')),
11161
+ onKeyDown: handleKeyDown,
11162
+ onTouchMove: handleTouchStart,
11163
+ onFocus: handleOnFocus,
11164
+ onBlur: handleOnBlur,
11165
+ children: [/*#__PURE__*/jsxRuntime.jsxs(Button, {
11166
+ ref: dropdownButtonReference,
11167
+ id: computedId,
11168
+ block: block,
11169
+ size: size,
11170
+ htmlType: "button",
11171
+ className: classNames__default.default(s('np-dropdown-toggle'), s('np-text-body-large'), inverse ? s('np-dropdown-toggle-navy') : null)
11172
+ // reset Button's styles
11173
+ ,
11174
+ type: null,
11175
+ priority: null,
11176
+ disabled: disabled,
11177
+ "aria-controls": listboxId,
11178
+ "aria-expanded": open,
11179
+ "aria-autocomplete": "none",
11180
+ onClick: handleOnClick,
11181
+ ...buttonProps,
11182
+ children: [selected ? /*#__PURE__*/jsxRuntime.jsx(Option$1, {
11183
+ ...selected,
11184
+ classNames: classNamesProp,
11185
+ selected: true
11186
+ }) : /*#__PURE__*/jsxRuntime.jsx("span", {
11187
+ className: s('form-control-placeholder'),
11188
+ children: placeholder
11189
+ }), /*#__PURE__*/jsxRuntime.jsx(Chevron$1
11190
+ // disabled={disabled}
11191
+ , {
11192
+ className: classNames__default.default(s('tw-icon'), s('tw-chevron-up-icon'), s('tw-chevron'), s('bottom'), s('np-select-chevron'))
11193
+ })]
11194
+ }), isMobile ? isSearchEnabled ? /*#__PURE__*/jsxRuntime.jsx(Drawer$1, {
11195
+ open: open,
11196
+ headerTitle: searchPlaceholder || formatMessage(messages$2.searchPlaceholder),
11197
+ onClose: handleCloseOptions,
11198
+ children: renderOptionsList()
11199
+ }) : /*#__PURE__*/jsxRuntime.jsx(BottomSheet$2, {
11200
+ open: open,
11201
+ onClose: handleCloseOptions,
11202
+ children: renderOptionsList({
11203
+ className: isModern ? '' : 'p-a-1'
11204
+ })
11205
+ }) : /*#__PURE__*/jsxRuntime.jsx(Panel$1, {
11206
+ open: open,
11207
+ flip: false,
11208
+ altAxis: true,
11209
+ anchorRef: selectReference,
11210
+ anchorWidth: isDropdownAutoWidth,
11211
+ position: dropdownUp ? exports.Position.TOP : exports.Position.BOTTOM,
11212
+ onClose: handleCloseOptions,
11213
+ children: renderOptionsList({
11214
+ className: 'p-a-1'
11215
+ })
11216
+ })]
11217
+ });
11218
+ }
11219
+ Select.propTypes = {
11220
+ placeholder: PropTypes__default.default.string,
11066
11221
  id: PropTypes__default.default.string,
11067
- label: PropTypes__default.default.string.isRequired,
11068
- name: PropTypes__default.default.string.isRequired,
11222
+ required: PropTypes__default.default.bool,
11223
+ disabled: PropTypes__default.default.bool,
11224
+ inverse: PropTypes__default.default.bool,
11225
+ dropdownRight: PropTypes__default.default.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
11226
+ dropdownWidth: PropTypes__default.default.oneOf(['sm', 'md', 'lg']),
11227
+ size: PropTypes__default.default.oneOf(['sm', 'md', 'lg']),
11228
+ block: PropTypes__default.default.bool,
11229
+ selected: PropTypes__default.default.shape({
11230
+ value: PropTypes__default.default.any.isRequired,
11231
+ label: PropTypes__default.default.node,
11232
+ icon: PropTypes__default.default.node,
11233
+ currency: PropTypes__default.default.string,
11234
+ note: PropTypes__default.default.node,
11235
+ secondary: PropTypes__default.default.node
11236
+ }),
11237
+ /**
11238
+ * Search toggle
11239
+ * if `true` default search functionality being enabled (not case sensitive search in option labels & currency props)
11240
+ * if `function` you can define your own search function to implement custom search experience. This search function used while filtering the options array. The custom search function takes two parameters. First is the option the second is the keyword.
11241
+ */
11242
+ search: PropTypes__default.default.oneOfType([PropTypes__default.default.bool, PropTypes__default.default.func]),
11069
11243
  onChange: PropTypes__default.default.func.isRequired,
11070
- secondary: PropTypes__default.default.string,
11071
- value: PropTypes__default.default.oneOfType([PropTypes__default.default.number, PropTypes__default.default.string]),
11072
- className: PropTypes__default.default.string
11073
- };
11074
- Radio.defaultProps = {
11075
- avatar: undefined,
11076
- checked: false,
11077
- disabled: false,
11078
- id: null,
11079
- secondary: null,
11080
- value: '',
11081
- className: undefined
11082
- };
11083
- var Radio$1 = Radio;
11084
-
11085
- class RadioGroup extends React.Component {
11086
- constructor(props) {
11087
- super(props);
11088
- this.state = {
11089
- selectedValue: props.selectedValue
11090
- };
11091
- }
11092
- handleOnChange = selectedValue => {
11093
- const {
11094
- onChange
11095
- } = this.props;
11096
- this.setState({
11097
- selectedValue
11098
- }, onChange && onChange(selectedValue));
11099
- };
11100
- render() {
11101
- const {
11102
- radios,
11103
- name
11104
- } = this.props;
11105
- const {
11106
- selectedValue
11107
- } = this.state;
11108
- return radios && radios.length > 0 ? /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
11109
- children: radios.map(({
11110
- id,
11111
- avatar,
11112
- value,
11113
- label,
11114
- disabled,
11115
- secondary,
11116
- readOnly
11117
- }, index) => /*#__PURE__*/jsxRuntime.jsx(Radio$1
11118
- // eslint-disable-next-line react/no-array-index-key
11119
- , {
11120
- id: id,
11121
- value: value,
11122
- label: label,
11123
- name: name,
11124
- disabled: disabled,
11125
- checked: selectedValue === value,
11126
- secondary: secondary,
11127
- readOnly: readOnly,
11128
- avatar: avatar,
11129
- onChange: value_ => this.handleOnChange(value_)
11130
- }, index))
11131
- }) : null;
11132
- }
11133
- }
11134
- RadioGroup.propTypes = {
11135
- radios: PropTypes__default.default.arrayOf(PropTypes__default.default.shape({
11136
- id: PropTypes__default.default.string,
11137
- avatar: PropTypes__default.default.element,
11138
- value: PropTypes__default.default.oneOfType([PropTypes__default.default.number, PropTypes__default.default.string]),
11139
- secondary: PropTypes__default.default.string,
11140
- label: PropTypes__default.default.string.isRequired,
11244
+ onFocus: PropTypes__default.default.func,
11245
+ onBlur: PropTypes__default.default.func,
11246
+ options: PropTypes__default.default.arrayOf(PropTypes__default.default.shape({
11247
+ value: PropTypes__default.default.any,
11248
+ label: PropTypes__default.default.node,
11249
+ header: PropTypes__default.default.node,
11250
+ icon: PropTypes__default.default.node,
11251
+ currency: PropTypes__default.default.string,
11252
+ note: PropTypes__default.default.node,
11253
+ secondary: PropTypes__default.default.node,
11254
+ separator: PropTypes__default.default.bool,
11141
11255
  disabled: PropTypes__default.default.bool,
11142
- readOnly: PropTypes__default.default.bool
11256
+ searchStrings: PropTypes__default.default.arrayOf(PropTypes__default.default.string)
11143
11257
  })).isRequired,
11144
- onChange: PropTypes__default.default.func.isRequired,
11145
- selectedValue: PropTypes__default.default.oneOfType([PropTypes__default.default.number, PropTypes__default.default.string]),
11146
- name: PropTypes__default.default.string.isRequired
11147
- };
11148
- RadioGroup.defaultProps = {
11149
- selectedValue: null
11150
- };
11151
- var RadioGroup$1 = RadioGroup;
11152
-
11153
- const RadioOption = ({
11154
- 'aria-label': ariaLabel,
11155
- media,
11156
- title,
11157
- content,
11158
- id,
11159
- name,
11160
- checked,
11161
- onChange,
11162
- complex,
11163
- disabled,
11164
- value,
11165
- showMediaCircle,
11166
- showMediaAtAllSizes,
11167
- isContainerAligned
11168
- }) => {
11169
- const sharedProps = {
11170
- 'aria-label': ariaLabel,
11171
- media,
11172
- title,
11173
- content,
11174
- name,
11175
- complex,
11176
- disabled,
11177
- showMediaCircle,
11178
- showMediaAtAllSizes,
11179
- isContainerAligned
11180
- };
11181
- return /*#__PURE__*/jsxRuntime.jsx(Option$2, {
11182
- ...sharedProps,
11183
- button: /*#__PURE__*/jsxRuntime.jsx(RadioButton$1, {
11184
- id: id,
11185
- name: name,
11186
- checked: checked,
11187
- disabled: disabled,
11188
- value: value,
11189
- onChange: onChange
11190
- })
11191
- });
11192
- };
11193
- RadioOption.propTypes = {
11194
- 'aria-label': PropTypes__default.default.string,
11195
- media: PropTypes__default.default.node,
11196
- id: PropTypes__default.default.string.isRequired,
11197
- name: PropTypes__default.default.string.isRequired,
11198
- title: PropTypes__default.default.node.isRequired,
11199
- content: PropTypes__default.default.node,
11200
- checked: PropTypes__default.default.bool,
11201
- onChange: PropTypes__default.default.func.isRequired,
11202
- complex: PropTypes__default.default.bool,
11203
- disabled: PropTypes__default.default.bool,
11204
- value: PropTypes__default.default.string,
11205
- showMediaCircle: PropTypes__default.default.bool,
11206
- showMediaAtAllSizes: PropTypes__default.default.bool,
11207
- isContainerAligned: PropTypes__default.default.bool
11258
+ /**
11259
+ * To have full control of your search value and response use `onSearchChange` function combined with `searchValue` and custom filtering on the options array.
11260
+ * DO NOT USE TOGETHER WITH `search` PROPERTY
11261
+ */
11262
+ onSearchChange: PropTypes__default.default.func,
11263
+ searchValue: PropTypes__default.default.string,
11264
+ searchPlaceholder: PropTypes__default.default.string,
11265
+ classNames: PropTypes__default.default.objectOf(PropTypes__default.default.string),
11266
+ dropdownUp: PropTypes__default.default.bool,
11267
+ buttonProps: PropTypes__default.default.object,
11268
+ dropdownProps: PropTypes__default.default.object
11208
11269
  };
11209
- RadioOption.defaultProps = {
11210
- 'aria-label': undefined,
11211
- media: null,
11212
- content: null,
11213
- checked: false,
11214
- complex: false,
11270
+ Select.defaultProps = {
11271
+ id: undefined,
11272
+ placeholder: undefined,
11273
+ size: 'md',
11274
+ dropdownRight: null,
11275
+ dropdownWidth: null,
11276
+ inverse: false,
11277
+ required: false,
11215
11278
  disabled: false,
11216
- showMediaCircle: true,
11217
- showMediaAtAllSizes: false,
11218
- isContainerAligned: false,
11219
- value: ''
11220
- };
11221
- var RadioOption$1 = RadioOption;
11222
-
11223
- const Section = ({
11224
- children,
11225
- className,
11226
- withHorizontalPadding = false
11227
- }) => {
11228
- return /*#__PURE__*/jsxRuntime.jsx("div", {
11229
- className: classNames__default.default('np-section', className, {
11230
- 'np-section--with-horizontal-padding': withHorizontalPadding
11231
- }),
11232
- children: children
11233
- });
11279
+ block: true,
11280
+ selected: null,
11281
+ onFocus: null,
11282
+ onBlur: null,
11283
+ onSearchChange: undefined,
11284
+ search: false,
11285
+ searchValue: '',
11286
+ searchPlaceholder: undefined,
11287
+ classNames: {},
11288
+ dropdownUp: false,
11289
+ buttonProps: {},
11290
+ dropdownProps: {}
11234
11291
  };
11235
11292
 
11236
11293
  const CSS_TRANSITION_DURATION = 400;
@@ -14663,9 +14720,11 @@ var cs = {
14663
14720
  "neptune.DateLookup.twentyYears": "20 let",
14664
14721
  "neptune.DateLookup.year": "rok",
14665
14722
  "neptune.FlowNavigation.back": "back to previous step",
14723
+ "neptune.Info.ariaLabel": "Více informací",
14666
14724
  "neptune.Link.opensInNewTab": "(opens in new tab)",
14667
14725
  "neptune.MoneyInput.Select.placeholder": "Vybrat možnost...",
14668
14726
  "neptune.Select.searchPlaceholder": "Hledat...",
14727
+ "neptune.SelectInput.noResultsFound": "Nebyly nalezeny žádné výsledky",
14669
14728
  "neptune.Summary.statusDone": "Položka dokončena",
14670
14729
  "neptune.Summary.statusNotDone": "Položka k dokončení",
14671
14730
  "neptune.Summary.statusPending": "Čekající položka",
@@ -14716,9 +14775,11 @@ var de = {
14716
14775
  "neptune.DateLookup.twentyYears": "20 Jahre",
14717
14776
  "neptune.DateLookup.year": "Jahr",
14718
14777
  "neptune.FlowNavigation.back": "zurück zum vorherigen Schritt",
14778
+ "neptune.Info.ariaLabel": "Weitere Informationen",
14719
14779
  "neptune.Link.opensInNewTab": "(wird in einem neuen Tab geöffnet)",
14720
14780
  "neptune.MoneyInput.Select.placeholder": "Wähle eine der Möglichkeiten aus...",
14721
14781
  "neptune.Select.searchPlaceholder": "Wird gesucht...",
14782
+ "neptune.SelectInput.noResultsFound": "Keine Ergebnisse gefunden",
14722
14783
  "neptune.Summary.statusDone": "Schritt erledigt",
14723
14784
  "neptune.Summary.statusNotDone": "Schritt noch zu erledigen",
14724
14785
  "neptune.Summary.statusPending": "Schritt ausstehend",
@@ -14769,9 +14830,11 @@ var es = {
14769
14830
  "neptune.DateLookup.twentyYears": "20 años",
14770
14831
  "neptune.DateLookup.year": "año",
14771
14832
  "neptune.FlowNavigation.back": "volver al paso anterior",
14833
+ "neptune.Info.ariaLabel": "Más información",
14772
14834
  "neptune.Link.opensInNewTab": "(se abre en una pestaña nueva)",
14773
14835
  "neptune.MoneyInput.Select.placeholder": "Selecciona una opción...",
14774
14836
  "neptune.Select.searchPlaceholder": "Buscar...",
14837
+ "neptune.SelectInput.noResultsFound": "No se han encontrado resultados",
14775
14838
  "neptune.Summary.statusDone": "Apartado listo",
14776
14839
  "neptune.Summary.statusNotDone": "Apartado a completar",
14777
14840
  "neptune.Summary.statusPending": "Apartado pendiente",
@@ -14822,9 +14885,11 @@ var fr = {
14822
14885
  "neptune.DateLookup.twentyYears": "20 ans",
14823
14886
  "neptune.DateLookup.year": "année",
14824
14887
  "neptune.FlowNavigation.back": "revenir à l'étape précédente",
14888
+ "neptune.Info.ariaLabel": "Plus d'informations",
14825
14889
  "neptune.Link.opensInNewTab": "(ouvre dans un nouvel onglet)",
14826
14890
  "neptune.MoneyInput.Select.placeholder": "Sélectionner une option...",
14827
14891
  "neptune.Select.searchPlaceholder": "Recherche...",
14892
+ "neptune.SelectInput.noResultsFound": "Aucun résultat trouvé",
14828
14893
  "neptune.Summary.statusDone": "Validé",
14829
14894
  "neptune.Summary.statusNotDone": "À compléter",
14830
14895
  "neptune.Summary.statusPending": "En attente",
@@ -14875,9 +14940,11 @@ var hu = {
14875
14940
  "neptune.DateLookup.twentyYears": "20 év",
14876
14941
  "neptune.DateLookup.year": "év",
14877
14942
  "neptune.FlowNavigation.back": "vissza az előző lépéshez",
14943
+ "neptune.Info.ariaLabel": "További információ",
14878
14944
  "neptune.Link.opensInNewTab": "(új lapon nyílik meg)",
14879
14945
  "neptune.MoneyInput.Select.placeholder": "Válassz ki egy lehetőséget...",
14880
14946
  "neptune.Select.searchPlaceholder": "Keresés...",
14947
+ "neptune.SelectInput.noResultsFound": "Nincs találat",
14881
14948
  "neptune.Summary.statusDone": "Kész",
14882
14949
  "neptune.Summary.statusNotDone": "Hátravan",
14883
14950
  "neptune.Summary.statusPending": "Függőben",
@@ -14928,9 +14995,11 @@ var id = {
14928
14995
  "neptune.DateLookup.twentyYears": "20 tahun",
14929
14996
  "neptune.DateLookup.year": "tahun",
14930
14997
  "neptune.FlowNavigation.back": "kembali ke langkah sebelumnya",
14998
+ "neptune.Info.ariaLabel": "Informasi lebih lanjut",
14931
14999
  "neptune.Link.opensInNewTab": "(terbuka di tab baru)",
14932
15000
  "neptune.MoneyInput.Select.placeholder": "Pilih opsi...",
14933
15001
  "neptune.Select.searchPlaceholder": "Cari...",
15002
+ "neptune.SelectInput.noResultsFound": "Hasil tidak ditemukan",
14934
15003
  "neptune.Summary.statusDone": "Item selesai",
14935
15004
  "neptune.Summary.statusNotDone": "Item yang harus dilakukan",
14936
15005
  "neptune.Summary.statusPending": "Item tertunda",
@@ -14981,9 +15050,11 @@ var it = {
14981
15050
  "neptune.DateLookup.twentyYears": "20 anni",
14982
15051
  "neptune.DateLookup.year": "anno",
14983
15052
  "neptune.FlowNavigation.back": "torna al passaggio precedente",
15053
+ "neptune.Info.ariaLabel": "Maggiori informazioni",
14984
15054
  "neptune.Link.opensInNewTab": "(si apre in una nuova scheda)",
14985
15055
  "neptune.MoneyInput.Select.placeholder": "Seleziona un'opzione...",
14986
15056
  "neptune.Select.searchPlaceholder": "Cerca...",
15057
+ "neptune.SelectInput.noResultsFound": "Nessun risultato trovato",
14987
15058
  "neptune.Summary.statusDone": "Completato",
14988
15059
  "neptune.Summary.statusNotDone": "Da completare",
14989
15060
  "neptune.Summary.statusPending": "In corso",
@@ -15034,9 +15105,11 @@ var ja = {
15034
15105
  "neptune.DateLookup.twentyYears": "20年",
15035
15106
  "neptune.DateLookup.year": "年",
15036
15107
  "neptune.FlowNavigation.back": "前のステップに戻る",
15108
+ "neptune.Info.ariaLabel": "詳細",
15037
15109
  "neptune.Link.opensInNewTab": "(新しいタブで開きます)",
15038
15110
  "neptune.MoneyInput.Select.placeholder": "選択してください...",
15039
15111
  "neptune.Select.searchPlaceholder": "検索... ",
15112
+ "neptune.SelectInput.noResultsFound": "結果が見つかりませんでした",
15040
15113
  "neptune.Summary.statusDone": "完了",
15041
15114
  "neptune.Summary.statusNotDone": "未対応",
15042
15115
  "neptune.Summary.statusPending": "保留中",
@@ -15087,9 +15160,11 @@ var pl = {
15087
15160
  "neptune.DateLookup.twentyYears": "20 lat",
15088
15161
  "neptune.DateLookup.year": "rok",
15089
15162
  "neptune.FlowNavigation.back": "wróć do poprzedniego kroku",
15163
+ "neptune.Info.ariaLabel": "Więcej informacji",
15090
15164
  "neptune.Link.opensInNewTab": "(otworzy się w nowej zakładce)",
15091
15165
  "neptune.MoneyInput.Select.placeholder": "Wybierz opcję...",
15092
15166
  "neptune.Select.searchPlaceholder": "Wyszukaj...",
15167
+ "neptune.SelectInput.noResultsFound": "Nie znaleziono wyników",
15093
15168
  "neptune.Summary.statusDone": "Czynność wykonana",
15094
15169
  "neptune.Summary.statusNotDone": "Czynność do wykonania",
15095
15170
  "neptune.Summary.statusPending": "Czynność oczekująca",
@@ -15132,17 +15207,19 @@ var pt = {
15132
15207
  "neptune.DateInput.month.label": "Mês",
15133
15208
  "neptune.DateInput.year.label": "Ano",
15134
15209
  "neptune.DateLookup.day": "dia",
15135
- "neptune.DateLookup.goTo20YearView": "Go to 20 year view",
15210
+ "neptune.DateLookup.goTo20YearView": "Acessar a visualização de 20 anos",
15136
15211
  "neptune.DateLookup.month": "mês",
15137
15212
  "neptune.DateLookup.next": "próximo",
15138
15213
  "neptune.DateLookup.previous": "anterior",
15139
15214
  "neptune.DateLookup.selected": "selecionada",
15140
15215
  "neptune.DateLookup.twentyYears": "20 anos",
15141
15216
  "neptune.DateLookup.year": "ano",
15142
- "neptune.FlowNavigation.back": "back to previous step",
15143
- "neptune.Link.opensInNewTab": "(abrir a página em uma nova aba)",
15217
+ "neptune.FlowNavigation.back": "voltar à etapa anterior",
15218
+ "neptune.Info.ariaLabel": "Mais informações",
15219
+ "neptune.Link.opensInNewTab": "(abre em uma nova aba)",
15144
15220
  "neptune.MoneyInput.Select.placeholder": "Escolha uma opção...",
15145
15221
  "neptune.Select.searchPlaceholder": "Buscar...",
15222
+ "neptune.SelectInput.noResultsFound": "Nenhum resultado encontrado",
15146
15223
  "neptune.Summary.statusDone": "Pronto",
15147
15224
  "neptune.Summary.statusNotDone": "Não iniciado",
15148
15225
  "neptune.Summary.statusPending": "Pendente",
@@ -15186,16 +15263,18 @@ var ro = {
15186
15263
  "neptune.DateInput.year.label": "An",
15187
15264
  "neptune.DateLookup.day": "zi",
15188
15265
  "neptune.DateLookup.goTo20YearView": "Accesează vizualizarea pe 20 de ani",
15189
- "neptune.DateLookup.month": "luna",
15266
+ "neptune.DateLookup.month": "lună",
15190
15267
  "neptune.DateLookup.next": "înainte",
15191
- "neptune.DateLookup.previous": "precedenta",
15268
+ "neptune.DateLookup.previous": "înapoi",
15192
15269
  "neptune.DateLookup.selected": "selectată",
15193
15270
  "neptune.DateLookup.twentyYears": "20 de ani",
15194
- "neptune.DateLookup.year": "anul",
15271
+ "neptune.DateLookup.year": "an",
15195
15272
  "neptune.FlowNavigation.back": "înapoi la pasul anterior",
15273
+ "neptune.Info.ariaLabel": "Mai multe informații",
15196
15274
  "neptune.Link.opensInNewTab": "(se deschide într-o filă nouă)",
15197
15275
  "neptune.MoneyInput.Select.placeholder": "Selectează o opţiune...",
15198
15276
  "neptune.Select.searchPlaceholder": "Caută...",
15277
+ "neptune.SelectInput.noResultsFound": "Nu s-a găsit niciun rezultat",
15199
15278
  "neptune.Summary.statusDone": "Finalizat",
15200
15279
  "neptune.Summary.statusNotDone": "De făcut",
15201
15280
  "neptune.Summary.statusPending": "În așteptare",
@@ -15241,14 +15320,16 @@ var ru = {
15241
15320
  "neptune.DateLookup.goTo20YearView": "Перейти к обзору 20 лет",
15242
15321
  "neptune.DateLookup.month": "месяц",
15243
15322
  "neptune.DateLookup.next": "далее",
15244
- "neptune.DateLookup.previous": "предыдущий",
15323
+ "neptune.DateLookup.previous": "назад",
15245
15324
  "neptune.DateLookup.selected": "выбрано",
15246
15325
  "neptune.DateLookup.twentyYears": "20 лет",
15247
15326
  "neptune.DateLookup.year": "год",
15248
15327
  "neptune.FlowNavigation.back": "вернуться к предыдущему шагу",
15328
+ "neptune.Info.ariaLabel": "Подробнее",
15249
15329
  "neptune.Link.opensInNewTab": "(откроется в новой вкладке)",
15250
15330
  "neptune.MoneyInput.Select.placeholder": "Выберите вариант...",
15251
15331
  "neptune.Select.searchPlaceholder": "Поиск...",
15332
+ "neptune.SelectInput.noResultsFound": "Ничего не найдено",
15252
15333
  "neptune.Summary.statusDone": "Этап завершен",
15253
15334
  "neptune.Summary.statusNotDone": "Этап к выполнению",
15254
15335
  "neptune.Summary.statusPending": "Этап в процессе",
@@ -15299,9 +15380,11 @@ var th = {
15299
15380
  "neptune.DateLookup.twentyYears": "20 ปี",
15300
15381
  "neptune.DateLookup.year": "ปี",
15301
15382
  "neptune.FlowNavigation.back": "back to previous step",
15383
+ "neptune.Info.ariaLabel": "ข้อมูลเพิ่มเติม",
15302
15384
  "neptune.Link.opensInNewTab": "(opens in new tab)",
15303
15385
  "neptune.MoneyInput.Select.placeholder": "เลือกตัวเลือก...",
15304
15386
  "neptune.Select.searchPlaceholder": "ค้นหา...",
15387
+ "neptune.SelectInput.noResultsFound": "ไม่พบผลลัพธ์",
15305
15388
  "neptune.Summary.statusDone": "รายการที่ทำแล้ว",
15306
15389
  "neptune.Summary.statusNotDone": "รายการที่ต้องทำ",
15307
15390
  "neptune.Summary.statusPending": "รายการที่รอดำเนินการ",
@@ -15352,9 +15435,11 @@ var tr = {
15352
15435
  "neptune.DateLookup.twentyYears": "20 yıl",
15353
15436
  "neptune.DateLookup.year": "yıl",
15354
15437
  "neptune.FlowNavigation.back": "önceki adıma dön",
15438
+ "neptune.Info.ariaLabel": "Daha fazla bilgi",
15355
15439
  "neptune.Link.opensInNewTab": "(yeni sekmede açılır)",
15356
15440
  "neptune.MoneyInput.Select.placeholder": "Bir seçenek seçin...",
15357
15441
  "neptune.Select.searchPlaceholder": "Ara...",
15442
+ "neptune.SelectInput.noResultsFound": "Sonuç bulunamadı",
15358
15443
  "neptune.Summary.statusDone": "Tamamlanan aşama",
15359
15444
  "neptune.Summary.statusNotDone": "Yapılacak",
15360
15445
  "neptune.Summary.statusPending": "Bekliyor",
@@ -15405,9 +15490,11 @@ var uk = {
15405
15490
  "neptune.DateLookup.twentyYears": "20 років",
15406
15491
  "neptune.DateLookup.year": "рік",
15407
15492
  "neptune.FlowNavigation.back": "back to previous step",
15493
+ "neptune.Info.ariaLabel": "Більше відомостей",
15408
15494
  "neptune.Link.opensInNewTab": "(opens in new tab)",
15409
15495
  "neptune.MoneyInput.Select.placeholder": "Виберіть варіант…",
15410
15496
  "neptune.Select.searchPlaceholder": "Пошук…",
15497
+ "neptune.SelectInput.noResultsFound": "Нічого не знайдено",
15411
15498
  "neptune.Summary.statusDone": "Виконано",
15412
15499
  "neptune.Summary.statusNotDone": "Не виконано",
15413
15500
  "neptune.Summary.statusPending": "Виконується",
@@ -15444,23 +15531,25 @@ var uk = {
15444
15531
  var zhCN = {
15445
15532
  "neptune.Button.loadingAriaLabel": "正在加载",
15446
15533
  "neptune.Chips.ariaLabel": "清除 {choice}",
15447
- "neptune.ClearButton.ariaLabel": "清晰",
15534
+ "neptune.ClearButton.ariaLabel": "清除",
15448
15535
  "neptune.CloseButton.ariaLabel": "关闭",
15449
15536
  "neptune.DateInput.day.label": "日",
15450
15537
  "neptune.DateInput.month.label": "月",
15451
15538
  "neptune.DateInput.year.label": "年",
15452
15539
  "neptune.DateLookup.day": "日",
15453
- "neptune.DateLookup.goTo20YearView": "Go to 20 year view",
15540
+ "neptune.DateLookup.goTo20YearView": "转到 20 年视图",
15454
15541
  "neptune.DateLookup.month": "月",
15455
15542
  "neptune.DateLookup.next": "下一页",
15456
15543
  "neptune.DateLookup.previous": "上一页",
15457
15544
  "neptune.DateLookup.selected": "已选",
15458
- "neptune.DateLookup.twentyYears": "20年",
15545
+ "neptune.DateLookup.twentyYears": "20 年",
15459
15546
  "neptune.DateLookup.year": "年",
15460
- "neptune.FlowNavigation.back": "back to previous step",
15461
- "neptune.Link.opensInNewTab": "(opens in new tab)",
15547
+ "neptune.FlowNavigation.back": "返回上一步",
15548
+ "neptune.Info.ariaLabel": "更多信息",
15549
+ "neptune.Link.opensInNewTab": "(在新标签页中打开)",
15462
15550
  "neptune.MoneyInput.Select.placeholder": "请选择...",
15463
15551
  "neptune.Select.searchPlaceholder": "搜索",
15552
+ "neptune.SelectInput.noResultsFound": "找不到结果",
15464
15553
  "neptune.Summary.statusDone": "已完成",
15465
15554
  "neptune.Summary.statusNotDone": "未完成",
15466
15555
  "neptune.Summary.statusPending": "待处理",
@@ -15476,7 +15565,7 @@ var zhCN = {
15476
15565
  "neptune.Upload.usPlaceholder": "拖放小于 5MB 的文件",
15477
15566
  "neptune.UploadButton.allFileTypes": "所有文件类型",
15478
15567
  "neptune.UploadButton.dropFiles": "拖放文件开始上传",
15479
- "neptune.UploadButton.instructions": "{fileTypes},小于 {size}MB",
15568
+ "neptune.UploadButton.instructions": "{fileTypes},小于 {size} MB",
15480
15569
  "neptune.UploadButton.uploadFile": "上传文件",
15481
15570
  "neptune.UploadButton.uploadFiles": "上传文件",
15482
15571
  "neptune.UploadInput.deleteModalBody": "删除此文件会将其从我们的系统中删除",
@@ -15511,9 +15600,11 @@ var zhHK = {
15511
15600
  "neptune.DateLookup.twentyYears": "20年",
15512
15601
  "neptune.DateLookup.year": "年",
15513
15602
  "neptune.FlowNavigation.back": "返回上一個步驟",
15603
+ "neptune.Info.ariaLabel": "更多資訊",
15514
15604
  "neptune.Link.opensInNewTab": "(在新分頁中開啟)",
15515
15605
  "neptune.MoneyInput.Select.placeholder": "選擇一個選項…",
15516
15606
  "neptune.Select.searchPlaceholder": "搜尋…",
15607
+ "neptune.SelectInput.noResultsFound": "找不到任何結果",
15517
15608
  "neptune.Summary.statusDone": "已完成事項",
15518
15609
  "neptune.Summary.statusNotDone": "未完成事項",
15519
15610
  "neptune.Summary.statusPending": "待處理事項",