playbook_ui 16.3.0.pre.alpha.PLAY2810toastaddmargin14803 → 16.3.0.pre.alpha.PLAY2814advancedtablesortparentonlyreact14813
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +5 -2
- data/app/pb_kits/playbook/pb_advanced_table/Utilities/RowModelUtils.ts +100 -0
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +4 -1
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +35 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_parent_only.jsx +175 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_parent_only.md +5 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_advanced_table/index.js +48 -29
- data/app/pb_kits/playbook/pb_collapsible/index.js +15 -26
- data/app/pb_kits/playbook/pb_dropdown/index.js +67 -37
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.scss +0 -4
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.tsx +0 -3
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/index.js +1 -2
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/fixed_confirmation_toast.rb +1 -7
- data/app/pb_kits/playbook/utilities/domHelpers.ts +50 -0
- data/dist/chunks/vendor.js +2 -2
- data/dist/menu.yml +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +6 -6
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin.html.erb +0 -46
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin.jsx +0 -42
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin_rails.md +0 -1
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin_react.md +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '08fb76d06568a9cfa7e70127d6025444f9f52640848d94b246e43f1d9a4e40bd'
|
|
4
|
+
data.tar.gz: 981afae84f0710df2dbb89c76fa81f0676f2d9bc795f034bc2cf07fe45b20226
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e588d74894b397d7fe857d87534df43f41330dc7cb223a30aacd2289abb505cd135e099ad4802290590dc7397ba81b9e34bc2ac390aff54b52bf0f069a684680
|
|
7
|
+
data.tar.gz: 917c919b3f66125c7fb7eeaf41f38d8912cadc0039653e8634fb780f2b171a1dd4f86208c9897b7e904abaf78f084a2208df591251a5479888065ae7a8fc9320
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { GenericObject } from "../../types";
|
|
13
13
|
import { createColumnHelper } from "@tanstack/react-table";
|
|
14
14
|
import { createCellFunction } from "../Utilities/CellRendererUtils";
|
|
15
|
+
import { getParentOnlySortedRowModel } from "../Utilities/RowModelUtils";
|
|
15
16
|
|
|
16
17
|
interface UseTableStateProps {
|
|
17
18
|
tableData: GenericObject[];
|
|
@@ -36,6 +37,7 @@ interface UseTableStateProps {
|
|
|
36
37
|
columnVisibilityControl?: GenericObject;
|
|
37
38
|
rowStyling?: GenericObject;
|
|
38
39
|
inlineRowLoading?: boolean;
|
|
40
|
+
sortParentOnly?: boolean;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
export function useTableState({
|
|
@@ -55,7 +57,8 @@ export function useTableState({
|
|
|
55
57
|
columnVisibilityControl,
|
|
56
58
|
pinnedRows,
|
|
57
59
|
rowStyling,
|
|
58
|
-
inlineRowLoading = false
|
|
60
|
+
inlineRowLoading = false,
|
|
61
|
+
sortParentOnly = false
|
|
59
62
|
}: UseTableStateProps) {
|
|
60
63
|
|
|
61
64
|
// Create a local state for expanded and setExpanded if expandedControl not used
|
|
@@ -190,7 +193,7 @@ export function useTableState({
|
|
|
190
193
|
getSubRows: (row: GenericObject) => row.children,
|
|
191
194
|
getCoreRowModel: getCoreRowModel(),
|
|
192
195
|
getExpandedRowModel: getExpandedRowModel(),
|
|
193
|
-
getSortedRowModel: getSortedRowModel(),
|
|
196
|
+
getSortedRowModel: sortParentOnly ? getParentOnlySortedRowModel() : getSortedRowModel(),
|
|
194
197
|
enableSortingRemoval: enableSortingRemoval,
|
|
195
198
|
sortDescFirst: true,
|
|
196
199
|
onRowSelectionChange: setRowSelection,
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Returns a row model getter that sorts only depth-0 (parent) rows so children and grandchild rows keep their original order under each parent.
|
|
2
|
+
|
|
3
|
+
import type { Table, Row, RowModel, RowData } from "@tanstack/react-table";
|
|
4
|
+
|
|
5
|
+
export function getParentOnlySortedRowModel<TData extends RowData>(): (
|
|
6
|
+
table: Table<TData>
|
|
7
|
+
) => () => RowModel<TData> {
|
|
8
|
+
return (table) => () => {
|
|
9
|
+
const sortingState = table.getState().sorting;
|
|
10
|
+
const rowModel = table.getPreSortedRowModel();
|
|
11
|
+
|
|
12
|
+
if (!rowModel.rows.length || !sortingState?.length) {
|
|
13
|
+
return rowModel;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const sortedFlatRows: Row<TData>[] = [];
|
|
17
|
+
const availableSorting = sortingState.filter((sort) =>
|
|
18
|
+
table.getColumn(sort.id)?.getCanSort()
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const columnInfoById: Record<
|
|
22
|
+
string,
|
|
23
|
+
{
|
|
24
|
+
sortUndefined?: false | -1 | 1 | "first" | "last";
|
|
25
|
+
invertSorting?: boolean;
|
|
26
|
+
sortingFn: (rowA: Row<TData>, rowB: Row<TData>, columnId: string) => number;
|
|
27
|
+
}
|
|
28
|
+
> = {};
|
|
29
|
+
|
|
30
|
+
availableSorting.forEach((sortEntry) => {
|
|
31
|
+
const column = table.getColumn(sortEntry.id);
|
|
32
|
+
if (!column) return;
|
|
33
|
+
columnInfoById[sortEntry.id] = {
|
|
34
|
+
sortUndefined: column.columnDef.sortUndefined,
|
|
35
|
+
invertSorting: column.columnDef.invertSorting,
|
|
36
|
+
sortingFn: column.getSortingFn(),
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const parentRows = rowModel.rows.map((row) => ({ ...row }));
|
|
41
|
+
parentRows.sort((rowA, rowB) => {
|
|
42
|
+
for (let i = 0; i < availableSorting.length; i += 1) {
|
|
43
|
+
const sortEntry = availableSorting[i]!;
|
|
44
|
+
const columnInfo = columnInfoById[sortEntry.id]!;
|
|
45
|
+
const sortUndefined = columnInfo.sortUndefined;
|
|
46
|
+
const isDesc = sortEntry?.desc ?? false;
|
|
47
|
+
let sortInt = 0;
|
|
48
|
+
|
|
49
|
+
if (sortUndefined) {
|
|
50
|
+
const aValue = rowA.getValue(sortEntry.id);
|
|
51
|
+
const bValue = rowB.getValue(sortEntry.id);
|
|
52
|
+
const aUndefined = aValue === undefined;
|
|
53
|
+
const bUndefined = bValue === undefined;
|
|
54
|
+
if (aUndefined || bUndefined) {
|
|
55
|
+
if (sortUndefined === "first") return aUndefined ? -1 : 1;
|
|
56
|
+
if (sortUndefined === "last") return aUndefined ? 1 : -1;
|
|
57
|
+
sortInt =
|
|
58
|
+
aUndefined && bUndefined
|
|
59
|
+
? 0
|
|
60
|
+
: aUndefined
|
|
61
|
+
? sortUndefined
|
|
62
|
+
: -sortUndefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (sortInt === 0) {
|
|
67
|
+
sortInt = columnInfo.sortingFn(rowA, rowB, sortEntry.id);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (sortInt !== 0) {
|
|
71
|
+
if (isDesc) sortInt *= -1;
|
|
72
|
+
if (columnInfo.invertSorting) sortInt *= -1;
|
|
73
|
+
return sortInt;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return rowA.index - rowB.index;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
function flattenRowsInOrder(rows: Row<TData>[]): void {
|
|
80
|
+
rows.forEach((row) => {
|
|
81
|
+
sortedFlatRows.push(row);
|
|
82
|
+
if (row.subRows?.length) {
|
|
83
|
+
flattenRowsInOrder(row.subRows);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
flattenRowsInOrder(parentRows);
|
|
88
|
+
|
|
89
|
+
const rowsById: Record<string, Row<TData>> = {};
|
|
90
|
+
sortedFlatRows.forEach((row) => {
|
|
91
|
+
rowsById[row.id] = row;
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
rows: parentRows,
|
|
96
|
+
flatRows: sortedFlatRows,
|
|
97
|
+
rowsById,
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -66,6 +66,7 @@ type AdvancedTableProps = {
|
|
|
66
66
|
showActionsBar?: boolean,
|
|
67
67
|
persistToggleExpansionButton?: boolean,
|
|
68
68
|
sortControl?: GenericObject
|
|
69
|
+
sortParentOnly?: boolean
|
|
69
70
|
tableData: GenericObject[]
|
|
70
71
|
tableOptions?: GenericObject
|
|
71
72
|
tableProps?: GenericObject
|
|
@@ -114,6 +115,7 @@ const AdvancedTable = (props: AdvancedTableProps) => {
|
|
|
114
115
|
selectableRows,
|
|
115
116
|
persistToggleExpansionButton = false,
|
|
116
117
|
sortControl,
|
|
118
|
+
sortParentOnly = false,
|
|
117
119
|
stickyLeftColumn,
|
|
118
120
|
tableData,
|
|
119
121
|
tableOptions,
|
|
@@ -159,7 +161,8 @@ const AdvancedTable = (props: AdvancedTableProps) => {
|
|
|
159
161
|
columnVisibilityControl,
|
|
160
162
|
pinnedRows,
|
|
161
163
|
rowStyling,
|
|
162
|
-
inlineRowLoading
|
|
164
|
+
inlineRowLoading,
|
|
165
|
+
sortParentOnly
|
|
163
166
|
});
|
|
164
167
|
|
|
165
168
|
// Initialize table actions
|
|
@@ -495,7 +495,41 @@ test("sort button exists and sorts column data", () => {
|
|
|
495
495
|
|
|
496
496
|
const row2 = kit.getElementsByTagName('tr')[2]
|
|
497
497
|
expect(row2.id).toBe("0-0-0-row")
|
|
498
|
-
})
|
|
498
|
+
})
|
|
499
|
+
|
|
500
|
+
test("sortParentOnly sorts only parent rows and keeps children grouped under parent", () => {
|
|
501
|
+
render(
|
|
502
|
+
<AdvancedTable
|
|
503
|
+
columnDefinitions={columnDefinitions}
|
|
504
|
+
data={{ testid: testId }}
|
|
505
|
+
sortParentOnly
|
|
506
|
+
tableData={MOCK_DATA}
|
|
507
|
+
>
|
|
508
|
+
<AdvancedTable.Header enableSorting />
|
|
509
|
+
<AdvancedTable.Body />
|
|
510
|
+
</AdvancedTable>
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
const kit = screen.getByTestId(testId)
|
|
514
|
+
const sortButton = kit.querySelector(".header-sort-button.pb_th_link")
|
|
515
|
+
expect(sortButton).toBeInTheDocument()
|
|
516
|
+
|
|
517
|
+
const tbody = kit.querySelector('tbody')
|
|
518
|
+
const rowsBefore = tbody.getElementsByTagName('tr')
|
|
519
|
+
expect(rowsBefore[0]).toHaveTextContent('2021')
|
|
520
|
+
|
|
521
|
+
sortButton.click()
|
|
522
|
+
|
|
523
|
+
const rowsAfter = tbody.getElementsByTagName('tr')
|
|
524
|
+
expect(rowsAfter[0]).toHaveTextContent('2022')
|
|
525
|
+
|
|
526
|
+
const expandButton = kit.querySelector(".gray-icon.expand-toggle-icon")
|
|
527
|
+
expandButton.click()
|
|
528
|
+
|
|
529
|
+
const rowsExpanded = tbody.getElementsByTagName('tr')
|
|
530
|
+
expect(rowsExpanded.length).toBeGreaterThan(1)
|
|
531
|
+
expect(rowsExpanded[1]).toHaveTextContent('Q1')
|
|
532
|
+
})
|
|
499
533
|
|
|
500
534
|
test("Generates Table.Header default + custom classname", () => {
|
|
501
535
|
render(
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import AdvancedTable from '../../pb_advanced_table/_advanced_table'
|
|
3
|
+
import MOCK_DATA from "./advanced_table_mock_data.json"
|
|
4
|
+
|
|
5
|
+
import Caption from "../../pb_caption/_caption"
|
|
6
|
+
|
|
7
|
+
const sharedColumnDefinitions = [
|
|
8
|
+
{
|
|
9
|
+
accessor: "year",
|
|
10
|
+
label: "Year",
|
|
11
|
+
cellAccessors: ["quarter", "month", "day"],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
accessor: "newEnrollments",
|
|
15
|
+
label: "New Enrollments",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
accessor: "scheduledMeetings",
|
|
19
|
+
label: "Scheduled Meetings",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
accessor: "attendanceRate",
|
|
23
|
+
label: "Attendance Rate",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
accessor: "completedClasses",
|
|
27
|
+
label: "Completed Classes",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
accessor: "classCompletionRate",
|
|
31
|
+
label: "Class Completion Rate",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
accessor: "graduatedStudents",
|
|
35
|
+
label: "Graduated Students",
|
|
36
|
+
},
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
const sortByColumnDefinitions = [
|
|
40
|
+
{
|
|
41
|
+
accessor: "year",
|
|
42
|
+
label: "Year",
|
|
43
|
+
cellAccessors: ["quarter", "month", "day"],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
accessor: "newEnrollments",
|
|
47
|
+
label: "New Enrollments",
|
|
48
|
+
enableSort: true,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
accessor: "scheduledMeetings",
|
|
52
|
+
label: "Scheduled Meetings",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
accessor: "attendanceRate",
|
|
56
|
+
label: "Attendance Rate",
|
|
57
|
+
enableSort: true,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
accessor: "completedClasses",
|
|
61
|
+
label: "Completed Classes",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
accessor: "classCompletionRate",
|
|
65
|
+
label: "Class Completion Rate",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
accessor: "graduatedStudents",
|
|
69
|
+
label: "Graduated Students",
|
|
70
|
+
},
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
const sortByColumnMultiDefinitions = [
|
|
74
|
+
{
|
|
75
|
+
accessor: "year",
|
|
76
|
+
label: "Year",
|
|
77
|
+
cellAccessors: ["quarter", "month", "day"],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
label: "Enrollment Data",
|
|
81
|
+
columns: [
|
|
82
|
+
{
|
|
83
|
+
label: "Enrollment Stats",
|
|
84
|
+
columns: [
|
|
85
|
+
{
|
|
86
|
+
accessor: "newEnrollments",
|
|
87
|
+
label: "New Enrollments",
|
|
88
|
+
enableSort: true,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
accessor: "scheduledMeetings",
|
|
92
|
+
label: "Scheduled Meetings",
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
label: "Performance Data",
|
|
100
|
+
columns: [
|
|
101
|
+
{
|
|
102
|
+
label: "Completion Metrics",
|
|
103
|
+
columns: [
|
|
104
|
+
{
|
|
105
|
+
accessor: "completedClasses",
|
|
106
|
+
label: "Completed Classes",
|
|
107
|
+
enableSort: true,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
accessor: "classCompletionRate",
|
|
111
|
+
label: "Class Completion Rate",
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
label: "Attendance",
|
|
117
|
+
columns: [
|
|
118
|
+
{
|
|
119
|
+
accessor: "attendanceRate",
|
|
120
|
+
label: "Attendance Rate",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
accessor: "scheduledMeetings",
|
|
124
|
+
label: "Scheduled Meetings",
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
const AdvancedTableSortParentOnly = (props) => {
|
|
133
|
+
return (
|
|
134
|
+
<div>
|
|
135
|
+
<Caption text="Enable Sorting (first column) + sortParentOnly" />
|
|
136
|
+
<AdvancedTable
|
|
137
|
+
columnDefinitions={sharedColumnDefinitions}
|
|
138
|
+
sortParentOnly
|
|
139
|
+
tableData={MOCK_DATA}
|
|
140
|
+
{...props}
|
|
141
|
+
>
|
|
142
|
+
<AdvancedTable.Header enableSorting />
|
|
143
|
+
<AdvancedTable.Body />
|
|
144
|
+
</AdvancedTable>
|
|
145
|
+
<Caption marginTop="md"
|
|
146
|
+
text="Sort by column + sortParentOnly"
|
|
147
|
+
/>
|
|
148
|
+
<AdvancedTable
|
|
149
|
+
columnDefinitions={sortByColumnDefinitions}
|
|
150
|
+
enableSortingRemoval
|
|
151
|
+
sortParentOnly
|
|
152
|
+
tableData={MOCK_DATA}
|
|
153
|
+
{...props}
|
|
154
|
+
>
|
|
155
|
+
<AdvancedTable.Header />
|
|
156
|
+
<AdvancedTable.Body />
|
|
157
|
+
</AdvancedTable>
|
|
158
|
+
<Caption marginTop="md"
|
|
159
|
+
text="Sort by column (multi-column) + sortParentOnly"
|
|
160
|
+
/>
|
|
161
|
+
<AdvancedTable
|
|
162
|
+
columnDefinitions={sortByColumnMultiDefinitions}
|
|
163
|
+
enableSortingRemoval
|
|
164
|
+
sortParentOnly
|
|
165
|
+
tableData={MOCK_DATA}
|
|
166
|
+
{...props}
|
|
167
|
+
>
|
|
168
|
+
<AdvancedTable.Header enableSorting />
|
|
169
|
+
<AdvancedTable.Body />
|
|
170
|
+
</AdvancedTable>
|
|
171
|
+
</div>
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export default AdvancedTableSortParentOnly
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
The `sortParentOnly` prop is a boolean set to `false` by default. When set to `true`, only parent (depth-0) rows are re-ordered when sorting; children and grandchildren stay grouped under their parent and keep their original order.
|
|
2
|
+
|
|
3
|
+
`sortParentOnly` works with every sorting mode: `enableSorting` on the header, per-column `enableSort: true`, and sortable leaf columns in the multi-header variant. Sort indicators behave as usual.
|
|
4
|
+
|
|
5
|
+
When omitted or `false`, sorting applies to all levels.
|
|
@@ -39,6 +39,7 @@ examples:
|
|
|
39
39
|
- advanced_table_sort_per_column: Enable Sort By Column
|
|
40
40
|
- advanced_table_sort_per_column_for_multi_column: Enable Sort By Column (Multi-Column)
|
|
41
41
|
- advanced_table_custom_sort: Custom Sort
|
|
42
|
+
- advanced_table_sort_parent_only: Sort Parent Only
|
|
42
43
|
- advanced_table_expanded_control: Expanded Control
|
|
43
44
|
- advanced_table_expand_by_depth: Expand by Depth
|
|
44
45
|
- advanced_table_subrow_headers: SubRow Headers
|
|
@@ -49,4 +49,5 @@ export { default as AdvancedTablePaddingControlPerRow } from './_advanced_table_
|
|
|
49
49
|
export { default as AdvancedTableColumnStylingBackground } from './_advanced_table_column_styling_background.jsx'
|
|
50
50
|
export { default as AdvancedTableColumnStylingBackgroundMulti } from './_advanced_table_column_styling_background_multi.jsx'
|
|
51
51
|
export { default as AdvancedTableColumnStylingBackgroundCustom } from './_advanced_table_column_styling_background_custom.jsx'
|
|
52
|
-
export { default as AdvancedTableCascadeCollapse } from './_advanced_table_cascade_collapse.jsx'
|
|
52
|
+
export { default as AdvancedTableCascadeCollapse } from './_advanced_table_cascade_collapse.jsx'
|
|
53
|
+
export { default as AdvancedTableSortParentOnly } from './_advanced_table_sort_parent_only.jsx'
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import PbEnhancedElement from "../pb_enhanced_element";
|
|
2
2
|
import { updateSelectionActionBar } from "./advanced_table_action_bar";
|
|
3
|
+
import { setArrowVisibility, toggleVisibility } from "../utilities/domHelpers";
|
|
3
4
|
|
|
4
5
|
const ADVANCED_TABLE_SELECTOR = "[data-advanced-table]";
|
|
5
6
|
const DOWN_ARROW_SELECTOR = "#advanced-table_open_icon";
|
|
@@ -20,10 +21,18 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
20
21
|
this.childRowsMap = new Map();
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
get table() {
|
|
25
|
+
return this.cachedTable || (this.cachedTable = this.element.closest("table"));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get mainTable() {
|
|
29
|
+
return this.cachedMainTable || (this.cachedMainTable = this.element.closest(".pb_advanced_table"));
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
// Fetch and cache child rows for a given parent row ID
|
|
24
33
|
childRowsFor(parentId) {
|
|
25
34
|
if (!this.childRowsMap.has(parentId)) {
|
|
26
|
-
const table = this.
|
|
35
|
+
const table = this.table;
|
|
27
36
|
const rows = Array.from(
|
|
28
37
|
table.querySelectorAll(`tr[data-row-parent="${parentId}"]`)
|
|
29
38
|
);
|
|
@@ -33,7 +42,8 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
updateTableSelectedRowsAttribute() {
|
|
36
|
-
const mainTable = this.
|
|
45
|
+
const mainTable = this.mainTable;
|
|
46
|
+
if (!mainTable) return;
|
|
37
47
|
mainTable.dataset.selectedRows = JSON.stringify(
|
|
38
48
|
Array.from(PbAdvancedTable.selectedRows)
|
|
39
49
|
);
|
|
@@ -41,7 +51,8 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
41
51
|
|
|
42
52
|
// Recalculate selected count based on all checked checkboxes
|
|
43
53
|
recalculateSelectedCount() {
|
|
44
|
-
const table = this.
|
|
54
|
+
const table = this.table;
|
|
55
|
+
if (!table) return;
|
|
45
56
|
|
|
46
57
|
// Get all checkboxes that could be part of the selection
|
|
47
58
|
// This includes row checkboxes and any parent checkboxes that might be programmatically checked
|
|
@@ -95,7 +106,7 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
95
106
|
});
|
|
96
107
|
|
|
97
108
|
this.updateTableSelectedRowsAttribute();
|
|
98
|
-
updateSelectionActionBar(
|
|
109
|
+
updateSelectionActionBar(this.mainTable, PbAdvancedTable.selectedRows.size);
|
|
99
110
|
|
|
100
111
|
// Sync header select-all state
|
|
101
112
|
if (selectAllCheckbox) {
|
|
@@ -139,7 +150,7 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
139
150
|
|
|
140
151
|
this.updateTableSelectedRowsAttribute();
|
|
141
152
|
|
|
142
|
-
const table =
|
|
153
|
+
const table = this.table;
|
|
143
154
|
const selectAllCheckbox = table.querySelector("#select-all-rows");
|
|
144
155
|
|
|
145
156
|
if (selectAllCheckbox) {
|
|
@@ -153,7 +164,7 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
153
164
|
);
|
|
154
165
|
selectAllInput.checked = allChecked;
|
|
155
166
|
}
|
|
156
|
-
updateSelectionActionBar(
|
|
167
|
+
updateSelectionActionBar(this.mainTable, PbAdvancedTable.selectedRows.size);
|
|
157
168
|
}
|
|
158
169
|
|
|
159
170
|
get target() {
|
|
@@ -161,10 +172,11 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
161
172
|
}
|
|
162
173
|
|
|
163
174
|
connect() {
|
|
164
|
-
const table = this.
|
|
175
|
+
const table = this.table;
|
|
176
|
+
if (!table) return;
|
|
165
177
|
|
|
166
178
|
this.hideCloseIcon();
|
|
167
|
-
const mainTable = this.
|
|
179
|
+
const mainTable = this.mainTable;
|
|
168
180
|
|
|
169
181
|
// This so it is hidden on first render
|
|
170
182
|
if (mainTable) {
|
|
@@ -271,9 +283,7 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
271
283
|
}
|
|
272
284
|
|
|
273
285
|
// Find direct child rows
|
|
274
|
-
const childRows =
|
|
275
|
-
table.querySelectorAll(`[data-row-parent="${toggleBtn.id}"]`)
|
|
276
|
-
);
|
|
286
|
+
const childRows = this.childRowsFor(toggleBtn.id);
|
|
277
287
|
this.toggleElement(childRows);
|
|
278
288
|
|
|
279
289
|
// Restore original element context
|
|
@@ -284,7 +294,8 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
284
294
|
}
|
|
285
295
|
|
|
286
296
|
addBorderRadiusOnLastVisibleRow() {
|
|
287
|
-
const parentElement = this.
|
|
297
|
+
const parentElement = this.mainTable;
|
|
298
|
+
if (!parentElement) return;
|
|
288
299
|
|
|
289
300
|
const table = document.getElementById(parentElement.id);
|
|
290
301
|
|
|
@@ -316,11 +327,9 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
316
327
|
elements.forEach((elem) => {
|
|
317
328
|
elem.style.display = "table-row";
|
|
318
329
|
elem.classList.add("is-visible");
|
|
319
|
-
const childRowsAll = this.
|
|
320
|
-
.
|
|
321
|
-
|
|
322
|
-
`[data-advanced-table-content^="${elem.dataset.advancedTableContent}-"]`
|
|
323
|
-
);
|
|
330
|
+
const childRowsAll = this.table.querySelectorAll(
|
|
331
|
+
`[data-advanced-table-content^="${elem.dataset.advancedTableContent}-"]`
|
|
332
|
+
);
|
|
324
333
|
|
|
325
334
|
childRowsAll.forEach((childRow) => {
|
|
326
335
|
const dataContent = childRow.dataset.advancedTableContent;
|
|
@@ -382,8 +391,7 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
382
391
|
const currentDepth = parseInt(elem.dataset.rowDepth);
|
|
383
392
|
if (childrenArray.length > currentDepth) {
|
|
384
393
|
// Find the child rows corresponding to this parent row
|
|
385
|
-
const childRows = this.
|
|
386
|
-
.closest("table")
|
|
394
|
+
const childRows = this.table
|
|
387
395
|
.querySelectorAll(
|
|
388
396
|
`[data-advanced-table-content^="${elem.dataset.advancedTableContent}-"]`
|
|
389
397
|
);
|
|
@@ -401,28 +409,39 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
|
401
409
|
|
|
402
410
|
const isVisible = elements[0].classList.contains("is-visible");
|
|
403
411
|
|
|
404
|
-
|
|
405
|
-
|
|
412
|
+
const isExpanded = toggleVisibility({
|
|
413
|
+
isVisible,
|
|
414
|
+
onHide: () => this.hideElement(elements),
|
|
415
|
+
onShow: () => this.showElement(elements),
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
isExpanded ? this.displayUpArrow() : this.displayDownArrow();
|
|
406
419
|
|
|
407
420
|
const row = this.element.closest("tr");
|
|
408
421
|
if (row) {
|
|
409
|
-
row.classList.toggle("bg-silver",
|
|
410
|
-
row.classList.toggle("pb-bg-row-white",
|
|
422
|
+
row.classList.toggle("bg-silver", isExpanded);
|
|
423
|
+
row.classList.toggle("pb-bg-row-white", !isExpanded);
|
|
411
424
|
}
|
|
412
425
|
|
|
413
426
|
this.addBorderRadiusOnLastVisibleRow();
|
|
414
427
|
}
|
|
415
428
|
|
|
416
429
|
displayDownArrow() {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
430
|
+
setArrowVisibility({
|
|
431
|
+
rootElement: this.element,
|
|
432
|
+
downSelector: DOWN_ARROW_SELECTOR,
|
|
433
|
+
upSelector: UP_ARROW_SELECTOR,
|
|
434
|
+
showDownArrow: true,
|
|
435
|
+
});
|
|
420
436
|
}
|
|
421
437
|
|
|
422
438
|
displayUpArrow() {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
439
|
+
setArrowVisibility({
|
|
440
|
+
rootElement: this.element,
|
|
441
|
+
downSelector: DOWN_ARROW_SELECTOR,
|
|
442
|
+
upSelector: UP_ARROW_SELECTOR,
|
|
443
|
+
showDownArrow: false,
|
|
444
|
+
});
|
|
426
445
|
}
|
|
427
446
|
|
|
428
447
|
static handleToggleAllHeaders(element) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import PbEnhancedElement from '../pb_enhanced_element'
|
|
2
|
+
import { getElementHeight, setArrowVisibility, toggleVisibility } from '../utilities/domHelpers'
|
|
2
3
|
|
|
3
4
|
const MAIN_SELECTOR = '[data-collapsible-main]'
|
|
4
5
|
const CONTENT_SELECTOR = '[data-collapsible-content]'
|
|
@@ -43,15 +44,7 @@ export default class PbCollapsible extends PbEnhancedElement {
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
showElement(elem) {
|
|
46
|
-
|
|
47
|
-
const getHeight = () => {
|
|
48
|
-
elem.style.display = 'block'
|
|
49
|
-
const height = elem.scrollHeight + 'px' // Get it's height
|
|
50
|
-
elem.style.display = '' // Hide it again
|
|
51
|
-
return height
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const height = getHeight()
|
|
47
|
+
const height = getElementHeight(elem)
|
|
55
48
|
elem.classList.add('is-visible')
|
|
56
49
|
elem.style.height = height // Update the max-height
|
|
57
50
|
elem.style.overflow = "hidden"
|
|
@@ -82,26 +75,22 @@ export default class PbCollapsible extends PbEnhancedElement {
|
|
|
82
75
|
}
|
|
83
76
|
|
|
84
77
|
toggleElement(elem) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
this.
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
this.
|
|
92
|
-
this.displayUpArrow()
|
|
78
|
+
const isExpanded = toggleVisibility({
|
|
79
|
+
isVisible: elem.classList.contains('is-visible'),
|
|
80
|
+
onHide: () => this.hideElement(elem),
|
|
81
|
+
onShow: () => this.showElement(elem),
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
isExpanded ? this.displayUpArrow() : this.displayDownArrow()
|
|
93
85
|
}
|
|
94
86
|
|
|
95
87
|
toggleArrows(showDownArrow) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
if (upArrow) {
|
|
103
|
-
upArrow.style.display = showDownArrow ? 'none' : 'inline-block';
|
|
104
|
-
}
|
|
88
|
+
setArrowVisibility({
|
|
89
|
+
rootElement: this.element,
|
|
90
|
+
downSelector: DOWN_ARROW_SELECTOR,
|
|
91
|
+
upSelector: UP_ARROW_SELECTOR,
|
|
92
|
+
showDownArrow,
|
|
93
|
+
})
|
|
105
94
|
}
|
|
106
95
|
|
|
107
96
|
displayDownArrow() {
|