playbook_ui 13.15.0.pre.alpha.1132globalpropdatepickerspacing1929 → 13.16.0.pre.alpha.PBNTR177NewAdvancedTableKit2010

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +14 -12
  3. data/app/pb_kits/playbook/index.js +2 -1
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/CollapsibleTrail.tsx +30 -0
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +59 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/Components/LoadingCell.tsx +5 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/Components/SortIconButton.tsx +30 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/Components/SubRowHeaderRow.tsx +61 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +120 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/Components/ToggleIconButton.tsx +28 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +5 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/SubComponents/TableBody.tsx +95 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/SubComponents/TableHeader.tsx +51 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/Utilities/helper_functions.tsx +77 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/Utilities/types.ts +8 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +97 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +237 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +56 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.jsx +52 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_mock_data.js +278 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +5 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -0
  23. data/app/pb_kits/playbook/pb_advanced_table/scss_partials/_loading.scss +60 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/scss_partials/_pseudo_states.scss +12 -0
  25. data/app/pb_kits/playbook/pb_date_picker/_date_picker.scss +3 -2
  26. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +1 -43
  27. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +1 -2
  28. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +1 -15
  29. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +40 -33
  30. data/app/pb_kits/playbook/pb_date_picker/plugins/quickPick.tsx +4 -4
  31. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_input_styles.scss +2 -1
  32. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.tsx +44 -30
  33. data/app/pb_kits/playbook/pb_flex/_flex.tsx +5 -5
  34. data/app/pb_kits/playbook/pb_form_group/_form_group.tsx +3 -2
  35. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +7 -4
  36. data/app/pb_kits/playbook/pb_gauge/_gauge.tsx +10 -10
  37. data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +10 -9
  38. data/app/pb_kits/playbook/pb_icon_stat_value/_icon_stat_value.tsx +3 -2
  39. data/app/pb_kits/playbook/pb_icon_value/_icon_value.tsx +3 -2
  40. data/app/pb_kits/playbook/pb_label_value/_label_value.tsx +1 -1
  41. data/app/pb_kits/playbook/pb_layout/_layout.tsx +2 -1
  42. data/app/pb_kits/playbook/pb_layout/layout.test.js +8 -4
  43. data/app/pb_kits/playbook/pb_legend/_legend.tsx +6 -6
  44. data/app/pb_kits/playbook/pb_lightbox/Carousel/Slides.tsx +4 -4
  45. data/app/pb_kits/playbook/pb_lightbox/Carousel/Thumbnail.tsx +1 -1
  46. data/app/pb_kits/playbook/pb_lightbox/Carousel/index.tsx +3 -3
  47. data/app/pb_kits/playbook/pb_lightbox/Header/_lightbox_header.tsx +30 -22
  48. data/app/pb_kits/playbook/pb_lightbox/_lightbox.tsx +5 -5
  49. data/app/pb_kits/playbook/pb_line_graph/_line_graph.tsx +4 -4
  50. data/app/pb_kits/playbook/pb_list/_list.tsx +15 -15
  51. data/app/pb_kits/playbook/pb_list/_list_item.tsx +1 -1
  52. data/app/pb_kits/playbook/pb_loading_inline/_loading_inline.tsx +9 -9
  53. data/app/pb_kits/playbook/pb_map/_map.tsx +8 -8
  54. data/app/pb_kits/playbook/pb_map/_map_controls.tsx +15 -7
  55. data/app/pb_kits/playbook/pb_map/_map_custom_button.tsx +4 -2
  56. data/app/pb_kits/playbook/pb_message/_message.tsx +1 -1
  57. data/app/pb_kits/playbook/pb_message/_message_mention.tsx +6 -6
  58. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +46 -42
  59. data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.tsx +20 -20
  60. data/app/pb_kits/playbook/pb_nav/_item.tsx +56 -47
  61. data/app/pb_kits/playbook/pb_nav/_nav.tsx +15 -15
  62. data/app/pb_kits/playbook/pb_passphrase/_passphrase.tsx +51 -50
  63. data/app/pb_kits/playbook/pb_person_contact/_person_contact.tsx +20 -19
  64. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +4 -3
  65. data/app/pb_kits/playbook/pb_popover/_popover.tsx +6 -4
  66. data/app/pb_kits/playbook/pb_progress_pills/_progress_pills.tsx +20 -20
  67. data/app/pb_kits/playbook/pb_progress_simple/_progress_simple.tsx +4 -4
  68. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/EditorButton.tsx +19 -17
  69. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/EditorTypes.ts +1 -1
  70. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/MoreExtensionsDropdown.tsx +23 -21
  71. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/Toolbar.tsx +18 -10
  72. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/ToolbarDropdown.tsx +46 -23
  73. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/ToolbarHistory.tsx +8 -8
  74. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/ToolbarNodes.tsx +7 -7
  75. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +17 -15
  76. data/app/pb_kits/playbook/pb_section_separator/_section_separator.tsx +9 -7
  77. data/app/pb_kits/playbook/pb_select/_select.scss +13 -4
  78. data/app/pb_kits/playbook/pb_select/_select.tsx +7 -4
  79. data/app/pb_kits/playbook/pb_select/docs/_select_inline_show_arrow.html.erb +24 -0
  80. data/app/pb_kits/playbook/pb_select/docs/_select_inline_show_arrow.jsx +38 -0
  81. data/app/pb_kits/playbook/pb_select/docs/example.yml +2 -0
  82. data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
  83. data/app/pb_kits/playbook/pb_select/select.rb +6 -1
  84. data/app/pb_kits/playbook/pb_selectable_card_icon/_selectable_card_icon.tsx +25 -24
  85. data/app/pb_kits/playbook/pb_selectable_icon/_selectable_icon.tsx +27 -26
  86. data/app/pb_kits/playbook/pb_selectable_list/_selectable_list.tsx +2 -1
  87. data/app/pb_kits/playbook/pb_source/_source.tsx +15 -15
  88. data/app/pb_kits/playbook/pb_table/_table.tsx +29 -29
  89. data/app/pb_kits/playbook/pb_text_input/_text_input.scss +1 -0
  90. data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +1 -4
  91. data/app/pb_kits/playbook/pb_text_input/text_input.rb +1 -5
  92. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +1 -1
  93. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_highlight.jsx +4 -2
  94. data/app/pb_kits/playbook/playbook-doc.js +2 -0
  95. data/app/pb_kits/playbook/utilities/globalProps.ts +1 -1
  96. data/dist/menu.yml +4 -1
  97. data/dist/playbook-rails.js +14 -6
  98. data/lib/playbook/version.rb +2 -2
  99. metadata +25 -2
@@ -0,0 +1,8 @@
1
+ import { ExpandedState } from "@tanstack/react-table"
2
+
3
+ export type ExpandedStateObject = Extract<
4
+ ExpandedState,
5
+ Record<string, boolean>
6
+ >
7
+
8
+ export type DataType = { [key: string]: any }
@@ -0,0 +1,97 @@
1
+ @import "../tokens/colors";
2
+ @import "../tokens/opacity";
3
+ @import "../tokens/border_radius";
4
+ @import "../tokens/spacing";
5
+ @import "./scss_partials/loading";
6
+ @import "./scss_partials/pseudo_states";
7
+
8
+ .pb_advanced_table {
9
+ $border-color: 1px solid $border_light !important;
10
+
11
+ //animation scss
12
+ @keyframes wave {
13
+ 0% {
14
+ background-position: -468px 0;
15
+ }
16
+ 100% {
17
+ background-position: 468px 0;
18
+ }
19
+ }
20
+ [id$="-span"] {
21
+ word-wrap: normal;
22
+ }
23
+
24
+ .bg-silver {
25
+ background-color: lighten($silver, $opacity_7);
26
+ }
27
+
28
+ .bg-white {
29
+ background-color: $white;
30
+ }
31
+
32
+ .full-width {
33
+ width: 100%;
34
+ }
35
+
36
+ .table-header-cells:first-child {
37
+ color: $primary !important;
38
+ min-width: 180px;
39
+ }
40
+ // Icons
41
+ .button-icon {
42
+ display: flex;
43
+ justify-content: center;
44
+ align-items: center;
45
+ background: none;
46
+ border: none;
47
+ }
48
+
49
+ .gray-icon {
50
+ color: $text_lt_light;
51
+ @extend %primary-color-pseudo;
52
+ }
53
+
54
+ .year-sort-icon {
55
+ @extend .button-icon;
56
+ padding: 2px;
57
+ }
58
+
59
+ .time-period-toggle-icon {
60
+ @extend .button-icon;
61
+ @extend %primary-color-pseudo;
62
+ padding: 2px 0;
63
+
64
+ &:focus-visible {
65
+ border-radius: $border_rad_lighter;
66
+ }
67
+ }
68
+
69
+ .expand-toggle-icon {
70
+ @extend .button-icon;
71
+ @extend %primary-color-pseudo;
72
+ position: relative;
73
+ bottom: 1px;
74
+ width: 18px;
75
+ height: 18px;
76
+ border-radius: 50%;
77
+ }
78
+
79
+ .header-sort-button {
80
+ @extend %primary-color-pseudo;
81
+ width: 100%;
82
+
83
+ &:focus-visible {
84
+ border-radius: $border_rad_heavier;
85
+ }
86
+ }
87
+
88
+ // Vertical separator
89
+ .table-header-cells:first-child,
90
+ td:first-child {
91
+ box-shadow: 1px 0px 0px 0px #e4e8f0 !important;
92
+ }
93
+
94
+ .chrome-styles:first-child {
95
+ border-right: $border-color;
96
+ }
97
+ }
@@ -0,0 +1,237 @@
1
+ import React, { useState, useEffect, useCallback } from "react";
2
+ import classnames from "classnames";
3
+ import { buildAriaProps, buildCss, buildDataProps } from "../utilities/props";
4
+ import { globalProps, GlobalProps } from "../utilities/globalProps";
5
+ import Table from "../pb_table/_table";
6
+ import {
7
+ createColumnHelper,
8
+ getCoreRowModel,
9
+ getExpandedRowModel,
10
+ getSortedRowModel,
11
+ Row,
12
+ useReactTable,
13
+ Getter,
14
+ } from "@tanstack/react-table";
15
+
16
+ import { updateExpandAndCollapseState } from "./Utilities/helper_functions";
17
+
18
+ import { CustomCell } from "./Components/CustomCell";
19
+ import AdvancedTableContext from "./Context/AdvancedTableContext";
20
+ import { TableHeader } from "./SubComponents/TableHeader";
21
+ import { TableBody } from "./SubComponents/TableBody";
22
+
23
+ import { DataType, ExpandedStateObject } from "./Utilities/types";
24
+
25
+ type AdvancedTableProps = {
26
+ aria?: { [key: string]: string };
27
+ className?: string;
28
+ data?: { [key: string]: string };
29
+ id?: string;
30
+ tableData: DataType[];
31
+ loading?: boolean | string;
32
+ columnDefinitions: DataType[];
33
+ children?: React.ReactNode | React.ReactNode[];
34
+ onRowToggleClick?: (arg: Row<DataType>) => void;
35
+ onToggleExpansionClick?: (arg: Row<DataType>) => void;
36
+ tableOptions?: DataType;
37
+ tableProps?: DataType;
38
+ enableToggleExpansion?: "all" | "header";
39
+ toggleExpansionIcon?: string | string[];
40
+ initialLoadingRowsCount?: number;
41
+ expandedControl?: DataType;
42
+ sortControl?: DataType;
43
+ } & GlobalProps;
44
+
45
+ const AdvancedTable = (props: AdvancedTableProps) => {
46
+ const {
47
+ aria = {},
48
+ className,
49
+ data = {},
50
+ id,
51
+ tableData,
52
+ loading,
53
+ onRowToggleClick,
54
+ onToggleExpansionClick,
55
+ columnDefinitions,
56
+ children,
57
+ tableOptions,
58
+ tableProps,
59
+ enableToggleExpansion = "header",
60
+ toggleExpansionIcon = "arrows-from-line",
61
+ initialLoadingRowsCount = 10,
62
+ expandedControl,
63
+ sortControl,
64
+ } = props;
65
+
66
+ const [loadingStateRowCount, setLoadingStateRowCount] = useState(
67
+ initialLoadingRowsCount
68
+ );
69
+
70
+ // Create a local state for expanded and setExpanded if expandedControl not used
71
+ const [localExpanded, setLocalExpanded] = useState({});
72
+
73
+ // Determine whether to use the prop or the local state
74
+ const expanded = expandedControl ? expandedControl.value : localExpanded;
75
+ const setExpanded = expandedControl
76
+ ? expandedControl.onChange
77
+ : setLocalExpanded;
78
+
79
+ const columnHelper = createColumnHelper<DataType>();
80
+
81
+ //Create cells for first columns
82
+ const createCellFunction = (cellAccessors: string[]) => {
83
+ const columnCells = ({
84
+ row,
85
+ getValue,
86
+ }: {
87
+ row: Row<DataType>;
88
+ getValue: Getter<string>;
89
+ }) => {
90
+ const rowData = row.original;
91
+
92
+ switch (row.depth) {
93
+ case 0: {
94
+ return (
95
+ <CustomCell
96
+ getValue={getValue}
97
+ onRowToggleClick={onRowToggleClick}
98
+ row={row}
99
+ />
100
+ );
101
+ }
102
+ default: {
103
+ // Handle other depths based on cellAccessors
104
+ const depthAccessor = cellAccessors[row.depth - 1]; // Adjust index for depth
105
+ const accessorValue = rowData[depthAccessor];
106
+ return accessorValue ? (
107
+ <CustomCell row={row}
108
+ value={accessorValue}
109
+ />
110
+ ) : (
111
+ "N/A"
112
+ );
113
+ }
114
+ }
115
+ };
116
+
117
+ return columnCells;
118
+ };
119
+
120
+ //Create column array in format needed by Tanstack
121
+ const columns =
122
+ columnDefinitions &&
123
+ columnDefinitions.map((column) => {
124
+ // Define the base column structure
125
+ const columnStructure = {
126
+ ...columnHelper.accessor(column.accessor, {
127
+ header: column.label,
128
+ }),
129
+ };
130
+ if (column.cellAccessors) {
131
+ columnStructure.cell = createCellFunction(column.cellAccessors);
132
+ }
133
+ return columnStructure;
134
+ });
135
+
136
+ //Syntax for sorting Array if we want to manage state ourselves
137
+ const sorting = [
138
+ {
139
+ id: columnDefinitions[0].accessor,
140
+ desc:
141
+ sortControl && sortControl.value !== null
142
+ ? !sortControl.value.desc
143
+ : false,
144
+ },
145
+ ];
146
+
147
+ const expandAndSortState = () => {
148
+ if (sortControl) {
149
+ return { state: { expanded, sorting } };
150
+ } else {
151
+ return { state: { expanded } };
152
+ }
153
+ };
154
+
155
+ const table = useReactTable({
156
+ data: loading ? Array(loadingStateRowCount).fill({}) : tableData,
157
+ columns,
158
+ onExpandedChange: setExpanded,
159
+ getSubRows: (row) => row.children,
160
+ getCoreRowModel: getCoreRowModel(),
161
+ getExpandedRowModel: getExpandedRowModel(),
162
+ getSortedRowModel: getSortedRowModel(),
163
+ enableSortingRemoval: false,
164
+ ...expandAndSortState(),
165
+ ...tableOptions,
166
+ });
167
+
168
+ const tableRows = table.getRowModel();
169
+
170
+ // Set table row count for loading state
171
+ const updateLoadingStateRowCount = useCallback(() => {
172
+ const rowsCount = table.getRowModel().rows.length;
173
+ if (rowsCount !== loadingStateRowCount && rowsCount !== 0) {
174
+ setLoadingStateRowCount(rowsCount);
175
+ }
176
+ }, [tableData, loadingStateRowCount]);
177
+
178
+ useEffect(() => {
179
+ if (!loading) {
180
+ updateLoadingStateRowCount();
181
+ }
182
+ }, [loading, updateLoadingStateRowCount]);
183
+
184
+ const handleExpandOrCollapse = (row: Row<DataType>) => {
185
+ onToggleExpansionClick && onToggleExpansionClick(row);
186
+
187
+ const expandedState = expanded as ExpandedStateObject;
188
+ const targetParent = row?.parentId;
189
+ return setExpanded(
190
+ updateExpandAndCollapseState(tableRows, expandedState, targetParent)
191
+ );
192
+ };
193
+
194
+ const ariaProps = buildAriaProps(aria);
195
+ const dataProps = buildDataProps(data);
196
+ const classes = classnames(
197
+ buildCss("pb_advanced_table"),
198
+ globalProps(props),
199
+ className
200
+ );
201
+
202
+ return (
203
+ <div {...ariaProps}
204
+ {...dataProps}
205
+ className={classes}
206
+ id={id}
207
+ >
208
+ <AdvancedTableContext.Provider
209
+ value={{
210
+ table,
211
+ handleExpandOrCollapse,
212
+ loading,
213
+ enableToggleExpansion,
214
+ toggleExpansionIcon,
215
+ setExpanded,
216
+ expanded,
217
+ sortControl,
218
+ }}
219
+ >
220
+ <Table
221
+ className={`${loading && "content-loading"}`}
222
+ dataTable
223
+ numberSpacing="tabular"
224
+ responsive="none"
225
+ {...tableProps}
226
+ >
227
+ {children}
228
+ </Table>
229
+ </AdvancedTableContext.Provider>
230
+ </div>
231
+ );
232
+ };
233
+
234
+ AdvancedTable.Header = TableHeader;
235
+ AdvancedTable.Body = TableBody;
236
+
237
+ export default AdvancedTable;
@@ -0,0 +1,56 @@
1
+ import React from "react";
2
+ import { render, screen } from "../utilities/test-utils";
3
+
4
+ import { AdvancedTable } from "../";
5
+
6
+ const MOCK_DATA = [
7
+ {
8
+ year: "2021",
9
+ quarter: null,
10
+ month: null,
11
+ day: null,
12
+ newEnrollments: "20",
13
+ scheduledMeetings: "10",
14
+ children: [
15
+ {
16
+ year: "2011",
17
+ quarter: "Q1",
18
+ month: null,
19
+ day: null,
20
+ newEnrollments: "2",
21
+ scheduledMeetings: "35",
22
+ },
23
+ ],
24
+ },
25
+ ];
26
+
27
+ const columnDefinitions = [
28
+ {
29
+ accessor: "year",
30
+ label: "Year",
31
+ cellAccessors: ["quarter", "month", "day"],
32
+ },
33
+ {
34
+ accessor: "newEnrollments",
35
+ label: "New Enrollments",
36
+ },
37
+ {
38
+ accessor: "scheduledMeetings",
39
+ label: "Scheduled Meetings",
40
+ },
41
+ ];
42
+
43
+ const testId = "advanced_table";
44
+
45
+ test("generated scaffold test", () => {
46
+ render(
47
+ <AdvancedTable
48
+ columnDefinitions={columnDefinitions}
49
+ data={{ testid: testId }}
50
+ tableData={MOCK_DATA}
51
+ />
52
+ );
53
+
54
+ const kit = screen.getByTestId(testId);
55
+ expect(kit).toBeInTheDocument();
56
+ });
@@ -0,0 +1,52 @@
1
+ import React from "react";
2
+ import { AdvancedTable } from "../../";
3
+ import { MOCK_DATA } from "./_mock_data";
4
+
5
+ const AdvancedTableDefault = (props) => {
6
+ const columnDefinitions = [
7
+ {
8
+ accessor: "year",
9
+ label: "Year",
10
+ cellAccessors: ["quarter", "month", "day"],
11
+ },
12
+ {
13
+ accessor: "newEnrollments",
14
+ label: "New Enrollments",
15
+ },
16
+ {
17
+ accessor: "scheduledMeetings",
18
+ label: "Scheduled Meetings",
19
+ },
20
+ {
21
+ accessor: "attendanceRate",
22
+ label: "Attendance Rate",
23
+ },
24
+ {
25
+ accessor: "completedClasses",
26
+ label: "Completed Classes",
27
+ },
28
+ {
29
+ accessor: "classCompletionRate",
30
+ label: "ClassCompletion Rate",
31
+ },
32
+ {
33
+ accessor: "graduatedStudents",
34
+ label: "Graduated Students",
35
+ },
36
+ ];
37
+
38
+ return (
39
+ <div>
40
+ <AdvancedTable
41
+ columnDefinitions={columnDefinitions}
42
+ tableData={MOCK_DATA}
43
+ {...props}
44
+ >
45
+ <AdvancedTable.Header/>
46
+ <AdvancedTable.Body/>
47
+ </AdvancedTable>
48
+ </div>
49
+ );
50
+ };
51
+
52
+ export default AdvancedTableDefault;