@popsure/dirty-swan 0.48.1 → 0.49.2

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 (53) hide show
  1. package/dist/cjs/index.js +79 -64
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/lib/components/comparisonTable/components/Row/index.d.ts +1 -0
  4. package/dist/cjs/lib/components/comparisonTable/components/TableRowHeader/index.d.ts +1 -1
  5. package/dist/cjs/lib/components/comparisonTable/hooks/useComparisonTable.d.ts +3 -2
  6. package/dist/cjs/lib/components/comparisonTable/index.d.ts +14 -4
  7. package/dist/cjs/lib/components/dateSelector/index.d.ts +2 -0
  8. package/dist/esm/components/comparisonTable/components/AccordionItem/AccordionItem.js +2 -2
  9. package/dist/esm/components/comparisonTable/components/AccordionItem/AccordionItem.js.map +1 -1
  10. package/dist/esm/components/comparisonTable/components/Row/index.js +11 -4
  11. package/dist/esm/components/comparisonTable/components/Row/index.js.map +1 -1
  12. package/dist/esm/components/comparisonTable/components/TableArrows/index.js +4 -2
  13. package/dist/esm/components/comparisonTable/components/TableArrows/index.js.map +1 -1
  14. package/dist/esm/components/comparisonTable/components/TableButton/index.js +9 -4
  15. package/dist/esm/components/comparisonTable/components/TableButton/index.js.map +1 -1
  16. package/dist/esm/components/comparisonTable/components/TableButton/index.test.js +13 -7
  17. package/dist/esm/components/comparisonTable/components/TableButton/index.test.js.map +1 -1
  18. package/dist/esm/components/comparisonTable/components/TableInfoButton/index.js +1 -1
  19. package/dist/esm/components/comparisonTable/components/TableInfoButton/index.js.map +1 -1
  20. package/dist/esm/components/comparisonTable/components/TableRowHeader/index.js +9 -2
  21. package/dist/esm/components/comparisonTable/components/TableRowHeader/index.js.map +1 -1
  22. package/dist/esm/components/comparisonTable/components/TableRowHeader/index.test.js +20 -17
  23. package/dist/esm/components/comparisonTable/components/TableRowHeader/index.test.js.map +1 -1
  24. package/dist/esm/components/comparisonTable/index.js +28 -33
  25. package/dist/esm/components/comparisonTable/index.js.map +1 -1
  26. package/dist/esm/components/dateSelector/index.js +23 -15
  27. package/dist/esm/components/dateSelector/index.js.map +1 -1
  28. package/dist/esm/components/dateSelector/index.test.js +36 -2
  29. package/dist/esm/components/dateSelector/index.test.js.map +1 -1
  30. package/dist/esm/lib/components/comparisonTable/components/Row/index.d.ts +1 -0
  31. package/dist/esm/lib/components/comparisonTable/components/TableRowHeader/index.d.ts +1 -1
  32. package/dist/esm/lib/components/comparisonTable/hooks/useComparisonTable.d.ts +3 -2
  33. package/dist/esm/lib/components/comparisonTable/index.d.ts +14 -4
  34. package/dist/esm/lib/components/dateSelector/index.d.ts +2 -0
  35. package/package.json +3 -3
  36. package/src/lib/components/comparisonTable/components/AccordionItem/AccordionItem.module.scss +3 -5
  37. package/src/lib/components/comparisonTable/components/AccordionItem/AccordionItem.tsx +2 -2
  38. package/src/lib/components/comparisonTable/components/Row/index.tsx +16 -13
  39. package/src/lib/components/comparisonTable/components/Row/style.module.scss +13 -9
  40. package/src/lib/components/comparisonTable/components/TableArrows/index.tsx +2 -0
  41. package/src/lib/components/comparisonTable/components/TableArrows/style.module.scss +4 -0
  42. package/src/lib/components/comparisonTable/components/TableButton/index.test.tsx +7 -8
  43. package/src/lib/components/comparisonTable/components/TableButton/index.tsx +9 -9
  44. package/src/lib/components/comparisonTable/components/TableButton/style.module.scss +7 -24
  45. package/src/lib/components/comparisonTable/components/TableInfoButton/index.tsx +1 -0
  46. package/src/lib/components/comparisonTable/components/TableRowHeader/index.test.tsx +18 -22
  47. package/src/lib/components/comparisonTable/components/TableRowHeader/index.tsx +16 -9
  48. package/src/lib/components/comparisonTable/hooks/useComparisonTable.ts +8 -18
  49. package/src/lib/components/comparisonTable/index.stories.mdx +55 -25
  50. package/src/lib/components/comparisonTable/index.tsx +64 -25
  51. package/src/lib/components/comparisonTable/style.module.scss +23 -8
  52. package/src/lib/components/dateSelector/index.test.tsx +32 -2
  53. package/src/lib/components/dateSelector/index.tsx +40 -21
@@ -1,7 +1,7 @@
1
1
  @use "../../../../scss/public/colors" as *;
2
2
  @use "../../../../scss/public/grid" as *;
3
3
 
4
- $cell-min-width: var(--cellWidth, 256px);
4
+ $cell-min-width: var(--cellWidth, 211px); // 195 + 16px
5
5
 
6
6
  .header {
7
7
  position: relative;
@@ -31,9 +31,13 @@ $cell-min-width: var(--cellWidth, 256px);
31
31
 
32
32
  line-height: 24px;
33
33
 
34
- padding: 16px;
34
+ padding: 16px 8px;
35
35
 
36
- color: $ds-grey-700;
36
+ &:first-child {
37
+ padding: 16px 8px 16px 16px;
38
+ }
39
+
40
+ color: $ds-grey-900;
37
41
 
38
42
  width: 50vw;
39
43
  max-width: calc(var(--tableWidth) / 2);
@@ -55,19 +59,19 @@ $cell-min-width: var(--cellWidth, 256px);
55
59
  @include p-size-tablet {
56
60
  flex: 1 0 $cell-min-width;
57
61
  width: $cell-min-width;
58
- padding: 24px;
59
-
60
- &:last-child {
62
+ &:first-child {
61
63
  padding: 24px 8px 24px 24px;
62
64
  }
65
+
66
+ padding: 24px 8px;
63
67
  }
64
68
  }
65
69
 
66
70
  h4.cell {
67
- // Set the max width of the first column to the supplied firstColumnWidth (or 288px if not specified) but only
71
+ // Set the max width of the first column to the supplied firstColumnWidth (or 212px if not specified) but only
68
72
  // if this value does not exceed half of the table's width.
69
73
  // This is to ensure that the first column is at most as wide as half the table, which will be the case on mobile where only the first column and one other are shown.
70
- max-width: min(var(--firstColumnWidth, 288px), calc(var(--tableWidth) / 2));
74
+ max-width: min(var(--firstColumnWidth, 212px), calc(var(--tableWidth) / 2));
71
75
  }
72
76
 
73
77
  .title {
@@ -116,7 +120,7 @@ h4.cell {
116
120
  h4.addon {
117
121
  border-right: none;
118
122
  max-width: calc(100vw - 64px);
119
- width: 100vw;
123
+ width: 100%;
120
124
 
121
125
  @include p-size-desktop {
122
126
  max-width: 976px;
@@ -25,6 +25,7 @@ const TableArrows = (props: TableArrowsProps) => {
25
25
  styles.arrow,
26
26
  {
27
27
  [styles.active]: active.left,
28
+ [styles.noPointerEvents]: !active.left,
28
29
  }
29
30
  )}
30
31
  >
@@ -38,6 +39,7 @@ const TableArrows = (props: TableArrowsProps) => {
38
39
  styles.arrow,
39
40
  {
40
41
  [styles.active]: active.right,
42
+ [styles.noPointerEvents]: !active.right,
41
43
  }
42
44
  )}
43
45
  >
@@ -53,3 +53,7 @@
53
53
  cursor: pointer;
54
54
  }
55
55
  }
56
+
57
+ .noPointerEvents {
58
+ pointer-events: none;
59
+ }
@@ -5,23 +5,22 @@ import TableButton from '.';
5
5
 
6
6
  const mockOnClick = jest.fn();
7
7
 
8
- const buttonContent = "Table Button label";
8
+ const buttonContent = 'Table Button label';
9
9
 
10
- const setup = () => render(
11
- <TableButton onClick={mockOnClick}>{buttonContent}</TableButton>
12
- );
10
+ const setup = () =>
11
+ render(<TableButton onClick={mockOnClick}>{buttonContent}</TableButton>);
13
12
 
14
13
  describe('TableButton component', () => {
15
- it("should render button content", () => {
14
+ it('should render button content', () => {
16
15
  const { getByText } = setup();
17
16
 
18
17
  expect(getByText(buttonContent)).toBeInTheDocument();
19
18
  });
20
19
 
21
- it("should call onClick", async () => {
22
- const { getByText, user } = setup();
20
+ it('should call onClick', async () => {
21
+ const { getByTestId, user } = setup();
23
22
 
24
- await user.click(getByText(buttonContent));
23
+ await user.click(getByTestId('ds-table-info-button'));
25
24
 
26
25
  expect(mockOnClick).toHaveBeenCalled();
27
26
  });
@@ -1,5 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
2
  import styles from './style.module.scss';
3
+ import TableInfoButton from '../TableInfoButton';
3
4
 
4
5
  interface Props {
5
6
  children: ReactNode;
@@ -12,15 +13,14 @@ const TableButton: React.FC<Props> = ({
12
13
  onClick,
13
14
  className = '',
14
15
  }) => (
15
- <button
16
- className={`${styles.button} ${className}`}
17
- data-testid="ds-table-button"
18
- onClick={onClick}
19
- >
20
- <span>
21
- {children}
22
- </span>
23
- </button>
16
+ <div className={styles.wrapper}>
17
+ {children}
18
+ <TableInfoButton
19
+ className={`${styles.infoButton} ${className}`}
20
+ data-testid="ds-table-button"
21
+ onClick={onClick}
22
+ />
23
+ </div>
24
24
  );
25
25
 
26
26
  export default TableButton;
@@ -1,26 +1,9 @@
1
- @use "../../../../scss/public/colors" as *;
2
-
3
- .button {
4
- background-color: transparent;
5
- color: $ds-grey-700;
6
- cursor: pointer;
7
- margin: 2px 0;
8
- padding: 2px;
9
- transition: color 0.3s ease;
10
-
11
- span {
12
- border-bottom: 2px dashed $ds-grey-600;
13
- display: inline;
14
- transition: border-color 0.3s ease;
15
- }
1
+ .wrapper {
2
+ position: relative;
3
+ }
16
4
 
17
- &:hover,
18
- &:focus {
19
- color: $ds-primary-500;
20
- outline-color: $ds-primary-500;
21
-
22
- span {
23
- border-color: $ds-primary-500;
24
- }
25
- }
5
+ .infoButton {
6
+ position: absolute;
7
+ right: -32px;
8
+ top: 0;
26
9
  }
@@ -11,6 +11,7 @@ const TableInfoButton = ({
11
11
  <button
12
12
  className={`p-btn--secondary ${styles.button} ${className}`}
13
13
  type="button"
14
+ data-testid="ds-table-info-button"
14
15
  onClick={onClick}
15
16
  >
16
17
  <Info size={20} />
@@ -5,62 +5,58 @@ import TableRowHeader, { TableRowHeaderProps } from '.';
5
5
 
6
6
  const mockOnClick = jest.fn();
7
7
 
8
- const label = "Table label";
9
- const subtitle = "Subtitle label";
10
- const icon = "🎉";
11
- const buttonTestId = "ds-table-button";
12
-
13
- const setup = (props: Partial<TableRowHeaderProps> = {}) => render(
14
- <TableRowHeader
15
- label={label}
16
- {...props}
17
- />
18
- );
8
+ const label = 'Table label';
9
+ const subtitle = 'Subtitle label';
10
+ const icon = '🎉';
11
+ const buttonTestId = 'ds-table-info-button';
12
+
13
+ const setup = (props: Partial<TableRowHeaderProps> = {}) =>
14
+ render(<TableRowHeader label={label} {...props} />);
19
15
 
20
16
  describe('TableRowHeader component', () => {
21
- it("should render label", () => {
17
+ it('should render label', () => {
22
18
  const { getByText } = setup();
23
19
 
24
20
  expect(getByText(label)).toBeInTheDocument();
25
21
  });
26
22
 
27
- it("should not render subtitle", () => {
23
+ it('should not render subtitle', () => {
28
24
  const { queryByText } = setup();
29
25
 
30
26
  expect(queryByText(subtitle)).not.toBeInTheDocument();
31
27
  });
32
28
 
33
- it("should render subtitle", () => {
29
+ it('should render subtitle', () => {
34
30
  const { getByText } = setup({ subtitle });
35
31
 
36
32
  expect(getByText(subtitle)).toBeInTheDocument();
37
33
  });
38
34
 
39
- it("should not render icon", () => {
35
+ it('should not render icon', () => {
40
36
  const { queryByText } = setup();
41
37
 
42
38
  expect(queryByText(icon)).not.toBeInTheDocument();
43
39
  });
44
40
 
45
- it("should render icon", () => {
41
+ it('should render icon', () => {
46
42
  const { getByText } = setup({ icon });
47
43
 
48
44
  expect(getByText(icon)).toBeInTheDocument();
49
45
  });
50
46
 
51
- it("should not render button if onClickInfo is not defined", () => {
47
+ it('should not render button if onClickInfo is not defined', () => {
52
48
  const { queryByTestId } = setup();
53
49
 
54
50
  expect(queryByTestId(buttonTestId)).not.toBeInTheDocument();
55
51
  });
56
52
 
57
- it("should render button if onClickInfo is defined", () => {
53
+ it('should render button if onClickInfo is defined', () => {
58
54
  const { getByTestId } = setup({ onClickInfo: mockOnClick });
59
55
 
60
56
  expect(getByTestId(buttonTestId)).toBeInTheDocument();
61
57
  });
62
58
 
63
- it("should not call onClickInfo if not defined", async () => {
59
+ it('should not call onClickInfo if not defined', async () => {
64
60
  const { getByText, user } = setup();
65
61
 
66
62
  await user.click(getByText(label));
@@ -68,10 +64,10 @@ describe('TableRowHeader component', () => {
68
64
  expect(mockOnClick).not.toHaveBeenCalled();
69
65
  });
70
66
 
71
- it("should call onClickInfo if defined", async () => {
72
- const { getByText, user } = setup({ onClickInfo: mockOnClick });
67
+ it('should call onClickInfo if defined', async () => {
68
+ const { getByTestId, user } = setup({ onClickInfo: mockOnClick });
73
69
 
74
- await user.click(getByText(label));
70
+ await user.click(getByTestId('ds-table-info-button'));
75
71
 
76
72
  expect(mockOnClick).toHaveBeenCalled();
77
73
  });
@@ -1,5 +1,6 @@
1
- import TableButton from '../TableButton';
1
+ import classNames from 'classnames';
2
2
  import styles from './style.module.scss';
3
+ import TableInfoButton from '../TableInfoButton';
3
4
 
4
5
  interface TableRowHeaderProps {
5
6
  label: string;
@@ -8,18 +9,24 @@ interface TableRowHeaderProps {
8
9
  onClickInfo?: () => void;
9
10
  }
10
11
 
11
- const TableRowHeader = ({ icon, label, subtitle, onClickInfo }: TableRowHeaderProps) => (
12
+ const TableRowHeader = ({
13
+ icon,
14
+ label,
15
+ subtitle,
16
+ onClickInfo,
17
+ }: TableRowHeaderProps) => (
12
18
  <div className="d-flex">
13
19
  {icon && <span className={`mr8 ${styles.icon}`}>{icon}</span>}
14
20
  <div>
15
21
  <p className="p-p d-inline">
16
- {!onClickInfo ? (
17
- <span>{label}</span>
18
- ) : (
19
- <TableButton className="mr8 ta-left" onClick={onClickInfo}>
20
- {label}
21
- </TableButton>
22
- )}
22
+ <span
23
+ className={classNames({
24
+ mr8: onClickInfo,
25
+ })}
26
+ >
27
+ {label}
28
+ </span>
29
+ {onClickInfo && <TableInfoButton onClick={onClickInfo} />}
23
30
  </p>
24
31
  {subtitle && <p className="p-p--small tc-grey-500">{subtitle}</p>}
25
32
  </div>
@@ -2,12 +2,14 @@ import debounce from 'lodash.debounce';
2
2
  import { useCallback, useEffect, useRef, useState } from 'react';
3
3
 
4
4
  import { ArrowValues } from '../components/TableArrows';
5
- import generateId from '../../../util/generateId';
6
5
 
7
- export const useComparisonTable = () => {
6
+ export const useComparisonTable = ({
7
+ onSelectionChanged,
8
+ }: {
9
+ onSelectionChanged?: (selectedIndex: number) => void;
10
+ }) => {
8
11
  const [showMore, setShowMore] = useState<boolean>(false);
9
12
  const [headerWidth, setHeaderWidth] = useState(1400);
10
- const [headerId, setHeaderId] = useState('');
11
13
  const [selectedTabIndex, setSelectedTabIndex] = useState(0);
12
14
  const [selectedSection, setSelectedSection] = useState('');
13
15
 
@@ -123,24 +125,12 @@ export const useComparisonTable = () => {
123
125
  };
124
126
 
125
127
  useEffect(() => {
126
- if (headerRef.current) {
127
- return;
128
- }
129
-
130
- const headerById = document.getElementById(headerId);
131
-
132
- if (headerById) {
133
- scrollContainerCallbackRef(headerById);
134
- }
135
- }, [headerId, scrollContainerCallbackRef]);
136
-
137
- useEffect(() => {
138
- setHeaderId(generateId());
139
- }, []);
128
+ onSelectionChanged?.(selectedTabIndex);
129
+ // eslint-disable-next-line react-hooks/exhaustive-deps
130
+ }, [selectedTabIndex]);
140
131
 
141
132
  return {
142
133
  headerWidth,
143
- headerId,
144
134
  contentContainerRef,
145
135
  selectedSection,
146
136
  setSelectedSection,
@@ -27,17 +27,22 @@ The Comparison Table component provides an easy way to compare vast amounts of i
27
27
 
28
28
  ## Arguments
29
29
 
30
- | attribute | unit | description | default value | required |
31
- | --------------------- | ------------------- | ---------------------------------------------------------- | ------------- | -------- |
32
- | headers | [Header[]](#header) | The structure of the table | n/a | true |
33
- | data | array | The title text that needs to be displayed | n/a | true |
34
- | hideDetails | boolean | Hide table groups that do not have the `default` attribute | false | false |
35
- | hideScrollBars | boolean | Hide scroll bars | false | false |
36
- | collapsibleSections | boolean | Make table groups with a label collapsible | false | false |
37
- | cellWidth | number | Width of a table content cell | 256px | false |
38
- | firstColumnWidth | number | Width of the first column of the table | 288px | false |
39
- | stickyHeaderTopOffset | number | Y-offset of the sticky header row | 0px | false |
40
- | growContent | boolean | Makes the content area grow to fill the available space | false | false |
30
+ | attribute | unit | description | default value | required |
31
+ | --------------------- | ----------------------------------------- | ------------------------------------------------------------------- | -------------- | -------- |
32
+ | headers | [Header[]](#header) | The structure of the table | n/a | true |
33
+ | data | array | The title text that needs to be displayed | n/a | true |
34
+ | hideDetails | boolean | Hide table groups that do not have the `default` attribute | false | false |
35
+ | hideDetailsCaption | string | Caption of the button to hide the details | 'Hide details' | false |
36
+ | showDetailsCaption | string | Caption of the button to show the details | 'Show details' | false |
37
+ | hideScrollBars | boolean | Hide scroll bars | false | false |
38
+ | hideScrollBarsMobile | boolean | Hide scroll bars on mobile only | false | false |
39
+ | collapsibleSections | boolean | Make table groups with a label collapsible | false | false |
40
+ | cellWidth | number | Width of a table content cell | 211px | false |
41
+ | firstColumnWidth | number | Width of the first column of the table | 212px | false |
42
+ | stickyHeaderTopOffset | number | Y-offset of the sticky header row | 0px | false |
43
+ | growContent | boolean | Makes the content area grow to fill the available space | false | false |
44
+ | onSelectionChanged | (number) => void | Callback to be called when the selected tab index changes on mobile | n/a | false |
45
+ | classNameOverrides | [ClassNameOverrides](#classnameoverrides) | "className" props to be passed down to various internal components | n/a | false |
41
46
 
42
47
  ## Types
43
48
 
@@ -63,6 +68,23 @@ export interface Header<T> {
63
68
  }
64
69
  ```
65
70
 
71
+ ### ClassNameOverrides
72
+
73
+ Note that if the component uses custom css such as media queries etc. for certain properties, the override must also use
74
+ custom css (and not just Dirty Swan classes) or else it won't to able override the existing rules.
75
+
76
+ ```typescript
77
+ export interface ClassNameOverrides {
78
+ header?: string;
79
+ container?: string;
80
+ cell?: string;
81
+ headerCell?: string;
82
+ collapsibleSection?: string;
83
+ section?: string;
84
+ hideDetailsButton?: string;
85
+ }
86
+ ```
87
+
66
88
  ## Default example
67
89
 
68
90
  export const ComparisonTableWithData = () => {
@@ -76,9 +98,7 @@ export const ComparisonTableWithData = () => {
76
98
  key: 'name',
77
99
  label: 'Films',
78
100
  render: (value) => (
79
- <TableButton onClick={() => {}}>
80
- {value}
81
- </TableButton>
101
+ <TableButton onClick={() => {}}>{value}</TableButton>
82
102
  ),
83
103
  },
84
104
  {
@@ -91,15 +111,18 @@ export const ComparisonTableWithData = () => {
91
111
  key: 'imdb',
92
112
  label: 'IMDB rating',
93
113
  render: (value) => (
94
- <TableButton onClick={() => {}}>
95
- {value}
96
- </TableButton>
114
+ <TableButton onClick={() => {}}>{value}</TableButton>
97
115
  ),
98
116
  },
99
117
  {
100
118
  id: 3,
101
119
  key: 'rating',
102
- label: <TableRowHeader label="Our rating of movies found online on IMDB lists" onClickInfo={() => {}} />,
120
+ label: (
121
+ <TableRowHeader
122
+ label="Our rating of movies found online on IMDB lists"
123
+ onClickInfo={() => {}}
124
+ />
125
+ ),
103
126
  render: (value) => (
104
127
  <TableButton onClick={() => {}}>
105
128
  <TableRating type="star" rating={value} />
@@ -286,6 +309,9 @@ export const ComparisonTableWithData = () => {
286
309
  headers={headers}
287
310
  collapsibleSections
288
311
  hideDetails
312
+ classNameOverrides={{
313
+ hideDetailsButton: 'p-container wmx6',
314
+ }}
289
315
  />
290
316
  );
291
317
  };
@@ -322,9 +348,7 @@ export const ComparisonTableWithData = () => {
322
348
  key: 'name',
323
349
  label: 'Films',
324
350
  render: (value) => (
325
- <TableButton onClick={() => {}}>
326
- {value}
327
- </TableButton>
351
+ <TableButton onClick={() => {}}>{value}</TableButton>
328
352
  ),
329
353
  },
330
354
  {
@@ -337,15 +361,18 @@ export const ComparisonTableWithData = () => {
337
361
  key: 'imdb',
338
362
  label: 'IMDB rating',
339
363
  render: (value) => (
340
- <TableButton onClick={() => {}}>
341
- {value}
342
- </TableButton>
364
+ <TableButton onClick={() => {}}>{value}</TableButton>
343
365
  ),
344
366
  },
345
367
  {
346
368
  id: 3,
347
369
  key: 'rating',
348
- label: <TableRowHeader label="Our rating of movies found online on IMDB lists" onClickInfo={() => {}} />,
370
+ label: (
371
+ <TableRowHeader
372
+ label="Our rating of movies found online on IMDB lists"
373
+ onClickInfo={() => {}}
374
+ />
375
+ ),
349
376
  render: (value) => (
350
377
  <TableButton onClick={() => {}}>
351
378
  <TableRating type="star" rating={value} />
@@ -532,6 +559,9 @@ export const ComparisonTableWithData = () => {
532
559
  headers={headers}
533
560
  collapsibleSections
534
561
  hideDetails
562
+ classNameOverrides={{
563
+ hideDetailsButton: 'p-container wmx6',
564
+ }}
535
565
  />
536
566
  );
537
567
  };