@transferwise/components 0.0.0-experimental-4d1e1cf → 0.0.0-experimental-a53ae95

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 (38) hide show
  1. package/README.md +14 -1
  2. package/build/index.esm.js +147 -49
  3. package/build/index.esm.js.map +1 -1
  4. package/build/index.js +147 -49
  5. package/build/index.js.map +1 -1
  6. package/build/mocks.esm.js +40 -0
  7. package/build/mocks.esm.js.map +1 -0
  8. package/build/mocks.js +43 -0
  9. package/build/mocks.js.map +1 -0
  10. package/build/types/index.d.ts +0 -1
  11. package/build/types/index.d.ts.map +1 -1
  12. package/build/types/mocks.d.ts +9 -0
  13. package/build/types/mocks.d.ts.map +1 -0
  14. package/build/types/test-utils/window-mock.d.ts.map +1 -1
  15. package/build/types/typeahead/Typeahead.d.ts +57 -98
  16. package/build/types/typeahead/Typeahead.d.ts.map +1 -1
  17. package/build/types/typeahead/index.d.ts +2 -2
  18. package/build/types/typeahead/index.d.ts.map +1 -1
  19. package/build/types/typeahead/typeaheadInput/TypeaheadInput.d.ts +41 -23
  20. package/build/types/typeahead/typeaheadInput/TypeaheadInput.d.ts.map +1 -1
  21. package/build/types/typeahead/typeaheadOption/TypeaheadOption.d.ts +17 -9
  22. package/build/types/typeahead/typeaheadOption/TypeaheadOption.d.ts.map +1 -1
  23. package/build/types/typeahead/util/highlight.d.ts +1 -2
  24. package/build/types/typeahead/util/highlight.d.ts.map +1 -1
  25. package/package.json +23 -10
  26. package/src/dimmer/Dimmer.spec.js +0 -4
  27. package/src/index.ts +0 -1
  28. package/src/mocks.ts +48 -0
  29. package/src/snackbar/Snackbar.spec.js +0 -4
  30. package/src/test-utils/window-mock.ts +7 -23
  31. package/src/typeahead/{Typeahead.tsx → Typeahead.js} +108 -107
  32. package/src/typeahead/{Typeahead.story.tsx → Typeahead.story.js} +7 -8
  33. package/src/typeahead/index.js +3 -0
  34. package/src/typeahead/typeaheadInput/{TypeaheadInput.tsx → TypeaheadInput.js} +51 -43
  35. package/src/typeahead/typeaheadOption/{TypeaheadOption.tsx → TypeaheadOption.js} +20 -10
  36. package/src/typeahead/util/{highlight.tsx → highlight.js} +1 -1
  37. package/src/withNextPortal/withNextPortal.spec.js +0 -4
  38. package/src/typeahead/index.ts +0 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  [![ci-cd](https://github.com/transferwise/neptune-web/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/transferwise/neptune-web/actions) [![NPM](https://badge.fury.io/js/%40transferwise%2Fcomponents.svg)](https://www.npmjs.com/package/@transferwise/components)
2
2
 
3
- # Neptune Web React Components Temp
3
+ # Neptune Web React Components
4
4
 
5
5
  Neptune is the Design System built by and used at TransferWise. Neptune Web is the Neptune framework for Web. Neptune Web provides a way to build high quality, consistent user experiences on the web with ease.
6
6
 
@@ -48,6 +48,19 @@ Note: types for some of components are not 100% accurate (some of them will be j
48
48
 
49
49
  Please follow [rules for JS components](https://github.com/transferwise/neptune-web/blob/main/packages/components/CONTRIBUTING.md#js-component-rules) in order to generate accurate types for them.
50
50
 
51
+ ### Mocks for testing
52
+
53
+ We expose reusable mocks for Jest and Vitest under an isolated entry point. They can be applied by passing the testing framework as the parameter:
54
+
55
+ ```ts
56
+ import { mockMatchMedia, mockResizeObserver } from '@transferwise/components/mocks';
57
+ import { jest } from '@jest/globals';
58
+ import { vi } from 'vitest';
59
+
60
+ mockMatchMedia(jest); // With Jest
61
+ mockResizeObserver(vi); // With Vitest
62
+ ```
63
+
51
64
  ## Documentation
52
65
 
53
66
  Visit the [docs](https://transferwise.github.io/neptune-web/about/Home) for information on getting started, usage information and examples for each component.
@@ -12210,10 +12210,8 @@ const TextareaWithDisplayFormat = props => /*#__PURE__*/jsx(WithDisplayFormat, {
12210
12210
  /* eslint-disable jsx-a11y/no-static-element-interactions */
12211
12211
  const DEFAULT_INPUT_MIN_WIDTH = 10;
12212
12212
  class TypeaheadInput extends Component {
12213
- inputRef = /*#__PURE__*/createRef();
12214
- sizerRef = /*#__PURE__*/createRef();
12215
- constructor(props) {
12216
- super(props);
12213
+ constructor() {
12214
+ super();
12217
12215
  this.state = {
12218
12216
  inputWidth: DEFAULT_INPUT_MIN_WIDTH
12219
12217
  };
@@ -12223,7 +12221,7 @@ class TypeaheadInput extends Component {
12223
12221
  autoFocus
12224
12222
  } = this.props;
12225
12223
  if (autoFocus) {
12226
- this.inputRef.current?.focus();
12224
+ this.inputRef.focus();
12227
12225
  }
12228
12226
  }
12229
12227
  componentDidUpdate(previousProps) {
@@ -12234,19 +12232,19 @@ class TypeaheadInput extends Component {
12234
12232
  recalculateWidth = () => {
12235
12233
  requestAnimationFrame(() => {
12236
12234
  this.setState({
12237
- inputWidth: Math.max(DEFAULT_INPUT_MIN_WIDTH, this.sizerRef.current?.scrollWidth ?? 0 + 10)
12235
+ inputWidth: Math.max(DEFAULT_INPUT_MIN_WIDTH, this.sizerRef.scrollWidth + 10)
12238
12236
  });
12239
12237
  });
12240
12238
  };
12241
12239
  renderInput = () => {
12242
12240
  const {
12243
12241
  typeaheadId,
12244
- autoFocus = false,
12242
+ autoFocus,
12245
12243
  multiple,
12246
12244
  name,
12247
- optionsShown = false,
12248
- placeholder = '',
12249
- selected = [],
12245
+ optionsShown,
12246
+ placeholder,
12247
+ selected,
12250
12248
  value,
12251
12249
  onChange,
12252
12250
  onKeyDown,
@@ -12259,7 +12257,9 @@ class TypeaheadInput extends Component {
12259
12257
  } = this.state;
12260
12258
  const hasPlaceholder = !multiple || selected.length === 0;
12261
12259
  return /*#__PURE__*/jsx(Input, {
12262
- ref: this.inputRef,
12260
+ ref: reference => {
12261
+ this.inputRef = reference;
12262
+ },
12263
12263
  className: classNames(multiple && 'typeahead__input'),
12264
12264
  name: name,
12265
12265
  id: `input-${typeaheadId}`,
@@ -12285,18 +12285,18 @@ class TypeaheadInput extends Component {
12285
12285
  render() {
12286
12286
  const {
12287
12287
  multiple,
12288
- selected = [],
12288
+ selected,
12289
12289
  value,
12290
- maxHeight = null,
12290
+ maxHeight,
12291
12291
  renderChip
12292
12292
  } = this.props;
12293
12293
  return multiple ? /*#__PURE__*/jsxs("div", {
12294
12294
  className: "form-control typeahead__input-container",
12295
- style: {
12296
- maxHeight: maxHeight ?? undefined
12295
+ style: maxHeight && {
12296
+ maxHeight
12297
12297
  },
12298
12298
  onClick: () => {
12299
- this.inputRef.current?.focus();
12299
+ this.inputRef.focus();
12300
12300
  },
12301
12301
  children: [/*#__PURE__*/jsxs("div", {
12302
12302
  className: "typeahead__input-wrapper",
@@ -12304,13 +12304,39 @@ class TypeaheadInput extends Component {
12304
12304
  className: "typeahead__input-aligner"
12305
12305
  })]
12306
12306
  }), /*#__PURE__*/jsx("div", {
12307
- ref: this.sizerRef,
12307
+ ref: reference => {
12308
+ this.sizerRef = reference;
12309
+ },
12308
12310
  className: "sizer form-control typeahead__input",
12309
12311
  children: value
12310
12312
  })]
12311
12313
  }) : this.renderInput();
12312
12314
  }
12313
12315
  }
12316
+ TypeaheadInput.propTypes = {
12317
+ typeaheadId: PropTypes.string.isRequired,
12318
+ name: PropTypes.string.isRequired,
12319
+ autoFocus: PropTypes.bool,
12320
+ multiple: PropTypes.bool.isRequired,
12321
+ value: PropTypes.string.isRequired,
12322
+ selected: PropTypes.arrayOf(PropTypes.object),
12323
+ placeholder: PropTypes.string,
12324
+ optionsShown: PropTypes.bool,
12325
+ maxHeight: PropTypes.number,
12326
+ autoComplete: PropTypes.string.isRequired,
12327
+ onChange: PropTypes.func.isRequired,
12328
+ renderChip: PropTypes.func.isRequired,
12329
+ onKeyDown: PropTypes.func.isRequired,
12330
+ onFocus: PropTypes.func.isRequired,
12331
+ onPaste: PropTypes.func.isRequired
12332
+ };
12333
+ TypeaheadInput.defaultProps = {
12334
+ autoFocus: false,
12335
+ maxHeight: null,
12336
+ placeholder: '',
12337
+ optionsShown: false,
12338
+ selected: []
12339
+ };
12314
12340
 
12315
12341
  function highlight(value, query) {
12316
12342
  if (value && query) {
@@ -12331,9 +12357,9 @@ function highlight(value, query) {
12331
12357
  const Option = props => {
12332
12358
  const {
12333
12359
  option,
12334
- selected = false,
12335
- onClick = () => {},
12336
- query = ''
12360
+ selected,
12361
+ onClick,
12362
+ query
12337
12363
  } = props;
12338
12364
  const {
12339
12365
  label,
@@ -12363,32 +12389,30 @@ const Option = props => {
12363
12389
  })
12364
12390
  });
12365
12391
  };
12392
+ Option.propTypes = {
12393
+ option: PropTypes.shape({
12394
+ label: PropTypes.string.isRequired,
12395
+ note: PropTypes.string,
12396
+ secondary: PropTypes.string
12397
+ }).isRequired,
12398
+ query: PropTypes.string,
12399
+ selected: PropTypes.bool,
12400
+ onClick: PropTypes.func
12401
+ };
12402
+ Option.defaultProps = {
12403
+ selected: false,
12404
+ query: '',
12405
+ onClick: () => {}
12406
+ };
12407
+ var TypeaheadOption = Option;
12366
12408
 
12367
12409
  /* eslint-disable jsx-a11y/anchor-is-valid */
12368
12410
  /* eslint-disable jsx-a11y/click-events-have-key-events */
12369
12411
  /* eslint-disable jsx-a11y/no-static-element-interactions */
12412
+
12370
12413
  const DEFAULT_MIN_QUERY_LENGTH = 3;
12371
12414
  const SEARCH_DELAY = 200;
12372
12415
  class Typeahead extends Component {
12373
- static defaultProps = {
12374
- addon: null,
12375
- allowNew: false,
12376
- autoFillOnBlur: true,
12377
- autoFocus: false,
12378
- chipSeparators: [],
12379
- clearable: true,
12380
- footer: null,
12381
- initialValue: [],
12382
- inputAutoComplete: 'new-password',
12383
- maxHeight: null,
12384
- minQueryLength: DEFAULT_MIN_QUERY_LENGTH,
12385
- multiple: false,
12386
- searchDelay: SEARCH_DELAY,
12387
- showSuggestions: true,
12388
- showNewEntry: true,
12389
- size: Size.MEDIUM,
12390
- validateChip: () => true
12391
- };
12392
12416
  constructor(props) {
12393
12417
  super(props);
12394
12418
  const {
@@ -12405,7 +12429,6 @@ class Typeahead extends Component {
12405
12429
  keyboardFocusedOptionIndex: null
12406
12430
  };
12407
12431
  }
12408
- handleSearchDebounced;
12409
12432
  UNSAFE_componentWillReceiveProps(nextProps) {
12410
12433
  if (nextProps.multiple !== this.props.multiple) {
12411
12434
  this.setState(previousState => {
@@ -12419,8 +12442,7 @@ class Typeahead extends Component {
12419
12442
  };
12420
12443
  }
12421
12444
  return {
12422
- query: '',
12423
- selected: previousState.selected
12445
+ query: ''
12424
12446
  };
12425
12447
  });
12426
12448
  }
@@ -12429,8 +12451,13 @@ class Typeahead extends Component {
12429
12451
  this.handleSearchDebounced.cancel();
12430
12452
  }
12431
12453
  handleOnFocus = () => {
12454
+ const {
12455
+ onFocus
12456
+ } = this.props;
12432
12457
  this.showMenu();
12433
- this.props.onFocus?.();
12458
+ if (onFocus) {
12459
+ this.props.onFocus();
12460
+ }
12434
12461
  };
12435
12462
  onOptionSelected = (event, item) => {
12436
12463
  event.preventDefault();
@@ -12513,7 +12540,7 @@ class Typeahead extends Component {
12513
12540
  break;
12514
12541
  case 'Enter':
12515
12542
  event.preventDefault();
12516
- if (keyboardFocusedOptionIndex && options[keyboardFocusedOptionIndex]) {
12543
+ if (options[keyboardFocusedOptionIndex]) {
12517
12544
  this.selectItem(options[keyboardFocusedOptionIndex]);
12518
12545
  } else if (allowNew && query.trim()) {
12519
12546
  this.selectItem({
@@ -12565,6 +12592,13 @@ class Typeahead extends Component {
12565
12592
  query
12566
12593
  });
12567
12594
  };
12595
+ stopPropagation = event => {
12596
+ event.stopPropagation();
12597
+ event.preventDefault();
12598
+ if (event.nativeEvent && event.nativeEvent.stopImmediatePropagation) {
12599
+ event.nativeEvent.stopImmediatePropagation();
12600
+ }
12601
+ };
12568
12602
  handleSearch = query => {
12569
12603
  const {
12570
12604
  onSearch
@@ -12649,7 +12683,7 @@ class Typeahead extends Component {
12649
12683
  }
12650
12684
  };
12651
12685
  renderChip = (option, idx) => {
12652
- const valid = this.props.validateChip?.(option);
12686
+ const valid = this.props.validateChip(option);
12653
12687
  return /*#__PURE__*/jsx(Chip, {
12654
12688
  label: option.label,
12655
12689
  className: classNames('m-t-1', {
@@ -12684,7 +12718,7 @@ class Typeahead extends Component {
12684
12718
  className: "dropdown-menu",
12685
12719
  role: "menu",
12686
12720
  "aria-labelledby": "dropdownMenu1",
12687
- children: [optionsToRender.map((option, idx) => /*#__PURE__*/jsx(Option, {
12721
+ children: [optionsToRender.map((option, idx) => /*#__PURE__*/jsx(TypeaheadOption, {
12688
12722
  query: query,
12689
12723
  option: option,
12690
12724
  selected: keyboardFocusedOptionIndex === idx,
@@ -12727,7 +12761,6 @@ class Typeahead extends Component {
12727
12761
  const menu = this.renderMenu({
12728
12762
  footer,
12729
12763
  options,
12730
- id,
12731
12764
  keyboardFocusedOptionIndex,
12732
12765
  query,
12733
12766
  allowNew,
@@ -12746,7 +12779,7 @@ class Typeahead extends Component {
12746
12779
  'typeahead--multiple': multiple,
12747
12780
  open: dropdownOpen
12748
12781
  }),
12749
- onClick: stopPropagation$1,
12782
+ onClick: this.stopPropagation,
12750
12783
  children: /*#__PURE__*/jsxs("div", {
12751
12784
  className: classNames('form-group', {
12752
12785
  'has-error': hasError,
@@ -12767,7 +12800,6 @@ class Typeahead extends Component {
12767
12800
  placeholder,
12768
12801
  selected,
12769
12802
  maxHeight,
12770
- id: id,
12771
12803
  name: name,
12772
12804
  value: query,
12773
12805
  typeaheadId: id,
@@ -12794,6 +12826,72 @@ class Typeahead extends Component {
12794
12826
  });
12795
12827
  }
12796
12828
  }
12829
+ Typeahead.propTypes = {
12830
+ id: PropTypes.string.isRequired,
12831
+ name: PropTypes.string.isRequired,
12832
+ options: PropTypes.arrayOf(PropTypes.shape({
12833
+ label: PropTypes.string.isRequired,
12834
+ note: PropTypes.string,
12835
+ secondary: PropTypes.string,
12836
+ value: PropTypes.object
12837
+ })).isRequired,
12838
+ initialValue: PropTypes.arrayOf(PropTypes.shape({
12839
+ label: PropTypes.string.isRequired,
12840
+ note: PropTypes.string,
12841
+ secondary: PropTypes.string
12842
+ })),
12843
+ onChange: PropTypes.func.isRequired,
12844
+ allowNew: PropTypes.bool,
12845
+ autoFocus: PropTypes.bool,
12846
+ clearable: PropTypes.bool,
12847
+ multiple: PropTypes.bool,
12848
+ showSuggestions: PropTypes.bool,
12849
+ showNewEntry: PropTypes.bool,
12850
+ searchDelay: PropTypes.number,
12851
+ maxHeight: PropTypes.number,
12852
+ minQueryLength: PropTypes.number,
12853
+ addon: PropTypes.node,
12854
+ placeholder: PropTypes.string,
12855
+ alert: PropTypes.shape({
12856
+ message: PropTypes.string.isRequired,
12857
+ type: PropTypes.oneOf(['error', 'warning', 'neutral']).isRequired
12858
+ }),
12859
+ footer: PropTypes.node,
12860
+ validateChip: PropTypes.func,
12861
+ onSearch: PropTypes.func,
12862
+ onBlur: PropTypes.func,
12863
+ onInputChange: PropTypes.func,
12864
+ onFocus: PropTypes.func,
12865
+ chipSeparators: PropTypes.arrayOf(PropTypes.string),
12866
+ size: PropTypes.oneOf(['md', 'lg']),
12867
+ inputAutoComplete: PropTypes.string,
12868
+ autoFillOnBlur: PropTypes.bool
12869
+ };
12870
+ Typeahead.defaultProps = {
12871
+ allowNew: false,
12872
+ autoFocus: false,
12873
+ clearable: true,
12874
+ multiple: false,
12875
+ maxHeight: null,
12876
+ showSuggestions: true,
12877
+ showNewEntry: true,
12878
+ searchDelay: SEARCH_DELAY,
12879
+ minQueryLength: DEFAULT_MIN_QUERY_LENGTH,
12880
+ addon: null,
12881
+ placeholder: null,
12882
+ alert: null,
12883
+ footer: null,
12884
+ size: Size.MEDIUM,
12885
+ chipSeparators: [],
12886
+ initialValue: [],
12887
+ onSearch: null,
12888
+ onBlur: null,
12889
+ onInputChange: null,
12890
+ onFocus: null,
12891
+ validateChip: () => true,
12892
+ inputAutoComplete: 'new-password',
12893
+ autoFillOnBlur: true
12894
+ };
12797
12895
 
12798
12896
  // TODO: consider to move this enum into component file once we migrate it on TypeScript or replace with some common enum
12799
12897
  var UploadStep;