@transferwise/components 46.81.0 → 46.82.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/i18n/en.json +5 -0
  2. package/build/i18n/en.json.js +5 -0
  3. package/build/i18n/en.json.js.map +1 -1
  4. package/build/i18n/en.json.mjs +5 -0
  5. package/build/i18n/en.json.mjs.map +1 -1
  6. package/build/main.css +274 -0
  7. package/build/money/Money.js +5 -2
  8. package/build/money/Money.js.map +1 -1
  9. package/build/money/Money.mjs +5 -2
  10. package/build/money/Money.mjs.map +1 -1
  11. package/build/styles/main.css +274 -0
  12. package/build/styles/table/Table.css +274 -0
  13. package/build/types/money/Money.d.ts +2 -1
  14. package/build/types/money/Money.d.ts.map +1 -1
  15. package/build/types/table/Table.d.ts +23 -0
  16. package/build/types/table/Table.d.ts.map +1 -0
  17. package/build/types/table/Table.messages.d.ts +24 -0
  18. package/build/types/table/Table.messages.d.ts.map +1 -0
  19. package/build/types/table/TableCell.d.ts +40 -0
  20. package/build/types/table/TableCell.d.ts.map +1 -0
  21. package/build/types/table/TableHeader.d.ts +13 -0
  22. package/build/types/table/TableHeader.d.ts.map +1 -0
  23. package/build/types/table/TableRow.d.ts +17 -0
  24. package/build/types/table/TableRow.d.ts.map +1 -0
  25. package/build/types/table/TableStatusText.d.ts +10 -0
  26. package/build/types/table/TableStatusText.d.ts.map +1 -0
  27. package/build/types/table/index.d.ts +6 -0
  28. package/build/types/table/index.d.ts.map +1 -0
  29. package/build/types/test-utils/index.d.ts +10 -0
  30. package/build/types/test-utils/index.d.ts.map +1 -1
  31. package/package.json +3 -3
  32. package/src/i18n/en.json +5 -0
  33. package/src/main.css +274 -0
  34. package/src/main.less +1 -0
  35. package/src/money/Money.tsx +9 -2
  36. package/src/table/Table.css +274 -0
  37. package/src/table/Table.less +334 -0
  38. package/src/table/Table.messages.ts +24 -0
  39. package/src/table/Table.spec.tsx +82 -0
  40. package/src/table/Table.story.tsx +356 -0
  41. package/src/table/Table.tsx +167 -0
  42. package/src/table/TableCell.spec.tsx +298 -0
  43. package/src/table/TableCell.tsx +149 -0
  44. package/src/table/TableHeader.spec.tsx +50 -0
  45. package/src/table/TableHeader.tsx +74 -0
  46. package/src/table/TableRow.spec.tsx +112 -0
  47. package/src/table/TableRow.tsx +70 -0
  48. package/src/table/TableStatusText.spec.tsx +53 -0
  49. package/src/table/TableStatusText.tsx +40 -0
  50. package/src/table/index.ts +11 -0
@@ -0,0 +1,334 @@
1
+ @import (reference) "../../node_modules/@transferwise/neptune-css/src/less/ring.less";
2
+
3
+ .np-table {
4
+ @table-background-color: var(--color-background-neutral);
5
+ @table-border-width: var(--size-8);
6
+ @table-border-radius: var(--radius-small);
7
+ @table-border-radius: var(--radius-medium);
8
+ @table-inner-border-radius: 10px;
9
+ @table-cell-border-radius: 6px;
10
+
11
+ @table-spacing-sm: var(--size-4);
12
+ @table-spacing-md: var(--size-8);
13
+ @table-spacing-lg: var(--size-12);
14
+ @table-spacing-xl: var(--size-16);
15
+
16
+ @header-min-width: 160px;
17
+ @header-min-width-loading: calc(@header-min-width * 2);
18
+
19
+ width: 100%;
20
+ background-color: transparent;
21
+
22
+ &-outer-container {
23
+ border-radius: @table-border-radius;
24
+
25
+ .focus-ring();
26
+ &:focus-visible {
27
+ outline-offset: 0;
28
+ }
29
+
30
+ &--center {
31
+ margin-right: auto;
32
+ margin-left: auto;
33
+
34
+ @media (--screen-sm-max) {
35
+ width: 100%;
36
+ }
37
+ }
38
+
39
+ &--full-width {
40
+ width: 100%;
41
+ }
42
+ }
43
+
44
+ &-container {
45
+ padding: @table-spacing-md;
46
+ background-color: @table-background-color;
47
+ border-radius: inherit;
48
+
49
+ &--loading {
50
+ .np-table-inner-container {
51
+ background-image: none;
52
+ }
53
+ }
54
+ }
55
+
56
+ &-inner-container {
57
+ background-image:
58
+ linear-gradient(to right, var(--color-contrast-overlay), var(--color-contrast-overlay)),
59
+ linear-gradient(to right, var(--color-contrast-overlay), var(--color-contrast-overlay)),
60
+ linear-gradient(to right, rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0)),
61
+ linear-gradient(to left, rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0));
62
+ background-position: left center, right center, left center, right center;
63
+ background-repeat: no-repeat;
64
+ background-color: var(--color-contrast-overlay);
65
+ background-size: 15px 100%, 15px 100%, 15px 100%, 15px 100%;
66
+ background-attachment: local, local, scroll, scroll;
67
+ overflow-x: auto;
68
+ border-radius: @table-inner-border-radius;
69
+
70
+ .np-theme-personal--dark & {
71
+ background-image:
72
+ linear-gradient(to right, var(--color-contrast-overlay), var(--color-contrast-overlay)),
73
+ linear-gradient(to right, var(--color-contrast-overlay), var(--color-contrast-overlay)),
74
+ linear-gradient(to right, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0)),
75
+ linear-gradient(to left, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
76
+ }
77
+ }
78
+
79
+ &-row {
80
+ &:last-child {
81
+ .np-table-cell {
82
+ &:first-child {
83
+ border-bottom-left-radius: @table-inner-border-radius;
84
+ }
85
+ &:last-child {
86
+ border-bottom-right-radius: @table-inner-border-radius;
87
+ }
88
+ }
89
+ }
90
+
91
+ .focus-ring();
92
+ &:focus-visible {
93
+ outline-offset: -2px;
94
+ border-radius: @table-cell-border-radius;
95
+ }
96
+
97
+ &--clickable {
98
+ .np-table-cell {
99
+ position: relative;
100
+ &:before {
101
+ display: none;
102
+ content: "";
103
+ position: absolute;
104
+ height: 100%;
105
+ width: 100%;
106
+ top: 0;
107
+ left: 0;
108
+ background-color: var(--color-background-screen-hover);
109
+ }
110
+
111
+ &:first-child,
112
+ &:last-child {
113
+ &:before {
114
+ width: calc(100% - @table-spacing-md);
115
+ }
116
+ }
117
+
118
+ &:first-child {
119
+ &:before {
120
+ left: @table-spacing-md;
121
+ border-top-left-radius: @table-cell-border-radius;
122
+ border-bottom-left-radius: @table-cell-border-radius;
123
+ }
124
+ }
125
+
126
+ &:last-child {
127
+ &:before {
128
+ border-top-right-radius: @table-cell-border-radius;
129
+ border-bottom-right-radius: @table-cell-border-radius;
130
+ }
131
+ }
132
+ }
133
+
134
+ &:hover {
135
+ .np-table-cell:before {
136
+ display: block;
137
+ }
138
+
139
+ &:focus-visible {
140
+ .np-table-cell {
141
+ &:first-child,
142
+ &:last-child {
143
+ &:before {
144
+ width: 100%;
145
+ }
146
+ }
147
+
148
+ &:first-child {
149
+ &:before {
150
+ left: 0;
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+
158
+ &--cosmetic {
159
+ .np-table-cell {
160
+ height: @table-spacing-md;
161
+ padding: 0;
162
+ }
163
+ }
164
+ }
165
+
166
+ &-header,
167
+ &-cell {
168
+ padding: 0;
169
+
170
+ &:first-child {
171
+ padding-left: @table-spacing-xl;
172
+
173
+ .np-table-header-content,
174
+ .np-table-cell-content {
175
+ padding-left: 0;
176
+ }
177
+ }
178
+
179
+ &:last-child {
180
+ padding-right: @table-spacing-xl;
181
+
182
+ .np-table-header-content,
183
+ .np-table-cell-content {
184
+ padding-right: 0;
185
+ }
186
+ }
187
+ }
188
+
189
+ &-header.np-table-header--right,
190
+ &-cell.np-table-cell--right {
191
+ > .np-text-body-default {
192
+ text-align: right;
193
+ }
194
+ }
195
+
196
+ &-header.np-table-header--right + .np-table-header:not(.np-table-header--right),
197
+ &-cell.np-table-cell--right + .np-table-cell:not(.np-table-cell--right) {
198
+ padding-left: calc(@table-spacing-md + @table-spacing-lg);
199
+ }
200
+
201
+ &-header.np-table-header--right .np-table-header-content,
202
+ &-cell.np-table-cell--right .np-table-content {
203
+ justify-content: end;
204
+ }
205
+
206
+ &-header-content,
207
+ &-content {
208
+ display: flex;
209
+ align-items: center;
210
+ justify-content: start;
211
+ }
212
+
213
+ &-header {
214
+ min-width: @header-min-width;
215
+ padding-right: @table-spacing-md;
216
+ padding-bottom: @table-spacing-md;
217
+ padding-left: @table-spacing-md;
218
+ background-color: var(--color-background-neutral);
219
+ color: var(--color-interactive-primary);
220
+
221
+ &-content {
222
+ padding-top: 5px;
223
+ padding-bottom: 5px;
224
+ white-space: nowrap;
225
+ line-height: var(--line-height-22);
226
+ letter-spacing: var(--letter-spacing-sm);
227
+ }
228
+
229
+ &--error {
230
+ color: var(--color-sentiment-negative);
231
+ }
232
+
233
+ &--action {
234
+ min-width: 0;
235
+ padding: 0;
236
+ }
237
+ }
238
+
239
+ &-cell {
240
+ padding: @table-spacing-xl @table-spacing-md;
241
+ position: relative;
242
+
243
+ &--cosmetic {
244
+ padding: 0;
245
+ }
246
+
247
+ &--primary {
248
+ min-width: 200px;
249
+ }
250
+
251
+ &--currency {
252
+ .np-text-body-default {
253
+ white-space: nowrap;
254
+ }
255
+ }
256
+
257
+ .tw-chevron {
258
+ margin-left: @table-spacing-md;
259
+ }
260
+
261
+ &-separator {
262
+ margin-top: @table-spacing-sm;
263
+ margin-bottom: @table-spacing-sm;
264
+ height: 1px;
265
+ background-color: @table-background-color;
266
+ padding: 0;
267
+ }
268
+
269
+ .np-text-body-default-bold {
270
+ display: flex;
271
+ align-items: center;
272
+ color: var(--color-content-primary);
273
+ white-space: nowrap;
274
+ }
275
+
276
+ .np-table-content--success {
277
+ color: var(--color-sentiment-positive);
278
+ }
279
+
280
+ .np-table-content--error {
281
+ color: var(--color-sentiment-negative);
282
+ }
283
+
284
+ .tw-loader {
285
+ // The loading area of the table should equals to 5 rows of the table for huge screens and 3 rows for small screens
286
+ margin: 150px auto;
287
+ @media (--screen-400-zoom) {
288
+ margin-top: 70px;
289
+ margin-bottom: 70px;
290
+ }
291
+ }
292
+ }
293
+
294
+ &-content {
295
+ gap: @table-spacing-lg;
296
+
297
+ &--success,
298
+ &--error {
299
+ gap: @table-spacing-sm;
300
+
301
+ .np-table-content-text {
302
+ line-height: 155%;
303
+ }
304
+ }
305
+
306
+ &-media {
307
+ flex-shrink: 0;
308
+ }
309
+
310
+ &-body {
311
+ display: flex;
312
+ flex-direction: column;
313
+ font-size: var(--font-size-12);
314
+ color: var(--color-content-tertiary);
315
+ }
316
+
317
+ &--reversed {
318
+ flex-direction: row-reverse;
319
+
320
+ .np-table-content-body {
321
+ align-items: end;
322
+ }
323
+ }
324
+ }
325
+
326
+ &-empty-data {
327
+ display: flex;
328
+ align-items: center;
329
+
330
+ .status-circle {
331
+ margin-right: @table-spacing-lg;
332
+ }
333
+ }
334
+ }
@@ -0,0 +1,24 @@
1
+ import { defineMessages } from 'react-intl';
2
+
3
+ export default defineMessages({
4
+ loading: {
5
+ id: 'neptune.Table.loading',
6
+ defaultMessage: 'Table data is loading',
7
+ },
8
+ loaded: {
9
+ id: 'neptune.Table.loaded',
10
+ defaultMessage: 'Table data has loaded',
11
+ },
12
+ emptyData: {
13
+ id: 'neptune.Table.emptyData',
14
+ defaultMessage: 'No results found',
15
+ },
16
+ refreshPage: {
17
+ id: 'neptune.Table.refreshPage',
18
+ defaultMessage: 'Refresh page',
19
+ },
20
+ actionHeader: {
21
+ id: 'neptune.Table.actionHeader',
22
+ defaultMessage: 'Action',
23
+ },
24
+ });
@@ -0,0 +1,82 @@
1
+ import React from 'react';
2
+ import { render, screen, mockMatchMedia } from '../test-utils';
3
+ import { userEvent } from '@testing-library/user-event';
4
+ import '@testing-library/jest-dom';
5
+ import Table, { TableProps } from './Table';
6
+
7
+ mockMatchMedia();
8
+
9
+ describe('Table Component', () => {
10
+ const defaultProps: TableProps = {
11
+ data: {
12
+ headers: [{ header: 'Header 1' }, { header: 'Header 2' }],
13
+ rows: [
14
+ {
15
+ cells: [
16
+ { cell: { type: 'text', text: 'Cell content 1' } },
17
+ { cell: { type: 'text', text: 'Cell content 2' } },
18
+ ],
19
+ },
20
+ {
21
+ cells: [
22
+ { cell: { type: 'text', text: 'Cell content 3' } },
23
+ { cell: { type: 'text', text: 'Cell content 4' } },
24
+ ],
25
+ },
26
+ ],
27
+ onRowClick: jest.fn(),
28
+ },
29
+ loading: false,
30
+ className: '',
31
+ fullWidth: true,
32
+ error: undefined,
33
+ };
34
+
35
+ it('renders table', () => {
36
+ render(<Table {...defaultProps} />);
37
+ expect(screen.getByText('Header 1')).toBeInTheDocument();
38
+ expect(screen.getByText('Header 2')).toBeInTheDocument();
39
+ expect(screen.getByText('Cell content 1')).toBeInTheDocument();
40
+ expect(screen.getByText('Cell content 2')).toBeInTheDocument();
41
+ expect(screen.getByText('Cell content 3')).toBeInTheDocument();
42
+ expect(screen.getByText('Cell content 4')).toBeInTheDocument();
43
+ });
44
+
45
+ it('renders `loading` state on loading', () => {
46
+ render(<Table {...defaultProps} loading />);
47
+ expect(screen.getAllByTestId('np-table-loader')).toHaveLength(1);
48
+ });
49
+
50
+ it('renders `empty data` message for empty table`s data', () => {
51
+ render(<Table {...defaultProps} data={{ headers: [], rows: [] }} />);
52
+ expect(screen.getAllByTestId('np-table-empty-data')).toHaveLength(1);
53
+ });
54
+
55
+ it('renders `error` message if `error` is passed', () => {
56
+ const errorProps: TableProps = {
57
+ ...defaultProps,
58
+ error: { message: 'Error occurred', action: { text: 'Retry' } },
59
+ };
60
+ render(<Table {...errorProps} />);
61
+ expect(screen.getByText('Error occurred')).toBeInTheDocument();
62
+ expect(screen.getByText('Retry')).toBeInTheDocument();
63
+ });
64
+
65
+ it('renders with custom class name', () => {
66
+ render(<Table {...defaultProps} className="custom-class" />);
67
+ expect(screen.getByTestId('np-table-outer-container')).toHaveClass('custom-class');
68
+ });
69
+
70
+ it('renders with `fullWidth` set to false', () => {
71
+ render(<Table {...defaultProps} fullWidth={false} />);
72
+ expect(screen.getByTestId('np-table-outer-container')).toHaveClass(
73
+ 'np-table-outer-container--center',
74
+ );
75
+ });
76
+
77
+ it('calls `onRowClick` when a row is clicked', async () => {
78
+ render(<Table {...defaultProps} />);
79
+ await userEvent.click(screen.getByText('Cell content 1'));
80
+ expect(defaultProps.data.onRowClick).toHaveBeenCalled();
81
+ });
82
+ });