@transferwise/components 0.0.0-experimental-688d30c → 0.0.0-experimental-aeb1e07

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 (45) 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 +292 -0
  7. package/build/styles/main.css +292 -0
  8. package/build/styles/table/Table.css +292 -0
  9. package/build/types/table/Table.d.ts +23 -0
  10. package/build/types/table/Table.d.ts.map +1 -0
  11. package/build/types/table/Table.messages.d.ts +24 -0
  12. package/build/types/table/Table.messages.d.ts.map +1 -0
  13. package/build/types/table/TableCell.d.ts +44 -0
  14. package/build/types/table/TableCell.d.ts.map +1 -0
  15. package/build/types/table/TableHeader.d.ts +13 -0
  16. package/build/types/table/TableHeader.d.ts.map +1 -0
  17. package/build/types/table/TableRow.d.ts +17 -0
  18. package/build/types/table/TableRow.d.ts.map +1 -0
  19. package/build/types/table/TableStatusText.d.ts +9 -0
  20. package/build/types/table/TableStatusText.d.ts.map +1 -0
  21. package/build/types/table/index.d.ts +6 -0
  22. package/build/types/table/index.d.ts.map +1 -0
  23. package/build/types/test-utils/index.d.ts +10 -0
  24. package/build/types/test-utils/index.d.ts.map +1 -1
  25. package/package.json +3 -3
  26. package/src/avatarView/AvatarView.story.tsx +1 -1
  27. package/src/avatarWrapper/AvatarWrapper.story.tsx +1 -1
  28. package/src/i18n/en.json +5 -0
  29. package/src/main.css +292 -0
  30. package/src/main.less +1 -0
  31. package/src/table/Table.css +292 -0
  32. package/src/table/Table.less +347 -0
  33. package/src/table/Table.messages.ts +24 -0
  34. package/src/table/Table.spec.tsx +82 -0
  35. package/src/table/Table.story.tsx +359 -0
  36. package/src/table/Table.tsx +166 -0
  37. package/src/table/TableCell.spec.tsx +298 -0
  38. package/src/table/TableCell.tsx +170 -0
  39. package/src/table/TableHeader.spec.tsx +50 -0
  40. package/src/table/TableHeader.tsx +75 -0
  41. package/src/table/TableRow.spec.tsx +112 -0
  42. package/src/table/TableRow.tsx +70 -0
  43. package/src/table/TableStatusText.spec.tsx +53 -0
  44. package/src/table/TableStatusText.tsx +36 -0
  45. package/src/table/index.ts +11 -0
@@ -0,0 +1,347 @@
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
+ .np-table-text-secondary {
189
+ color: var(--color-content-tertiary);
190
+ font-size: var(--font-size-12);
191
+ font-style: normal;
192
+ font-weight: var(--font-weight-regular);
193
+ line-height: var(--line-height-18);
194
+ }
195
+ }
196
+
197
+ &-header.np-table-header--right,
198
+ &-cell.np-table-cell--right {
199
+ > .np-text-body-default {
200
+ text-align: right;
201
+ }
202
+ }
203
+
204
+ &-header.np-table-header--right + .np-table-header:not(.np-table-header--right),
205
+ &-cell.np-table-cell--right + .np-table-cell:not(.np-table-cell--right) {
206
+ padding-left: calc(@table-spacing-md + @table-spacing-lg);
207
+ }
208
+
209
+ &-header.np-table-header--right .np-table-header-content,
210
+ &-cell.np-table-cell--right .np-table-content {
211
+ justify-content: end;
212
+ }
213
+
214
+ &-header-content,
215
+ &-content {
216
+ display: flex;
217
+ align-items: center;
218
+ justify-content: start;
219
+ }
220
+
221
+ &-header {
222
+ min-width: @header-min-width;
223
+ padding-right: @table-spacing-md;
224
+ padding-bottom: @table-spacing-md;
225
+ padding-left: @table-spacing-md;
226
+ background-color: var(--color-background-neutral);
227
+ color: var(--color-interactive-primary);
228
+
229
+ &-content {
230
+ padding-top: 5px;
231
+ padding-bottom: 5px;
232
+ white-space: nowrap;
233
+ line-height: var(--line-height-22);
234
+ letter-spacing: var(--letter-spacing-sm);
235
+ }
236
+
237
+ &--error {
238
+ color: var(--color-sentiment-negative);
239
+ }
240
+
241
+ &--action {
242
+ min-width: 0;
243
+ padding: 0;
244
+ }
245
+ }
246
+
247
+ &-cell {
248
+ padding: @table-spacing-xl @table-spacing-md;
249
+ position: relative;
250
+
251
+ &--cosmetic {
252
+ padding: 0;
253
+ }
254
+
255
+ &--primary {
256
+ min-width: 200px;
257
+ }
258
+
259
+ &--currency {
260
+ .np-text-body-default {
261
+ white-space: nowrap;
262
+ }
263
+ }
264
+
265
+ .tw-chevron {
266
+ margin-left: @table-spacing-md;
267
+ }
268
+
269
+ &-separator {
270
+ margin-top: @table-spacing-sm;
271
+ margin-bottom: @table-spacing-sm;
272
+ height: 1px;
273
+ background-color: @table-background-color;
274
+ padding: 0;
275
+ }
276
+
277
+ .np-text-body-default {
278
+ line-height: var(--line-height-22);
279
+ letter-spacing: var(--letter-spacing-xs);
280
+ }
281
+
282
+ .np-text-body-default-bold {
283
+ display: flex;
284
+ align-items: center;
285
+ color: var(--color-content-primary);
286
+ white-space: nowrap;
287
+ }
288
+
289
+ .np-table-content--success {
290
+ color: var(--color-sentiment-positive);
291
+ }
292
+
293
+ .np-table-content--error {
294
+ color: var(--color-sentiment-negative);
295
+ }
296
+
297
+ .tw-loader {
298
+ // The loading area of the table should equals to 5 rows of the table for huge screens and 3 rows for small screens
299
+ margin: 150px auto;
300
+ @media (--screen-400-zoom) {
301
+ margin-top: 70px;
302
+ margin-bottom: 70px;
303
+ }
304
+ }
305
+ }
306
+
307
+ &-content {
308
+ gap: @table-spacing-lg;
309
+
310
+ &--success,
311
+ &--error {
312
+ gap: @table-spacing-sm;
313
+
314
+ .np-table-content-text {
315
+ line-height: 155%;
316
+ }
317
+ }
318
+
319
+ &-media {
320
+ flex-shrink: 0;
321
+ }
322
+
323
+ &-body {
324
+ display: flex;
325
+ flex-direction: column;
326
+ font-size: var(--font-size-12);
327
+ color: var(--color-content-tertiary);
328
+ }
329
+
330
+ &--reversed {
331
+ flex-direction: row-reverse;
332
+
333
+ .np-table-content-body {
334
+ align-items: end;
335
+ }
336
+ }
337
+ }
338
+
339
+ &-empty-data {
340
+ display: flex;
341
+ align-items: center;
342
+
343
+ .status-circle {
344
+ margin-right: @table-spacing-lg;
345
+ }
346
+ }
347
+ }
@@ -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
+ });