@onewelcome/react-lib-components 0.1.8-alpha → 0.1.9-alpha

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.
@@ -1,6 +1,6 @@
1
1
  declare type KeyValuePair = {
2
2
  [key: string]: unknown;
3
3
  };
4
- export declare const generateID: (length?: number, stringToWeaveIn?: string | undefined) => string;
4
+ export declare const generateID: (length?: number, stringToWeaveIn?: string) => string;
5
5
  export declare const filterProps: (props: any, regexPattern: RegExp, returnFiltered?: boolean) => KeyValuePair;
6
6
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onewelcome/react-lib-components",
3
- "version": "0.1.8-alpha",
3
+ "version": "0.1.9-alpha",
4
4
  "license": "Apache-2.0",
5
5
  "author": "OneWelcome B.V.",
6
6
  "main": "dist/index.js",
@@ -49,16 +49,16 @@
49
49
  "devDependencies": {
50
50
  "@babel/core": "^7.18.0",
51
51
  "@size-limit/preset-small-lib": "^7.0.8",
52
- "@storybook/addon-a11y": "^6.5.8",
53
- "@storybook/addon-docs": "^6.5.8",
54
- "@storybook/addon-essentials": "^6.5.8",
55
- "@storybook/addon-links": "^6.5.8",
56
- "@storybook/addons": "^6.5.8",
57
- "@storybook/builder-webpack5": "^6.5.8",
58
- "@storybook/manager-webpack5": "^6.5.8",
52
+ "@storybook/addon-a11y": "^6.5.9",
53
+ "@storybook/addon-docs": "^6.5.9",
54
+ "@storybook/addon-essentials": "^6.5.9",
55
+ "@storybook/addon-links": "^6.5.9",
56
+ "@storybook/addons": "^6.5.9",
57
+ "@storybook/builder-webpack5": "^6.5.9",
58
+ "@storybook/manager-webpack5": "^6.5.9",
59
59
  "@storybook/preset-scss": "^1.0.3",
60
- "@storybook/react": "^6.5.8",
61
- "@storybook/theming": "^6.5.8",
60
+ "@storybook/react": "^6.5.9",
61
+ "@storybook/theming": "^6.5.9",
62
62
  "@testing-library/dom": "^8.13.0",
63
63
  "@testing-library/jest-dom": "^5.16.4",
64
64
  "@testing-library/react": "^12.1.5",
@@ -70,8 +70,6 @@
70
70
  "@types/mdx": "^2.0.2",
71
71
  "@types/react": "^17.0.45",
72
72
  "@types/react-dom": "^17.0.17",
73
- "@types/react-router": "^5.1.18",
74
- "@types/react-router-dom": "^5.3.3",
75
73
  "babel-loader": "^8.2.5",
76
74
  "dts-cli": "^1.5.1",
77
75
  "html-webpack-plugin": "^5.5.0",
@@ -1,3 +1,7 @@
1
+ .grid-wrapper {
2
+ padding: 1rem 0;
3
+ }
4
+
1
5
  .table-wrapper {
2
6
  overflow-x: auto;
3
7
  }
@@ -274,3 +274,148 @@ describe('ref should work', () => {
274
274
  render(<ExampleComponent propagateRef={refCheck} />);
275
275
  });
276
276
  });
277
+
278
+ describe('spacing should work correctly', () => {
279
+ it('gives the proper paddings to the right elements', () => {
280
+ const { dataGrid } = createDataGrid((defaultParams) => ({
281
+ ...defaultParams,
282
+ spacing: { padding: 4 },
283
+ paginationProps: {
284
+ totalElements: 105,
285
+ pageSize: 10,
286
+ currentPage: 2,
287
+ onPageChange: jest.fn(),
288
+ onPageSizeChange: jest.fn(),
289
+ },
290
+ }));
291
+
292
+ const firstHeaderCell = dataGrid.querySelector('.table .thead .row .header-cell');
293
+ const lastHeaderCell = dataGrid.querySelector('.table .thead .row td');
294
+ const firstBodyCell = dataGrid.querySelector('.table tbody .row .cell');
295
+ const lastBodyCell = dataGrid.querySelector('.table tbody .row td:last-of-type');
296
+ const pagination = dataGrid.querySelector('.pagination-wrapper');
297
+
298
+ expect(dataGrid).toHaveStyle({ 'padding-top': '1rem', 'padding-bottom': '1rem' });
299
+ expect(firstHeaderCell).toHaveStyle({ 'padding-left': '1rem' });
300
+ expect(lastHeaderCell).toHaveStyle({ 'padding-right': '1rem' });
301
+ expect(firstBodyCell).toHaveStyle({ 'padding-left': '1rem' });
302
+ expect(lastBodyCell).toHaveStyle({ 'padding-right': '1rem' });
303
+ expect(pagination).toHaveStyle({ 'padding-left': '1rem', 'padding-right': '1rem' });
304
+ });
305
+
306
+ it('gives the proper paddings to the right elements', () => {
307
+ const { dataGrid } = createDataGrid((defaultParams) => ({
308
+ ...defaultParams,
309
+ spacing: { padding: '4 5' },
310
+ paginationProps: {
311
+ totalElements: 105,
312
+ pageSize: 10,
313
+ currentPage: 2,
314
+ onPageChange: jest.fn(),
315
+ onPageSizeChange: jest.fn(),
316
+ },
317
+ }));
318
+
319
+ const firstHeaderCell = dataGrid.querySelector('.table .thead .row .header-cell');
320
+ const lastHeaderCell = dataGrid.querySelector('.table .thead .row td');
321
+ const firstBodyCell = dataGrid.querySelector('.table tbody .row .cell');
322
+ const lastBodyCell = dataGrid.querySelector('.table tbody .row td:last-of-type');
323
+ const pagination = dataGrid.querySelector('.pagination-wrapper');
324
+
325
+ expect(dataGrid).toHaveStyle({ 'padding-top': '1rem', 'padding-bottom': '1rem' });
326
+ expect(firstHeaderCell).toHaveStyle({ 'padding-left': '1.25rem' });
327
+ expect(lastHeaderCell).toHaveStyle({ 'padding-right': '1.25rem' });
328
+ expect(firstBodyCell).toHaveStyle({ 'padding-left': '1.25rem' });
329
+ expect(lastBodyCell).toHaveStyle({ 'padding-right': '1.25rem' });
330
+ expect(pagination).toHaveStyle({ 'padding-left': '1.25rem', 'padding-right': '1.25rem' });
331
+ });
332
+
333
+ it('gives the proper paddings to the right elements', () => {
334
+ const { dataGrid } = createDataGrid((defaultParams) => ({
335
+ ...defaultParams,
336
+ spacing: { padding: '4 5 8' },
337
+ paginationProps: {
338
+ totalElements: 105,
339
+ pageSize: 10,
340
+ currentPage: 2,
341
+ onPageChange: jest.fn(),
342
+ onPageSizeChange: jest.fn(),
343
+ },
344
+ }));
345
+
346
+ const firstHeaderCell = dataGrid.querySelector('.table .thead .row .header-cell');
347
+ const lastHeaderCell = dataGrid.querySelector('.table .thead .row td');
348
+ const firstBodyCell = dataGrid.querySelector('.table tbody .row .cell');
349
+ const lastBodyCell = dataGrid.querySelector('.table tbody .row td:last-of-type');
350
+ const pagination = dataGrid.querySelector('.pagination-wrapper');
351
+
352
+ expect(dataGrid).toHaveStyle({ 'padding-top': '1rem', 'padding-bottom': '2rem' });
353
+ expect(firstHeaderCell).toHaveStyle({ 'padding-left': '1.25rem' });
354
+ expect(lastHeaderCell).toHaveStyle({ 'padding-right': '1.25rem' });
355
+ expect(firstBodyCell).toHaveStyle({ 'padding-left': '1.25rem' });
356
+ expect(lastBodyCell).toHaveStyle({ 'padding-right': '1.25rem' });
357
+ expect(pagination).toHaveStyle({ 'padding-left': '1.25rem', 'padding-right': '1.25rem' });
358
+ });
359
+
360
+ it('gives the proper paddings to the right elements', () => {
361
+ const { dataGrid } = createDataGrid((defaultParams) => ({
362
+ ...defaultParams,
363
+ spacing: { padding: '6 4 8 8' },
364
+ paginationProps: {
365
+ totalElements: 105,
366
+ pageSize: 10,
367
+ currentPage: 2,
368
+ onPageChange: jest.fn(),
369
+ onPageSizeChange: jest.fn(),
370
+ },
371
+ }));
372
+
373
+ const firstHeaderCell = dataGrid.querySelector('.table .thead .row .header-cell');
374
+ const lastHeaderCell = dataGrid.querySelector('.table .thead .row td');
375
+ const firstBodyCell = dataGrid.querySelector('.table tbody .row .cell');
376
+ const lastBodyCell = dataGrid.querySelector('.table tbody .row td:last-of-type');
377
+ const pagination = dataGrid.querySelector('.pagination-wrapper');
378
+
379
+ expect(dataGrid).toHaveStyle({ 'padding-top': '1.5rem', 'padding-bottom': '2rem' });
380
+ expect(firstHeaderCell).toHaveStyle({ 'padding-left': '2rem' });
381
+ expect(lastHeaderCell).toHaveStyle({ 'padding-right': '1rem' });
382
+ expect(firstBodyCell).toHaveStyle({ 'padding-left': '2rem' });
383
+ expect(lastBodyCell).toHaveStyle({ 'padding-right': '1rem' });
384
+ expect(pagination).toHaveStyle({ 'padding-left': '2rem', 'padding-right': '1rem' });
385
+ });
386
+
387
+ it('gives the proper paddings to the right elements, also with contextmenu disabled', () => {
388
+ const { dataGrid } = createDataGrid((defaultParams) => ({
389
+ ...defaultParams,
390
+ spacing: { padding: '6 4 8 8' },
391
+ disableContextMenuColumn: true,
392
+ paginationProps: {
393
+ totalElements: 105,
394
+ pageSize: 10,
395
+ currentPage: 2,
396
+ onPageChange: jest.fn(),
397
+ onPageSizeChange: jest.fn(),
398
+ },
399
+ children: ({ item }) => (
400
+ <DataGridRow key={item.firstName}>
401
+ <DataGridCell>{item.firstName}</DataGridCell>
402
+ <DataGridCell>{item.lastName}</DataGridCell>
403
+ <DataGridCell>{item.date}</DataGridCell>
404
+ </DataGridRow>
405
+ ),
406
+ }));
407
+
408
+ const firstHeaderCell = dataGrid.querySelector('.table .thead .row .header-cell');
409
+ const lastHeaderCell = dataGrid.querySelector('.table .thead .row th:last-of-type');
410
+ const firstBodyCell = dataGrid.querySelector('.table tbody .row .cell');
411
+ const lastBodyCell = dataGrid.querySelector('.table tbody .row td:last-of-type');
412
+ const pagination = dataGrid.querySelector('.pagination-wrapper');
413
+
414
+ expect(dataGrid).toHaveStyle({ 'padding-top': '1.5rem', 'padding-bottom': '2rem' });
415
+ expect(firstHeaderCell).toHaveStyle({ 'padding-left': '2rem' });
416
+ expect(lastHeaderCell).toHaveStyle({ 'padding-right': '1rem' });
417
+ expect(firstBodyCell).toHaveStyle({ 'padding-left': '2rem' });
418
+ expect(lastBodyCell).toHaveStyle({ 'padding-right': '1rem' });
419
+ expect(pagination).toHaveStyle({ 'padding-left': '2rem', 'padding-right': '1rem' });
420
+ });
421
+ });
@@ -6,6 +6,7 @@ import { DataGridActions } from './DataGridActions/DataGridActions';
6
6
  import { DataGridBody } from './DataGridBody/DataGridBody';
7
7
  import { ColumnName, HeaderCell, OnSortFunction, Sort } from './datagrid.interfaces';
8
8
  import { Pagination, Props as PaginationProps } from '../Pagination/Pagination';
9
+ import { Spacing, useSpacing } from '../hooks/useSpacing';
9
10
 
10
11
  export interface Props<T> extends ComponentPropsWithRef<'div'> {
11
12
  children: ({ item, index }: { item: T; index: number }) => ReactElement;
@@ -26,6 +27,7 @@ export interface Props<T> extends ComponentPropsWithRef<'div'> {
26
27
  disableContextMenuColumn?: boolean;
27
28
  isLoading?: boolean;
28
29
  enableMultiSorting?: boolean;
30
+ spacing?: Spacing;
29
31
  }
30
32
 
31
33
  const DataGridInner = <T extends {}>(
@@ -41,6 +43,8 @@ const DataGridInner = <T extends {}>(
41
43
  isLoading,
42
44
  enableMultiSorting,
43
45
  emptyLabel,
46
+ spacing,
47
+ style,
44
48
  ...rest
45
49
  }: Props<T>,
46
50
  ref: Ref<HTMLDivElement>
@@ -53,6 +57,7 @@ const DataGridInner = <T extends {}>(
53
57
  }
54
58
 
55
59
  const [internalHeaders, setInternalHeaders] = useState(headers);
60
+ const styleWithSpacing = useSpacing(spacing, style);
56
61
 
57
62
  useEffect(() => setInternalHeaders(headers), [headers]);
58
63
 
@@ -64,9 +69,53 @@ const DataGridInner = <T extends {}>(
64
69
  );
65
70
  };
66
71
 
72
+ if (styleWithSpacing?.padding) {
73
+ const splitPaddings = styleWithSpacing.padding.toString().split(' ');
74
+
75
+ let paddingLeftIndex: number = 0;
76
+
77
+ if (splitPaddings.length >= 2) {
78
+ paddingLeftIndex = 1;
79
+ }
80
+ if (splitPaddings.length === 4) {
81
+ paddingLeftIndex = 3;
82
+ }
83
+
84
+ Object.defineProperties(styleWithSpacing, {
85
+ paddingTop: {
86
+ value: splitPaddings[0],
87
+ },
88
+ paddingRight: {
89
+ value: splitPaddings[splitPaddings.length - 1 > 0 ? 1 : 0],
90
+ },
91
+ paddingBottom: {
92
+ value: splitPaddings[splitPaddings.length / 3 >= 1 ? 2 : 0],
93
+ },
94
+ paddingLeft: {
95
+ value: splitPaddings[paddingLeftIndex],
96
+ },
97
+ });
98
+ }
99
+
67
100
  return (
68
- <div {...rest} ref={ref}>
69
- <DataGridActions {...actions} headers={internalHeaders} onColumnToggled={onColumnToggled} />
101
+ <div
102
+ {...rest}
103
+ className={classes['grid-wrapper']}
104
+ ref={ref}
105
+ style={{
106
+ paddingTop: styleWithSpacing?.paddingTop,
107
+ paddingBottom: styleWithSpacing?.paddingBottom,
108
+ }}
109
+ >
110
+ <DataGridActions
111
+ {...actions}
112
+ style={{
113
+ paddingLeft: styleWithSpacing?.paddingLeft,
114
+ paddingRight: styleWithSpacing?.paddingRight,
115
+ }}
116
+ headers={internalHeaders}
117
+ onColumnToggled={onColumnToggled}
118
+ />
70
119
  <div className={classes['table-wrapper']}>
71
120
  <table className={classes['table']}>
72
121
  <DataGridHeader
@@ -75,6 +124,7 @@ const DataGridInner = <T extends {}>(
75
124
  onSort={onSort}
76
125
  disableContextMenuColumn={disableContextMenuColumn}
77
126
  enableMultiSorting={enableMultiSorting}
127
+ spacing={styleWithSpacing}
78
128
  />
79
129
  <DataGridBody
80
130
  children={children}
@@ -83,12 +133,18 @@ const DataGridInner = <T extends {}>(
83
133
  isLoading={isLoading}
84
134
  disableContextMenuColumn={disableContextMenuColumn}
85
135
  emptyLabel={emptyLabel}
136
+ spacing={styleWithSpacing}
86
137
  />
87
138
  </table>
88
139
  </div>
89
140
  {paginationProps && !isLoading && (
90
141
  <Pagination
91
142
  {...paginationProps}
143
+ style={{
144
+ ...paginationProps.style,
145
+ paddingLeft: styleWithSpacing?.paddingLeft,
146
+ paddingRight: styleWithSpacing?.paddingRight,
147
+ }}
92
148
  className={`${classes['pagination']} ${paginationProps.className ?? ''}`}
93
149
  />
94
150
  )}
@@ -12,12 +12,22 @@ export interface Props<T> extends ComponentPropsWithRef<'tbody'> {
12
12
  isLoading?: boolean;
13
13
  disableContextMenuColumn?: boolean;
14
14
  emptyLabel?: string;
15
+ spacing?: React.CSSProperties;
15
16
  }
16
17
 
17
18
  const skeletonLoadingRows = 9;
18
19
 
19
20
  const DataGridBodyInner = <T extends {}>(
20
- { children, data, headers, isLoading, disableContextMenuColumn, emptyLabel, ...rest }: Props<T>,
21
+ {
22
+ children,
23
+ data,
24
+ headers,
25
+ isLoading,
26
+ disableContextMenuColumn,
27
+ emptyLabel,
28
+ spacing,
29
+ ...rest
30
+ }: Props<T>,
21
31
  ref: Ref<HTMLTableSectionElement>
22
32
  ) => {
23
33
  const renderContent = () => {
@@ -49,7 +59,13 @@ const DataGridBodyInner = <T extends {}>(
49
59
  );
50
60
  }
51
61
 
52
- return data?.map((item, index) => React.cloneElement(children({ item, index }), { headers }));
62
+ return data?.map((item, index) => {
63
+ return React.cloneElement(children({ item, index }), {
64
+ headers,
65
+ spacing,
66
+ disableContextMenuColumn,
67
+ });
68
+ });
53
69
  };
54
70
 
55
71
  return (
@@ -5,12 +5,45 @@ import classes from './DataGridCell.module.scss';
5
5
  export interface Props extends ComponentPropsWithRef<'td'> {
6
6
  children?: ReactChild;
7
7
  isLoading?: boolean;
8
+ spacing?: React.CSSProperties;
9
+ cellIndex?: number;
10
+ columnLength?: number;
11
+ disableContextMenuColumn?: boolean;
8
12
  }
9
13
 
10
14
  export const DataGridCell = React.forwardRef<HTMLTableCellElement, Props>(
11
- ({ children, className, isLoading, ...rest }: Props, ref) => {
15
+ (
16
+ {
17
+ children,
18
+ className,
19
+ isLoading,
20
+ spacing,
21
+ cellIndex,
22
+ columnLength,
23
+ disableContextMenuColumn,
24
+ ...rest
25
+ }: Props,
26
+ ref
27
+ ) => {
28
+ let cellStyle: React.CSSProperties = {};
29
+
30
+ if (cellIndex === 0) {
31
+ cellStyle.paddingLeft = spacing?.paddingLeft;
32
+ }
33
+ if (
34
+ (cellIndex === columnLength && !disableContextMenuColumn) ||
35
+ (columnLength && cellIndex === columnLength - 1 && disableContextMenuColumn)
36
+ ) {
37
+ cellStyle.paddingRight = spacing?.paddingRight;
38
+ }
39
+
12
40
  return (
13
- <td {...rest} ref={ref} className={`${classes['cell']} ${className ?? ''}`}>
41
+ <td
42
+ {...rest}
43
+ ref={ref}
44
+ style={{ ...rest.style, ...cellStyle }}
45
+ className={`${classes['cell']} ${className ?? ''}`}
46
+ >
14
47
  {isLoading && (
15
48
  <div className={classes['loading']} aria-busy="true" aria-live="polite"></div>
16
49
  )}
@@ -5,13 +5,28 @@ import classes from './DataGridRow.module.scss';
5
5
  export interface Props extends ComponentPropsWithRef<'tr'> {
6
6
  headers?: HeaderCell[];
7
7
  isLoading?: boolean;
8
+ spacing?: React.CSSProperties;
9
+ disableContextMenuColumn?: boolean;
8
10
  }
9
11
 
10
12
  export const DataGridRow = React.forwardRef<HTMLTableRowElement, Props>(
11
- ({ children, className, headers, isLoading, ...rest }: Props, ref) => {
12
- const visibleCells = React.Children.map(children, (child, index) => {
13
- const visible = headers?.length! > index ? !headers![index].hidden : true;
14
- return visible && child;
13
+ (
14
+ { children, className, headers, isLoading, spacing, disableContextMenuColumn, ...rest }: Props,
15
+ ref
16
+ ) => {
17
+ const visibleCells = React.Children.map(children as React.ReactElement[], (child, index) => {
18
+ if (child) {
19
+ const cellWithSpacing = React.cloneElement(child, {
20
+ spacing: spacing,
21
+ cellIndex: index,
22
+ columnLength: headers?.length,
23
+ disableContextMenuColumn,
24
+ });
25
+
26
+ const visible = headers?.length! > index ? !headers![index].hidden : true;
27
+ return visible && cellWithSpacing;
28
+ }
29
+ return null;
15
30
  });
16
31
 
17
32
  const classNames = [classes['row']];
@@ -9,13 +9,22 @@ export interface Props extends ComponentPropsWithRef<'thead'> {
9
9
  onSort?: OnSortFunction;
10
10
  disableContextMenuColumn?: boolean;
11
11
  enableMultiSorting?: boolean;
12
+ spacing?: React.CSSProperties;
12
13
  }
13
14
 
14
15
  const sortingStates = [undefined, 'ASC', 'DESC'] as (Direction | undefined)[];
15
16
 
16
17
  export const DataGridHeader = React.forwardRef<HTMLTableSectionElement, Props>(
17
18
  (
18
- { initialSort, onSort, headers, disableContextMenuColumn, enableMultiSorting, ...rest }: Props,
19
+ {
20
+ initialSort,
21
+ onSort,
22
+ headers,
23
+ disableContextMenuColumn,
24
+ enableMultiSorting,
25
+ spacing,
26
+ ...rest
27
+ }: Props,
19
28
  ref
20
29
  ) => {
21
30
  const [sortList, setSortList] = useState(initialSort || []);
@@ -48,11 +57,20 @@ export const DataGridHeader = React.forwardRef<HTMLTableSectionElement, Props>(
48
57
  setSortList(newSort);
49
58
  };
50
59
 
51
- const headerCells = headers.map((header) => {
60
+ const headerCells = headers.map((header, index) => {
52
61
  if (header.hidden) {
53
62
  return null;
54
63
  }
55
64
 
65
+ let headerStyle: React.CSSProperties = {};
66
+
67
+ if (index === 0) {
68
+ headerStyle.paddingLeft = spacing?.paddingLeft;
69
+ }
70
+ if (index === headers.length - 1 && disableContextMenuColumn) {
71
+ headerStyle.paddingRight = spacing?.paddingRight;
72
+ }
73
+
56
74
  const sort = sortList.find((item) => item.name === header.name);
57
75
  return (
58
76
  <DataGridHeaderCell
@@ -62,6 +80,7 @@ export const DataGridHeader = React.forwardRef<HTMLTableSectionElement, Props>(
62
80
  disableSorting={header.disableSorting || !onSort}
63
81
  onSort={wrapOnSort}
64
82
  activeSortDirection={sort?.direction}
83
+ style={headerStyle}
65
84
  />
66
85
  );
67
86
  });
@@ -71,7 +90,11 @@ export const DataGridHeader = React.forwardRef<HTMLTableSectionElement, Props>(
71
90
  <tr className={classes['row']}>
72
91
  {headerCells}
73
92
  {!disableContextMenuColumn && (
74
- <td aria-label="context menu" className={classes['context-menu']}></td>
93
+ <td
94
+ style={{ paddingRight: spacing?.paddingRight }}
95
+ aria-label="context menu"
96
+ className={classes['context-menu']}
97
+ ></td>
75
98
  )}
76
99
  </tr>
77
100
  </thead>
@@ -3,6 +3,7 @@
3
3
  }
4
4
 
5
5
  .floating-label {
6
+ font-family: var(--font-family);
6
7
  font-size: 1rem;
7
8
  position: absolute;
8
9
  z-index: 1;
@@ -106,7 +106,7 @@
106
106
  .previous,
107
107
  .next {
108
108
  button {
109
- margin: 0.5rem;
109
+ margin: 0 0.5rem;
110
110
  }
111
111
  }
112
112
  }