@integrigo/integrigo-ui 1.6.17-f → 1.6.17-h

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 (41) hide show
  1. package/jest.config.js +1 -1
  2. package/lib/index.esm.js +1 -1
  3. package/lib/index.esm.js.map +1 -1
  4. package/lib/index.js +1 -1
  5. package/lib/index.js.map +1 -1
  6. package/lib/src/components/atoms/Chip/Chip.stories.d.ts +5 -4
  7. package/lib/src/components/atoms/Dot/Dot.stories.d.ts +3 -3
  8. package/lib/src/components/atoms/Icon/Icon.d.ts +1 -0
  9. package/lib/src/components/atoms/Icon/Icon.stories.d.ts +2 -2
  10. package/lib/src/components/atoms/Icon/IconAddition.d.ts +5 -5
  11. package/lib/src/components/atoms/Icon/icons/Eye.d.ts +3 -0
  12. package/lib/src/components/atoms/Icon/icons/Search.d.ts +3 -0
  13. package/lib/src/components/molecules/Checkbox/Checkbox.stories.d.ts +4 -4
  14. package/lib/src/components/molecules/Input/Input.d.ts +8 -8
  15. package/lib/src/components/molecules/Input/Input.stories.d.ts +9 -9
  16. package/lib/src/components/molecules/Radio/Radio.stories.d.ts +4 -4
  17. package/lib/src/components/molecules/Switch/Switch.d.ts +1 -0
  18. package/lib/src/components/organisms/Table/Table.d.ts +12 -0
  19. package/lib/src/components/organisms/Table/Table.stories.d.ts +7 -0
  20. package/lib/src/components/organisms/Table/Table.test.d.ts +1 -0
  21. package/lib/src/components/organisms/Table/index.d.ts +1 -0
  22. package/lib/src/components/organisms/index.d.ts +1 -0
  23. package/lib/src/index.d.ts +4 -4
  24. package/package.json +7 -6
  25. package/src/components/atoms/Chip/Chip.stories.tsx +21 -20
  26. package/src/components/atoms/Icon/Icon.tsx +2 -0
  27. package/src/components/atoms/Icon/IconAddition.tsx +22 -20
  28. package/src/components/atoms/Icon/icons/Eye.tsx +9 -0
  29. package/src/components/atoms/Icon/icons/Search.tsx +9 -0
  30. package/src/components/molecules/Button/BasicButton.tsx +2 -1
  31. package/src/components/molecules/Button/Button.tsx +5 -4
  32. package/src/components/molecules/Input/Input.tsx +51 -47
  33. package/src/components/molecules/Switch/Switch.stories.tsx +3 -0
  34. package/src/components/molecules/Switch/Switch.tsx +3 -0
  35. package/src/components/organisms/Table/Table.stories.tsx +180 -0
  36. package/src/components/organisms/Table/Table.test.tsx +82 -0
  37. package/src/components/organisms/Table/Table.tsx +162 -0
  38. package/src/components/organisms/Table/__snapshots__/Table.test.tsx.snap +101 -0
  39. package/src/components/organisms/Table/index.ts +1 -0
  40. package/src/components/organisms/index.ts +3 -2
  41. package/src/index.ts +4 -4
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+
3
+ const Search: React.FCS = (props) => (
4
+ <svg viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg" {...props}>
5
+ <path d="M25.1375 23.3625L20.5 18.7625C22.3001 16.518 23.1719 13.6691 22.936 10.8016C22.7001 7.93413 21.3746 5.26598 19.2319 3.34581C17.0892 1.42564 14.2923 0.39939 11.4162 0.478091C8.54005 0.556791 5.8034 1.73445 3.76893 3.76893C1.73445 5.8034 0.556791 8.54005 0.478091 11.4162C0.39939 14.2923 1.42564 17.0892 3.34581 19.2319C5.26598 21.3746 7.93413 22.7001 10.8016 22.936C13.6691 23.1719 16.518 22.3001 18.7625 20.5L23.3625 25.1C23.4787 25.2172 23.617 25.3102 23.7693 25.3736C23.9216 25.4371 24.085 25.4697 24.25 25.4697C24.415 25.4697 24.5784 25.4371 24.7307 25.3736C24.883 25.3102 25.0213 25.2172 25.1375 25.1C25.3628 24.8669 25.4887 24.5554 25.4887 24.2313C25.4887 23.9071 25.3628 23.5956 25.1375 23.3625ZM11.75 20.5C10.0194 20.5 8.32769 19.9868 6.88876 19.0254C5.44983 18.0639 4.32832 16.6973 3.66606 15.0985C3.00379 13.4996 2.83051 11.7403 3.16813 10.043C3.50575 8.34563 4.33911 6.78653 5.56282 5.56282C6.78653 4.33911 8.34563 3.50575 10.043 3.16813C11.7403 2.83051 13.4996 3.00379 15.0985 3.66606C16.6973 4.32832 18.0639 5.44983 19.0254 6.88876C19.9868 8.32769 20.5 10.0194 20.5 11.75C20.5 14.0706 19.5781 16.2962 17.9372 17.9372C16.2962 19.5781 14.0706 20.5 11.75 20.5Z" fill="#595959"/>
6
+ </svg>
7
+ );
8
+
9
+ export default Search;
@@ -14,7 +14,7 @@ export const sizeVariants = {
14
14
  font: '16px',
15
15
  },
16
16
  m: {
17
- iconPadding: '28px',
17
+ iconPadding: '32px',
18
18
  padding: '10px 16px',
19
19
  ghostPadding: '20px',
20
20
  font: '12px',
@@ -65,6 +65,7 @@ export const BasicButton = styled.div<{
65
65
  padding: ${(p) => sizeVariants[p.sizeVariant].padding};
66
66
  font-weight: var(--font-bold);
67
67
  font-size: ${(p) => sizeVariants[p.sizeVariant].font};
68
+ line-height: ${(p) => sizeVariants[p.sizeVariant].font};
68
69
  cursor: pointer;
69
70
  overflow: hidden;
70
71
  position: relative;
@@ -72,7 +72,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
72
72
  {...props}
73
73
  >
74
74
  {direction !== 'rtl' && (
75
- <IconOffset size={size} ghost={Boolean(props.ghost)}>
75
+ // <IconOffset size={size} ghost={Boolean(props.ghost)}>
76
76
  <IconAddition
77
77
  icon={icon}
78
78
  size={size}
@@ -81,7 +81,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
81
81
  direction={direction}
82
82
  onClick={onIconClick}
83
83
  />
84
- </IconOffset>
84
+ // </IconOffset>
85
85
  )}
86
86
 
87
87
  <ButtonComponent
@@ -103,7 +103,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
103
103
  </ButtonComponent>
104
104
 
105
105
  {direction === 'rtl' && (
106
- <IconOffset size={size} ghost={Boolean(props.ghost)} right>
106
+ // <IconOffset size={size} ghost={Boolean(props.ghost)} right>
107
107
  <IconAddition
108
108
  icon={icon}
109
109
  size={size}
@@ -112,7 +112,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
112
112
  direction={direction}
113
113
  onClick={onIconClick}
114
114
  />
115
- </IconOffset>
115
+ // </IconOffset>
116
116
  )}
117
117
  </ButtonWrapper>
118
118
  );
@@ -152,6 +152,7 @@ const IconOffset = styled.div<{
152
152
  }>`
153
153
  position: absolute;
154
154
  bottom: 0;
155
+
155
156
  ${(p) =>
156
157
  p.right
157
158
  ? `right: ${p.ghost ? 0 : sizeVariant[p.size]}`
@@ -1,36 +1,36 @@
1
- import React from 'react';
2
- import styled, { css, FlattenSimpleInterpolation } from 'styled-components';
3
- import { FieldProps } from 'formik';
1
+ import React from "react";
2
+ import styled, { css, FlattenSimpleInterpolation } from "styled-components";
3
+ import { FieldProps } from "formik";
4
4
 
5
- import { getValidationTypeProps } from '../../../helpers/validation';
6
- import { ValidationType } from '../../../types/validation';
7
- import { IconAddition, IconType } from '../../atoms/Icon';
8
- import { Label } from '../../atoms/Typography/Label';
9
- import { FieldLabel, fieldSizeVariants, FieldWrapper } from '../../atoms/Field';
5
+ import { getValidationTypeProps } from "../../../helpers/validation";
6
+ import { ValidationType } from "../../../types/validation";
7
+ import { IconAddition, IconType } from "../../atoms/Icon";
8
+ import { Label } from "../../atoms/Typography/Label";
9
+ import { FieldLabel, fieldSizeVariants, FieldWrapper } from "../../atoms/Field";
10
10
 
11
11
  export type InputProps = Omit<
12
- React.InputHTMLAttributes<HTMLInputElement>,
13
- 'size'
12
+ React.InputHTMLAttributes<HTMLInputElement>,
13
+ "size"
14
14
  > &
15
- FieldProps & {
16
- label?: string;
17
- validationType?: ValidationType;
18
- icon?: IconType;
19
- size?: 'xl' | 'l' | 'm' | 's';
20
- direction?: 'ltr' | 'rtl';
21
- onIconClick?: () => void;
22
- };
15
+ FieldProps & {
16
+ label?: string;
17
+ validationType?: ValidationType;
18
+ icon?: IconType;
19
+ size?: "xl" | "l" | "m" | "s";
20
+ direction?: "ltr" | "rtl";
21
+ onIconClick?: () => void;
22
+ };
23
23
 
24
24
  const getDirectionPadding = (
25
- direction: InputProps['direction'],
26
- padding: string,
25
+ direction: InputProps["direction"],
26
+ padding: string
27
27
  ): FlattenSimpleInterpolation => {
28
28
  switch (direction) {
29
- case 'ltr':
29
+ case "ltr":
30
30
  return css`
31
31
  padding-left: ${padding};
32
32
  `;
33
- case 'rtl':
33
+ case "rtl":
34
34
  return css`
35
35
  padding-right: ${padding};
36
36
  `;
@@ -40,7 +40,7 @@ const getDirectionPadding = (
40
40
  };
41
41
 
42
42
  export const Input = React.forwardRef<HTMLInputElement, InputProps>(
43
- ({ icon, label, size = 'm', onIconClick, field, ...props }, ref) => (
43
+ ({ icon, label, size = "m", onIconClick, field, ...props }, ref) => (
44
44
  <FieldWrapper withLabel={Boolean(label)} sizeVariant={size}>
45
45
  {label && (
46
46
  <FieldLabel sizeVariant={size}>
@@ -48,34 +48,36 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
48
48
  </FieldLabel>
49
49
  )}
50
50
 
51
- {props.direction !== 'rtl' && (
52
- <IconAddition
53
- icon={icon}
54
- disabled={props.disabled}
55
- direction={props.direction}
56
- onClick={onIconClick}
57
- size={size}
58
- />
59
- )}
51
+ <InputWrapper>
52
+ {props.direction !== "rtl" && (
53
+ <IconAddition
54
+ icon={icon}
55
+ disabled={props.disabled}
56
+ direction={props.direction}
57
+ onClick={onIconClick}
58
+ size={size}
59
+ />
60
+ )}
60
61
 
61
- <InputElement ref={ref} sizeVariant={size} {...field} {...props} />
62
+ <InputElement ref={ref} sizeVariant={size} {...field} {...props} />
62
63
 
63
- {props.direction === 'rtl' && (
64
- <IconAddition
65
- icon={icon}
66
- disabled={props.disabled}
67
- direction={props.direction}
68
- onClick={onIconClick}
69
- />
70
- )}
64
+ {props.direction === "rtl" && (
65
+ <IconAddition
66
+ icon={icon}
67
+ disabled={props.disabled}
68
+ direction={props.direction}
69
+ onClick={onIconClick}
70
+ />
71
+ )}
72
+ </InputWrapper>
71
73
  </FieldWrapper>
72
- ),
74
+ )
73
75
  );
74
76
 
75
77
  const InputElement = styled.input<
76
- Pick<InputProps, 'validationType' | 'direction'> & {
77
- sizeVariant: 'xl' | 'l' | 'm' | 's';
78
- }
78
+ Pick<InputProps, "validationType" | "direction"> & {
79
+ sizeVariant: "xl" | "l" | "m" | "s";
80
+ }
79
81
  >`
80
82
  background-color: var(--color-white);
81
83
  border: 2px solid var(--shades-of-grey-80);
@@ -105,7 +107,7 @@ Pick<InputProps, 'validationType' | 'direction'> & {
105
107
  ${(p) =>
106
108
  getDirectionPadding(
107
109
  p.direction,
108
- fieldSizeVariants[p.sizeVariant].iconPadding,
110
+ fieldSizeVariants[p.sizeVariant].iconPadding
109
111
  )};
110
112
 
111
113
  &:disabled {
@@ -117,4 +119,6 @@ Pick<InputProps, 'validationType' | 'direction'> & {
117
119
  }
118
120
  `;
119
121
 
120
- Input.displayName = 'Input';
122
+ const InputWrapper = styled.div`
123
+ position: relative;
124
+ `;
@@ -11,6 +11,7 @@ const Template: ComponentStory<typeof Switch> = (args) => <Switch {...args} />;
11
11
 
12
12
  export const TwoOptions = Template.bind({});
13
13
  TwoOptions.args = {
14
+ onClick: (id) => console.log(id),
14
15
  options: [
15
16
  { id: "1", name: "One" },
16
17
  { id: "2", name: "Two" },
@@ -19,6 +20,7 @@ TwoOptions.args = {
19
20
 
20
21
  export const ThreeOptions = Template.bind({});
21
22
  ThreeOptions.args = {
23
+ onClick: (id) => console.log(id),
22
24
  options: [
23
25
  { id: "1", name: "One" },
24
26
  { id: "2", name: "Two" },
@@ -28,6 +30,7 @@ ThreeOptions.args = {
28
30
 
29
31
  export const ThreeWithDisabled = Template.bind({});
30
32
  ThreeWithDisabled.args = {
33
+ onClick: (id) => console.log(id),
31
34
  options: [
32
35
  { id: "1", name: "One" },
33
36
  { id: "2", name: "Two", disabled: true },
@@ -12,11 +12,13 @@ export interface SwitchProps {
12
12
  | [SwitchOption, SwitchOption]
13
13
  | [SwitchOption, SwitchOption, SwitchOption];
14
14
  active?: SwitchOption["id"];
15
+ onClick: (id: SwitchOption["id"]) => void;
15
16
  }
16
17
 
17
18
  export const Switch: React.FC<SwitchProps> = ({
18
19
  options,
19
20
  active: defaultActive,
21
+ onClick,
20
22
  }) => {
21
23
  const [active, setActive] = useState(defaultActive);
22
24
 
@@ -29,6 +31,7 @@ export const Switch: React.FC<SwitchProps> = ({
29
31
  }
30
32
 
31
33
  setActive(id);
34
+ onClick(id);
32
35
  };
33
36
 
34
37
  return (
@@ -0,0 +1,180 @@
1
+ import React from 'react';
2
+ import { Table } from './Table';
3
+ import { ComponentMeta, ComponentStory } from '@storybook/react';
4
+
5
+ import {
6
+ Column,
7
+ createColumnHelper,
8
+ } from '@tanstack/react-table';
9
+ import { Button, Profile } from '../../molecules';
10
+
11
+ export default {
12
+ title: 'Organisms/Table',
13
+ component: Table,
14
+ argTypes: {
15
+ variant: {
16
+ name: 'Color variant',
17
+ type: {
18
+ name: 'string',
19
+ required: false,
20
+ },
21
+ control: {
22
+ type: 'select',
23
+ },
24
+ options: ['primary', 'secondary'],
25
+ defaultValue: 'primary',
26
+ },
27
+ textAlign: {
28
+ name: 'Text alignment',
29
+ type: {
30
+ name: 'string',
31
+ required: false,
32
+ },
33
+ control: {
34
+ type: 'select',
35
+ },
36
+ options: ['left', 'right', 'center'],
37
+ defaultValue: 'center',
38
+ },
39
+ },
40
+ } as ComponentMeta<typeof Table>;
41
+
42
+ export const Primary: ComponentStory<typeof Table> = (args) => {
43
+ type Person = {
44
+ firstName: string
45
+ lastName: string
46
+ age: number
47
+ visits: number
48
+ status: string
49
+ progress: number
50
+ };
51
+
52
+ const personData: Person[] = [
53
+ {
54
+ firstName: 'tanner',
55
+ lastName: 'linsley',
56
+ age: 24,
57
+ visits: 100,
58
+ status: 'In Relationship',
59
+ progress: 50,
60
+ },
61
+ {
62
+ firstName: 'tandy',
63
+ lastName: 'miller',
64
+ age: 40,
65
+ visits: 40,
66
+ status: 'Single',
67
+ progress: 80,
68
+ },
69
+ {
70
+ firstName: 'joe',
71
+ lastName: 'dirte',
72
+ age: 45,
73
+ visits: 20,
74
+ status: 'Complicated',
75
+ progress: 10,
76
+ },
77
+ ];
78
+
79
+ const personColumnHelper = createColumnHelper<Person>();
80
+
81
+ const personColumns = [
82
+ personColumnHelper.accessor('firstName', {
83
+ cell: info => info.getValue(),
84
+ footer: info => info.column.id,
85
+ }),
86
+ personColumnHelper.accessor(row => row.lastName, {
87
+ id: 'lastName',
88
+ cell: info => info.getValue(),
89
+ header: () => 'Last Name',
90
+ footer: info => info.column.id,
91
+ }),
92
+ personColumnHelper.accessor('age', {
93
+ header: () => 'Age',
94
+ cell: info => info.renderValue(),
95
+ footer: info => info.column.id,
96
+ }),
97
+ personColumnHelper.accessor('visits', {
98
+ header: () => 'Visits',
99
+ footer: info => info.column.id,
100
+ }),
101
+ personColumnHelper.accessor('status', {
102
+ header: 'Status',
103
+ footer: info => info.column.id,
104
+ }),
105
+ personColumnHelper.accessor('progress', {
106
+ header: 'Profile Progress',
107
+ footer: info => info.column.id,
108
+ }),
109
+ ] as Column<Person>[];
110
+
111
+ return (
112
+ <Table columns={personColumns} data={personData} variant={args.variant} textAlign={args.textAlign}/>
113
+ );
114
+ };
115
+
116
+ export const WithProfile: ComponentStory<typeof Table> = (args) => {
117
+ type DataType = {
118
+ fullName: string;
119
+ points: number;
120
+ avatar: string;
121
+ email: string;
122
+ };
123
+
124
+ const data: DataType[] = [
125
+ {
126
+ fullName: 'Tanner Linsley',
127
+ points: 24,
128
+ avatar: 'https://img.freepik.com/darmowe-zdjecie/dosc-usmiechnieta-radosnie-kobieta-o-jasnych-wlosach-ubrana-swobodnie-wygladajaca-z-zadowoleniem_176420-15187.jpg?w=1380&t=st=1660198496~exp=1660199096~hmac=7401572065d2cd7bb67d9f43dbde5c116b90aad419b179fffac1196df24869f2',
129
+ email: 'abc@abc.pl',
130
+ },
131
+ {
132
+ fullName: 'Tandy Miller',
133
+ points: 80,
134
+ avatar: 'https://img.freepik.com/darmowe-zdjecie/dosc-usmiechnieta-radosnie-kobieta-o-jasnych-wlosach-ubrana-swobodnie-wygladajaca-z-zadowoleniem_176420-15187.jpg?w=1380&t=st=1660198496~exp=1660199096~hmac=7401572065d2cd7bb67d9f43dbde5c116b90aad419b179fffac1196df24869f2',
135
+ email: 'def@def.pl',
136
+ },
137
+ {
138
+ fullName: 'Joe Dirte',
139
+ points: 45,
140
+ avatar: 'https://img.freepik.com/darmowe-zdjecie/dosc-usmiechnieta-radosnie-kobieta-o-jasnych-wlosach-ubrana-swobodnie-wygladajaca-z-zadowoleniem_176420-15187.jpg?w=1380&t=st=1660198496~exp=1660199096~hmac=7401572065d2cd7bb67d9f43dbde5c116b90aad419b179fffac1196df24869f2',
141
+ email: 'ghi@ghi.pl',
142
+ },
143
+ ];
144
+
145
+ const profileColumnHelper = createColumnHelper<DataType>();
146
+
147
+ const columns = [
148
+ profileColumnHelper.accessor('fullName', {
149
+ cell: info => {
150
+ return (
151
+ <div style={{ display: 'flex', alignItems: 'center' }}>
152
+ <div style={{ flexBasis: '20px' }}>{info.row.index + 1}.</div>
153
+ <Profile
154
+ name={info.getValue()}
155
+ src={info.row.original.avatar}
156
+ >
157
+ <span>{info.row.original.email}</span>
158
+ </Profile>
159
+ </div>
160
+ );
161
+ },
162
+ header: () => 'Team member',
163
+ footer: info => info.column.id,
164
+ }),
165
+ profileColumnHelper.accessor('points', {
166
+ header: () => 'Points',
167
+ cell: info => info.renderValue(),
168
+ footer: info => info.column.id,
169
+ }),
170
+ profileColumnHelper.display({
171
+ header: 'Actions',
172
+ id: 'Actions',
173
+ cell: () => <div style={{ width: '30px' }}><Button direction={'ltr'} icon={'edit'} ghost>Edit</Button></div>,
174
+ }),
175
+ ] as Column<DataType>[];
176
+
177
+ return (
178
+ <Table columns={columns} data={data} variant={args.variant} width={'100%'} textAlign={"left"}/>
179
+ );
180
+ };
@@ -0,0 +1,82 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { Table } from './Table';
4
+ import { Column, createColumnHelper } from '@tanstack/react-table';
5
+
6
+ type Person = {
7
+ firstName: string
8
+ lastName: string
9
+ age: number
10
+ visits: number
11
+ status: string
12
+ progress: number
13
+ };
14
+
15
+ const data: Person[] = [
16
+ {
17
+ firstName: 'tanner',
18
+ lastName: 'linsley',
19
+ age: 24,
20
+ visits: 100,
21
+ status: 'In Relationship',
22
+ progress: 50,
23
+ },
24
+ {
25
+ firstName: 'tandy',
26
+ lastName: 'miller',
27
+ age: 40,
28
+ visits: 40,
29
+ status: 'Single',
30
+ progress: 80,
31
+ },
32
+ {
33
+ firstName: 'joe',
34
+ lastName: 'dirte',
35
+ age: 45,
36
+ visits: 20,
37
+ status: 'Complicated',
38
+ progress: 10,
39
+ },
40
+ ];
41
+
42
+ const columnHelper = createColumnHelper<Person>();
43
+
44
+ const columns = [
45
+ columnHelper.accessor('firstName', {
46
+ cell: info => info.getValue(),
47
+ footer: info => info.column.id,
48
+ }),
49
+ columnHelper.accessor(row => row.lastName, {
50
+ id: 'lastName',
51
+ cell: info => info.getValue(),
52
+ header: () => 'Last Name',
53
+ footer: info => info.column.id,
54
+ }),
55
+ columnHelper.accessor('age', {
56
+ header: () => 'Age',
57
+ cell: info => info.renderValue(),
58
+ footer: info => info.column.id,
59
+ }),
60
+ columnHelper.accessor('visits', {
61
+ header: () => 'Visits',
62
+ footer: info => info.column.id,
63
+ }),
64
+ columnHelper.accessor('status', {
65
+ header: 'Status',
66
+ footer: info => info.column.id,
67
+ }),
68
+ columnHelper.accessor('progress', {
69
+ header: 'Profile Progress',
70
+ footer: info => info.column.id,
71
+ }),
72
+ ] as Column<Person>[];
73
+
74
+ describe('<Table />', () => {
75
+ it('should render', () => {
76
+ render(<Table columns={columns} data={data}/>);
77
+ });
78
+ it('enabled - should match snapshot', () => {
79
+ const { container } = render(<Table columns={columns} data={data}/>);
80
+ expect(container).toMatchSnapshot();
81
+ });
82
+ });
@@ -0,0 +1,162 @@
1
+ import React from 'react';
2
+ import {
3
+ Column,
4
+ flexRender,
5
+ getCoreRowModel,
6
+ useReactTable,
7
+ } from '@tanstack/react-table';
8
+ import styled from 'styled-components';
9
+
10
+ type Variant = 'primary' | 'secondary';
11
+ type Alignment = 'left' | 'right' | 'center';
12
+
13
+ const colorVariant = {
14
+ primary: {
15
+ backgroundColor: 'var(--color-orange)',
16
+ fontColor: 'var(--color-white)',
17
+ },
18
+ secondary: {
19
+ backgroundColor: 'var(--color-navy)',
20
+ fontColor: 'var(--color-white)',
21
+ },
22
+ };
23
+
24
+ export interface Props <T extends Record<string, unknown>> extends React.TableHTMLAttributes<HTMLTableElement> {
25
+ data: T[];
26
+ columns: Column<T>[];
27
+ variant?: Variant;
28
+ textAlign?: Alignment
29
+ }
30
+
31
+ export const Table = <T extends Record<string, unknown>>({
32
+ data,
33
+ columns,
34
+ variant = 'primary',
35
+ textAlign = 'center',
36
+ ...props
37
+ }: Props<T>) => {
38
+
39
+ const table = useReactTable({
40
+ data,
41
+ columns,
42
+ getCoreRowModel: getCoreRowModel(),
43
+ });
44
+
45
+ return (
46
+ <div>
47
+ <StyledTable cellSpacing={0} {...props}>
48
+ <StyledHead variant={variant} textAlign={textAlign}>
49
+ {table.getHeaderGroups().map(headerGroup => (
50
+ <tr key={headerGroup.id}>
51
+ {headerGroup.headers.map(header => (
52
+ <th key={header.id}>
53
+ {header.isPlaceholder
54
+ ? null
55
+ : flexRender(
56
+ header.column.columnDef.header,
57
+ header.getContext(),
58
+ )}
59
+ </th>
60
+ ))}
61
+ </tr>
62
+ ))}
63
+ </StyledHead>
64
+ <StyledBody textAlign={textAlign}>
65
+ {table.getRowModel().rows.map(row => (
66
+ <tr key={row.id}>
67
+ {row.getVisibleCells().map(cell => (
68
+ <td key={cell.id}>
69
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
70
+ </td>
71
+ ))}
72
+ </tr>
73
+ ))}
74
+ </StyledBody>
75
+ </StyledTable>
76
+ </div>
77
+ );
78
+ };
79
+
80
+ const StyledTable = styled.table`
81
+
82
+ `;
83
+
84
+ StyledTable.displayName = 'StyledTable';
85
+
86
+ const StyledHead = styled.thead<{ variant: Variant, textAlign: Alignment }>`
87
+ padding: 15px 10px;
88
+ height: 54px;
89
+
90
+ & tr th {
91
+ font-weight: 700;
92
+ font-size: 16px;
93
+ line-height: 24px;
94
+ padding: 15px 10px;
95
+ color: white;
96
+ text-align: ${props => props.textAlign};
97
+ }
98
+
99
+ ${(p) => `
100
+ background-color: ${colorVariant[p.variant].backgroundColor};
101
+ color: ${colorVariant[p.variant].fontColor};
102
+
103
+ & th:first-child {
104
+ box-shadow: -10px 0px 10px 1px rgba(0, 0, 0, 0.1);
105
+ border-radius: 5px 0px 0px 0px;
106
+ }
107
+
108
+ & th:last-child {
109
+ box-shadow: 10px 0px 10px 1px rgba(0, 0, 0, 0.1);
110
+ border-radius: 0px 5px 0px 0px;
111
+ }
112
+ `}
113
+ `;
114
+
115
+ StyledHead.displayName = 'StyledHead';
116
+
117
+ const StyledBody = styled.tbody<{ textAlign: Alignment }>`
118
+ tr, td {
119
+ //height for td works like min-height. Table cells will grow when the content does not fit.
120
+ height: 52px;
121
+ }
122
+
123
+ tr td {
124
+ padding: 10px;
125
+ text-align: ${props => props.textAlign};
126
+ }
127
+
128
+ tr:nth-child(even) {
129
+ background-color: var(--shades-of-grey-0);
130
+ }
131
+
132
+ tr:nth-child(odd) {
133
+ background-color: var(--shades-of-grey-20);
134
+ }
135
+
136
+ tr:hover {
137
+ background-color: rgba(224, 154, 51, 0.2);
138
+
139
+ td {
140
+ border-top: solid 2px var(--color-orange);
141
+ border-bottom: solid 2px var(--color-orange);
142
+ }
143
+
144
+ td:first-child {
145
+ border-left: solid 2px var(--color-orange);
146
+ border-bottom: solid 2px var(--color-orange);
147
+ border-top: solid 2px var(--color-orange);
148
+ border-top-left-radius: 10px;
149
+ border-bottom-left-radius: 10px;
150
+ }
151
+
152
+ td:last-child {
153
+ border-right: solid 2px var(--color-orange);
154
+ border-bottom: solid 2px var(--color-orange);
155
+ border-top: solid 2px var(--color-orange);
156
+ border-top-right-radius: 10px;
157
+ border-bottom-right-radius: 10px;
158
+ }
159
+ }
160
+ `;
161
+
162
+ StyledBody.displayName = 'StyledBody';