@transferwise/components 0.0.0-experimental-4533565 → 0.0.0-experimental-feb2ddf
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.
- package/build/flowNavigation/animatedLabel/AnimatedLabel.js +1 -1
- package/build/flowNavigation/animatedLabel/AnimatedLabel.js.map +1 -1
- package/build/flowNavigation/animatedLabel/AnimatedLabel.mjs +1 -1
- package/build/flowNavigation/animatedLabel/AnimatedLabel.mjs.map +1 -1
- package/build/index.js +3 -3
- package/build/index.mjs +2 -2
- package/build/{listItem/ListItem.js → legacylistItem/LegacyListItem.js} +3 -3
- package/build/legacylistItem/LegacyListItem.js.map +1 -0
- package/build/{listItem/ListItem.mjs → legacylistItem/LegacyListItem.mjs} +3 -3
- package/build/legacylistItem/LegacyListItem.mjs.map +1 -0
- package/build/legacylistItem/List.js.map +1 -0
- package/build/legacylistItem/List.mjs.map +1 -0
- package/build/main.css +60 -57
- package/build/phoneNumberInput/PhoneNumberInput.js +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.mjs +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
- package/build/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.js +2 -2
- package/build/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.js.map +1 -1
- package/build/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.mjs +2 -2
- package/build/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.mjs.map +1 -1
- package/build/styles/legacylistItem/LegacyListItem.css +6 -0
- package/build/styles/listItem/ListItem.css +185 -3
- package/build/styles/main.css +60 -57
- package/build/styles/switch/Switch.css +3 -0
- package/build/types/index.d.ts +3 -3
- package/build/types/index.d.ts.map +1 -1
- package/build/types/legacylistItem/LegacyListItem.d.ts +13 -0
- package/build/types/legacylistItem/LegacyListItem.d.ts.map +1 -0
- package/build/types/legacylistItem/List.d.ts.map +1 -0
- package/build/types/legacylistItem/index.d.ts +5 -0
- package/build/types/legacylistItem/index.d.ts.map +1 -0
- package/build/types/listItem/ListItem.d.ts +38 -8
- package/build/types/listItem/ListItem.d.ts.map +1 -1
- package/build/types/{item/ItemAdditionalInfo.d.ts → listItem/ListItemAdditionalInfo.d.ts} +1 -1
- package/build/types/listItem/ListItemAdditionalInfo.d.ts.map +1 -0
- package/build/types/{item/ItemButton.d.ts → listItem/ListItemButton.d.ts} +1 -1
- package/build/types/listItem/ListItemButton.d.ts.map +1 -0
- package/build/types/{item/ItemCheckbox.d.ts → listItem/ListItemCheckbox.d.ts} +1 -1
- package/build/types/listItem/ListItemCheckbox.d.ts.map +1 -0
- package/build/types/{item/ItemIconButton.d.ts → listItem/ListItemIconButton.d.ts} +1 -1
- package/build/types/listItem/ListItemIconButton.d.ts.map +1 -0
- package/build/types/{item/ItemMedia.d.ts → listItem/ListItemMedia.d.ts} +1 -1
- package/build/types/listItem/ListItemMedia.d.ts.map +1 -0
- package/build/types/{item/ItemNavigation.d.ts → listItem/ListItemNavigation.d.ts} +1 -1
- package/build/types/listItem/ListItemNavigation.d.ts.map +1 -0
- package/build/types/{item/ItemSwitch.d.ts → listItem/ListItemSwitch.d.ts} +1 -1
- package/build/types/listItem/ListItemSwitch.d.ts.map +1 -0
- package/build/types/listItem/index.d.ts +4 -3
- package/build/types/listItem/index.d.ts.map +1 -1
- package/build/types/listItem/prompt/Prompt.d.ts.map +1 -0
- package/build/types/listItem/useItemControl.d.ts +5 -0
- package/build/types/listItem/useItemControl.d.ts.map +1 -0
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts +2 -2
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/flowNavigation/animatedLabel/AnimatedLabel.tsx +1 -1
- package/src/index.ts +3 -3
- package/src/legacylistItem/LegacyListItem.css +6 -0
- package/src/legacylistItem/LegacyListItem.less +7 -0
- package/src/legacylistItem/LegacyListItem.story.tsx +120 -0
- package/src/{listItem/ListItem.tests.story.tsx → legacylistItem/LegacyListItem.tests.story.tsx} +2 -2
- package/src/legacylistItem/LegacyListItem.tsx +53 -0
- package/src/legacylistItem/index.ts +4 -0
- package/src/listItem/ListItem.css +185 -3
- package/src/listItem/ListItem.less +180 -5
- package/src/listItem/ListItem.story.tsx +250 -97
- package/src/listItem/ListItem.tsx +167 -37
- package/src/{item/ItemAdditionalInfo.tsx → listItem/ListItemAdditionalInfo.tsx} +2 -2
- package/src/{item/ItemButton.spec.tsx → listItem/ListItemButton.spec.tsx} +4 -4
- package/src/listItem/index.ts +5 -3
- package/src/listItem/useItemControl.tsx +12 -0
- package/src/main.css +60 -57
- package/src/main.less +2 -2
- package/src/phoneNumberInput/PhoneNumberInput.spec.tsx +4 -4
- package/src/phoneNumberInput/PhoneNumberInput.story.tsx +22 -0
- package/src/phoneNumberInput/PhoneNumberInput.tsx +1 -1
- package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.ts +4 -3
- package/src/switch/Switch.css +3 -0
- package/src/switch/Switch.less +1 -0
- package/build/listItem/List.js.map +0 -1
- package/build/listItem/List.mjs.map +0 -1
- package/build/listItem/ListItem.js.map +0 -1
- package/build/listItem/ListItem.mjs.map +0 -1
- package/build/styles/item/Item.css +0 -188
- package/build/types/item/Item.d.ts +0 -43
- package/build/types/item/Item.d.ts.map +0 -1
- package/build/types/item/ItemAdditionalInfo.d.ts.map +0 -1
- package/build/types/item/ItemButton.d.ts.map +0 -1
- package/build/types/item/ItemCheckbox.d.ts.map +0 -1
- package/build/types/item/ItemIconButton.d.ts.map +0 -1
- package/build/types/item/ItemMedia.d.ts.map +0 -1
- package/build/types/item/ItemNavigation.d.ts.map +0 -1
- package/build/types/item/ItemSwitch.d.ts.map +0 -1
- package/build/types/item/index.d.ts +0 -6
- package/build/types/item/index.d.ts.map +0 -1
- package/build/types/item/prompt/Prompt.d.ts.map +0 -1
- package/build/types/item/useItemControl.d.ts +0 -5
- package/build/types/item/useItemControl.d.ts.map +0 -1
- package/build/types/listItem/List.d.ts.map +0 -1
- package/src/item/Item.css +0 -188
- package/src/item/Item.less +0 -182
- package/src/item/Item.story.tsx +0 -273
- package/src/item/Item.tsx +0 -181
- package/src/item/index.ts +0 -6
- package/src/item/useItemControl.tsx +0 -12
- /package/build/{listItem → legacylistItem}/List.js +0 -0
- /package/build/{listItem → legacylistItem}/List.mjs +0 -0
- /package/build/types/{listItem → legacylistItem}/List.d.ts +0 -0
- /package/build/types/{item → listItem}/prompt/Prompt.d.ts +0 -0
- /package/src/{listItem/ListItem.spec.tsx → legacylistItem/LegacyListItem.spec.tsx} +0 -0
- /package/src/{listItem → legacylistItem}/List.tsx +0 -0
- /package/src/{item/ItemButton.tsx → listItem/ListItemButton.tsx} +0 -0
- /package/src/{item/ItemCheckbox.tsx → listItem/ListItemCheckbox.tsx} +0 -0
- /package/src/{item/ItemIconButton.tsx → listItem/ListItemIconButton.tsx} +0 -0
- /package/src/{item/ItemMedia.tsx → listItem/ListItemMedia.tsx} +0 -0
- /package/src/{item/ItemNavigation.tsx → listItem/ListItemNavigation.tsx} +0 -0
- /package/src/{item/ItemSwitch.tsx → listItem/ListItemSwitch.tsx} +0 -0
- /package/src/{item → listItem}/prompt/Prompt.spec.tsx +0 -0
- /package/src/{item → listItem}/prompt/Prompt.story.tsx +0 -0
- /package/src/{item → listItem}/prompt/Prompt.tsx +0 -0
|
@@ -1,120 +1,273 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import ListItem, { Props as ItemProps } from './ListItem';
|
|
2
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import React, { useState } from 'react';
|
|
4
|
+
import { FastFlag, MultiCurrency, Plus, Receipt, Savings } from '@transferwise/icons';
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
6
|
+
import { lorem10, lorem20, lorem40, lorem5 } from '../test-utils';
|
|
7
|
+
import { Flag } from '@wise/art';
|
|
8
|
+
import { List } from '../legacylistItem/List';
|
|
9
|
+
import Money from '../money';
|
|
10
|
+
import Section from '../section';
|
|
11
|
+
import Header from '../header';
|
|
10
12
|
|
|
11
13
|
export default {
|
|
12
14
|
component: ListItem,
|
|
13
|
-
title: '
|
|
14
|
-
|
|
15
|
+
title: 'Content/Item',
|
|
16
|
+
} satisfies Meta<ItemProps>;
|
|
17
|
+
|
|
18
|
+
type Story = StoryObj<ItemProps>;
|
|
19
|
+
|
|
20
|
+
// TODO: delete this story later when we have more peace of the List Item puzzle
|
|
21
|
+
export const TempPlayground: Story = {
|
|
22
|
+
render: () => {
|
|
23
|
+
const [checked, setChecked] = useState(false);
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div>
|
|
27
|
+
<ListItem
|
|
28
|
+
media={
|
|
29
|
+
<ListItem.AvatarView badge={{ type: 'action' }}>
|
|
30
|
+
<Flag code="BBD" />
|
|
31
|
+
</ListItem.AvatarView>
|
|
32
|
+
}
|
|
33
|
+
title="Test title"
|
|
34
|
+
subtitle="Test subtitle"
|
|
35
|
+
additionalInfo={<ListItem.AdditionalInfo>{lorem10}</ListItem.AdditionalInfo>}
|
|
36
|
+
/>
|
|
37
|
+
<ListItem
|
|
38
|
+
media={
|
|
39
|
+
<ListItem.AvatarLayout
|
|
40
|
+
avatars={[{ asset: <Flag code="BBD" /> }, { asset: <Flag code="MXN" /> }]}
|
|
41
|
+
/>
|
|
42
|
+
}
|
|
43
|
+
title="Test title"
|
|
44
|
+
subtitle={lorem10}
|
|
45
|
+
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
46
|
+
/>
|
|
47
|
+
<ListItem
|
|
48
|
+
media={
|
|
49
|
+
<ListItem.AvatarLayout
|
|
50
|
+
size={72}
|
|
51
|
+
orientation="diagonal"
|
|
52
|
+
avatars={[{ asset: <Flag code="BBD" /> }, { asset: <Flag code="MXN" /> }]}
|
|
53
|
+
/>
|
|
54
|
+
}
|
|
55
|
+
title="Test title"
|
|
56
|
+
subtitle={lorem10}
|
|
57
|
+
valueTitle="100 GBP"
|
|
58
|
+
valueSubtitle="100 USD"
|
|
59
|
+
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
60
|
+
/>
|
|
61
|
+
<ListItem
|
|
62
|
+
media={<ListItem.AvatarView profileType="BUSINESS" notification />}
|
|
63
|
+
title="Test title"
|
|
64
|
+
subtitle="Test subtitle"
|
|
65
|
+
additionalInfo={
|
|
66
|
+
<ListItem.AdditionalInfo
|
|
67
|
+
action={{ label: 'Learn more', href: 'https://wise.com', target: '_blank' }}
|
|
68
|
+
>
|
|
69
|
+
{lorem10}
|
|
70
|
+
</ListItem.AdditionalInfo>
|
|
71
|
+
}
|
|
72
|
+
prompt={<ListItem.Prompt type="negative">You have done something wrong</ListItem.Prompt>}
|
|
73
|
+
/>
|
|
74
|
+
<ListItem
|
|
75
|
+
media={<ListItem.AvatarView imgSrc="../avatar-square-dude.webp" selected />}
|
|
76
|
+
title="Test title"
|
|
77
|
+
additionalInfo={<ListItem.AdditionalInfo>{lorem10}</ListItem.AdditionalInfo>}
|
|
78
|
+
prompt={
|
|
79
|
+
<ListItem.Prompt
|
|
80
|
+
type="discount"
|
|
81
|
+
action={{
|
|
82
|
+
href: 'https://wise.com',
|
|
83
|
+
target: '_blank',
|
|
84
|
+
'aria-label': 'clickable prompt',
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
The whole prompt is secretly clickable
|
|
88
|
+
</ListItem.Prompt>
|
|
89
|
+
}
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
<ListItem
|
|
93
|
+
media={<ListItem.Image src="../apple-pay-logo.svg" />}
|
|
94
|
+
title="Accepting Apple Pay"
|
|
95
|
+
subtitle={lorem10}
|
|
96
|
+
/>
|
|
97
|
+
|
|
98
|
+
<ListItem
|
|
99
|
+
media={<ListItem.Image src="../wise-card.svg" />}
|
|
100
|
+
title="Wise Business Card"
|
|
101
|
+
subtitle={lorem5}
|
|
102
|
+
/>
|
|
103
|
+
|
|
104
|
+
<ListItem
|
|
105
|
+
title="Test title"
|
|
106
|
+
disabled
|
|
107
|
+
subtitle={lorem10}
|
|
108
|
+
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
109
|
+
control={<ListItem.Button priority="secondary-neutral">as Button</ListItem.Button>}
|
|
110
|
+
/>
|
|
111
|
+
<ListItem
|
|
112
|
+
title="Test title"
|
|
113
|
+
disabled
|
|
114
|
+
subtitle={lorem10}
|
|
115
|
+
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
116
|
+
control={
|
|
117
|
+
<ListItem.IconButton>
|
|
118
|
+
<Plus />
|
|
119
|
+
</ListItem.IconButton>
|
|
120
|
+
}
|
|
121
|
+
/>
|
|
122
|
+
|
|
123
|
+
<ListItem
|
|
124
|
+
title="Test title"
|
|
125
|
+
subtitle={lorem10}
|
|
126
|
+
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
127
|
+
control={
|
|
128
|
+
<ListItem.Button
|
|
129
|
+
priority="secondary-neutral"
|
|
130
|
+
as="a"
|
|
131
|
+
target="dfdf"
|
|
132
|
+
aria-label="adsfasfd"
|
|
133
|
+
href="wise.com"
|
|
134
|
+
>
|
|
135
|
+
as Link
|
|
136
|
+
</ListItem.Button>
|
|
137
|
+
}
|
|
138
|
+
/>
|
|
139
|
+
|
|
140
|
+
<ListItem
|
|
141
|
+
title="Test title"
|
|
142
|
+
subtitle={lorem10}
|
|
143
|
+
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
144
|
+
control={<ListItem.Checkbox indeterminate />}
|
|
145
|
+
/>
|
|
146
|
+
|
|
147
|
+
<ListItem
|
|
148
|
+
title="Test title"
|
|
149
|
+
subtitle={lorem10}
|
|
150
|
+
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
151
|
+
control={
|
|
152
|
+
<ListItem.Switch
|
|
153
|
+
checked={checked}
|
|
154
|
+
onClick={() => {
|
|
155
|
+
setChecked(!checked);
|
|
156
|
+
}}
|
|
157
|
+
/>
|
|
158
|
+
}
|
|
159
|
+
/>
|
|
160
|
+
</div>
|
|
161
|
+
);
|
|
162
|
+
},
|
|
15
163
|
};
|
|
16
164
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
165
|
+
export const ItemRadio: Story = {
|
|
166
|
+
render: () => (
|
|
167
|
+
<div>
|
|
168
|
+
{/* Basic */}
|
|
169
|
+
{/* with additional info */}
|
|
170
|
+
{/* with prompt */}
|
|
171
|
+
{/* Disabled */}
|
|
172
|
+
{/* Spotlight */}
|
|
173
|
+
{/* Active */}
|
|
174
|
+
</div>
|
|
175
|
+
),
|
|
23
176
|
};
|
|
24
177
|
|
|
25
|
-
export const
|
|
26
|
-
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
178
|
+
export const ItemButton: Story = {
|
|
179
|
+
render: () => (
|
|
180
|
+
<div>
|
|
181
|
+
{/* Basic */}
|
|
182
|
+
{/* with additional info */}
|
|
183
|
+
{/* with prompt */}
|
|
184
|
+
{/* partially interactive */}
|
|
185
|
+
{/* Disabled */}
|
|
186
|
+
{/* Spotlight */}
|
|
187
|
+
{/* Active */}
|
|
188
|
+
</div>
|
|
189
|
+
),
|
|
31
190
|
};
|
|
32
191
|
|
|
33
|
-
export const
|
|
34
|
-
|
|
192
|
+
export const ItemNonInteractive: Story = {
|
|
193
|
+
render: () => (
|
|
35
194
|
<div>
|
|
36
|
-
<
|
|
37
|
-
<
|
|
195
|
+
<Section>
|
|
196
|
+
<Header title="Transcation Details" />
|
|
38
197
|
<List>
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<List>
|
|
45
|
-
<Template
|
|
46
|
-
title="Sandra Pepper"
|
|
47
|
-
value="Personal account"
|
|
48
|
-
media={<AvatarView profileName="Super Pepa" badge={{ icon: <FastFlag /> }} />}
|
|
49
|
-
/>
|
|
50
|
-
</List>
|
|
51
|
-
</div>
|
|
52
|
-
<div className="m-t-4 m-b-2">
|
|
53
|
-
<Title type="title-body">With Avatar and Action</Title>
|
|
54
|
-
<List>
|
|
55
|
-
<Template
|
|
56
|
-
title="Account holder"
|
|
57
|
-
value="Sandra Pepper"
|
|
58
|
-
media={<AvatarView profileName="Super Pepa" badge={{ icon: <FastFlag /> }} />}
|
|
59
|
-
action={
|
|
60
|
-
<Button v2 size="sm">
|
|
61
|
-
Share details
|
|
62
|
-
</Button>
|
|
198
|
+
<ListItem
|
|
199
|
+
media={
|
|
200
|
+
<ListItem.AvatarView>
|
|
201
|
+
<MultiCurrency />
|
|
202
|
+
</ListItem.AvatarView>
|
|
63
203
|
}
|
|
204
|
+
title="Estimated costs"
|
|
205
|
+
subtitle="Other providers"
|
|
206
|
+
valueTitle={<Money amount={100} currency="GBP" />}
|
|
64
207
|
/>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
<Template title="Sort code" value="23-14-71" />
|
|
71
|
-
<Template title="Account number" value="12345678" />
|
|
72
|
-
</List>
|
|
73
|
-
</div>
|
|
74
|
-
<div className="m-t-4 m-b-2">
|
|
75
|
-
<Title type="title-body">Text With Action Button</Title>
|
|
76
|
-
<List>
|
|
77
|
-
<Template
|
|
78
|
-
title="SWIFT/BIC"
|
|
79
|
-
value="••• •••"
|
|
80
|
-
action={
|
|
81
|
-
<Button v2 size="sm" onClick={() => action('clicked')}>
|
|
82
|
-
Reveal
|
|
83
|
-
</Button>
|
|
208
|
+
<ListItem
|
|
209
|
+
media={
|
|
210
|
+
<ListItem.AvatarView>
|
|
211
|
+
<FastFlag />
|
|
212
|
+
</ListItem.AvatarView>
|
|
84
213
|
}
|
|
214
|
+
title="Total paid"
|
|
215
|
+
subtitle="Wise"
|
|
216
|
+
valueTitle={<Money amount={12.15} currency="GBP" />}
|
|
217
|
+
valueSubtitle={<Money amount={100.9} currency="GBP" />}
|
|
85
218
|
/>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<Template
|
|
92
|
-
title="Account number"
|
|
93
|
-
value="123456789"
|
|
94
|
-
action={
|
|
95
|
-
<IconButton size={24} aria-label="Copy" priority="minimal">
|
|
96
|
-
<Documents />
|
|
97
|
-
</IconButton>
|
|
219
|
+
<ListItem
|
|
220
|
+
media={
|
|
221
|
+
<ListItem.AvatarView>
|
|
222
|
+
<Receipt />
|
|
223
|
+
</ListItem.AvatarView>
|
|
98
224
|
}
|
|
225
|
+
title="Total fees"
|
|
226
|
+
subtitle={lorem5}
|
|
227
|
+
valueSubtitle={<Money amount={5.5} currency="GBP" />}
|
|
99
228
|
/>
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<Template
|
|
106
|
-
title="Routing number"
|
|
107
|
-
value="987654"
|
|
108
|
-
action={
|
|
109
|
-
<Info
|
|
110
|
-
size="lg"
|
|
111
|
-
aria-label="More information"
|
|
112
|
-
content="Use this routing number to receive ACH and Wire transfers."
|
|
113
|
-
/>
|
|
229
|
+
<ListItem
|
|
230
|
+
media={
|
|
231
|
+
<ListItem.AvatarView>
|
|
232
|
+
<Savings />
|
|
233
|
+
</ListItem.AvatarView>
|
|
114
234
|
}
|
|
235
|
+
title="You saved"
|
|
236
|
+
valueSubtitle={<Money amount={1000} currency="GBP" />}
|
|
115
237
|
/>
|
|
116
238
|
</List>
|
|
117
|
-
</
|
|
239
|
+
</Section>
|
|
240
|
+
|
|
241
|
+
<ListItem
|
|
242
|
+
as="div"
|
|
243
|
+
title="Bank name and address"
|
|
244
|
+
subtitle="Bank Ltd, 2 Street Boulevard, Singapore, 1213423"
|
|
245
|
+
additionalInfo={
|
|
246
|
+
<ListItem.AdditionalInfo
|
|
247
|
+
action={{ label: 'Learn more', href: 'https://wise.com', target: '_blank' }}
|
|
248
|
+
>
|
|
249
|
+
This is our partner bank in Singapore.
|
|
250
|
+
</ListItem.AdditionalInfo>
|
|
251
|
+
}
|
|
252
|
+
/>
|
|
253
|
+
<ListItem
|
|
254
|
+
as="div"
|
|
255
|
+
title="Bank name and address"
|
|
256
|
+
subtitle="Capital Ltd, 2 Canal Street, London, E14 111"
|
|
257
|
+
additionalInfo={
|
|
258
|
+
<ListItem.AdditionalInfo
|
|
259
|
+
action={{ label: 'Learn more', href: 'https://wise.com', target: '_blank' }}
|
|
260
|
+
/>
|
|
261
|
+
}
|
|
262
|
+
/>
|
|
263
|
+
{/* Basic */}
|
|
264
|
+
{/* with additional info */}
|
|
265
|
+
{/* with prompt */}
|
|
266
|
+
{/* Disabled */}
|
|
267
|
+
{/* Spotlight */}
|
|
268
|
+
{/* Active */}
|
|
118
269
|
</div>
|
|
119
|
-
)
|
|
270
|
+
),
|
|
120
271
|
};
|
|
272
|
+
|
|
273
|
+
// add intaces with dark mode
|
|
@@ -1,53 +1,183 @@
|
|
|
1
|
+
import { createContext, ReactNode, useId, useMemo, useState } from 'react';
|
|
2
|
+
import { Typography } from '../common';
|
|
3
|
+
import Body from '../body';
|
|
4
|
+
import { AdditionalInfo } from './ListItemAdditionalInfo';
|
|
5
|
+
import { IconButton } from './ListItemIconButton';
|
|
6
|
+
import { Checkbox } from './ListItemCheckbox';
|
|
7
|
+
import { Navigation } from './ListItemNavigation';
|
|
1
8
|
import { clsx } from 'clsx';
|
|
2
|
-
import {
|
|
9
|
+
import { Button } from './ListItemButton';
|
|
10
|
+
import { Switch } from './ListItemSwitch';
|
|
11
|
+
import { AvatarLayout, AvatarView, Image } from './ListItemMedia';
|
|
12
|
+
import Prompt from './prompt/Prompt';
|
|
3
13
|
|
|
4
|
-
|
|
14
|
+
export type ListItemTypes =
|
|
15
|
+
| 'non-interactive'
|
|
16
|
+
| 'navigation'
|
|
17
|
+
| 'radio'
|
|
18
|
+
| 'checkbox'
|
|
19
|
+
| 'switch'
|
|
20
|
+
| 'button'
|
|
21
|
+
| 'icon-button';
|
|
5
22
|
|
|
6
|
-
export type
|
|
23
|
+
export type Props = {
|
|
24
|
+
as?: 'li' | 'div' | 'span';
|
|
25
|
+
inverted?: boolean;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
spotlight?: 'active' | 'inactive';
|
|
7
28
|
title: ReactNode;
|
|
8
|
-
|
|
29
|
+
subtitle?: ReactNode;
|
|
30
|
+
additionalInfo?: ReactNode;
|
|
31
|
+
valueTitle?: ReactNode;
|
|
32
|
+
valueSubtitle?: ReactNode;
|
|
9
33
|
media?: ReactNode;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
isContainerAligned?: boolean;
|
|
13
|
-
as?: ElementType;
|
|
34
|
+
control?: ReactNode;
|
|
35
|
+
prompt?: ReactNode;
|
|
14
36
|
};
|
|
15
37
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
38
|
+
export type ListItemContextData = {
|
|
39
|
+
setControlType: (type: ListItemTypes) => void;
|
|
40
|
+
ids: {
|
|
41
|
+
label: string;
|
|
42
|
+
additionalInfo: string;
|
|
43
|
+
value: string;
|
|
44
|
+
control: string;
|
|
45
|
+
prompt: string;
|
|
46
|
+
};
|
|
47
|
+
props: Pick<Props, 'as' | 'disabled' | 'inverted'>;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// @ts-expect-error for now let's mock it with `null` value
|
|
51
|
+
// but actually by default we should specify `setControlType('none')`
|
|
52
|
+
export const ListItemContext = createContext<ListItemContextData>(null);
|
|
53
|
+
|
|
54
|
+
export const ListItem = ({
|
|
55
|
+
as: View = 'li',
|
|
20
56
|
title,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
57
|
+
subtitle,
|
|
58
|
+
additionalInfo,
|
|
59
|
+
prompt,
|
|
60
|
+
inverted,
|
|
61
|
+
media,
|
|
62
|
+
spotlight = undefined,
|
|
63
|
+
valueTitle,
|
|
64
|
+
valueSubtitle,
|
|
65
|
+
control = null,
|
|
66
|
+
disabled,
|
|
67
|
+
}: Props) => {
|
|
68
|
+
/*
|
|
69
|
+
const returnType = (): ReactNode => {
|
|
70
|
+
switch (type) {
|
|
71
|
+
case 'Navigation':
|
|
72
|
+
return <Chevron orientation={Position.RIGHT} disabled />;
|
|
73
|
+
case 'Radio':
|
|
74
|
+
return <RadioButton name="Hello" checked />;
|
|
75
|
+
case 'Checkbox':
|
|
76
|
+
return <CheckboxButton name="Hello" checked />;
|
|
77
|
+
case 'Switch':
|
|
78
|
+
return <Switch onClick={() => console.log('clicked')} />;
|
|
79
|
+
case 'Button':
|
|
80
|
+
return <Button v2>Hello</Button>;
|
|
81
|
+
case 'IconButton':
|
|
82
|
+
return (
|
|
83
|
+
<IconButton size={40} priority="minimal">
|
|
84
|
+
<InfoCircle />
|
|
85
|
+
</IconButton>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
*/
|
|
90
|
+
const idPrefix = useId();
|
|
91
|
+
|
|
92
|
+
const [controlType, setControlType] = useState<ListItemTypes>('non-interactive');
|
|
93
|
+
const ids = {
|
|
94
|
+
label: `${idPrefix}_label`,
|
|
95
|
+
value: `${idPrefix}_value`,
|
|
96
|
+
control: `${idPrefix}_control`,
|
|
97
|
+
prompt: `${idPrefix}_prompt`,
|
|
98
|
+
additionalInfo: `${idPrefix}_additional-info`,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const listItemContext = useMemo(
|
|
102
|
+
() => ({ setControlType, ids, props: { as: View, disabled, inverted } }),
|
|
103
|
+
[],
|
|
104
|
+
);
|
|
27
105
|
|
|
28
106
|
return (
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
</Body>
|
|
41
|
-
{value && (
|
|
42
|
-
<Body type="body-large" className="text-primary text-overflow-wrap m-b-0">
|
|
43
|
-
{value}
|
|
44
|
-
</Body>
|
|
107
|
+
<ListItemContext.Provider value={listItemContext}>
|
|
108
|
+
<View
|
|
109
|
+
className={clsx(
|
|
110
|
+
'wds-list-item',
|
|
111
|
+
{ 'wds-list-item-interactive': controlType !== 'non-interactive' },
|
|
112
|
+
`wds-list-item-${controlType}`,
|
|
113
|
+
'd-flex flex-row',
|
|
114
|
+
{ 'align-items-center': !subtitle },
|
|
115
|
+
{
|
|
116
|
+
[`wds-list-item-spotlight-${spotlight}`]: !!spotlight,
|
|
117
|
+
},
|
|
45
118
|
)}
|
|
46
|
-
|
|
119
|
+
aria-describedby={[ids.additionalInfo].join(' ')}
|
|
120
|
+
>
|
|
121
|
+
{media && <div className="wds-list-item-media">{media}</div>}
|
|
47
122
|
|
|
48
|
-
|
|
49
|
-
|
|
123
|
+
{/* Title + Subtitle + Values + Additional Info - Group */}
|
|
124
|
+
<div className="wds-list-item-body">
|
|
125
|
+
{/* Title + Subtitle + Values - Group */}
|
|
126
|
+
<div className="d-flex justify-content-between">
|
|
127
|
+
<span>
|
|
128
|
+
{/* @ts-expect-error div can have role and aria-lavel props */}
|
|
129
|
+
<Body
|
|
130
|
+
type={Typography.BODY_LARGE_BOLD}
|
|
131
|
+
className="wds-list-item-title"
|
|
132
|
+
// for a11y this needs to be a header but for SEO it shouldn't be `h*` tag
|
|
133
|
+
// so we enable header semantics via `role` and `aria-level` attrs
|
|
134
|
+
role="heading"
|
|
135
|
+
aria-level="4"
|
|
136
|
+
>
|
|
137
|
+
{title}
|
|
138
|
+
</Body>
|
|
139
|
+
<Body className="wds-list-item-subtitle">{subtitle}</Body>
|
|
140
|
+
</span>
|
|
141
|
+
{(valueTitle || valueSubtitle) && (
|
|
142
|
+
<span
|
|
143
|
+
id={ids.value}
|
|
144
|
+
className={clsx('wds-list-item-value', 'd-flex align-items-center', {
|
|
145
|
+
'flex-column': valueTitle !== undefined && valueSubtitle !== undefined,
|
|
146
|
+
})}
|
|
147
|
+
>
|
|
148
|
+
{valueTitle && (
|
|
149
|
+
<Body type={Typography.BODY_LARGE_BOLD} className="wds-list-item-title-value">
|
|
150
|
+
{valueTitle}
|
|
151
|
+
</Body>
|
|
152
|
+
)}
|
|
153
|
+
{valueSubtitle && (
|
|
154
|
+
<Body className="wds-list-item-subtitle-value">{valueSubtitle}</Body>
|
|
155
|
+
)}
|
|
156
|
+
</span>
|
|
157
|
+
)}
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
{/* Additional Info and Prompt here */}
|
|
161
|
+
{Boolean(subtitle) && additionalInfo}
|
|
162
|
+
</div>
|
|
163
|
+
{control === null ? null : <Body className="wds-list-item-control">{control}</Body>}
|
|
164
|
+
{prompt}
|
|
165
|
+
</View>
|
|
166
|
+
</ListItemContext.Provider>
|
|
50
167
|
);
|
|
51
168
|
};
|
|
52
169
|
|
|
170
|
+
/* eslint-disable functional/immutable-data */
|
|
171
|
+
ListItem.Image = Image;
|
|
172
|
+
ListItem.AvatarView = AvatarView;
|
|
173
|
+
ListItem.AvatarLayout = AvatarLayout;
|
|
174
|
+
ListItem.AdditionalInfo = AdditionalInfo;
|
|
175
|
+
ListItem.Checkbox = Checkbox;
|
|
176
|
+
ListItem.IconButton = IconButton;
|
|
177
|
+
ListItem.Navigation = Navigation;
|
|
178
|
+
ListItem.Button = Button;
|
|
179
|
+
ListItem.Switch = Switch;
|
|
180
|
+
ListItem.Prompt = Prompt;
|
|
181
|
+
/* eslint-enable functional/immutable-data */
|
|
182
|
+
|
|
53
183
|
export default ListItem;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PropsWithChildren, useContext } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ListItemContext, ListItemContextData } from './ListItem';
|
|
3
3
|
import Body from '../body';
|
|
4
4
|
import Link, { LinkProps } from '../link';
|
|
5
5
|
import { Typography } from '../common';
|
|
@@ -9,7 +9,7 @@ export type ItemAdditionalInfoProps = PropsWithChildren<{
|
|
|
9
9
|
}>;
|
|
10
10
|
|
|
11
11
|
export const AdditionalInfo = function ({ children, action }: ItemAdditionalInfoProps) {
|
|
12
|
-
const { ids } = useContext<
|
|
12
|
+
const { ids } = useContext<ListItemContextData>(ListItemContext);
|
|
13
13
|
|
|
14
14
|
return (
|
|
15
15
|
<Body
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { render, screen, mockMatchMedia } from '../test-utils';
|
|
2
|
-
import { Button as ItemButton } from './
|
|
2
|
+
import { Button as ItemButton } from './ListItemButton';
|
|
3
3
|
import { ButtonPriority } from '../button/Button.types';
|
|
4
|
-
import {
|
|
4
|
+
import { ListItemContext } from './ListItem';
|
|
5
5
|
|
|
6
6
|
mockMatchMedia();
|
|
7
7
|
|
|
@@ -10,7 +10,7 @@ describe('ItemButton', () => {
|
|
|
10
10
|
|
|
11
11
|
const renderWithItemContext = (ui: React.ReactNode) => {
|
|
12
12
|
return render(
|
|
13
|
-
<
|
|
13
|
+
<ListItemContext.Provider
|
|
14
14
|
value={{
|
|
15
15
|
setControlType: mockSetControlType,
|
|
16
16
|
ids: {
|
|
@@ -24,7 +24,7 @@ describe('ItemButton', () => {
|
|
|
24
24
|
}}
|
|
25
25
|
>
|
|
26
26
|
{ui}
|
|
27
|
-
</
|
|
27
|
+
</ListItemContext.Provider>,
|
|
28
28
|
);
|
|
29
29
|
};
|
|
30
30
|
|
package/src/listItem/index.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
1
|
+
export type { Props as ItemProps } from './ListItem';
|
|
2
|
+
export type { ItemAdditionalInfoProps } from './ListItemAdditionalInfo';
|
|
3
|
+
export type { ItemCheckboxProps } from './ListItemCheckbox';
|
|
4
|
+
export type { ItemImageProps, ItemAvatarViewProps, ItemAvatarLayoutProps } from './ListItemMedia';
|
|
5
|
+
|
|
3
6
|
export { default } from './ListItem';
|
|
4
|
-
export type { ListItemProps } from './ListItem';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useContext, useEffect } from 'react';
|
|
2
|
+
import { ListItemContext, ListItemContextData, ListItemTypes } from './ListItem';
|
|
3
|
+
|
|
4
|
+
export function useItemControl(controlType: ListItemTypes) {
|
|
5
|
+
const { setControlType, props: baseItemProps } = useContext<ListItemContextData>(ListItemContext);
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
setControlType(controlType);
|
|
9
|
+
}, [controlType, setControlType]);
|
|
10
|
+
|
|
11
|
+
return { baseItemProps };
|
|
12
|
+
}
|