@transferwise/components 46.3.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 (41) hide show
  1. package/build/index.esm.js +119 -127
  2. package/build/index.esm.js.map +1 -1
  3. package/build/index.js +119 -127
  4. package/build/index.js.map +1 -1
  5. package/build/types/common/responsivePanel/ResponsivePanel.d.ts.map +1 -1
  6. package/build/types/dimmer/Dimmer.d.ts.map +1 -1
  7. package/build/types/index.d.ts +1 -0
  8. package/build/types/index.d.ts.map +1 -1
  9. package/build/types/inputs/SelectInput.d.ts +2 -2
  10. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  11. package/build/types/inputs/_BottomSheet.d.ts.map +1 -1
  12. package/build/types/inputs/_Popover.d.ts.map +1 -1
  13. package/build/types/moneyInput/MoneyInput.d.ts +45 -31
  14. package/build/types/moneyInput/MoneyInput.d.ts.map +1 -1
  15. package/build/types/moneyInput/MoneyInput.messages.d.ts +6 -6
  16. package/build/types/moneyInput/MoneyInput.messages.d.ts.map +1 -1
  17. package/build/types/moneyInput/currencyFormatting.d.ts +2 -2
  18. package/build/types/moneyInput/currencyFormatting.d.ts.map +1 -1
  19. package/build/types/moneyInput/index.d.ts +2 -1
  20. package/build/types/moneyInput/index.d.ts.map +1 -1
  21. package/package.json +1 -1
  22. package/src/common/bottomSheet/__snapshots__/BottomSheet.spec.tsx.snap +1 -1
  23. package/src/common/responsivePanel/ResponsivePanel.tsx +1 -2
  24. package/src/dimmer/Dimmer.tsx +5 -1
  25. package/src/flowNavigation/FlowNavigation.story.js +1 -1
  26. package/src/index.ts +6 -0
  27. package/src/inputs/SelectInput.tsx +2 -2
  28. package/src/inputs/_BottomSheet.tsx +5 -1
  29. package/src/inputs/_Popover.tsx +5 -1
  30. package/src/moneyInput/{MoneyInput.rtl.spec.js → MoneyInput.rtl.spec.tsx} +4 -4
  31. package/src/moneyInput/MoneyInput.spec.js +109 -49
  32. package/src/moneyInput/MoneyInput.story.tsx +6 -14
  33. package/src/moneyInput/{MoneyInput.js → MoneyInput.tsx} +189 -173
  34. package/src/moneyInput/{currencyFormatting.spec.js → currencyFormatting.spec.ts} +2 -2
  35. package/src/moneyInput/{currencyFormatting.js → currencyFormatting.ts} +7 -10
  36. package/src/moneyInput/index.ts +7 -0
  37. package/src/popover/__snapshots__/Popover.spec.js.snap +1 -1
  38. package/src/radioGroup/RadioGroup.js +2 -2
  39. package/src/radioGroup/RadioGroup.rtl.spec.tsx +16 -0
  40. package/src/moneyInput/index.js +0 -1
  41. /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
  }
@@ -1677,8 +1677,8 @@ const DimmerWrapper = ({
1677
1677
  theme
1678
1678
  } = useTheme();
1679
1679
  return open || hasNotExited ? /*#__PURE__*/jsx(ThemeProvider, {
1680
- theme: theme,
1681
- screenMode: screenMode,
1680
+ theme: "personal",
1681
+ screenMode: theme === 'personal' ? screenMode : 'light',
1682
1682
  isNotRootProvider: true,
1683
1683
  children: children
1684
1684
  }) : /*#__PURE__*/jsx(Fragment, {
@@ -3336,9 +3336,6 @@ const ResponsivePanel = /*#__PURE__*/forwardRef(({
3336
3336
  open = false,
3337
3337
  position = Position.BOTTOM
3338
3338
  }, reference) => {
3339
- const {
3340
- className: themeClassname
3341
- } = useTheme();
3342
3339
  const {
3343
3340
  isMobile
3344
3341
  } = useLayout();
@@ -3357,7 +3354,7 @@ const ResponsivePanel = /*#__PURE__*/forwardRef(({
3357
3354
  open: open,
3358
3355
  position: position,
3359
3356
  anchorRef: anchorRef,
3360
- className: classNames(themeClassname, className),
3357
+ className: className,
3361
3358
  onClose: onClose,
3362
3359
  children: children
3363
3360
  }, "panel");
@@ -5402,6 +5399,7 @@ var DynamicFieldDefinitionList$1 = DynamicFieldDefinitionList;
5402
5399
  const ESCAPED_OPENING_CHEVRON = '<';
5403
5400
  const ESCAPED_CLOSING_CHEVRON = '>';
5404
5401
  class EmphasisHtmlTransformer {
5402
+ tags;
5405
5403
  constructor(whitelistedTags) {
5406
5404
  this.tags = (whitelistedTags || []).map(tag => {
5407
5405
  return {
@@ -6511,8 +6509,8 @@ function BottomSheet({
6511
6509
  getInteractionProps: getReferenceProps
6512
6510
  }), /*#__PURE__*/jsx(FloatingPortal, {
6513
6511
  children: /*#__PURE__*/jsx(ThemeProvider, {
6514
- theme: theme,
6515
- screenMode: screenMode,
6512
+ theme: "personal",
6513
+ screenMode: theme === 'personal' ? screenMode : 'light',
6516
6514
  isNotRootProvider: true,
6517
6515
  children: /*#__PURE__*/jsx(Transition, {
6518
6516
  show: open,
@@ -6659,8 +6657,8 @@ function Popover({
6659
6657
  getInteractionProps: getReferenceProps
6660
6658
  }), /*#__PURE__*/jsx(FloatingPortal, {
6661
6659
  children: /*#__PURE__*/jsx(ThemeProvider, {
6662
- theme: theme,
6663
- screenMode: screenMode,
6660
+ theme: "personal",
6661
+ screenMode: theme === 'personal' ? screenMode : 'light',
6664
6662
  isNotRootProvider: true,
6665
6663
  children: /*#__PURE__*/jsx(Transition, {
6666
6664
  show: open,
@@ -7835,20 +7833,17 @@ function getValidLocale(locale) {
7835
7833
  Intl.NumberFormat(noUnderscoreLocale);
7836
7834
  return noUnderscoreLocale;
7837
7835
  } catch {
7838
- return 'en-GB';
7836
+ return DEFAULT_LOCALE;
7839
7837
  }
7840
7838
  }
7841
- function getCurrencyDecimals(currency = '') {
7839
+ function getCurrencyDecimals(currency) {
7842
7840
  const upperCaseCurrency = currency.toUpperCase();
7843
- if (Object.prototype.hasOwnProperty.call(currencyDecimals, upperCaseCurrency)) {
7844
- return currencyDecimals[upperCaseCurrency];
7845
- }
7846
- return DEFAULT_CURRENCY_DECIMALS;
7841
+ return currencyDecimals[upperCaseCurrency] ?? DEFAULT_CURRENCY_DECIMALS;
7847
7842
  }
7848
7843
  function getDecimalSeparator(locale) {
7849
7844
  return isNumberLocaleSupported() ? 1.1.toLocaleString(locale)[1] : '.';
7850
7845
  }
7851
- function parseAmount(number, currency, locale) {
7846
+ function parseAmount(number, currency, locale = DEFAULT_LOCALE) {
7852
7847
  const validLocale = getValidLocale(locale);
7853
7848
  const precision = getCurrencyDecimals(currency);
7854
7849
  const groupSeparator = isNumberLocaleSupported() ? 10000 .toLocaleString(validLocale)[2] : ',';
@@ -7858,53 +7853,67 @@ function parseAmount(number, currency, locale) {
7858
7853
  return Math.abs(parsedAmount);
7859
7854
  }
7860
7855
 
7861
- const Currency = PropTypes.shape({
7862
- header: PropTypes.string,
7863
- value: PropTypes.string,
7864
- label: PropTypes.string,
7865
- currency: PropTypes.string,
7866
- note: PropTypes.string,
7867
- searchable: PropTypes.string
7868
- });
7869
7856
  const isNumberOrNull = v => isNumber(v) || isNull(v);
7870
- const formatAmountIfSet = (amount, currency, locale, maxLengthOverride) => {
7857
+ const formatAmountIfSet = ({
7858
+ amount,
7859
+ currency,
7860
+ locale,
7861
+ maxLengthOverride
7862
+ }) => {
7871
7863
  if (maxLengthOverride) {
7872
- return amount || '';
7864
+ return amount != null ? String(amount) : '';
7873
7865
  } else {
7874
7866
  return typeof amount === 'number' ? formatAmount(amount, currency, locale) : '';
7875
7867
  }
7876
7868
  };
7877
- const parseNumber = (amount, currency, locale, maxLengthOverride) => {
7869
+ const parseNumber = ({
7870
+ amount,
7871
+ currency,
7872
+ locale,
7873
+ maxLengthOverride
7874
+ }) => {
7878
7875
  if (!maxLengthOverride) {
7879
7876
  return parseAmount(amount, currency, locale);
7880
7877
  }
7881
7878
  if (maxLengthOverride && amount.length > maxLengthOverride) {
7882
7879
  return 0;
7883
7880
  }
7884
- return +amount;
7881
+ return Number(amount);
7885
7882
  };
7886
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]);
7887
7884
  const inputKeyAllowlist = new Set([Key.PERIOD, Key.COMMA]);
7888
7885
  class MoneyInput extends Component {
7886
+ static defaultProps = {
7887
+ size: Size.LARGE,
7888
+ classNames: {},
7889
+ selectProps: {}
7890
+ };
7891
+ amountFocused = false;
7889
7892
  constructor(props) {
7890
7893
  super(props);
7891
- const {
7892
- locale
7893
- } = this.props.intl;
7894
- this.formatMessage = this.props.intl.formatMessage;
7895
7894
  this.state = {
7896
7895
  searchQuery: '',
7897
- formattedAmount: formatAmountIfSet(props.amount, props.selectedCurrency.currency, locale, props.maxLengthOverride),
7898
- 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
7899
7903
  };
7900
7904
  }
7901
7905
  UNSAFE_componentWillReceiveProps(nextProps) {
7902
7906
  this.setState({
7903
- locale: nextProps?.intl?.locale
7907
+ locale: nextProps.intl.locale
7904
7908
  });
7905
7909
  if (!this.amountFocused) {
7906
7910
  this.setState({
7907
- 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
+ })
7908
7917
  });
7909
7918
  }
7910
7919
  }
@@ -7924,16 +7933,26 @@ class MoneyInput extends Component {
7924
7933
  }
7925
7934
  };
7926
7935
  handlePaste = event => {
7927
- const paste = (event.clipboardData || window.clipboardData).getData('text');
7936
+ const paste = event.clipboardData.getData('text');
7928
7937
  const {
7929
7938
  locale
7930
7939
  } = this.state;
7931
- 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
+ });
7932
7946
  if (isNumberOrNull(parsed)) {
7933
7947
  this.setState({
7934
- 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
+ })
7935
7954
  });
7936
- this.props.onAmountChange(parsed);
7955
+ this.props.onAmountChange?.(parsed);
7937
7956
  }
7938
7957
  event.preventDefault();
7939
7958
  };
@@ -7944,9 +7963,14 @@ class MoneyInput extends Component {
7944
7963
  this.setState({
7945
7964
  formattedAmount: value
7946
7965
  });
7947
- 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
+ });
7948
7972
  if (isNumberOrNull(parsed)) {
7949
- this.props.onAmountChange(parsed);
7973
+ this.props.onAmountChange?.(parsed);
7950
7974
  }
7951
7975
  };
7952
7976
  onAmountBlur = () => {
@@ -7956,68 +7980,67 @@ class MoneyInput extends Component {
7956
7980
  onAmountFocus = () => {
7957
7981
  this.amountFocused = true;
7958
7982
  };
7959
- mapOption = item => {
7960
- return {
7961
- type: 'option',
7962
- value: item,
7963
- filterMatchers: [item.value, item.label, item.note, item.searchable]
7964
- };
7965
- };
7966
7983
  getSelectOptions() {
7967
- const selectOptions = [...filterOptionsForQuery(this.props.currencies, this.state.searchQuery)];
7968
- let formattedOptions = [];
7969
- let groupIndex = null;
7984
+ const selectOptions = filterCurrenciesForQuery(this.props.currencies, this.state.searchQuery);
7985
+ const formattedOptions = [];
7986
+ let currentGroupOptions;
7970
7987
  selectOptions.forEach(item => {
7971
- if (item.header) {
7988
+ if (item.header != null) {
7989
+ currentGroupOptions = [];
7972
7990
  formattedOptions.push({
7973
7991
  type: 'group',
7974
7992
  label: item.header,
7975
- options: []
7993
+ options: currentGroupOptions
7976
7994
  });
7977
- groupIndex = formattedOptions.length - 1;
7978
7995
  } else {
7979
- if (groupIndex === null) {
7980
- formattedOptions.push(this.mapOption(item));
7981
- } else {
7982
- formattedOptions[groupIndex]?.options.push(this.mapOption(item));
7983
- }
7996
+ (currentGroupOptions ?? formattedOptions).push({
7997
+ type: 'option',
7998
+ value: item,
7999
+ filterMatchers: [item.value, item.label, item.note ?? '', item.searchable ?? '']
8000
+ });
7984
8001
  }
7985
8002
  });
7986
8003
  return formattedOptions;
7987
8004
  }
7988
8005
  setAmount() {
7989
8006
  this.setState(previousState => {
7990
- 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
+ });
7991
8013
  if (!isNumberOrNull(parsed)) {
7992
8014
  return {
7993
8015
  formattedAmount: previousState.formattedAmount
7994
8016
  };
7995
8017
  }
7996
8018
  return {
7997
- 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
+ })
7998
8025
  };
7999
8026
  });
8000
8027
  }
8001
8028
  handleSelectChange = value => {
8002
8029
  this.handleSearchChange('');
8003
- this.props.onCurrencyChange(value);
8030
+ this.props.onCurrencyChange?.(value);
8004
8031
  };
8005
8032
  handleCustomAction = () => {
8006
8033
  this.handleSearchChange('');
8007
- if (this.props.onCustomAction) {
8008
- this.props.onCustomAction();
8009
- }
8034
+ this.props.onCustomAction?.();
8010
8035
  };
8011
8036
  handleSearchChange = searchQuery => {
8012
8037
  this.setState({
8013
8038
  searchQuery
8014
8039
  });
8015
- if (this.props.onSearchChange) {
8016
- this.props.onSearchChange({
8017
- searchQuery,
8018
- filteredOptions: filterOptionsForQuery(this.props.currencies, searchQuery)
8019
- });
8020
- }
8040
+ this.props.onSearchChange?.({
8041
+ searchQuery,
8042
+ filteredOptions: filterCurrenciesForQuery(this.props.currencies, searchQuery)
8043
+ });
8021
8044
  };
8022
8045
  style = className => this.props.classNames[className] || className;
8023
8046
  render() {
@@ -8057,7 +8080,12 @@ class MoneyInput extends Component {
8057
8080
  inputMode: "decimal",
8058
8081
  disabled: disabled,
8059
8082
  maxLength: maxLengthOverride,
8060
- 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
+ }),
8061
8089
  autoComplete: "off",
8062
8090
  onKeyDown: this.handleKeyDown,
8063
8091
  onChange: this.onAmountChange,
@@ -8102,11 +8130,11 @@ class MoneyInput extends Component {
8102
8130
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events
8103
8131
  jsx("div", {
8104
8132
  role: "button",
8105
- tabIndex: "0",
8133
+ tabIndex: 0,
8106
8134
  onClick: this.handleCustomAction,
8107
8135
  children: this.props.customActionLabel
8108
- }) : null,
8109
- placeholder: this.formatMessage(messages$3.selectPlaceholder),
8136
+ }) : undefined,
8137
+ placeholder: this.props.intl.formatMessage(messages$3.selectPlaceholder),
8110
8138
  filterable: true,
8111
8139
  filterPlaceholder: this.props.searchPlaceholder,
8112
8140
  disabled: disabled,
@@ -8123,25 +8151,25 @@ class MoneyInput extends Component {
8123
8151
  });
8124
8152
  }
8125
8153
  }
8126
- function filterOptionsForQuery(options, query) {
8154
+ function filterCurrenciesForQuery(currencies, query) {
8127
8155
  if (!query) {
8128
- return options;
8156
+ return [...currencies];
8129
8157
  }
8130
- 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));
8131
8160
  return sortOptionsLabelsToFirst(filteredOptions, query);
8132
8161
  }
8133
8162
  function removeDuplicateValueOptions(options) {
8134
- const result = [];
8135
- const resultValues = [];
8136
- options.forEach(option => {
8137
- if (option.value && !resultValues.includes(option.value)) {
8138
- result.push(option);
8139
- 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;
8140
8168
  }
8169
+ return false;
8141
8170
  });
8142
- return result;
8143
8171
  }
8144
- function isCurrencyOptionAndFitsQuery(option, query) {
8172
+ function currencyOptionFitsQuery(option, query) {
8145
8173
  if (!option.value) {
8146
8174
  return false;
8147
8175
  }
@@ -8166,43 +8194,6 @@ function sortOptionsLabelsToFirst(options, query) {
8166
8194
  return 0;
8167
8195
  });
8168
8196
  }
8169
- MoneyInput.propTypes = {
8170
- id: PropTypes.string,
8171
- currencies: PropTypes.arrayOf(Currency).isRequired,
8172
- selectedCurrency: Currency.isRequired,
8173
- onCurrencyChange: PropTypes.func,
8174
- placeholder: PropTypes.number,
8175
- amount: PropTypes.number,
8176
- size: PropTypes.oneOf(['sm', 'md', 'lg']),
8177
- onAmountChange: PropTypes.func,
8178
- addon: PropTypes.node,
8179
- searchPlaceholder: PropTypes.string,
8180
- /**
8181
- * Allows the consumer to react to searching, while the search itself is handled internally. Called with `{ searchQuery: string, filteredOptions: Currency[] }`
8182
- */
8183
- onSearchChange: PropTypes.func,
8184
- customActionLabel: PropTypes.node,
8185
- onCustomAction: PropTypes.func,
8186
- classNames: PropTypes.objectOf(PropTypes.string),
8187
- selectProps: PropTypes.object,
8188
- maxLengthOverride: PropTypes.number
8189
- };
8190
- MoneyInput.defaultProps = {
8191
- id: null,
8192
- size: Size.LARGE,
8193
- addon: null,
8194
- searchPlaceholder: '',
8195
- onSearchChange: undefined,
8196
- onCurrencyChange: null,
8197
- placeholder: null,
8198
- amount: null,
8199
- onAmountChange: null,
8200
- customActionLabel: '',
8201
- onCustomAction: null,
8202
- classNames: {},
8203
- selectProps: {},
8204
- maxLengthOverride: null
8205
- };
8206
8197
  var MoneyInput$1 = injectIntl(MoneyInput);
8207
8198
 
8208
8199
  const NavigationOptionList = ({
@@ -10475,7 +10466,8 @@ class RadioGroup extends Component {
10475
10466
  const {
10476
10467
  selectedValue
10477
10468
  } = this.state;
10478
- return radios && radios.length > 0 ? /*#__PURE__*/jsx(Fragment, {
10469
+ return radios && radios.length > 0 ? /*#__PURE__*/jsx("div", {
10470
+ role: "radiogroup",
10479
10471
  children: radios.map(({
10480
10472
  id,
10481
10473
  avatar,