@transferwise/components 0.0.0-experimental-dd50468 → 0.0.0-experimental-e77309f

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/alert/Alert.js +52 -49
  2. package/build/alert/Alert.js.map +1 -1
  3. package/build/alert/Alert.mjs +53 -50
  4. package/build/alert/Alert.mjs.map +1 -1
  5. package/build/i18n/en.json +0 -2
  6. package/build/i18n/en.json.js +0 -2
  7. package/build/i18n/en.json.js.map +1 -1
  8. package/build/i18n/en.json.mjs +0 -2
  9. package/build/i18n/en.json.mjs.map +1 -1
  10. package/build/main.css +0 -214
  11. package/build/styles/main.css +0 -214
  12. package/build/types/alert/Alert.d.ts +3 -1
  13. package/build/types/alert/Alert.d.ts.map +1 -1
  14. package/package.json +3 -3
  15. package/src/alert/Alert.spec.tsx +20 -0
  16. package/src/alert/Alert.story.tsx +50 -2
  17. package/src/alert/Alert.tsx +57 -50
  18. package/src/i18n/en.json +0 -2
  19. package/src/main.css +0 -214
  20. package/src/main.less +0 -1
  21. package/build/styles/table/Table.css +0 -214
  22. package/build/types/table/Table.d.ts +0 -23
  23. package/build/types/table/Table.d.ts.map +0 -1
  24. package/build/types/table/Table.messages.d.ts +0 -12
  25. package/build/types/table/Table.messages.d.ts.map +0 -1
  26. package/build/types/table/TableCell.d.ts +0 -37
  27. package/build/types/table/TableCell.d.ts.map +0 -1
  28. package/build/types/table/TableHeader.d.ts +0 -12
  29. package/build/types/table/TableHeader.d.ts.map +0 -1
  30. package/build/types/table/TableRow.d.ts +0 -17
  31. package/build/types/table/TableRow.d.ts.map +0 -1
  32. package/build/types/table/TableStatusText.d.ts +0 -9
  33. package/build/types/table/TableStatusText.d.ts.map +0 -1
  34. package/build/types/table/index.d.ts +0 -6
  35. package/build/types/table/index.d.ts.map +0 -1
  36. package/src/table/Table.css +0 -214
  37. package/src/table/Table.less +0 -253
  38. package/src/table/Table.messages.ts +0 -12
  39. package/src/table/Table.spec.tsx +0 -80
  40. package/src/table/Table.story.tsx +0 -352
  41. package/src/table/Table.tsx +0 -121
  42. package/src/table/TableCell.spec.tsx +0 -161
  43. package/src/table/TableCell.tsx +0 -143
  44. package/src/table/TableHeader.spec.tsx +0 -58
  45. package/src/table/TableHeader.tsx +0 -50
  46. package/src/table/TableRow.spec.tsx +0 -69
  47. package/src/table/TableRow.tsx +0 -62
  48. package/src/table/TableStatusText.spec.tsx +0 -42
  49. package/src/table/TableStatusText.tsx +0 -35
  50. package/src/table/index.ts +0 -11
@@ -1,143 +0,0 @@
1
- import TableStatusText from './TableStatusText';
2
- import Avatar, { AvatarType } from '../avatar';
3
- import StatusIcon from '../statusIcon';
4
- import { Flag } from '@wise/art';
5
- import Body from '../body';
6
- import { formatMoney } from '@transferwise/formatting';
7
- import { useIntl } from 'react-intl';
8
- import React from 'react';
9
- import { clsx } from 'clsx';
10
-
11
- // `Leading` and `Status` cells' types have 2 text fields: primary and secondary
12
- interface TextPropsType {
13
- primaryText?: string;
14
- secondaryText?: string;
15
- }
16
-
17
- // `Leading`, `Text` and `Status` cells' types can have a status indicator with `error` or `success` values
18
- interface StatusPropsType {
19
- status?: 'error' | 'success';
20
- }
21
-
22
- // TODO: Instead of initials it should be an avatar, change implementation
23
- export interface LeadingContentType extends TextPropsType, StatusPropsType {
24
- initials?: string;
25
- }
26
-
27
- export interface TextContentType extends StatusPropsType {
28
- text?: string;
29
- }
30
-
31
- interface CurrencyType {
32
- value: string | number;
33
- currency: string;
34
- }
35
-
36
- export interface CurrencyContentType extends StatusPropsType {
37
- primaryCurrency?: CurrencyType;
38
- secondaryCurrency?: CurrencyType;
39
- }
40
-
41
- export interface StatusContentType extends TextPropsType {
42
- sentiment?: 'negative' | 'neutral' | 'positive' | 'warning' | 'pending';
43
- }
44
-
45
- export interface TableCellProps {
46
- type?: 'leading' | 'text' | 'currency' | 'status';
47
- content?: LeadingContentType & TextContentType & CurrencyContentType & StatusContentType;
48
- alignment?: 'right' | 'left';
49
- className?: string;
50
- colSpan?: number;
51
- hasSeparator?: boolean;
52
- children?: React.ReactNode;
53
- }
54
-
55
- const TableCell = ({
56
- type = 'text',
57
- content,
58
- alignment,
59
- className,
60
- colSpan,
61
- hasSeparator,
62
- children,
63
- }: TableCellProps) => {
64
- const { locale } = useIntl();
65
-
66
- const getContentMedia = () => {
67
- if (type === 'leading') {
68
- return (
69
- content?.initials && (
70
- <Avatar size={40} type={AvatarType.INITIALS}>
71
- {content?.initials}
72
- </Avatar>
73
- )
74
- );
75
- }
76
-
77
- if (type === 'currency') {
78
- return (
79
- content?.primaryCurrency?.currency && (
80
- <Flag code={content?.primaryCurrency?.currency?.toLowerCase()} intrinsicSize={24} />
81
- )
82
- );
83
- }
84
-
85
- if (type === 'status') {
86
- return content?.sentiment && <StatusIcon size="md" sentiment={content?.sentiment} />;
87
- }
88
- };
89
-
90
- const formatCurrencyValue = (currency?: CurrencyType) => {
91
- if (currency) {
92
- return formatMoney(Number(currency.value), currency.currency, locale, {
93
- alwaysShowDecimals: true,
94
- });
95
- }
96
-
97
- return '';
98
- };
99
-
100
- return (
101
- <td
102
- className={clsx('np-table-cell', `np-table-cell--${type}`, className, {
103
- 'np-table-cell--right': alignment === 'right',
104
- })}
105
- colSpan={colSpan}
106
- >
107
- {type === 'text' && content?.text && (
108
- <TableStatusText text={content?.text} status={content?.status} />
109
- )}
110
- {['leading', 'currency', 'status'].includes(type) && (
111
- <div
112
- className={clsx('np-table-content', {
113
- 'np-table-content--reversed': type === 'currency',
114
- })}
115
- >
116
- <div className="np-table-content-media">{getContentMedia()}</div>
117
- <div className="np-table-content-body">
118
- <TableStatusText
119
- text={
120
- type === 'currency'
121
- ? formatCurrencyValue(content?.primaryCurrency)
122
- : (content?.primaryText ?? '')
123
- }
124
- status={type !== 'status' ? content?.status : undefined}
125
- typography="large-bold"
126
- />
127
- <Body>
128
- {type === 'currency'
129
- ? formatCurrencyValue(content?.secondaryCurrency)
130
- : content?.secondaryText}
131
- </Body>
132
- </div>
133
- </div>
134
- )}
135
- {hasSeparator && (
136
- <div className="np-table-cell-separator" data-testid="np-table-cell-separator" />
137
- )}
138
- {children}
139
- </td>
140
- );
141
- };
142
-
143
- export default TableCell;
@@ -1,58 +0,0 @@
1
- import { render, screen } from '@testing-library/react';
2
- import TableHeader, { TableHeaderProps } from './TableHeader';
3
-
4
- describe('TableHeader Component', () => {
5
- const renderComponent = (props: Partial<TableHeaderProps> = {}) => {
6
- const defaultProps = {
7
- header: '',
8
- className: '',
9
- alignment: 'left',
10
- hasError: false,
11
- } satisfies TableHeaderProps;
12
- return render(<TableHeader {...defaultProps} {...props} />);
13
- };
14
-
15
- it('should render without crashing', () => {
16
- const { container } = renderComponent();
17
- expect(container).toBeInTheDocument();
18
- });
19
-
20
- it('should render header text when provided', () => {
21
- const headerText = 'Test Header';
22
- renderComponent({ header: headerText });
23
- expect(screen.getByText(headerText)).toBeInTheDocument();
24
- });
25
-
26
- it('should apply custom className', () => {
27
- const className = 'custom-class';
28
- renderComponent({ className });
29
- expect(screen.getByRole('columnheader')).toHaveClass(className);
30
- });
31
-
32
- it('should align text to the right when alignment is set to right', () => {
33
- renderComponent({ alignment: 'right' });
34
- expect(screen.getByRole('columnheader')).toHaveClass('np-table-header--right');
35
- });
36
-
37
- it('should show error class when hasError is passed', () => {
38
- renderComponent({ hasError: true });
39
- expect(screen.getByRole('columnheader')).toHaveClass('np-table-header--has-error');
40
- });
41
-
42
- it('should render empty header content when header is not provided', () => {
43
- renderComponent();
44
- expect(screen.getByTestId('np-table-empty-header').innerHTML).toBe('&nbsp;');
45
- });
46
-
47
- it('should render with colSpan of 2 when hasActionColumn is passed', () => {
48
- renderComponent({ hasActionColumn: true });
49
- expect(screen.getByRole('columnheader')).toHaveAttribute('colSpan', '2');
50
- });
51
-
52
- it('should render TableStatusText with error status when hasError is passed', () => {
53
- const headerText = 'Test Header';
54
- renderComponent({ header: headerText, hasError: true });
55
- expect(screen.getByText(headerText)).toHaveClass('np-table-content--error');
56
- expect(screen.getByTestId('alert-icon')).toBeInTheDocument();
57
- });
58
- });
@@ -1,50 +0,0 @@
1
- import TableStatusText from './TableStatusText';
2
- import { clsx } from 'clsx';
3
-
4
- // TODO: Add `width` prop in next iterations
5
- export interface TableHeaderType {
6
- header?: string;
7
- className?: string;
8
- alignment?: 'right' | 'left';
9
- hasError?: boolean;
10
- }
11
-
12
- export interface TableHeaderProps extends TableHeaderType {
13
- hasActionColumn?: boolean;
14
- }
15
-
16
- const TableHeader: React.FC<TableHeaderProps> = ({
17
- header,
18
- className,
19
- alignment = 'left',
20
- hasError = false,
21
- hasActionColumn = false,
22
- }: TableHeaderProps) => {
23
- return (
24
- <th
25
- className={clsx('np-table-header', className, {
26
- 'np-table-header--right': alignment === 'right',
27
- 'np-table-header--has-error': hasError,
28
- })}
29
- colSpan={hasActionColumn ? 2 : undefined}
30
- >
31
- {header ? (
32
- <TableStatusText
33
- text={header}
34
- className="np-table-header-content"
35
- status={hasError ? 'error' : undefined}
36
- typography="large-bold"
37
- />
38
- ) : (
39
- <div
40
- className="np-table-header-content np-text-body-large-bold"
41
- data-testid="np-table-empty-header"
42
- >
43
- &nbsp;
44
- </div>
45
- )}
46
- </th>
47
- );
48
- };
49
-
50
- export default TableHeader;
@@ -1,69 +0,0 @@
1
- import { render, screen } from '@testing-library/react';
2
- import TableRow, { TableRowType, TableRowClickableType } from './TableRow';
3
- import { IntlProvider } from 'react-intl';
4
- import userEvent from '@testing-library/user-event';
5
-
6
- describe('TableRow Component', () => {
7
- const mockData = {
8
- rowContent: [{ content: { text: 'Cell content 1' } }, { content: { text: 'Cell content 2' } }],
9
- } satisfies TableRowType;
10
-
11
- const mockDataClickable = {
12
- id: 1,
13
- rowContent: mockData.rowContent,
14
- } satisfies TableRowClickableType;
15
-
16
- const handleClick = jest.fn();
17
-
18
- const renderWithIntl = (component: React.ReactElement) => {
19
- return render(<IntlProvider locale="en">{component}</IntlProvider>);
20
- };
21
-
22
- it('renders without crashing', () => {
23
- renderWithIntl(<TableRow />);
24
- expect(screen.getByTestId('np-table-row')).toBeInTheDocument();
25
- });
26
-
27
- it('renders children when data is not provided', () => {
28
- renderWithIntl(
29
- <TableRow>
30
- <td>Cell text</td>
31
- </TableRow>,
32
- );
33
- expect(screen.getByText('Cell text')).toBeInTheDocument();
34
- });
35
-
36
- it('renders TableCell components when data is provided', () => {
37
- renderWithIntl(<TableRow rowData={mockData} />);
38
- expect(screen.getByText('Cell content 1')).toBeInTheDocument();
39
- expect(screen.getByText('Cell content 2')).toBeInTheDocument();
40
- });
41
-
42
- it('renders a separator row when hasSeparator is passed', () => {
43
- renderWithIntl(<TableRow rowData={mockData} hasSeparator />);
44
- expect(screen.getAllByTestId('np-table-row')).toHaveLength(1);
45
- expect(screen.getAllByTestId('np-table-row--separator')).toHaveLength(1);
46
- });
47
-
48
- it('does not call onRowClick when row is not clickable', async () => {
49
- renderWithIntl(<TableRow rowData={mockData} />);
50
- await userEvent.click(screen.getByTestId('np-table-row'));
51
- expect(handleClick).not.toHaveBeenCalled();
52
- });
53
-
54
- it('applies the np-table-row--clickable class when row is clickable', () => {
55
- renderWithIntl(<TableRow rowData={mockDataClickable} onRowClick={handleClick} />);
56
- expect(screen.getAllByTestId('np-table-row')[0]).toHaveClass('np-table-row--clickable');
57
- });
58
-
59
- it('calls onRowClick when row is clicked', async () => {
60
- renderWithIntl(<TableRow rowData={mockDataClickable} onRowClick={handleClick} />);
61
- await userEvent.click(screen.getByTestId('np-table-row'));
62
- expect(handleClick).toHaveBeenCalledWith(mockDataClickable);
63
- });
64
-
65
- it('renders a chevron icon when row is clickable', () => {
66
- renderWithIntl(<TableRow rowData={mockDataClickable} onRowClick={handleClick} />);
67
- expect(screen.getByTestId('chevron-up-icon')).toBeInTheDocument();
68
- });
69
- });
@@ -1,62 +0,0 @@
1
- import React from 'react';
2
- import TableCell, { TableCellProps } from './TableCell';
3
- import Chevron from '../chevron';
4
- import { Position } from '../common';
5
- import clsx from 'clsx';
6
-
7
- export interface TableRowType {
8
- rowContent?: TableCellProps[];
9
- }
10
-
11
- export interface TableRowClickableType extends TableRowType {
12
- id: number | string; // `id` is mandatory for clickable rows
13
- }
14
-
15
- export interface TableRowProps {
16
- rowData?: TableRowType | TableRowClickableType;
17
- hasSeparator?: boolean;
18
- children?: React.ReactNode;
19
- onRowClick?: (rowData: TableRowType | TableRowClickableType) => void;
20
- }
21
-
22
- const TableRow = ({ rowData, hasSeparator = false, children, onRowClick }: TableRowProps) => {
23
- return (
24
- <>
25
- <tr
26
- className={clsx('np-table-row', { 'np-table-row--clickable': !!onRowClick })}
27
- data-testid="np-table-row"
28
- onClick={onRowClick && rowData ? () => onRowClick(rowData) : undefined}
29
- >
30
- {rowData?.rowContent
31
- ? rowData?.rowContent?.map((cellItem, index) => {
32
- return (
33
- <TableCell
34
- key={(
35
- cellItem.content?.text ?? cellItem.content?.primaryText?.toString()
36
- )?.concat(index.toString())}
37
- {...cellItem}
38
- />
39
- );
40
- })
41
- : children}
42
- {onRowClick && (
43
- <TableCell>
44
- <Chevron orientation={Position.RIGHT} />
45
- </TableCell>
46
- )}
47
- </tr>
48
- {hasSeparator && (
49
- <tr className="np-table-row np-table-row--separator" data-testid="np-table-row--separator">
50
- <TableCell
51
- hasSeparator
52
- colSpan={
53
- onRowClick ? Number(rowData?.rowContent?.length) + 1 : rowData?.rowContent?.length
54
- }
55
- />
56
- </tr>
57
- )}
58
- </>
59
- );
60
- };
61
-
62
- export default TableRow;
@@ -1,42 +0,0 @@
1
- import { render, screen } from '@testing-library/react';
2
- import TableStatusText, { TableStatusTextProps } from './TableStatusText';
3
-
4
- describe('TableStatusText Component', () => {
5
- const renderComponent = (props: Partial<TableStatusTextProps> = {}) => {
6
- const defaultProps: TableStatusTextProps = {
7
- text: 'Status Text',
8
- ...props,
9
- };
10
- return render(<TableStatusText {...defaultProps} />);
11
- };
12
-
13
- it('applies the custom class name', () => {
14
- renderComponent({ className: 'custom-class' });
15
- expect(screen.getByText('Status Text')).toHaveClass('custom-class');
16
- });
17
-
18
- it('renders the text and applies the default class', () => {
19
- renderComponent();
20
- expect(screen.getByText('Status Text')).toBeInTheDocument();
21
- expect(screen.getByText('Status Text')).toHaveClass('np-text-body-default');
22
- });
23
-
24
- it('applies the typography class when typography is `large-bold`', () => {
25
- renderComponent({ typography: 'large-bold' });
26
- expect(screen.getByText('Status Text')).toHaveClass('np-text-body-large-bold');
27
- });
28
-
29
- it('applies the typography and status classes, renders the success icon', () => {
30
- renderComponent({ status: 'success' });
31
- expect(screen.getByText('Status Text')).toHaveClass('np-text-body-large-bold');
32
- expect(screen.getByText('Status Text')).toHaveClass('np-table-content--success');
33
- expect(screen.getByTestId('check-icon')).toBeInTheDocument();
34
- });
35
-
36
- it('applies the typography and status classes, renders the error icon', () => {
37
- renderComponent({ status: 'error' });
38
- expect(screen.getByText('Status Text')).toHaveClass('np-text-body-large-bold');
39
- expect(screen.getByText('Status Text')).toHaveClass('np-table-content--error');
40
- expect(screen.getByTestId('alert-icon')).toBeInTheDocument();
41
- });
42
- });
@@ -1,35 +0,0 @@
1
- import { AlertCircle, CheckCircle } from '@transferwise/icons';
2
- import clsx from 'clsx';
3
-
4
- export interface TableStatusTextProps {
5
- text: string;
6
- className?: string;
7
- status?: 'success' | 'error';
8
- typography?: 'default' | 'large-bold';
9
- }
10
-
11
- const TableStatusText: React.FC<TableStatusTextProps> = ({
12
- text,
13
- status,
14
- className,
15
- typography = 'default',
16
- }: TableStatusTextProps) => {
17
- return (
18
- <div
19
- className={clsx(
20
- className,
21
- `np-text-body-${(status ?? typography === 'large-bold') ? 'large-bold' : 'default'}`,
22
- {
23
- 'np-table-content--success': status === 'success',
24
- 'np-table-content--error': status === 'error',
25
- },
26
- )}
27
- >
28
- {text}
29
- {status === 'success' && <CheckCircle className="tw-icon--status" data-testid="check-icon" />}
30
- {status === 'error' && <AlertCircle className="tw-icon--status" data-testid="alert-icon" />}
31
- </div>
32
- );
33
- };
34
-
35
- export default TableStatusText;
@@ -1,11 +0,0 @@
1
- export { default } from './Table';
2
- export type { TableProps } from './Table';
3
- export type { TableRowType, TableRowClickableType } from './TableRow';
4
- export type { TableHeaderType } from './TableHeader';
5
- export type {
6
- LeadingContentType,
7
- TextContentType,
8
- CurrencyContentType,
9
- StatusContentType,
10
- TableCellProps,
11
- } from './TableCell';