@popsure/dirty-swan 0.66.12 → 0.66.13
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.
- package/dist/cjs/index.js +49 -34
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/components/table/Table.d.ts +3 -1
- package/dist/cjs/lib/components/table/Table.stories.d.ts +10 -2
- package/dist/cjs/lib/components/table/components/TableCell/TableCell.d.ts +3 -1
- package/dist/cjs/lib/components/table/components/TableContents/TableContents.d.ts +2 -1
- package/dist/cjs/lib/components/table/components/TableSection/TableSection.d.ts +2 -1
- package/dist/cjs/lib/models/styles.d.ts +1 -1
- package/dist/esm/{TableSection-CEhD4eoy.js → TableSection-Cm50RX-V.js} +28 -9
- package/dist/esm/TableSection-Cm50RX-V.js.map +1 -0
- package/dist/esm/components/table/Table.js +10 -10
- package/dist/esm/components/table/Table.js.map +1 -1
- package/dist/esm/components/table/Table.stories.js +79 -4
- package/dist/esm/components/table/Table.stories.js.map +1 -1
- package/dist/esm/components/table/Table.test.js +7 -1
- package/dist/esm/components/table/Table.test.js.map +1 -1
- package/dist/esm/components/table/components/TableCell/BaseCell/BaseCell.js +1 -1
- package/dist/esm/components/table/components/TableCell/BaseCell/BaseCell.js.map +1 -1
- package/dist/esm/components/table/components/TableCell/TableCell.js +6 -4
- package/dist/esm/components/table/components/TableCell/TableCell.js.map +1 -1
- package/dist/esm/components/table/components/TableContents/TableContents.js +9 -15
- package/dist/esm/components/table/components/TableContents/TableContents.js.map +1 -1
- package/dist/esm/components/table/components/TableContents/TableContents.test.js +14 -2
- package/dist/esm/components/table/components/TableContents/TableContents.test.js.map +1 -1
- package/dist/esm/components/table/components/TableSection/TableSection.js +1 -1
- package/dist/esm/components/table/components/TableSection/TableSection.test.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/lib/components/table/Table.d.ts +3 -1
- package/dist/esm/lib/components/table/Table.stories.d.ts +10 -2
- package/dist/esm/lib/components/table/components/TableCell/TableCell.d.ts +3 -1
- package/dist/esm/lib/components/table/components/TableContents/TableContents.d.ts +2 -1
- package/dist/esm/lib/components/table/components/TableSection/TableSection.d.ts +2 -1
- package/dist/esm/lib/models/styles.d.ts +1 -1
- package/package.json +1 -1
- package/src/lib/components/table/Table.module.scss +3 -0
- package/src/lib/components/table/Table.stories.tsx +92 -0
- package/src/lib/components/table/Table.test.tsx +15 -0
- package/src/lib/components/table/Table.tsx +27 -20
- package/src/lib/components/table/components/TableCell/BaseCell/BaseCell.tsx +1 -1
- package/src/lib/components/table/components/TableCell/TableCell.module.scss +9 -3
- package/src/lib/components/table/components/TableCell/TableCell.tsx +7 -1
- package/src/lib/components/table/components/TableContents/TableContents.module.scss +23 -24
- package/src/lib/components/table/components/TableContents/TableContents.test.tsx +22 -1
- package/src/lib/components/table/components/TableContents/TableContents.tsx +40 -31
- package/src/lib/components/table/components/TableSection/TableSection.module.scss +7 -0
- package/src/lib/components/table/components/TableSection/TableSection.tsx +32 -3
- package/src/lib/models/styles.ts +1 -0
- package/dist/esm/TableSection-CEhD4eoy.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { TableProps } from './Table';
|
|
|
2
2
|
import { TableData } from './types';
|
|
3
3
|
declare const story: {
|
|
4
4
|
title: string;
|
|
5
|
-
component: ({ cellReplacements, className, collapsibleSections, hideColumns, hideDetails, hideRows, imageComponent, modalContentRenderer, onModalOpen, onSelectionChanged, scrollOnOpen, scrollTopOffset, stickyHeaderTopOffset, tableData, textOverrides: definedTextOverrides, title, activeSection: externalActiveSection, hideTableNavigation, }: TableProps) => JSX.Element;
|
|
5
|
+
component: ({ cellReplacements, className, collapsibleSections, hideColumns, hideDetails, hideRows, imageComponent, modalContentRenderer, onModalOpen, onSelectionChanged, scrollOnOpen, scrollTopOffset, stickyHeaderTopOffset, tableData, textOverrides: definedTextOverrides, title, activeSection: externalActiveSection, hideTableNavigation, hideStickyHeader, showSelectedColumn, }: TableProps) => JSX.Element;
|
|
6
6
|
argTypes: {
|
|
7
7
|
tableData: {
|
|
8
8
|
subContent: string;
|
|
@@ -22,6 +22,9 @@ declare const story: {
|
|
|
22
22
|
hideDetails: {
|
|
23
23
|
subContent: string;
|
|
24
24
|
};
|
|
25
|
+
hideStickyHeader: {
|
|
26
|
+
subContent: string;
|
|
27
|
+
};
|
|
25
28
|
stickyHeaderTopOffset: {
|
|
26
29
|
subContent: string;
|
|
27
30
|
};
|
|
@@ -69,10 +72,15 @@ declare const story: {
|
|
|
69
72
|
hideColumns: never[];
|
|
70
73
|
hideRows: never[];
|
|
71
74
|
hideTableNavigation: boolean;
|
|
75
|
+
showSelectedColumn: boolean;
|
|
72
76
|
};
|
|
73
77
|
};
|
|
74
78
|
export declare const TableStory: {
|
|
75
|
-
render: ({ collapsibleSections, scrollOnOpen, scrollTopOffset, tableData, hideColumns, hideDetails, hideRows, stickyHeaderTopOffset, textOverrides, title, activeSection, hideTableNavigation, }: TableProps) => JSX.Element;
|
|
79
|
+
render: ({ collapsibleSections, scrollOnOpen, scrollTopOffset, tableData, hideColumns, hideDetails, hideRows, stickyHeaderTopOffset, textOverrides, title, activeSection, hideTableNavigation, showSelectedColumn, }: TableProps) => JSX.Element;
|
|
80
|
+
name: string;
|
|
81
|
+
};
|
|
82
|
+
export declare const SinglePlanQuoteTable: {
|
|
83
|
+
render: () => JSX.Element;
|
|
76
84
|
name: string;
|
|
77
85
|
};
|
|
78
86
|
export declare const TableDataType: () => JSX.Element;
|
|
@@ -5,9 +5,11 @@ type ExtraTableCellProps = {
|
|
|
5
5
|
isFirstCellInRow?: boolean;
|
|
6
6
|
isTopLeftCell?: boolean;
|
|
7
7
|
isNavigation?: boolean;
|
|
8
|
+
isSelectedColumn?: boolean;
|
|
9
|
+
selectedColumnPosition?: 'top' | 'bottom' | 'middle';
|
|
8
10
|
imageComponent?: (args: any) => JSX.Element;
|
|
9
11
|
isBelowDesktop?: boolean;
|
|
10
12
|
};
|
|
11
13
|
export type TableCellProps = TableCellData & ExtraTableCellProps;
|
|
12
|
-
declare const TableCell: React.MemoExoticComponent<({ isFirstCellInRow, isHeader, isNavigation, isTopLeftCell, colSpan, isBelowDesktop, ...cellProps }: TableCellProps) => JSX.Element>;
|
|
14
|
+
declare const TableCell: React.MemoExoticComponent<({ isFirstCellInRow, isHeader, isNavigation, isSelectedColumn, selectedColumnPosition, isTopLeftCell, colSpan, isBelowDesktop, ...cellProps }: TableCellProps) => JSX.Element>;
|
|
13
15
|
export { TableCell };
|
|
@@ -16,6 +16,7 @@ export interface TableContentsProps {
|
|
|
16
16
|
title: string;
|
|
17
17
|
cellReplacements?: CellReplacements;
|
|
18
18
|
imageComponent?: (args: any) => JSX.Element;
|
|
19
|
+
selectedColumn?: number;
|
|
19
20
|
}
|
|
20
|
-
declare const TableContents: ({ className, collapsibleSections, scrollOnOpen, scrollTopOffset, stickyHeaderRef, tableData, hideColumns, hideDetails, hideRows, isMobile, openModal, shouldHideDetails, title, cellReplacements, imageComponent, }: TableContentsProps) => JSX.Element;
|
|
21
|
+
declare const TableContents: ({ className, collapsibleSections, scrollOnOpen, scrollTopOffset, stickyHeaderRef, tableData, hideColumns, hideDetails, hideRows, isMobile, openModal, shouldHideDetails, title, cellReplacements, imageComponent, selectedColumn, }: TableContentsProps) => JSX.Element;
|
|
21
22
|
export { TableContents };
|
|
@@ -10,6 +10,7 @@ export interface TableSectionProps {
|
|
|
10
10
|
width?: number | string;
|
|
11
11
|
cellReplacements?: CellReplacements;
|
|
12
12
|
imageComponent?: (args: any) => JSX.Element;
|
|
13
|
+
selectedColumn?: number;
|
|
13
14
|
}
|
|
14
|
-
declare const TableSection: ({ className, tableCellRows, hideColumns, hideRows, hideHeader, openModal, title, width, cellReplacements, imageComponent, }: TableSectionProps) => JSX.Element;
|
|
15
|
+
declare const TableSection: ({ className, tableCellRows, hideColumns, hideRows, hideHeader, openModal, title, width, cellReplacements, imageComponent, selectedColumn, }: TableSectionProps) => JSX.Element;
|
|
15
16
|
export { TableSection };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type Color = 'transparent' | 'blue-100' | 'blue-300' | 'blue-500' | 'blue-700' | 'blue-900' | 'purple-50' | 'purple-100' | 'purple-200' | 'purple-300' | 'purple-400' | 'purple-500' | 'purple-600' | 'purple-700' | 'purple-800' | 'purple-900' | 'red-100' | 'red-300' | 'red-500' | 'red-700' | 'red-900' | 'neutral-50' | 'neutral-100' | 'neutral-300' | 'neutral-400' | 'neutral-600' | 'neutral-700' | 'neutral-800' | 'neutral-900' | 'green-100' | 'green-300' | 'green-500' | 'green-700' | 'green-900' | 'yellow-100' | 'yellow-300' | 'yellow-500' | 'yellow-700' | 'yellow-900';
|
|
1
|
+
export type Color = 'transparent' | 'blue-100' | 'blue-300' | 'blue-500' | 'blue-700' | 'blue-900' | 'purple-50' | 'purple-100' | 'purple-200' | 'purple-300' | 'purple-400' | 'purple-500' | 'purple-600' | 'purple-700' | 'purple-800' | 'purple-900' | 'red-100' | 'red-300' | 'red-500' | 'red-700' | 'red-900' | 'neutral-50' | 'neutral-100' | 'neutral-300' | 'neutral-400' | 'neutral-500' | 'neutral-600' | 'neutral-700' | 'neutral-800' | 'neutral-900' | 'green-100' | 'green-300' | 'green-500' | 'green-700' | 'green-900' | 'yellow-100' | 'yellow-300' | 'yellow-500' | 'yellow-700' | 'yellow-900';
|
|
2
2
|
export type Size = 0 | 4 | 8 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 40 | 48 | 56 | 64 | 72 | 80 | 88 | 96;
|
package/package.json
CHANGED
|
@@ -255,6 +255,10 @@ const story = {
|
|
|
255
255
|
hideDetails: {
|
|
256
256
|
subContent: 'This property allows to hide the details of the table.',
|
|
257
257
|
},
|
|
258
|
+
hideStickyHeader: {
|
|
259
|
+
subContent:
|
|
260
|
+
'This property allows to hide the sticky header row on desktop, e.g. for single plan tables without a plan selector.',
|
|
261
|
+
},
|
|
258
262
|
stickyHeaderTopOffset: {
|
|
259
263
|
subContent:
|
|
260
264
|
'This property allows to set the offset of the sticky header.',
|
|
@@ -307,6 +311,7 @@ const story = {
|
|
|
307
311
|
hideColumns: [],
|
|
308
312
|
hideRows: [],
|
|
309
313
|
hideTableNavigation: true,
|
|
314
|
+
showSelectedColumn: false,
|
|
310
315
|
},
|
|
311
316
|
};
|
|
312
317
|
|
|
@@ -324,6 +329,7 @@ export const TableStory = {
|
|
|
324
329
|
title,
|
|
325
330
|
activeSection,
|
|
326
331
|
hideTableNavigation,
|
|
332
|
+
showSelectedColumn,
|
|
327
333
|
}: TableProps) => {
|
|
328
334
|
const [price, setPrice] = useState(999);
|
|
329
335
|
return (
|
|
@@ -367,6 +373,7 @@ export const TableStory = {
|
|
|
367
373
|
title={title}
|
|
368
374
|
activeSection={activeSection}
|
|
369
375
|
hideTableNavigation={hideTableNavigation}
|
|
376
|
+
showSelectedColumn={showSelectedColumn}
|
|
370
377
|
/>
|
|
371
378
|
</div>
|
|
372
379
|
);
|
|
@@ -375,6 +382,91 @@ export const TableStory = {
|
|
|
375
382
|
name: 'Table',
|
|
376
383
|
};
|
|
377
384
|
|
|
385
|
+
const singlePlanData: TableData = [
|
|
386
|
+
{
|
|
387
|
+
rows: [
|
|
388
|
+
[{ text: '' }, { text: '' }],
|
|
389
|
+
[
|
|
390
|
+
{ text: 'Price' },
|
|
391
|
+
{
|
|
392
|
+
text: '€9.99',
|
|
393
|
+
description: 'With monthly cancellation',
|
|
394
|
+
fontVariant: 'PRICE',
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
[
|
|
398
|
+
{
|
|
399
|
+
text: 'Regular vet visits & medication',
|
|
400
|
+
modalContent: 'Some stories about vets',
|
|
401
|
+
},
|
|
402
|
+
{ text: 'Up to €1 million' },
|
|
403
|
+
],
|
|
404
|
+
[
|
|
405
|
+
{
|
|
406
|
+
text: 'Specialist visits',
|
|
407
|
+
modalContent: 'Some stories about specialists',
|
|
408
|
+
},
|
|
409
|
+
{ text: '4 visits per year' },
|
|
410
|
+
],
|
|
411
|
+
[{ text: 'Medication' }, { text: '80% covered' }],
|
|
412
|
+
[{ text: 'Grooming' }, { checkmarkValue: false }],
|
|
413
|
+
[{ text: 'Boarding fees' }, { checkmarkValue: false }],
|
|
414
|
+
[
|
|
415
|
+
{
|
|
416
|
+
text: 'Alternative treatments',
|
|
417
|
+
description: 'E.g. physiotherapy, hydrotherapy',
|
|
418
|
+
},
|
|
419
|
+
{ checkmarkValue: false },
|
|
420
|
+
],
|
|
421
|
+
],
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
section: {
|
|
425
|
+
title: 'Dental',
|
|
426
|
+
},
|
|
427
|
+
rows: [
|
|
428
|
+
[{ text: 'Dental cleanings' }, { text: 'Up to €500' }],
|
|
429
|
+
[{ text: 'Dental treatments' }, { text: 'Up to €500' }],
|
|
430
|
+
[{ text: 'Operations' }, { checkmarkValue: true }],
|
|
431
|
+
],
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
section: {
|
|
435
|
+
title: 'Travel',
|
|
436
|
+
},
|
|
437
|
+
rows: [
|
|
438
|
+
[{ text: 'Trips abroad' }, { checkmarkValue: true }],
|
|
439
|
+
[{ text: 'Emergency care abroad' }, { checkmarkValue: true }],
|
|
440
|
+
],
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
section: {
|
|
444
|
+
title: 'Add-ons',
|
|
445
|
+
},
|
|
446
|
+
rows: [
|
|
447
|
+
[{ text: 'Extended coverage' }, { checkmarkValue: true }],
|
|
448
|
+
[{ text: 'Equipment protection' }, { checkmarkValue: true }],
|
|
449
|
+
],
|
|
450
|
+
},
|
|
451
|
+
];
|
|
452
|
+
|
|
453
|
+
export const SinglePlanQuoteTable = {
|
|
454
|
+
render: () => (
|
|
455
|
+
<div style={{ maxWidth: 756 }}>
|
|
456
|
+
<Table
|
|
457
|
+
tableData={singlePlanData}
|
|
458
|
+
title="Single plan quote"
|
|
459
|
+
collapsibleSections
|
|
460
|
+
hideTableNavigation
|
|
461
|
+
hideStickyHeader
|
|
462
|
+
showSelectedColumn
|
|
463
|
+
/>
|
|
464
|
+
</div>
|
|
465
|
+
),
|
|
466
|
+
|
|
467
|
+
name: 'Single Plan Quote',
|
|
468
|
+
};
|
|
469
|
+
|
|
378
470
|
export const TableDataType = () => {
|
|
379
471
|
return (
|
|
380
472
|
<pre>
|
|
@@ -75,6 +75,21 @@ describe('Table', () => {
|
|
|
75
75
|
expect(screen.getByText('Hide details')).toBeVisible();
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
+
it('does not render the sticky header row when hideStickyHeader is true', () => {
|
|
79
|
+
const { rerender } = render(
|
|
80
|
+
<Table tableData={tableData} title="Test Table" />
|
|
81
|
+
);
|
|
82
|
+
const countWithStickyHeader = screen.getAllByText('Item 1').length;
|
|
83
|
+
|
|
84
|
+
rerender(
|
|
85
|
+
<Table tableData={tableData} hideStickyHeader title="Test Table" />
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
expect(screen.getAllByText('Item 1')).toHaveLength(
|
|
89
|
+
countWithStickyHeader - 1
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
78
93
|
it('shows a modal when clicking on info icon', async () => {
|
|
79
94
|
const { user } = render(<Table tableData={tableData} title="Test Table" />);
|
|
80
95
|
|
|
@@ -47,6 +47,8 @@ export interface TableProps {
|
|
|
47
47
|
title: string;
|
|
48
48
|
activeSection?: number;
|
|
49
49
|
hideTableNavigation?: boolean;
|
|
50
|
+
hideStickyHeader?: boolean;
|
|
51
|
+
showSelectedColumn?: boolean;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
const defaultTextOverrides = {
|
|
@@ -73,6 +75,8 @@ const Table = ({
|
|
|
73
75
|
title,
|
|
74
76
|
activeSection: externalActiveSection,
|
|
75
77
|
hideTableNavigation = false,
|
|
78
|
+
hideStickyHeader = false,
|
|
79
|
+
showSelectedColumn = false,
|
|
76
80
|
}: TableProps) => {
|
|
77
81
|
const textOverrides = { ...defaultTextOverrides, ...definedTextOverrides };
|
|
78
82
|
const isMobile = useMediaQuery('BELOW_MOBILE');
|
|
@@ -99,7 +103,7 @@ const Table = ({
|
|
|
99
103
|
};
|
|
100
104
|
const currentActiveSection = tableData?.[0]?.rows?.[0]?.[activeSection];
|
|
101
105
|
const currentActiveSectionReplacements =
|
|
102
|
-
(currentActiveSection
|
|
106
|
+
(currentActiveSection?.cellId &&
|
|
103
107
|
cellReplacements?.[currentActiveSection.cellId]) ||
|
|
104
108
|
{};
|
|
105
109
|
|
|
@@ -133,7 +137,7 @@ const Table = ({
|
|
|
133
137
|
/>
|
|
134
138
|
)}
|
|
135
139
|
|
|
136
|
-
{!hideTableNavigation && (
|
|
140
|
+
{!hideTableNavigation && currentActiveSection && (
|
|
137
141
|
<TableControls
|
|
138
142
|
activeSection={activeSection}
|
|
139
143
|
columnsLength={columnsLength}
|
|
@@ -158,25 +162,27 @@ const Table = ({
|
|
|
158
162
|
)}
|
|
159
163
|
</>
|
|
160
164
|
) : (
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
<
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
165
|
+
!hideStickyHeader && (
|
|
166
|
+
<div
|
|
167
|
+
ref={stickyHeaderRef}
|
|
168
|
+
aria-hidden
|
|
169
|
+
className={styles.stickyHeader}
|
|
170
|
+
style={{ top: `${stickyHeaderTopOffset}px` }}
|
|
171
|
+
>
|
|
172
|
+
<div className={styles.container} ref={headerRef}>
|
|
173
|
+
<TableSection
|
|
174
|
+
cellReplacements={cellReplacements}
|
|
175
|
+
className={className}
|
|
176
|
+
hideColumns={hideColumns}
|
|
177
|
+
hideRows={hideRows}
|
|
178
|
+
openModal={handleOpenModal}
|
|
179
|
+
tableCellRows={[tableData?.[0]?.rows?.[0]]}
|
|
180
|
+
title={title}
|
|
181
|
+
imageComponent={imageComponent}
|
|
182
|
+
/>
|
|
183
|
+
</div>
|
|
178
184
|
</div>
|
|
179
|
-
|
|
185
|
+
)
|
|
180
186
|
)}
|
|
181
187
|
|
|
182
188
|
<div ref={containerRef} className={classNames(styles.container, 'pb8')}>
|
|
@@ -196,6 +202,7 @@ const Table = ({
|
|
|
196
202
|
openModal={handleOpenModal}
|
|
197
203
|
cellReplacements={cellReplacements}
|
|
198
204
|
imageComponent={imageComponent}
|
|
205
|
+
selectedColumn={showSelectedColumn ? activeSection : undefined}
|
|
199
206
|
/>
|
|
200
207
|
</div>
|
|
201
208
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
vertical-align: middle;
|
|
6
6
|
scroll-snap-align: end;
|
|
7
7
|
width: 50%;
|
|
8
|
+
padding: 28px 24px;
|
|
8
9
|
|
|
9
10
|
@include p-size-tablet {
|
|
10
11
|
width: auto;
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
position: sticky;
|
|
27
28
|
left: 0;
|
|
28
29
|
z-index: 2;
|
|
30
|
+
padding-left: 0;
|
|
29
31
|
|
|
30
32
|
&:after {
|
|
31
33
|
content: '';
|
|
@@ -36,10 +38,14 @@
|
|
|
36
38
|
width: 1px;
|
|
37
39
|
background-color: $ds-neutral-100;
|
|
38
40
|
}
|
|
41
|
+
}
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
.selectedColumnTop {
|
|
44
|
+
border-radius: 16px 16px 0 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.selectedColumnBottom {
|
|
48
|
+
border-radius: 0 0 16px 16px;
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
.fixedCard {
|
|
@@ -13,6 +13,8 @@ type ExtraTableCellProps = {
|
|
|
13
13
|
isFirstCellInRow?: boolean;
|
|
14
14
|
isTopLeftCell?: boolean;
|
|
15
15
|
isNavigation?: boolean;
|
|
16
|
+
isSelectedColumn?: boolean;
|
|
17
|
+
selectedColumnPosition?: 'top' | 'bottom' | 'middle';
|
|
16
18
|
imageComponent?: (args: any) => JSX.Element;
|
|
17
19
|
isBelowDesktop?: boolean;
|
|
18
20
|
};
|
|
@@ -24,6 +26,8 @@ const TableCell = React.memo(
|
|
|
24
26
|
isFirstCellInRow = false,
|
|
25
27
|
isHeader = false,
|
|
26
28
|
isNavigation = false,
|
|
29
|
+
isSelectedColumn = false,
|
|
30
|
+
selectedColumnPosition,
|
|
27
31
|
isTopLeftCell = false,
|
|
28
32
|
colSpan = 0,
|
|
29
33
|
isBelowDesktop,
|
|
@@ -46,11 +50,13 @@ const TableCell = React.memo(
|
|
|
46
50
|
return (
|
|
47
51
|
<Tag
|
|
48
52
|
{...scope}
|
|
49
|
-
className={classNames('bg-
|
|
53
|
+
className={classNames(isSelectedColumn ? 'bg-orange-50' : 'bg-white', styles.th, {
|
|
50
54
|
'ta-left': isFirstCellInRow,
|
|
51
55
|
[styles.thNavigation]: isNavigation,
|
|
52
56
|
[styles.fixedCell]: isFirstCellInRow && colSpan < 1 ,
|
|
53
57
|
[styles.fixedCard]: cellProps.type === 'CARD',
|
|
58
|
+
[styles.selectedColumnTop]: selectedColumnPosition === 'top',
|
|
59
|
+
[styles.selectedColumnBottom]: selectedColumnPosition === 'bottom',
|
|
54
60
|
})}
|
|
55
61
|
colSpan={isBelowDesktop && cellProps.type === 'CARD' ? 2 : colSpan}
|
|
56
62
|
>
|
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
@use "../../../../scss/public/colors" as *;
|
|
2
2
|
|
|
3
|
-
.
|
|
4
|
-
height:
|
|
3
|
+
.sectionButtonWrapper {
|
|
4
|
+
height: 74px;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
.sectionButton {
|
|
8
|
+
position: absolute;
|
|
9
|
+
left: 24px;
|
|
10
|
+
right: 24px;
|
|
11
|
+
z-index: 3;
|
|
12
|
+
height: 74px;
|
|
13
|
+
border: none;
|
|
14
|
+
border-bottom: 1px solid $ds-neutral-300;
|
|
15
|
+
color: $ds-neutral-900;
|
|
16
|
+
padding: 0;
|
|
17
|
+
}
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
outline-color: transparent!important;
|
|
15
|
-
box-shadow: none!important;
|
|
16
|
-
background-color: $ds-orange-100!important;
|
|
17
|
-
}
|
|
19
|
+
button.sectionButton {
|
|
20
|
+
cursor: pointer;
|
|
18
21
|
|
|
19
|
-
&:
|
|
20
|
-
|
|
22
|
+
&:hover {
|
|
23
|
+
color: $ds-neutral-700;
|
|
24
|
+
|
|
25
|
+
:global(.p-h3) {
|
|
26
|
+
color: $ds-neutral-700;
|
|
27
|
+
}
|
|
21
28
|
}
|
|
22
29
|
}
|
|
23
30
|
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
left: 0;
|
|
27
|
-
right: 0;
|
|
28
|
-
z-index: 3;
|
|
31
|
+
div:last-child > .sectionButtonWrapper > .sectionButton {
|
|
32
|
+
border-bottom: none;
|
|
29
33
|
}
|
|
30
|
-
|
|
31
|
-
.cardIcon {
|
|
32
|
-
width: 20px;
|
|
33
|
-
margin-right: 8px;
|
|
34
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { render, screen } from '../../../../util/testUtils';
|
|
1
|
+
import { fireEvent, render, screen } from '../../../../util/testUtils';
|
|
2
2
|
import { TableContents, TableContentsProps } from './TableContents';
|
|
3
3
|
|
|
4
4
|
const mockData: TableContentsProps['tableData'] = [
|
|
@@ -39,6 +39,27 @@ describe('TableContents', () => {
|
|
|
39
39
|
expect(screen.getByText('Item 2.2.1')).toBeInTheDocument();
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
+
it('renders collapsible section headers as buttons and toggles them', () => {
|
|
43
|
+
render(
|
|
44
|
+
<TableContents collapsibleSections tableData={mockData} title="Table" />
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const sectionButton = screen.getByRole('button', { name: 'Section 2' });
|
|
48
|
+
expect(sectionButton).toHaveAttribute('aria-expanded', 'false');
|
|
49
|
+
|
|
50
|
+
fireEvent.click(sectionButton);
|
|
51
|
+
expect(sectionButton).toHaveAttribute('aria-expanded', 'true');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('renders section headers without a button when not collapsible', () => {
|
|
55
|
+
render(<TableContents tableData={mockData} title="Table" />);
|
|
56
|
+
|
|
57
|
+
expect(
|
|
58
|
+
screen.queryByRole('button', { name: 'Section 2' })
|
|
59
|
+
).not.toBeInTheDocument();
|
|
60
|
+
expect(screen.getByText('Section 2')).toBeInTheDocument();
|
|
61
|
+
});
|
|
62
|
+
|
|
42
63
|
it('hides the table sections when hideDetails and shouldHideDetails is true', () => {
|
|
43
64
|
render(
|
|
44
65
|
<TableContents
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { MutableRefObject, useCallback, useRef, useState } from 'react';
|
|
2
2
|
import { TableSection } from '../TableSection/TableSection';
|
|
3
3
|
import { ChevronDownIcon, ChevronUpIcon } from '../../../icon';
|
|
4
|
-
import { Card } from '../../../cards/card';
|
|
5
4
|
|
|
6
5
|
import styles from './TableContents.module.scss';
|
|
7
6
|
import classNames from 'classnames';
|
|
@@ -25,6 +24,7 @@ export interface TableContentsProps {
|
|
|
25
24
|
title: string;
|
|
26
25
|
cellReplacements?: CellReplacements;
|
|
27
26
|
imageComponent?: (args: any) => JSX.Element;
|
|
27
|
+
selectedColumn?: number;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const TableContents = ({
|
|
@@ -43,6 +43,7 @@ const TableContents = ({
|
|
|
43
43
|
title,
|
|
44
44
|
cellReplacements,
|
|
45
45
|
imageComponent,
|
|
46
|
+
selectedColumn,
|
|
46
47
|
}: TableContentsProps) => {
|
|
47
48
|
const [isSectionOpen, setOpenSection] = useState<number | null>(null);
|
|
48
49
|
const lastToggledSection = useRef<number | null>(null);
|
|
@@ -96,35 +97,40 @@ const TableContents = ({
|
|
|
96
97
|
const result = (isFirstSection || isVisible) && (
|
|
97
98
|
<div key={index} ref={(el) => { sectionRefs.current[index] = el; }}>
|
|
98
99
|
{section?.title && (
|
|
99
|
-
<div className={styles.
|
|
100
|
-
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
100
|
+
<div className={styles.sectionButtonWrapper}>
|
|
101
|
+
{collapsibleSections ? (
|
|
102
|
+
<button
|
|
103
|
+
type="button"
|
|
104
|
+
aria-expanded={isExpanded}
|
|
105
|
+
className={classNames(
|
|
106
|
+
'd-flex ai-center jc-between ta-left bg-white',
|
|
107
|
+
styles.sectionButton
|
|
108
|
+
)}
|
|
109
|
+
onClick={() => handleToggleSection(index)}
|
|
110
|
+
>
|
|
111
|
+
<span className="d-flex ai-center gap8">
|
|
112
|
+
{renderedIcon}
|
|
113
|
+
<span className="p-h3">{section.title}</span>
|
|
114
|
+
</span>
|
|
115
|
+
{isExpanded ? (
|
|
116
|
+
<ChevronUpIcon size={20} />
|
|
117
|
+
) : (
|
|
118
|
+
<ChevronDownIcon size={20} />
|
|
119
|
+
)}
|
|
120
|
+
</button>
|
|
121
|
+
) : (
|
|
122
|
+
<div
|
|
123
|
+
className={classNames(
|
|
124
|
+
'd-flex ai-center jc-between ta-left bg-white',
|
|
125
|
+
styles.sectionButton
|
|
126
|
+
)}
|
|
127
|
+
>
|
|
128
|
+
<span className="d-flex ai-center gap8">
|
|
129
|
+
{renderedIcon}
|
|
130
|
+
<span className="p-h3">{section.title}</span>
|
|
131
|
+
</span>
|
|
132
|
+
</div>
|
|
133
|
+
)}
|
|
128
134
|
</div>
|
|
129
135
|
)}
|
|
130
136
|
|
|
@@ -133,7 +139,9 @@ const TableContents = ({
|
|
|
133
139
|
onTransitionEnd={() => handleScrollToSection(index)}
|
|
134
140
|
>
|
|
135
141
|
<TableSection
|
|
136
|
-
className={classNames(className, '
|
|
142
|
+
className={classNames(className, 'mb16', {
|
|
143
|
+
mt16: !!section?.title,
|
|
144
|
+
})}
|
|
137
145
|
tableCellRows={
|
|
138
146
|
isFirstSection ? rows : [firstHeadRow, ...rows]
|
|
139
147
|
}
|
|
@@ -147,6 +155,7 @@ const TableContents = ({
|
|
|
147
155
|
width={tableWidth}
|
|
148
156
|
cellReplacements={cellReplacements}
|
|
149
157
|
imageComponent={imageComponent}
|
|
158
|
+
selectedColumn={selectedColumn}
|
|
150
159
|
/>
|
|
151
160
|
</Collapsible>
|
|
152
161
|
</div>
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
.table {
|
|
5
5
|
border-collapse: collapse;
|
|
6
6
|
table-layout: fixed;
|
|
7
|
+
}
|
|
7
8
|
|
|
9
|
+
.tableMultiplePlans {
|
|
8
10
|
@include p-size-tablet {
|
|
9
11
|
min-width: 845px;
|
|
10
12
|
}
|
|
@@ -12,4 +14,9 @@
|
|
|
12
14
|
|
|
13
15
|
.tr {
|
|
14
16
|
min-height: 72px;
|
|
17
|
+
border-bottom: 1px solid $ds-neutral-300;
|
|
18
|
+
|
|
19
|
+
&:last-child {
|
|
20
|
+
border-bottom: none;
|
|
21
|
+
}
|
|
15
22
|
}
|