@transferwise/components 46.7.0 → 46.9.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 (50) hide show
  1. package/build/index.esm.js +154 -76
  2. package/build/index.esm.js.map +1 -1
  3. package/build/index.js +155 -76
  4. package/build/index.js.map +1 -1
  5. package/build/main.css +101 -0
  6. package/build/styles/main.css +101 -0
  7. package/build/styles/segmentedControl/SegmentedControl.css +101 -0
  8. package/build/types/checkboxOption/CheckboxOption.d.ts +2 -2
  9. package/build/types/checkboxOption/CheckboxOption.d.ts.map +1 -1
  10. package/build/types/index.d.ts +4 -0
  11. package/build/types/index.d.ts.map +1 -1
  12. package/build/types/segmentedControl/SegmentedControl.d.ts +31 -0
  13. package/build/types/segmentedControl/SegmentedControl.d.ts.map +1 -0
  14. package/build/types/segmentedControl/index.d.ts +3 -0
  15. package/build/types/segmentedControl/index.d.ts.map +1 -0
  16. package/build/types/snackbar/Snackbar.d.ts +30 -22
  17. package/build/types/snackbar/Snackbar.d.ts.map +1 -1
  18. package/build/types/snackbar/SnackbarContext.d.ts +7 -2
  19. package/build/types/snackbar/SnackbarContext.d.ts.map +1 -1
  20. package/build/types/snackbar/SnackbarProvider.d.ts +7 -12
  21. package/build/types/snackbar/SnackbarProvider.d.ts.map +1 -1
  22. package/build/types/snackbar/index.d.ts +2 -0
  23. package/build/types/snackbar/index.d.ts.map +1 -0
  24. package/build/types/snackbar/useSnackbar.d.ts +1 -1
  25. package/build/types/snackbar/useSnackbar.d.ts.map +1 -1
  26. package/build/types/withNextPortal/withNextPortal.d.ts +1 -1
  27. package/build/types/withNextPortal/withNextPortal.d.ts.map +1 -1
  28. package/package.json +9 -18
  29. package/src/checkboxOption/CheckboxOption.tsx +2 -2
  30. package/src/index.ts +4 -0
  31. package/src/main.css +101 -0
  32. package/src/main.less +1 -0
  33. package/src/segmentedControl/SegmentedControl.css +101 -0
  34. package/src/segmentedControl/SegmentedControl.less +101 -0
  35. package/src/segmentedControl/SegmentedControl.spec.tsx +106 -0
  36. package/src/segmentedControl/SegmentedControl.story.tsx +55 -0
  37. package/src/segmentedControl/SegmentedControl.tsx +175 -0
  38. package/src/segmentedControl/index.ts +2 -0
  39. package/src/snackbar/{Snackbar.story.js → Snackbar.story.tsx} +2 -1
  40. package/src/snackbar/{Snackbar.js → Snackbar.tsx} +31 -32
  41. package/src/snackbar/SnackbarContext.ts +11 -0
  42. package/src/snackbar/SnackbarProvider.tsx +39 -0
  43. package/src/ssr.spec.js +17 -0
  44. package/src/withDisplayFormat/WithDisplayFormat.spec.js +1 -1
  45. package/src/withDisplayFormat/WithDisplayFormat.tsx +1 -1
  46. package/src/withNextPortal/withNextPortal.tsx +1 -1
  47. package/src/snackbar/SnackbarContext.js +0 -4
  48. package/src/snackbar/SnackbarProvider.js +0 -51
  49. /package/src/snackbar/{index.js → index.ts} +0 -0
  50. /package/src/snackbar/{useSnackbar.js → useSnackbar.ts} +0 -0
@@ -1,5 +1,6 @@
1
1
  import { action } from '@storybook/addon-actions';
2
2
  import { number } from '@storybook/addon-knobs';
3
+ import { StoryContext } from '@storybook/react';
3
4
  import { Mobile, Theme, Switch, Bulb, Info, Coins } from '@transferwise/icons';
4
5
 
5
6
  import Button from '../button';
@@ -120,7 +121,7 @@ export const basic = () => {
120
121
  );
121
122
  };
122
123
 
123
- basic.play = async ({ canvasElement }) => {
124
+ basic.play = ({ canvasElement }: StoryContext) => {
124
125
  const canvas = within(canvasElement);
125
126
  userEvent.click(canvas.getByRole('button'));
126
127
  };
@@ -1,21 +1,36 @@
1
- import PropTypes from 'prop-types';
2
- import { Component, createRef, RefObject } from 'react';
1
+ import { Component, createRef } from 'react';
3
2
  import { CSSTransition } from 'react-transition-group';
4
3
 
5
4
  import ActionButton from '../actionButton';
6
5
  import Body from '../body';
7
- import { Theme } from '../common';
6
+ import { Theme, ThemeDark, ThemeLight } from '../common';
8
7
  import { DirectionContext } from '../provider/direction';
9
8
  import withNextPortal from '../withNextPortal/withNextPortal';
10
9
 
11
10
  export const CSS_TRANSITION_DURATION = 400;
12
11
 
13
- export class Snackbar extends Component {
14
- /** @type {RefObject<HTMLSpanElement>} */
15
- bodyRef = createRef();
12
+ export interface SnackbarProps {
13
+ action?: {
14
+ label: string;
15
+ onClick?: React.MouseEventHandler<HTMLButtonElement>;
16
+ };
17
+ text: React.ReactNode;
18
+ theme?: ThemeLight | ThemeDark;
19
+ timeout: number;
20
+ timestamp: number;
21
+ }
22
+
23
+ interface SnackbarState extends Pick<SnackbarProps, 'action' | 'text' | 'theme'> {
24
+ visible: boolean;
25
+ }
26
+
27
+ export class Snackbar extends Component<SnackbarProps, SnackbarState> {
28
+ bodyRef = createRef<HTMLSpanElement>();
29
+ timeout = 0;
30
+ transitionTimeout = 0;
16
31
 
17
- constructor() {
18
- super();
32
+ constructor(props: SnackbarProps) {
33
+ super(props);
19
34
  this.state = {
20
35
  visible: false,
21
36
  text: '',
@@ -23,11 +38,11 @@ export class Snackbar extends Component {
23
38
  }
24
39
 
25
40
  componentWillUnmount() {
26
- clearTimeout(this.timeout);
27
- clearTimeout(this.transitionTimeout);
41
+ window.clearTimeout(this.timeout);
42
+ window.clearTimeout(this.transitionTimeout);
28
43
  }
29
44
 
30
- shouldComponentUpdate(nextProps, nextState) {
45
+ shouldComponentUpdate(nextProps: SnackbarProps, nextState: SnackbarState) {
31
46
  if (!nextProps.text) {
32
47
  return false;
33
48
  }
@@ -45,12 +60,12 @@ export class Snackbar extends Component {
45
60
  setLeaveTimeout = () => {
46
61
  const { timeout } = this.props;
47
62
 
48
- this.timeout = setTimeout(() => {
63
+ this.timeout = window.setTimeout(() => {
49
64
  this.setState({ visible: false });
50
65
  }, timeout);
51
66
  };
52
67
 
53
- componentDidUpdate(previousProps) {
68
+ componentDidUpdate(previousProps: SnackbarProps) {
54
69
  const { action, text, theme, timestamp } = this.props;
55
70
 
56
71
  if (!previousProps.text) {
@@ -58,11 +73,11 @@ export class Snackbar extends Component {
58
73
  this.setLeaveTimeout();
59
74
  });
60
75
  } else if (previousProps.timestamp !== timestamp) {
61
- clearTimeout(this.timeout);
76
+ window.clearTimeout(this.timeout);
62
77
 
63
78
  if (this.state.visible) {
64
79
  this.setState({ visible: false }, () => {
65
- this.transitionTimeout = setTimeout(() => {
80
+ this.transitionTimeout = window.setTimeout(() => {
66
81
  this.setState({ visible: true, action, text, theme });
67
82
  this.setLeaveTimeout();
68
83
  }, CSS_TRANSITION_DURATION);
@@ -75,7 +90,7 @@ export class Snackbar extends Component {
75
90
  }
76
91
 
77
92
  render() {
78
- const { action, text, theme, visible } = this.state;
93
+ const { action, text, theme = Theme.LIGHT, visible } = this.state;
79
94
  const { timeout } = this.props;
80
95
 
81
96
  return (
@@ -112,20 +127,4 @@ export class Snackbar extends Component {
112
127
 
113
128
  Snackbar.contextType = DirectionContext;
114
129
 
115
- Snackbar.propTypes = {
116
- action: PropTypes.shape({
117
- label: PropTypes.string.isRequired,
118
- onClick: PropTypes.func,
119
- }),
120
- text: PropTypes.node.isRequired,
121
- theme: PropTypes.oneOf(['light', 'dark']),
122
- timeout: PropTypes.number.isRequired,
123
- timestamp: PropTypes.number.isRequired,
124
- };
125
-
126
- Snackbar.defaultProps = {
127
- action: null,
128
- theme: Theme.LIGHT,
129
- };
130
-
131
130
  export default withNextPortal(Snackbar);
@@ -0,0 +1,11 @@
1
+ import { createContext } from 'react';
2
+
3
+ import { SnackbarProps } from './Snackbar';
4
+
5
+ export type SnackbarContextType = {
6
+ createSnackbar: (props: Omit<SnackbarProps, 'timeout' | 'timestamp'>) => void;
7
+ };
8
+
9
+ export const SnackbarContext = createContext<SnackbarContextType>({ createSnackbar: () => {} });
10
+
11
+ export const SnackbarConsumer = SnackbarContext.Consumer;
@@ -0,0 +1,39 @@
1
+ import { useMemo, useState } from 'react';
2
+
3
+ import SnackbarPortal, { SnackbarProps } from './Snackbar';
4
+ import { SnackbarContext } from './SnackbarContext';
5
+
6
+ export interface SnackbarProviderProps {
7
+ timeout?: number;
8
+ children?: React.ReactNode;
9
+ }
10
+
11
+ export default function SnackbarProvider({ timeout = 4500, children }: SnackbarProviderProps) {
12
+ const [state, setState] = useState<Omit<SnackbarProps, 'timeout'>>({
13
+ text: '',
14
+ timestamp: 0,
15
+ });
16
+ const { action, text, theme, timestamp } = state;
17
+
18
+ return (
19
+ <SnackbarContext.Provider
20
+ value={useMemo(
21
+ () => ({
22
+ createSnackbar: ({ action, text, theme }) => {
23
+ setState({ action, text, theme, timestamp: Date.now() });
24
+ },
25
+ }),
26
+ [],
27
+ )}
28
+ >
29
+ <SnackbarPortal
30
+ action={action}
31
+ text={text}
32
+ timestamp={timestamp}
33
+ timeout={timeout}
34
+ theme={theme}
35
+ />
36
+ {children}
37
+ </SnackbarContext.Provider>
38
+ );
39
+ }
package/src/ssr.spec.js CHANGED
@@ -154,6 +154,23 @@ describe('Server side rendering', () => {
154
154
  label: 'Two',
155
155
  },
156
156
  ],
157
+ segments: [
158
+ {
159
+ id: '1',
160
+ value: 'accounting',
161
+ label: 'Accounting',
162
+ },
163
+ {
164
+ id: '2',
165
+ value: 'payroll',
166
+ label: 'Payroll',
167
+ },
168
+ {
169
+ id: '3',
170
+ value: 'reporting',
171
+ label: 'Reporting',
172
+ },
173
+ ],
157
174
  };
158
175
 
159
176
  // Override props in case of name collision.
@@ -145,7 +145,7 @@ describe('InputWithTextFormat', () => {
145
145
  });
146
146
 
147
147
  describe('set cursor position', () => {
148
- const triggerEventA = { ...triggerEvent, currentTarget: { setSelectionRange: () => {} } };
148
+ const triggerEventA = { ...triggerEvent, target: { setSelectionRange: () => {} } };
149
149
  beforeEach(() => {
150
150
  component.setState({
151
151
  triggerEvent: triggerEventA,
@@ -284,7 +284,7 @@ class WithDisplayFormat<T extends TextElementProps> extends Component<
284
284
 
285
285
  setTimeout(() => {
286
286
  if (triggerEvent) {
287
- triggerEvent.currentTarget.setSelectionRange(cursorPosition, cursorPosition);
287
+ (triggerEvent.target as HTMLTextElement).setSelectionRange(cursorPosition, cursorPosition);
288
288
  }
289
289
  this.setState({ selectionStart: cursorPosition, selectionEnd: cursorPosition });
290
290
  }, 0);
@@ -2,7 +2,7 @@ import { useState, useEffect } from 'react';
2
2
  import { createPortal } from 'react-dom';
3
3
 
4
4
  export default function withNextPortalWrapper<T extends Record<string, any>>(
5
- Component: React.FunctionComponent<T>,
5
+ Component: React.ComponentType<T>,
6
6
  ) {
7
7
  return function (props: T) {
8
8
  const [mounted, setMounted] = useState(false);
@@ -1,4 +0,0 @@
1
- import { createContext } from 'react';
2
-
3
- export const SnackbarContext = createContext();
4
- export const SnackbarConsumer = SnackbarContext.Consumer;
@@ -1,51 +0,0 @@
1
- import PropTypes from 'prop-types';
2
- import { Component } from 'react';
3
-
4
- import SnackbarPortal from './Snackbar';
5
- import { SnackbarContext } from './SnackbarContext';
6
-
7
- class SnackbarProvider extends Component {
8
- constructor() {
9
- super();
10
- this.state = {
11
- text: '',
12
- timestamp: 0,
13
- };
14
- }
15
-
16
- create = ({ action, text, theme }) => {
17
- this.setState({ action, text, theme, timestamp: Date.now() });
18
- };
19
-
20
- render() {
21
- const { action, text, theme, timestamp } = this.state;
22
-
23
- return (
24
- <SnackbarContext.Provider
25
- value={{
26
- createSnackbar: this.create,
27
- }}
28
- >
29
- <SnackbarPortal
30
- action={action}
31
- text={text}
32
- timestamp={timestamp}
33
- timeout={this.props.timeout}
34
- theme={theme}
35
- />
36
- {this.props.children}
37
- </SnackbarContext.Provider>
38
- );
39
- }
40
- }
41
-
42
- SnackbarProvider.propTypes = {
43
- children: PropTypes.node.isRequired,
44
- timeout: PropTypes.number,
45
- };
46
-
47
- SnackbarProvider.defaultProps = {
48
- timeout: 4500,
49
- };
50
-
51
- export default SnackbarProvider;
File without changes
File without changes