@transferwise/components 46.4.0 → 46.5.0

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 (29) hide show
  1. package/build/index.esm.js +110 -116
  2. package/build/index.esm.js.map +1 -1
  3. package/build/index.js +110 -116
  4. package/build/index.js.map +1 -1
  5. package/build/types/index.d.ts +1 -0
  6. package/build/types/index.d.ts.map +1 -1
  7. package/build/types/inputs/SelectInput.d.ts +2 -2
  8. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  9. package/build/types/moneyInput/MoneyInput.d.ts +45 -31
  10. package/build/types/moneyInput/MoneyInput.d.ts.map +1 -1
  11. package/build/types/moneyInput/MoneyInput.messages.d.ts +6 -6
  12. package/build/types/moneyInput/MoneyInput.messages.d.ts.map +1 -1
  13. package/build/types/moneyInput/currencyFormatting.d.ts +2 -2
  14. package/build/types/moneyInput/currencyFormatting.d.ts.map +1 -1
  15. package/build/types/moneyInput/index.d.ts +2 -1
  16. package/build/types/moneyInput/index.d.ts.map +1 -1
  17. package/package.json +1 -1
  18. package/src/flowNavigation/FlowNavigation.story.js +1 -1
  19. package/src/index.ts +6 -0
  20. package/src/inputs/SelectInput.tsx +2 -2
  21. package/src/moneyInput/{MoneyInput.rtl.spec.js → MoneyInput.rtl.spec.tsx} +4 -4
  22. package/src/moneyInput/MoneyInput.spec.js +109 -49
  23. package/src/moneyInput/MoneyInput.story.tsx +6 -14
  24. package/src/moneyInput/{MoneyInput.js → MoneyInput.tsx} +189 -173
  25. package/src/moneyInput/{currencyFormatting.spec.js → currencyFormatting.spec.ts} +2 -2
  26. package/src/moneyInput/{currencyFormatting.js → currencyFormatting.ts} +7 -10
  27. package/src/moneyInput/index.ts +7 -0
  28. package/src/moneyInput/index.js +0 -1
  29. /package/src/moneyInput/{MoneyInput.messages.js → MoneyInput.messages.ts} +0 -0
@@ -1523,7 +1523,7 @@ class DimmerManager {
1523
1523
  /**
1524
1524
  * Dimmer refs
1525
1525
  */
1526
-
1526
+ dimmers;
1527
1527
  constructor() {
1528
1528
  this.dimmers = [];
1529
1529
  }
@@ -5399,6 +5399,7 @@ var DynamicFieldDefinitionList$1 = DynamicFieldDefinitionList;
5399
5399
  const ESCAPED_OPENING_CHEVRON = '<';
5400
5400
  const ESCAPED_CLOSING_CHEVRON = '>';
5401
5401
  class EmphasisHtmlTransformer {
5402
+ tags;
5402
5403
  constructor(whitelistedTags) {
5403
5404
  this.tags = (whitelistedTags || []).map(tag => {
5404
5405
  return {
@@ -7832,20 +7833,17 @@ function getValidLocale(locale) {
7832
7833
  Intl.NumberFormat(noUnderscoreLocale);
7833
7834
  return noUnderscoreLocale;
7834
7835
  } catch {
7835
- return 'en-GB';
7836
+ return DEFAULT_LOCALE;
7836
7837
  }
7837
7838
  }
7838
- function getCurrencyDecimals(currency = '') {
7839
+ function getCurrencyDecimals(currency) {
7839
7840
  const upperCaseCurrency = currency.toUpperCase();
7840
- if (Object.prototype.hasOwnProperty.call(currencyDecimals, upperCaseCurrency)) {
7841
- return currencyDecimals[upperCaseCurrency];
7842
- }
7843
- return DEFAULT_CURRENCY_DECIMALS;
7841
+ return currencyDecimals[upperCaseCurrency] ?? DEFAULT_CURRENCY_DECIMALS;
7844
7842
  }
7845
7843
  function getDecimalSeparator(locale) {
7846
7844
  return isNumberLocaleSupported() ? 1.1.toLocaleString(locale)[1] : '.';
7847
7845
  }
7848
- function parseAmount(number, currency, locale) {
7846
+ function parseAmount(number, currency, locale = DEFAULT_LOCALE) {
7849
7847
  const validLocale = getValidLocale(locale);
7850
7848
  const precision = getCurrencyDecimals(currency);
7851
7849
  const groupSeparator = isNumberLocaleSupported() ? 10000 .toLocaleString(validLocale)[2] : ',';
@@ -7855,53 +7853,67 @@ function parseAmount(number, currency, locale) {
7855
7853
  return Math.abs(parsedAmount);
7856
7854
  }
7857
7855
 
7858
- const Currency = PropTypes.shape({
7859
- header: PropTypes.string,
7860
- value: PropTypes.string,
7861
- label: PropTypes.string,
7862
- currency: PropTypes.string,
7863
- note: PropTypes.string,
7864
- searchable: PropTypes.string
7865
- });
7866
7856
  const isNumberOrNull = v => isNumber(v) || isNull(v);
7867
- const formatAmountIfSet = (amount, currency, locale, maxLengthOverride) => {
7857
+ const formatAmountIfSet = ({
7858
+ amount,
7859
+ currency,
7860
+ locale,
7861
+ maxLengthOverride
7862
+ }) => {
7868
7863
  if (maxLengthOverride) {
7869
- return amount || '';
7864
+ return amount != null ? String(amount) : '';
7870
7865
  } else {
7871
7866
  return typeof amount === 'number' ? formatAmount(amount, currency, locale) : '';
7872
7867
  }
7873
7868
  };
7874
- const parseNumber = (amount, currency, locale, maxLengthOverride) => {
7869
+ const parseNumber = ({
7870
+ amount,
7871
+ currency,
7872
+ locale,
7873
+ maxLengthOverride
7874
+ }) => {
7875
7875
  if (!maxLengthOverride) {
7876
7876
  return parseAmount(amount, currency, locale);
7877
7877
  }
7878
7878
  if (maxLengthOverride && amount.length > maxLengthOverride) {
7879
7879
  return 0;
7880
7880
  }
7881
- return +amount;
7881
+ return Number(amount);
7882
7882
  };
7883
7883
  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]);
7884
7884
  const inputKeyAllowlist = new Set([Key.PERIOD, Key.COMMA]);
7885
7885
  class MoneyInput extends Component {
7886
+ static defaultProps = {
7887
+ size: Size.LARGE,
7888
+ classNames: {},
7889
+ selectProps: {}
7890
+ };
7891
+ amountFocused = false;
7886
7892
  constructor(props) {
7887
7893
  super(props);
7888
- const {
7889
- locale
7890
- } = this.props.intl;
7891
- this.formatMessage = this.props.intl.formatMessage;
7892
7894
  this.state = {
7893
7895
  searchQuery: '',
7894
- formattedAmount: formatAmountIfSet(props.amount, props.selectedCurrency.currency, locale, props.maxLengthOverride),
7895
- locale
7896
+ formattedAmount: formatAmountIfSet({
7897
+ amount: props.amount,
7898
+ currency: props.selectedCurrency.currency,
7899
+ locale: props.intl.locale,
7900
+ maxLengthOverride: props.maxLengthOverride
7901
+ }),
7902
+ locale: props.intl.locale
7896
7903
  };
7897
7904
  }
7898
7905
  UNSAFE_componentWillReceiveProps(nextProps) {
7899
7906
  this.setState({
7900
- locale: nextProps?.intl?.locale
7907
+ locale: nextProps.intl.locale
7901
7908
  });
7902
7909
  if (!this.amountFocused) {
7903
7910
  this.setState({
7904
- formattedAmount: formatAmountIfSet(nextProps.amount, nextProps.selectedCurrency.currency, nextProps?.intl?.locale, nextProps.maxLengthOverride)
7911
+ formattedAmount: formatAmountIfSet({
7912
+ amount: nextProps.amount,
7913
+ currency: nextProps.selectedCurrency.currency,
7914
+ locale: nextProps.intl.locale,
7915
+ maxLengthOverride: nextProps.maxLengthOverride
7916
+ })
7905
7917
  });
7906
7918
  }
7907
7919
  }
@@ -7921,16 +7933,26 @@ class MoneyInput extends Component {
7921
7933
  }
7922
7934
  };
7923
7935
  handlePaste = event => {
7924
- const paste = (event.clipboardData || window.clipboardData).getData('text');
7936
+ const paste = event.clipboardData.getData('text');
7925
7937
  const {
7926
7938
  locale
7927
7939
  } = this.state;
7928
- const parsed = isEmpty(paste) ? null : parseNumber(paste, this.props.selectedCurrency.currency, locale, this.props.maxLengthOverride);
7940
+ const parsed = isEmpty(paste) ? null : parseNumber({
7941
+ amount: paste,
7942
+ currency: this.props.selectedCurrency.currency,
7943
+ locale: locale,
7944
+ maxLengthOverride: this.props.maxLengthOverride
7945
+ });
7929
7946
  if (isNumberOrNull(parsed)) {
7930
7947
  this.setState({
7931
- formattedAmount: formatAmountIfSet(parsed, this.props.selectedCurrency.currency, locale, this.props.maxLengthOverride)
7948
+ formattedAmount: formatAmountIfSet({
7949
+ amount: parsed,
7950
+ currency: this.props.selectedCurrency.currency,
7951
+ locale: locale,
7952
+ maxLengthOverride: this.props.maxLengthOverride
7953
+ })
7932
7954
  });
7933
- this.props.onAmountChange(parsed);
7955
+ this.props.onAmountChange?.(parsed);
7934
7956
  }
7935
7957
  event.preventDefault();
7936
7958
  };
@@ -7941,9 +7963,14 @@ class MoneyInput extends Component {
7941
7963
  this.setState({
7942
7964
  formattedAmount: value
7943
7965
  });
7944
- const parsed = isEmpty(value) ? null : parseNumber(value, this.props.selectedCurrency.currency, this.state.locale, this.props.maxLengthOverride);
7966
+ const parsed = isEmpty(value) ? null : parseNumber({
7967
+ amount: value,
7968
+ currency: this.props.selectedCurrency.currency,
7969
+ locale: this.state.locale,
7970
+ maxLengthOverride: this.props.maxLengthOverride
7971
+ });
7945
7972
  if (isNumberOrNull(parsed)) {
7946
- this.props.onAmountChange(parsed);
7973
+ this.props.onAmountChange?.(parsed);
7947
7974
  }
7948
7975
  };
7949
7976
  onAmountBlur = () => {
@@ -7953,68 +7980,67 @@ class MoneyInput extends Component {
7953
7980
  onAmountFocus = () => {
7954
7981
  this.amountFocused = true;
7955
7982
  };
7956
- mapOption = item => {
7957
- return {
7958
- type: 'option',
7959
- value: item,
7960
- filterMatchers: [item.value, item.label, item.note, item.searchable]
7961
- };
7962
- };
7963
7983
  getSelectOptions() {
7964
- const selectOptions = [...filterOptionsForQuery(this.props.currencies, this.state.searchQuery)];
7965
- let formattedOptions = [];
7966
- let groupIndex = null;
7984
+ const selectOptions = filterCurrenciesForQuery(this.props.currencies, this.state.searchQuery);
7985
+ const formattedOptions = [];
7986
+ let currentGroupOptions;
7967
7987
  selectOptions.forEach(item => {
7968
- if (item.header) {
7988
+ if (item.header != null) {
7989
+ currentGroupOptions = [];
7969
7990
  formattedOptions.push({
7970
7991
  type: 'group',
7971
7992
  label: item.header,
7972
- options: []
7993
+ options: currentGroupOptions
7973
7994
  });
7974
- groupIndex = formattedOptions.length - 1;
7975
7995
  } else {
7976
- if (groupIndex === null) {
7977
- formattedOptions.push(this.mapOption(item));
7978
- } else {
7979
- formattedOptions[groupIndex]?.options.push(this.mapOption(item));
7980
- }
7996
+ (currentGroupOptions ?? formattedOptions).push({
7997
+ type: 'option',
7998
+ value: item,
7999
+ filterMatchers: [item.value, item.label, item.note ?? '', item.searchable ?? '']
8000
+ });
7981
8001
  }
7982
8002
  });
7983
8003
  return formattedOptions;
7984
8004
  }
7985
8005
  setAmount() {
7986
8006
  this.setState(previousState => {
7987
- const parsed = parseNumber(previousState.formattedAmount, this.props.selectedCurrency.currency, previousState.locale, this.props.maxLengthOverride);
8007
+ const parsed = parseNumber({
8008
+ amount: previousState.formattedAmount,
8009
+ currency: this.props.selectedCurrency.currency,
8010
+ locale: previousState.locale,
8011
+ maxLengthOverride: this.props.maxLengthOverride
8012
+ });
7988
8013
  if (!isNumberOrNull(parsed)) {
7989
8014
  return {
7990
8015
  formattedAmount: previousState.formattedAmount
7991
8016
  };
7992
8017
  }
7993
8018
  return {
7994
- formattedAmount: formatAmountIfSet(parsed, this.props.selectedCurrency.currency, previousState.locale, this.props.maxLengthOverride)
8019
+ formattedAmount: formatAmountIfSet({
8020
+ amount: parsed,
8021
+ currency: this.props.selectedCurrency.currency,
8022
+ locale: previousState.locale,
8023
+ maxLengthOverride: this.props.maxLengthOverride
8024
+ })
7995
8025
  };
7996
8026
  });
7997
8027
  }
7998
8028
  handleSelectChange = value => {
7999
8029
  this.handleSearchChange('');
8000
- this.props.onCurrencyChange(value);
8030
+ this.props.onCurrencyChange?.(value);
8001
8031
  };
8002
8032
  handleCustomAction = () => {
8003
8033
  this.handleSearchChange('');
8004
- if (this.props.onCustomAction) {
8005
- this.props.onCustomAction();
8006
- }
8034
+ this.props.onCustomAction?.();
8007
8035
  };
8008
8036
  handleSearchChange = searchQuery => {
8009
8037
  this.setState({
8010
8038
  searchQuery
8011
8039
  });
8012
- if (this.props.onSearchChange) {
8013
- this.props.onSearchChange({
8014
- searchQuery,
8015
- filteredOptions: filterOptionsForQuery(this.props.currencies, searchQuery)
8016
- });
8017
- }
8040
+ this.props.onSearchChange?.({
8041
+ searchQuery,
8042
+ filteredOptions: filterCurrenciesForQuery(this.props.currencies, searchQuery)
8043
+ });
8018
8044
  };
8019
8045
  style = className => this.props.classNames[className] || className;
8020
8046
  render() {
@@ -8054,7 +8080,12 @@ class MoneyInput extends Component {
8054
8080
  inputMode: "decimal",
8055
8081
  disabled: disabled,
8056
8082
  maxLength: maxLengthOverride,
8057
- placeholder: formatAmountIfSet(this.props.placeholder, this.props.selectedCurrency.currency, this.state.locale, this.props.maxLengthOverride),
8083
+ placeholder: formatAmountIfSet({
8084
+ amount: this.props.placeholder,
8085
+ currency: this.props.selectedCurrency.currency,
8086
+ locale: this.state.locale,
8087
+ maxLengthOverride: this.props.maxLengthOverride
8088
+ }),
8058
8089
  autoComplete: "off",
8059
8090
  onKeyDown: this.handleKeyDown,
8060
8091
  onChange: this.onAmountChange,
@@ -8099,11 +8130,11 @@ class MoneyInput extends Component {
8099
8130
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events
8100
8131
  jsx("div", {
8101
8132
  role: "button",
8102
- tabIndex: "0",
8133
+ tabIndex: 0,
8103
8134
  onClick: this.handleCustomAction,
8104
8135
  children: this.props.customActionLabel
8105
- }) : null,
8106
- placeholder: this.formatMessage(messages$3.selectPlaceholder),
8136
+ }) : undefined,
8137
+ placeholder: this.props.intl.formatMessage(messages$3.selectPlaceholder),
8107
8138
  filterable: true,
8108
8139
  filterPlaceholder: this.props.searchPlaceholder,
8109
8140
  disabled: disabled,
@@ -8120,25 +8151,25 @@ class MoneyInput extends Component {
8120
8151
  });
8121
8152
  }
8122
8153
  }
8123
- function filterOptionsForQuery(options, query) {
8154
+ function filterCurrenciesForQuery(currencies, query) {
8124
8155
  if (!query) {
8125
- return options;
8156
+ return [...currencies];
8126
8157
  }
8127
- const filteredOptions = removeDuplicateValueOptions(options).filter(option => isCurrencyOptionAndFitsQuery(option, query));
8158
+ const options = currencies.filter(option => option.header == null);
8159
+ const filteredOptions = removeDuplicateValueOptions(options).filter(option => currencyOptionFitsQuery(option, query));
8128
8160
  return sortOptionsLabelsToFirst(filteredOptions, query);
8129
8161
  }
8130
8162
  function removeDuplicateValueOptions(options) {
8131
- const result = [];
8132
- const resultValues = [];
8133
- options.forEach(option => {
8134
- if (option.value && !resultValues.includes(option.value)) {
8135
- result.push(option);
8136
- resultValues.push(option.value);
8163
+ const uniqueValues = new Set();
8164
+ return options.filter(option => {
8165
+ if (!uniqueValues.has(option.value)) {
8166
+ uniqueValues.add(option.value);
8167
+ return true;
8137
8168
  }
8169
+ return false;
8138
8170
  });
8139
- return result;
8140
8171
  }
8141
- function isCurrencyOptionAndFitsQuery(option, query) {
8172
+ function currencyOptionFitsQuery(option, query) {
8142
8173
  if (!option.value) {
8143
8174
  return false;
8144
8175
  }
@@ -8163,43 +8194,6 @@ function sortOptionsLabelsToFirst(options, query) {
8163
8194
  return 0;
8164
8195
  });
8165
8196
  }
8166
- MoneyInput.propTypes = {
8167
- id: PropTypes.string,
8168
- currencies: PropTypes.arrayOf(Currency).isRequired,
8169
- selectedCurrency: Currency.isRequired,
8170
- onCurrencyChange: PropTypes.func,
8171
- placeholder: PropTypes.number,
8172
- amount: PropTypes.number,
8173
- size: PropTypes.oneOf(['sm', 'md', 'lg']),
8174
- onAmountChange: PropTypes.func,
8175
- addon: PropTypes.node,
8176
- searchPlaceholder: PropTypes.string,
8177
- /**
8178
- * Allows the consumer to react to searching, while the search itself is handled internally. Called with `{ searchQuery: string, filteredOptions: Currency[] }`
8179
- */
8180
- onSearchChange: PropTypes.func,
8181
- customActionLabel: PropTypes.node,
8182
- onCustomAction: PropTypes.func,
8183
- classNames: PropTypes.objectOf(PropTypes.string),
8184
- selectProps: PropTypes.object,
8185
- maxLengthOverride: PropTypes.number
8186
- };
8187
- MoneyInput.defaultProps = {
8188
- id: null,
8189
- size: Size.LARGE,
8190
- addon: null,
8191
- searchPlaceholder: '',
8192
- onSearchChange: undefined,
8193
- onCurrencyChange: null,
8194
- placeholder: null,
8195
- amount: null,
8196
- onAmountChange: null,
8197
- customActionLabel: '',
8198
- onCustomAction: null,
8199
- classNames: {},
8200
- selectProps: {},
8201
- maxLengthOverride: null
8202
- };
8203
8197
  var MoneyInput$1 = injectIntl(MoneyInput);
8204
8198
 
8205
8199
  const NavigationOptionList = ({