@transferwise/components 0.0.0-experimental-9462b09 → 0.0.0-experimental-343827b

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 (52) hide show
  1. package/build/i18n/en.json +0 -2
  2. package/build/index.js +2358 -2453
  3. package/build/index.js.map +1 -1
  4. package/build/index.mjs +2361 -2455
  5. package/build/index.mjs.map +1 -1
  6. package/build/main.css +2 -49
  7. package/build/styles/main.css +2 -49
  8. package/build/styles/segmentedControl/SegmentedControl.css +2 -2
  9. package/build/types/checkboxButton/CheckboxButton.d.ts.map +1 -1
  10. package/build/types/common/responsivePanel/ResponsivePanel.d.ts.map +1 -1
  11. package/build/types/field/Field.d.ts +2 -1
  12. package/build/types/field/Field.d.ts.map +1 -1
  13. package/build/types/index.d.ts +0 -2
  14. package/build/types/index.d.ts.map +1 -1
  15. package/build/types/segmentedControl/SegmentedControl.d.ts.map +1 -1
  16. package/build/types/tabs/TabList.d.ts +3 -8
  17. package/build/types/tabs/TabList.d.ts.map +1 -1
  18. package/package.json +1 -1
  19. package/src/checkbox/Checkbox.spec.tsx +13 -0
  20. package/src/checkbox/Checkbox.story.tsx +13 -0
  21. package/src/checkboxButton/CheckboxButton.tsx +12 -4
  22. package/src/common/responsivePanel/ResponsivePanel.tsx +0 -2
  23. package/src/field/Field.tsx +11 -5
  24. package/src/i18n/en.json +0 -2
  25. package/src/index.ts +0 -2
  26. package/src/main.css +2 -49
  27. package/src/main.less +0 -1
  28. package/src/segmentedControl/SegmentedControl.css +2 -2
  29. package/src/segmentedControl/SegmentedControl.less +1 -1
  30. package/src/segmentedControl/SegmentedControl.spec.tsx +10 -0
  31. package/src/segmentedControl/SegmentedControl.story.tsx +42 -4
  32. package/src/segmentedControl/SegmentedControl.tsx +5 -1
  33. package/src/ssr.spec.js +0 -1
  34. package/src/tabs/TabList.tsx +15 -0
  35. package/src/tabs/Tabs.rtl.spec.tsx +40 -0
  36. package/src/tabs/Tabs.story.tsx +88 -0
  37. package/build/styles/selectOption/SelectOption.css +0 -47
  38. package/build/types/selectOption/SelectOption.d.ts +0 -21
  39. package/build/types/selectOption/SelectOption.d.ts.map +0 -1
  40. package/build/types/selectOption/SelectOption.messages.d.ts +0 -12
  41. package/build/types/selectOption/SelectOption.messages.d.ts.map +0 -1
  42. package/build/types/selectOption/index.d.ts +0 -3
  43. package/build/types/selectOption/index.d.ts.map +0 -1
  44. package/src/selectOption/SelectOption.css +0 -47
  45. package/src/selectOption/SelectOption.less +0 -45
  46. package/src/selectOption/SelectOption.messages.ts +0 -12
  47. package/src/selectOption/SelectOption.spec.tsx +0 -89
  48. package/src/selectOption/SelectOption.story.tsx +0 -269
  49. package/src/selectOption/SelectOption.tsx +0 -151
  50. package/src/selectOption/index.ts +0 -2
  51. package/src/tabs/TabList.js +0 -15
  52. package/src/tabs/Tabs.story.js +0 -135
@@ -1,269 +0,0 @@
1
- import type { StoryObj } from '@storybook/react';
2
- import { Flag } from '@wise/art';
3
- import SelectOption, {
4
- SelectOptionProps,
5
- SelectOptionValue,
6
- SelectOptiopsSection,
7
- } from './SelectOption';
8
- import { Bank, BankTransfer, Beach, Briefcase, Card, Plane } from '@transferwise/icons';
9
- import { Field } from '../field/Field';
10
- import { lorem10 } from '../test-utils';
11
- import Badge from '../badge';
12
- import Avatar from '../avatar';
13
- import { Sentiment } from '../common';
14
-
15
- export default {
16
- title: 'Option/SelectOption',
17
- };
18
-
19
- type Story = StoryObj<typeof SelectOption>;
20
-
21
- type CustomData = { data?: string };
22
-
23
- function cardPaymentMethod(index?: number): SelectOptionValue<CustomData> {
24
- return {
25
- media: <Card />,
26
- title: `Credit card ${index}`,
27
- content: (
28
- <>
29
- <div>Transfer the money to Wise using your bank account.</div>
30
- <div>0.32 GBP in fees, should arrive in seconds</div>
31
- </>
32
- ),
33
- };
34
- }
35
-
36
- const recentPaymentMethods: SelectOptionValue<CustomData>[] = [
37
- cardPaymentMethod(1),
38
- cardPaymentMethod(2),
39
- ];
40
-
41
- const allOtherPaymentMethods: SelectOptionValue<CustomData>[] = [
42
- {
43
- media: <Flag code="gbp" />,
44
- title: 'Wise GBP balance',
45
- content: (
46
- <>
47
- <span>300 GBP available</span>
48
- <span>0 GBP in fees, should arrive in seconds</span>
49
- </>
50
- ),
51
- disabled: true,
52
- value: { data: lorem10 },
53
- },
54
- cardPaymentMethod(1),
55
- {
56
- media: <Card />,
57
- title: 'Debit card',
58
- content: (
59
- <>
60
- <span>Send from your Visa or Mastercard.</span>
61
- <span>0.74 GBP in fees, should arrive in seconds</span>
62
- </>
63
- ),
64
- },
65
- {
66
- media: <Bank />,
67
- title: 'Swift Transfer',
68
- content: (
69
- <>
70
- <span>Send money internationally. Your bank will charge you extra fees.</span>
71
- <span>0.32 GBP in fees, should arrive by Thursday</span>
72
- </>
73
- ),
74
- },
75
- {
76
- media: <BankTransfer />,
77
- title: 'Bank Transfer',
78
- content: (
79
- <>
80
- <span>Transfer the money to Wise using your bank account.</span>
81
- <span>0.32 GBP in fees, should arrive in seconds</span>
82
- </>
83
- ),
84
- },
85
- {
86
- media: <BankTransfer />,
87
- title: 'Withdraw from your U.S. bank account (ACH)',
88
- content: (
89
- <>
90
- <span>1.63 USD in total fees.</span>
91
- <span>
92
- Pay with ACH using the bank account you’ve connected to Wise. Should arrive in seconds.
93
- </span>
94
- </>
95
- ),
96
- },
97
- cardPaymentMethod(1),
98
- cardPaymentMethod(2),
99
- cardPaymentMethod(3),
100
- cardPaymentMethod(4),
101
- cardPaymentMethod(5),
102
- cardPaymentMethod(6),
103
- ];
104
-
105
- const paymentMethods: SelectOptiopsSection<CustomData>[] = [
106
- {
107
- title: 'Recently used',
108
- options: recentPaymentMethods,
109
- },
110
- {
111
- title: 'Payment methods',
112
- options: allOtherPaymentMethods,
113
- },
114
- ];
115
-
116
- const balances: SelectOptiopsSection[] = [
117
- {
118
- title: 'Balances',
119
- options: [
120
- {
121
- media: <Flag code="gbp" />,
122
- title: 'Wise GBP balance',
123
- },
124
- {
125
- media: <Flag code="eur" />,
126
- title: 'Wise EUR balance',
127
- },
128
- ],
129
- },
130
- {
131
- title: 'Jars',
132
- options: [
133
- {
134
- media: (
135
- <Badge badge={<Flag code="usd" />} size="md">
136
- <Avatar type="icon" size="md" backgroundColor="var(--color-bright-pink)">
137
- <Beach size="24" />
138
- </Avatar>
139
- </Badge>
140
- ),
141
- title: 'Hawaii Holiday',
142
- content: 'Wise USD jar',
143
- },
144
- {
145
- media: (
146
- <Badge badge={<Flag code="aed" />} size="md">
147
- <Avatar type="icon" size="md" backgroundColor="var(--color-bright-yellow)">
148
- <Briefcase size="24" />
149
- </Avatar>
150
- </Badge>
151
- ),
152
- title: 'Emirates Business Trip',
153
- content: 'Wise AED jar',
154
- },
155
- {
156
- media: (
157
- <Badge badge={<Flag code="jpy" />} size="md">
158
- <Avatar type="icon" size="md" backgroundColor="var(--color-bright-blue)">
159
- <Plane size="24" />
160
- </Avatar>
161
- </Badge>
162
- ),
163
- title: 'Trip to Mars',
164
- content: 'Wise Jpy jar',
165
- },
166
- ],
167
- },
168
- ];
169
-
170
- export const Basic: Story = {
171
- args: {
172
- placeholder: { title: 'No balance selected' },
173
- options: balances,
174
- onChange: (value) => {
175
- console.log('selected balance', value);
176
- },
177
- },
178
- render: (args: SelectOptionProps) => {
179
- return (
180
- <div className="row">
181
- <div className="col-md-8 col-md-offset-2">
182
- <Field label="Balances">
183
- <SelectOption {...args} />
184
- </Field>
185
- </div>
186
- </div>
187
- );
188
- },
189
- };
190
-
191
- export const Variants: Story = {
192
- render: () => {
193
- function onChange(value: SelectOptionValue<CustomData>): void {
194
- console.log(value);
195
- }
196
- return (
197
- <div className="row">
198
- <div className="col-md-8 col-md-offset-2">
199
- <SelectOption<CustomData>
200
- className="d-block"
201
- aria-label="Choose one of payment methods"
202
- placeholder={{ title: 'No method selected', actionLabel: 'Select' }}
203
- selected={paymentMethods[1].options[1]}
204
- options={paymentMethods}
205
- onChange={onChange}
206
- />
207
- </div>
208
-
209
- <div className="col-md-8 col-md-offset-2">
210
- <Field label={<>Payment method</>}>
211
- <SelectOption<CustomData>
212
- aria-label="Choose one of payment methods"
213
- placeholder={{ title: 'No method selected', actionLabel: 'Select' }}
214
- selected={paymentMethods[1].options[1]}
215
- options={paymentMethods}
216
- onChange={onChange}
217
- />
218
- </Field>
219
- </div>
220
-
221
- <div className="col-md-8 col-md-offset-2">
222
- <Field
223
- label={<>Payment method</>}
224
- sentiment={Sentiment.NEGATIVE}
225
- message="Just an example of validation message"
226
- >
227
- <SelectOption<CustomData>
228
- aria-label="Choose one of payment methods"
229
- placeholder={{ title: 'No method selected', actionLabel: 'Select' }}
230
- selected={paymentMethods[1].options[1]}
231
- options={paymentMethods}
232
- onChange={onChange}
233
- />
234
- </Field>
235
- </div>
236
-
237
- <div className="col-md-8 col-md-offset-2">
238
- <Field
239
- label={<>Payment method</>}
240
- sentiment={Sentiment.NEGATIVE}
241
- message="Just an example of validation message"
242
- >
243
- <SelectOption<CustomData>
244
- aria-label="Choose one of payment methods"
245
- placeholder={{ title: 'No method selected', actionLabel: 'Select' }}
246
- options={paymentMethods}
247
- onChange={onChange}
248
- />
249
- </Field>
250
- </div>
251
-
252
- <div className="col-md-8 col-md-offset-2">
253
- <Field
254
- label={<>Payment method</>}
255
- sentiment={Sentiment.NEGATIVE}
256
- message="Example of disabled select option"
257
- >
258
- <SelectOption<CustomData>
259
- disabled
260
- placeholder={{ title: 'No method selected' }}
261
- options={paymentMethods}
262
- onChange={onChange}
263
- />
264
- </Field>
265
- </div>
266
- </div>
267
- );
268
- },
269
- };
@@ -1,151 +0,0 @@
1
- import { useRef, useState } from 'react';
2
- import { ActionButtonProps } from '../actionButton';
3
- import classNames from 'classnames';
4
- import Option from '../common/Option';
5
- import type { OptionProps } from '../common/Option/Option';
6
- import { Breakpoint, Position } from '../common';
7
- import Section from '../section';
8
- import Header from '../header';
9
- import { HeaderProps } from '../header/Header';
10
- import NavigationOption from '../navigationOption';
11
- import NavigationOptionsList from '../navigationOptionsList';
12
- import { useInputAttributes } from '../inputs/contexts';
13
- import messages from './SelectOption.messages';
14
- import { useIntl } from 'react-intl';
15
- import ResponsivePanel from '../common/responsivePanel';
16
- import { useScreenSize } from '../common/hooks/useScreenSize';
17
- import { ChevronDown, Plus } from '@transferwise/icons';
18
-
19
- export type SelectOptiopsSection<T = unknown> = {
20
- title?: HeaderProps['title'];
21
- options: SelectOptionValue<T>[];
22
- };
23
-
24
- export type SelectOptionValue<T = unknown> = Pick<
25
- OptionProps,
26
- 'media' | 'title' | 'content' | 'disabled'
27
- > & {
28
- value?: T;
29
- };
30
-
31
- export type SelectOptionPlaceholder = Pick<OptionProps, 'media' | 'title' | 'content'> & {
32
- actionLabel?: ActionButtonProps['children'];
33
- };
34
-
35
- export type SelectOptionProps<T = unknown> = {
36
- onChange: (selected: SelectOptionValue<T>) => void;
37
- selected?: SelectOptionValue<T>;
38
- options: SelectOptiopsSection<T>[];
39
- placeholder: SelectOptionPlaceholder;
40
- } & Omit<
41
- OptionProps,
42
- 'as' | 'title' | 'media' | 'content' | 'onClick' | 'onChange' | 'showMediaAtAllSizes' | 'decision'
43
- >;
44
-
45
- export default function SelectOption<T>({
46
- selected: selectedValueProp = undefined,
47
- options,
48
- onChange,
49
- placeholder,
50
- disabled,
51
- ...props
52
- }: SelectOptionProps<T>) {
53
- const intl = useIntl();
54
- const rootRef = useRef(null);
55
- const [selected, setSelected] = useState(selectedValueProp);
56
- const [showOptions, setShowOptions] = useState(false);
57
-
58
- const hasSelected = selected !== undefined;
59
- const isLargeScreen = useScreenSize(Breakpoint.SMALL);
60
-
61
- const inputAttributes = useInputAttributes();
62
- const ariaLabelledBy = props['aria-labelledby'] ?? inputAttributes?.['aria-labelledby'];
63
-
64
- function handleOnClick(showOptionsStatus: boolean) {
65
- return () => {
66
- setShowOptions(showOptionsStatus);
67
- };
68
- }
69
-
70
- function handleOnChange(data: SelectOptionValue<T>) {
71
- return () => {
72
- setShowOptions(false);
73
- setSelected(data);
74
- onChange(data);
75
- };
76
- }
77
-
78
- function getOptions(isLargeScreen = false) {
79
- return (
80
- <div className={classNames({ 'np-select-option-list': isLargeScreen })}>
81
- {options.map((optionsSection, index) => (
82
- <Section key={index} className={classNames({ 'p-x-2 p-y-1': isLargeScreen })}>
83
- {optionsSection.title && <Header title={optionsSection.title} />}
84
- <NavigationOptionsList>
85
- {optionsSection.options.map((option, index) => {
86
- return (
87
- <NavigationOption
88
- key={index}
89
- isContainerAligned={!isLargeScreen}
90
- showMediaCircle
91
- showMediaAtAllSizes
92
- onClick={handleOnChange(option)}
93
- {...option}
94
- />
95
- );
96
- })}
97
- </NavigationOptionsList>
98
- </Section>
99
- ))}
100
- </div>
101
- );
102
- }
103
-
104
- return (
105
- <>
106
- <Option
107
- ref={rootRef}
108
- showMediaAtAllSizes
109
- disabled={disabled}
110
- decision={false}
111
- media={hasSelected ? selected.media : placeholder.media ?? <Plus size={24} />}
112
- title={(hasSelected ? selected : placeholder).title}
113
- className={classNames(
114
- 'np-select-option',
115
- 'clickable',
116
- hasSelected ? 'np-select-option-selected' : 'np-select-option-placeholder',
117
- props.className,
118
- )}
119
- button={
120
- <button
121
- {...inputAttributes}
122
- type="button"
123
- disabled={disabled}
124
- aria-labelledby={ariaLabelledBy}
125
- aria-haspopup="dialog"
126
- aria-expanded={showOptions}
127
- className={hasSelected ? 'btn-unstyled' : 'np-action-btn'}
128
- aria-label={hasSelected ? undefined : props['aria-label']}
129
- onClick={handleOnClick(true)}
130
- >
131
- {hasSelected ? (
132
- <ChevronDown title={intl.formatMessage(messages.selectedActionLabel)} />
133
- ) : (
134
- placeholder.actionLabel || intl.formatMessage(messages.actionLabel)
135
- )}
136
- </button>
137
- }
138
- />
139
- <ResponsivePanel
140
- anchorWidth
141
- altAxis
142
- anchorRef={rootRef}
143
- open={showOptions}
144
- position={Position.BOTTOM}
145
- onClose={handleOnClick(false)}
146
- >
147
- {getOptions(isLargeScreen)}
148
- </ResponsivePanel>
149
- </>
150
- );
151
- }
@@ -1,2 +0,0 @@
1
- export { default } from './SelectOption';
2
- export type { SelectOptionProps, SelectOptionValue, SelectOptiopsSection } from './SelectOption';
@@ -1,15 +0,0 @@
1
- import PropTypes from 'prop-types';
2
-
3
- const TabList = ({ children }) => {
4
- return (
5
- <ul className="tabs__tab-list" role="tablist">
6
- {children}
7
- </ul>
8
- );
9
- };
10
-
11
- TabList.propTypes = {
12
- children: PropTypes.oneOfType([PropTypes.object, PropTypes.array]).isRequired,
13
- };
14
-
15
- export default TabList;
@@ -1,135 +0,0 @@
1
- import { useState } from 'react';
2
-
3
- import { Size, Width } from '../common';
4
-
5
- import Tabs from './Tabs';
6
-
7
- export default {
8
- component: Tabs,
9
- title: 'Navigation/Tabs',
10
- };
11
-
12
- export const Basic = () => {
13
- const [selected, setSelected] = useState(0);
14
- return (
15
- <Tabs
16
- className="tabs-custom-class"
17
- name="tabs-docs"
18
- transitionSpacing={Size.MEDIUM}
19
- tabs={[
20
- {
21
- title: 'Title 1',
22
- disabled: false,
23
- content: (
24
- <div className="p-a-2">
25
- Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum totam debitis similique
26
- </div>
27
- ),
28
- },
29
- {
30
- title: 'Title 2',
31
- disabled: false,
32
- content: (
33
- <div className="p-a-2">Lorem ipsum dolor, sit amet consectetur adipisicing elit.</div>
34
- ),
35
- },
36
- {
37
- title: 'Title 3',
38
- disabled: true,
39
- content: (
40
- <div className="p-a-2">
41
- Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum totam debitis similique
42
- </div>
43
- ),
44
- },
45
- ]}
46
- selected={selected}
47
- animatePanelsOnClick
48
- onTabSelect={(index) => setSelected(index)}
49
- />
50
- );
51
- };
52
-
53
- export const AutoTabHeaderWidth = () => {
54
- const [selected, setSelected] = useState(0);
55
- return (
56
- <Tabs
57
- className="tabs-custom-class"
58
- name="tabs-docs"
59
- transitionSpacing={Size.MEDIUM}
60
- headerWidth={Width.AUTO}
61
- tabs={[
62
- {
63
- title: 'Title 1',
64
- disabled: false,
65
- content: (
66
- <div className="p-a-2">
67
- Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum totam debitis similique
68
- </div>
69
- ),
70
- },
71
- {
72
- title: 'Title 2',
73
- disabled: false,
74
- content: (
75
- <div className="p-a-2">
76
- Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum totam debitis similique
77
- </div>
78
- ),
79
- },
80
- {
81
- title: 'Title 3',
82
- disabled: true,
83
- content: (
84
- <div className="p-a-2">
85
- Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum totam debitis similique
86
- </div>
87
- ),
88
- },
89
- ]}
90
- selected={selected}
91
- onTabSelect={(index) => setSelected(index)}
92
- />
93
- );
94
- };
95
-
96
- export const NoPanelAnimation = () => {
97
- const [selected, setSelected] = useState(0);
98
- return (
99
- <Tabs
100
- animatePanels={false}
101
- className="tabs-custom-class"
102
- name="tabs-docs"
103
- transitionSpacing={Size.MEDIUM}
104
- tabs={[
105
- {
106
- title: 'Title 1',
107
- disabled: false,
108
- content: (
109
- <div className="p-a-2">
110
- Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum totam debitis similique
111
- </div>
112
- ),
113
- },
114
- {
115
- title: 'Title 2',
116
- disabled: false,
117
- content: (
118
- <div className="p-a-2">Lorem ipsum dolor, sit amet consectetur adipisicing elit.</div>
119
- ),
120
- },
121
- {
122
- title: 'Title 3',
123
- disabled: true,
124
- content: (
125
- <div className="p-a-2">
126
- Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum totam debitis similique
127
- </div>
128
- ),
129
- },
130
- ]}
131
- selected={selected}
132
- onTabSelect={(index) => setSelected(index)}
133
- />
134
- );
135
- };