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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3d5b87f2b6c16e79587bb3c5e948214ab861f720b447f1de049940fe74d6d3f
4
- data.tar.gz: 35f0b35d0c9e112c30f0ca5af3916e1b57f05068650e320c1da973a97cf12936
3
+ metadata.gz: f15a8ac0110aaa64e75c62164518fb815e028873c5909c72a57b6322c2b98661
4
+ data.tar.gz: fbe1cc5a5f53f2c9387b9b2ff209abe5c9f808d16f248a285e20bb9ab980c33e
5
5
  SHA512:
6
- metadata.gz: dcec116e1d5fb1e095e0b92fec1a0a80f85407472821bcd7a22bafdafbd6e3d412d72237ab150c3338e934043e7a5427e567ceb87b2615836716e1cf2928c5a1
7
- data.tar.gz: 88b6924b8a19996f02acad09f739e80a04aec6c2caf49374bb5ec37709f84939c29ecc8a9e591297d4d436c5e80c2c5060552423a073ba1bc3be4c02e38b4be8
6
+ metadata.gz: ab28994eae8dd6bcceb5d9ca44a65ec378060cba26a86c519742e892fc721b13ff6fca4a1f526385c942f4db7b30e9f8f3a96d37b6e7c1571bf84e76bf6f9a40
7
+ data.tar.gz: a23907ecbcf8a0afa5a3abca06e60b9c18e227a0f5bac019731d9be43f209ef689159e2d5b067d4a511ed8d1245739372689385d2e6830ff17dac8363d866d61
@@ -1,16 +1,17 @@
1
+
2
+
3
+ @import 'pb_advanced_table/advanced_table';
4
+ @import 'pb_avatar/avatar';
5
+ @import 'pb_avatar_action_button/avatar_action_button';
1
6
  @import 'pb_background/background';
7
+ @import 'pb_badge/badge';
8
+ @import 'pb_bar_graph/bar_graph';
2
9
  @import 'pb_body/body';
3
10
  @import 'pb_bread_crumbs/bread_crumbs';
4
11
  @import 'pb_button/button';
5
12
  @import 'pb_button_toolbar/button_toolbar';
6
13
  @import 'pb_caption/caption';
7
14
  @import 'pb_card/card';
8
- @import 'pb_detail/detail';
9
- @import 'pb_title/title';
10
- @import 'pb_avatar/avatar';
11
- @import 'pb_avatar_action_button/avatar_action_button';
12
- @import 'pb_badge/badge';
13
- @import 'pb_bar_graph/bar_graph';
14
15
  @import 'pb_checkbox/checkbox';
15
16
  @import 'pb_circle_chart/circle_chart';
16
17
  @import 'pb_circle_icon_button/circle_icon_button';
@@ -20,21 +21,22 @@
20
21
  @import 'pb_dashboard_value/dashboard_value';
21
22
  @import 'pb_date/date';
22
23
  @import 'pb_date_picker/date_picker';
23
- @import 'pb_date_time/date_time';
24
24
  @import 'pb_date_range_inline/date_range_inline';
25
25
  @import 'pb_date_range_stacked/date_range_stacked';
26
26
  @import 'pb_date_stacked/date_stacked';
27
+ @import 'pb_date_time/date_time';
27
28
  @import 'pb_date_time_stacked/date_time_stacked';
28
29
  @import 'pb_date_year_stacked/date_year_stacked';
30
+ @import 'pb_detail/detail';
29
31
  @import 'pb_dialog/dialog';
30
32
  @import 'pb_distribution_bar/distribution_bar';
31
33
  @import 'pb_file_upload/file_upload';
32
34
  @import 'pb_filter/filter';
33
35
  @import 'pb_fixed_confirmation_toast/fixed_confirmation_toast';
36
+ @import 'pb_flex/flex';
34
37
  @import 'pb_form/form';
35
38
  @import 'pb_form_group/form_group';
36
39
  @import 'pb_form_pill/form_pill';
37
- @import 'pb_flex/flex';
38
40
  @import 'pb_gauge/gauge';
39
41
  @import 'pb_hashtag/hashtag';
40
42
  @import 'pb_highlight/highlight';
@@ -55,6 +57,7 @@
55
57
  @import 'pb_map/map';
56
58
  @import 'pb_map/pb_map_button_mixin';
57
59
  @import 'pb_message/message';
60
+ @import 'pb_multi_level_select/multi_level_select';
58
61
  @import 'pb_multiple_users/multiple_users';
59
62
  @import 'pb_multiple_users_stacked/multiple_users_stacked';
60
63
  @import 'pb_nav/nav';
@@ -85,9 +88,11 @@
85
88
  @import 'pb_text_input/text_input';
86
89
  @import 'pb_textarea/textarea';
87
90
  @import 'pb_time/time';
88
- @import 'pb_timeline/timeline';
89
91
  @import 'pb_time_range_inline/time_range_inline';
92
+ @import 'pb_time_stacked/time_stacked';
93
+ @import 'pb_timeline/timeline';
90
94
  @import 'pb_timestamp/timestamp';
95
+ @import 'pb_title/title';
91
96
  @import 'pb_title_count/title_count';
92
97
  @import 'pb_title_detail/title_detail';
93
98
  @import 'pb_toggle/toggle';
@@ -96,7 +101,6 @@
96
101
  @import 'pb_typeahead/typeahead';
97
102
  @import 'pb_user/user';
98
103
  @import 'pb_user_badge/user_badge';
99
- @import 'pb_time_stacked/time_stacked';
100
104
  @import 'pb_walkthrough/walkthrough';
101
105
  @import 'pb_weekday_stacked/weekday_stacked';
102
106
  @import './utilities/mixins';
@@ -115,5 +119,3 @@
115
119
  @import './utilities/text_align';
116
120
  @import './utilities/overflow';
117
121
  @import './utilities/truncate';
118
-
119
- @import 'pb_multi_level_select/multi_level_select';
@@ -4,6 +4,7 @@ import 'lazysizes/plugins/attrchange/ls.attrchange'
4
4
  import 'lazysizes'
5
5
 
6
6
  // vvv React Component JSX Imports from the React Kits vvv
7
+ export { default as AdvancedTable} from './pb_advanced_table/_advanced_table'
7
8
  export { default as Avatar } from './pb_avatar/_avatar'
8
9
  export { default as AvatarActionButton } from './pb_avatar_action_button/_avatar_action_button'
9
10
  export { default as Background } from './pb_background/_background'
@@ -59,8 +60,8 @@ export { default as LineGraph } from './pb_line_graph/_line_graph'
59
60
  export { default as List } from './pb_list/_list'
60
61
  export { default as ListItem } from './pb_list/_list_item'
61
62
  export { default as LoadingInline } from './pb_loading_inline/_loading_inline'
62
- export { default as Map} from './pb_map/_map'
63
63
  export { default as MapCustomButton } from './pb_map/_map_custom_button'
64
+ export { default as Map} from './pb_map/_map'
64
65
  export { default as Message } from './pb_message/_message'
65
66
  export { default as MultiLevelSelect} from './pb_multi_level_select/_multi_level_select'
66
67
  export { default as MultipleUsers } from './pb_multiple_users/_multiple_users'
@@ -0,0 +1,30 @@
1
+ import React from "react"
2
+
3
+ //CollapsibleTrail component
4
+ const CollapsibleTrail = ({ leftOffset }: { leftOffset: number }) => {
5
+ const style: { [key: string]: string | number } = {
6
+ position: "absolute",
7
+ left: `${leftOffset}rem`,
8
+ top: 0,
9
+ bottom: 0,
10
+ width: "2px",
11
+ backgroundColor: "#E4E8F0",
12
+ }
13
+
14
+ return <div style={style} />
15
+ }
16
+
17
+ // Updated function to render multiple trails depending on depth
18
+ export const renderCollapsibleTrail = (currentDepth: number) => {
19
+ const lines = []
20
+ for (let i = 1; i <= currentDepth; i++) {
21
+ // Calculate leftOffset with additional 0.4rem for each depth level above 1
22
+ const additionalOffset = i > 1 ? (i - 1) * 0.4 : 0
23
+ const leftOffset = i * 1.6 + additionalOffset
24
+ lines.push(<CollapsibleTrail key={i}
25
+ leftOffset={leftOffset}
26
+ />
27
+ )
28
+ }
29
+ return lines
30
+ }
@@ -0,0 +1,59 @@
1
+ import React, { useContext } from "react";
2
+
3
+ import Flex from "../../pb_flex/_flex";
4
+ import FlexItem from "../../pb_flex/_flex_item";
5
+ import Icon from "../../pb_icon/_icon";
6
+ import { GlobalProps } from "../../utilities/globalProps";
7
+
8
+ import { Getter, Row } from "@tanstack/react-table";
9
+ import { DataType } from "../Utilities/types";
10
+ import AdvancedTableContext from "../Context/AdvancedTableContext";
11
+
12
+ interface CustomCellProps {
13
+ row: Row<DataType>;
14
+ getValue?: Getter<string>;
15
+ value?: string;
16
+ onRowToggleClick?: (arg: Row<DataType>) => void;
17
+ }
18
+
19
+ export const CustomCell = ({
20
+ row,
21
+ getValue,
22
+ value,
23
+ onRowToggleClick,
24
+ }: CustomCellProps & GlobalProps) => {
25
+ const { setExpanded, expanded } = useContext(AdvancedTableContext);
26
+ const RowWithoutChildren = row.originalSubRows === undefined;
27
+
28
+ const handleOnExpand = (row: Row<DataType>) => {
29
+ onRowToggleClick && onRowToggleClick(row);
30
+ setExpanded({ ...expanded, [row.id]: !row.getIsExpanded() });
31
+ };
32
+
33
+ return (
34
+ <div style={{ paddingLeft: `${row.depth * 2}rem` }}>
35
+ <Flex alignItems="center"
36
+ columnGap="xs"
37
+ orientation="row"
38
+ >
39
+ {!RowWithoutChildren ? (
40
+ <button
41
+ className="gray-icon expand-toggle-icon"
42
+ onClick={() => handleOnExpand(row)}
43
+ >
44
+ {row.getIsExpanded() ? (
45
+ <Icon icon="circle-play"
46
+ rotation={90}
47
+ />
48
+ ) : (
49
+ <Icon icon="circle-play" />
50
+ )}
51
+ </button>
52
+ ) : null}
53
+ <FlexItem paddingLeft={!RowWithoutChildren ? "none" : "xs"}>
54
+ {row.depth === 0 ? getValue() : value}
55
+ </FlexItem>
56
+ </Flex>
57
+ </div>
58
+ );
59
+ };
@@ -0,0 +1,5 @@
1
+ import React from "react"
2
+
3
+ export const LoadingCell = () => {
4
+ return <div className="loading-cell" />
5
+ }
@@ -0,0 +1,30 @@
1
+ import React from "react"
2
+ import Icon from "../../pb_icon/_icon"
3
+ import { Header } from "@tanstack/react-table"
4
+ import { DataType } from "../Utilities/types"
5
+ import { displayIcon } from "../Utilities/helper_functions"
6
+
7
+ type SortIconButtonProps = {
8
+ header: Header<DataType, unknown>
9
+ sortIcon?: string | string[]
10
+ }
11
+ export const SortIconButton = ({ header, sortIcon }: SortIconButtonProps) => {
12
+
13
+ return (
14
+ <>
15
+ {header.column.getIsSorted() === "desc" ? (
16
+ <div className="year-sort-icon"
17
+ key={displayIcon(sortIcon)[0]}
18
+ >
19
+ <Icon icon={displayIcon(sortIcon)[0]} />
20
+ </div>
21
+ ) : (
22
+ <div className="year-sort-icon"
23
+ key={displayIcon(sortIcon)[1]}
24
+ >
25
+ <Icon icon={displayIcon(sortIcon)[1]} />
26
+ </div>
27
+ )}
28
+ </>
29
+ )
30
+ }
@@ -0,0 +1,61 @@
1
+ import React from "react"
2
+ import Flex from "../../pb_flex/_flex"
3
+ import Caption from "../../pb_caption/_caption"
4
+ import { Row, Table } from "@tanstack/react-table"
5
+
6
+ import { ToggleIconButton } from "./ToggleIconButton"
7
+ import { renderCollapsibleTrail } from "./CollapsibleTrail"
8
+
9
+ import { isChrome } from "../Utilities/helper_functions"
10
+ import { DataType } from "../Utilities/types"
11
+ import { GlobalProps } from "../../utilities/globalProps"
12
+
13
+ interface SubRowHeaderRowProps {
14
+ onClick: (row: Row<DataType>) => void
15
+ row: Row<DataType>
16
+ table: Table<DataType>
17
+ collapsibleTrail?: boolean
18
+ subRowHeaders?: string[]
19
+ enableToggleExpansion?: "all" | "header"
20
+ }
21
+
22
+ export const SubRowHeaderRow = ({
23
+ row,
24
+ table,
25
+ onClick,
26
+ collapsibleTrail,
27
+ subRowHeaders,
28
+ enableToggleExpansion,
29
+ }: SubRowHeaderRowProps & GlobalProps) => {
30
+ const numberOfColumns = table.getAllFlatColumns().length
31
+
32
+ return (
33
+ <tr className="custom-row bg-silver">
34
+ <td
35
+ className={`custom-row-first-column ${
36
+ isChrome() ? "chrome-styles" : ""
37
+ }`}
38
+ colSpan={1}
39
+ >
40
+ {collapsibleTrail && row.depth > 0 && renderCollapsibleTrail(row.depth)}
41
+ <div style={{ paddingLeft: `${row.depth * 2}rem` }}>
42
+ <Flex align="center"
43
+ columnGap="xs"
44
+ >
45
+ {enableToggleExpansion === "all" && row.getCanExpand() ? (
46
+ <ToggleIconButton onClick={onClick}
47
+ row={row}
48
+ />
49
+ ) : null}
50
+ <Caption
51
+ marginLeft={row.getCanExpand() ? "none" : "xs"}
52
+ text={subRowHeaders[row.depth - 1]}
53
+ />
54
+ </Flex>
55
+ </div>
56
+ </td>
57
+
58
+ <td colSpan={numberOfColumns - 1} />
59
+ </tr>
60
+ )
61
+ }
@@ -0,0 +1,120 @@
1
+ import React, { useContext } from "react"
2
+ import Flex from "../../pb_flex/_flex"
3
+ import { flexRender, Header } from "@tanstack/react-table"
4
+
5
+ import { SortIconButton } from "./SortIconButton"
6
+ import { ToggleIconButton } from "./ToggleIconButton"
7
+ import { isChrome } from "../Utilities/helper_functions"
8
+ import { DataType } from "../Utilities/types"
9
+ import AdvancedTableContext from "../Context/AdvancedTableContext"
10
+ import { GlobalProps } from "../../utilities/globalProps"
11
+
12
+ type TableHeaderCellProps = {
13
+ headerChildren?: React.ReactNode | React.ReactNode[]
14
+ enableSorting?: boolean
15
+ enableToggleExpansion?: "all" | "header"
16
+ handleExpandOrCollapse?: () => void
17
+ header?: Header<DataType, unknown>
18
+ headerId?: string
19
+ loading?: boolean
20
+ sortIcon?: string | string[]
21
+ } & GlobalProps
22
+
23
+ export const TableHeaderCell = ({
24
+ header,
25
+ headerId,
26
+ enableSorting,
27
+ sortIcon,
28
+ headerChildren,
29
+ loading,
30
+ enableToggleExpansion,
31
+ handleExpandOrCollapse,
32
+ }: TableHeaderCellProps) => {
33
+ const { sortControl } = useContext(AdvancedTableContext)
34
+
35
+ const toggleSortButton = (event: React.SyntheticEvent) => {
36
+ if (sortControl) {
37
+ const sortIsDesc = header.column.getIsSorted() === "desc"
38
+ sortIsDesc
39
+ ? sortControl.onChange({ desc: true })
40
+ : sortControl.onChange({ desc: false })
41
+ } else {
42
+ header.column.getToggleSortingHandler()(event)
43
+ }
44
+ }
45
+
46
+ return (
47
+ <th
48
+ align="right"
49
+ className={`table-header-cells ${isChrome() ? "chrome-styles" : ""}`}
50
+ id={`${
51
+ loading
52
+ ? `loading-${header.id}-${headerId}`
53
+ : `${header.id}-${headerId}`
54
+ }`}
55
+ key={`${header.id}-header`}
56
+ >
57
+ {header.isPlaceholder ? null : headerChildren && header.index === 0 ? (
58
+ <Flex alignItems="center">
59
+ {headerChildren}
60
+ <div>
61
+ {flexRender(header.column.columnDef.header, header.getContext())}
62
+ </div>
63
+ </Flex>
64
+ ) : (
65
+ <Flex
66
+ alignItems="center"
67
+ justify={header.index === 0 ? "between" : "none"}
68
+ paddingLeft={loading ? "sm" : "none"}
69
+ >
70
+ {header.index === 0 &&
71
+ !loading &&
72
+ (enableToggleExpansion === "all" || "header") && (
73
+ <ToggleIconButton onClick={handleExpandOrCollapse} />
74
+ )}
75
+
76
+ {header.index === 0 &&
77
+ loading &&
78
+ (enableToggleExpansion === "all" || "header") && (
79
+ <div className="loading-toggle-icon header-toggle-icon" />
80
+ )}
81
+
82
+ <Flex
83
+ className={`${header.index === 0 &&
84
+ enableSorting &&
85
+ "header-sort-button pb_th_link"}`}
86
+ cursor={header.index === 0 && enableSorting ? "pointer" : "default"}
87
+ {...(header.index === 0 &&
88
+ enableSorting && {
89
+ htmlOptions: {
90
+ onClick: (event: React.MouseEvent) => toggleSortButton(event),
91
+ onKeyDown: (event: React.KeyboardEvent) => {
92
+ if (event.key === "Enter") {
93
+ toggleSortButton(event)
94
+ }
95
+ },
96
+ tabIndex: 0,
97
+ },
98
+ })}
99
+ justify={header.index === 0 && enableSorting ? "between" : "none"}
100
+ >
101
+ <div>
102
+ {flexRender(header.column.columnDef.header, header.getContext())}
103
+ </div>
104
+
105
+ {header.index === 0 &&
106
+ header.column.getCanSort() &&
107
+ enableSorting &&
108
+ (loading ? (
109
+ <div className="loading-toggle-icon header-sort-icon" />
110
+ ) : (
111
+ <SortIconButton header={header}
112
+ sortIcon={sortIcon}
113
+ />
114
+ ))}
115
+ </Flex>
116
+ </Flex>
117
+ )}
118
+ </th>
119
+ )
120
+ }
@@ -0,0 +1,28 @@
1
+ import React, { useContext } from "react"
2
+ import Icon from "../../pb_icon/_icon"
3
+ import { Row } from "@tanstack/react-table"
4
+ import AdvancedTableContext from "../Context/AdvancedTableContext"
5
+ import { DataType } from "../Utilities/types"
6
+ import { displayIcon } from "../Utilities/helper_functions"
7
+
8
+ interface ToggleIconButtonProps {
9
+ row?: Row<DataType>
10
+ onClick: (row: Row<DataType>) => void
11
+ }
12
+
13
+ export const ToggleIconButton = ({ row, onClick }: ToggleIconButtonProps) => {
14
+ const { toggleExpansionIcon } = useContext(AdvancedTableContext)
15
+ return (
16
+ <button
17
+ className="gray-icon time-period-toggle-icon"
18
+ key={displayIcon(toggleExpansionIcon)[0]}
19
+ onClick={() => onClick(row)}
20
+ >
21
+ <Icon
22
+ cursor="pointer"
23
+ fixedWidth
24
+ icon={displayIcon(toggleExpansionIcon)[0]}
25
+ />
26
+ </button>
27
+ )
28
+ }
@@ -0,0 +1,5 @@
1
+ import { createContext } from "react"
2
+
3
+ const AdvancedTableContext = createContext<any>({})
4
+
5
+ export default AdvancedTableContext
@@ -0,0 +1,95 @@
1
+ import React, { useContext } from "react"
2
+ import LoadingInline from "../../pb_loading_inline/_loading_inline"
3
+ import { flexRender, Row } from "@tanstack/react-table"
4
+
5
+ import { SubRowHeaderRow } from "../Components/SubRowHeaderRow"
6
+ import { LoadingCell } from "../Components/LoadingCell"
7
+ import { renderCollapsibleTrail } from "../Components/CollapsibleTrail"
8
+ import AdvancedTableContext from "../Context/AdvancedTableContext"
9
+ import { isChrome } from "../Utilities/helper_functions"
10
+ import { DataType } from "../Utilities/types"
11
+
12
+ type TableBodyProps = {
13
+ collapsibleTrail?: boolean
14
+ subRowHeaders?: string[]
15
+ }
16
+
17
+ export const TableBody = ({
18
+ collapsibleTrail = true,
19
+ subRowHeaders,
20
+ }: TableBodyProps) => {
21
+ const {
22
+ table,
23
+ handleExpandOrCollapse,
24
+ loading,
25
+ enableToggleExpansion,
26
+ } = useContext(AdvancedTableContext)
27
+ return (
28
+ <>
29
+ <tbody>
30
+ {table.getRowModel().rows.map((row: Row<DataType>) => {
31
+ const isExpandable = row.getIsExpanded()
32
+ const isFirstChildofSubrow = row.depth > 0 && row.index === 0
33
+ const rowHasNoChildren = !row.original.children?.length
34
+ const numberOfColumns = table.getAllFlatColumns().length
35
+
36
+ return (
37
+ <React.Fragment key={`${row.index}-${row.id}-${row.depth}-row`}>
38
+ {isFirstChildofSubrow && subRowHeaders && (
39
+ <SubRowHeaderRow
40
+ collapsibleTrail={collapsibleTrail}
41
+ enableToggleExpansion={enableToggleExpansion}
42
+ onClick={handleExpandOrCollapse}
43
+ row={row}
44
+ subRowHeaders={subRowHeaders}
45
+ table={table}
46
+ />
47
+ )}
48
+
49
+ <tr
50
+ className={`${isExpandable ? "bg-silver" : "bg-white"} ${
51
+ row.depth > 0 ? `depth-sub-row-${row.depth}` : ""
52
+ }`}
53
+ id={`${row.index}-${row.id}-${row.depth}-row`}
54
+ >
55
+ {row.getVisibleCells().map((cell, i) => (
56
+ <td
57
+ align="right"
58
+ className={`${cell.id}-cell position_relative ${
59
+ isChrome() ? "chrome-styles" : ""
60
+ }`}
61
+ key={`${cell.id}-data`}
62
+ >
63
+ {collapsibleTrail &&
64
+ i === 0 &&
65
+ row.depth > 0 &&
66
+ renderCollapsibleTrail(row.depth)}
67
+ <span id={`${cell.id}-span`}>
68
+ {loading ? (
69
+ <LoadingCell />
70
+ ) : (
71
+ flexRender(
72
+ cell.column.columnDef.cell,
73
+ cell.getContext()
74
+ )
75
+ )}
76
+ </span>
77
+ </td>
78
+ ))}
79
+ </tr>
80
+
81
+ {/* Display LoadingInline if getYearData is querying and there are no children already */}
82
+ {isExpandable && rowHasNoChildren && row.depth === 0 ? (
83
+ <tr key={`${row.id}-row`}>
84
+ <td colSpan={numberOfColumns}>
85
+ <LoadingInline />
86
+ </td>
87
+ </tr>
88
+ ) : null}
89
+ </React.Fragment>
90
+ )
91
+ })}
92
+ </tbody>
93
+ </>
94
+ )
95
+ }
@@ -0,0 +1,51 @@
1
+ import React, { useContext } from "react"
2
+ import { HeaderGroup } from "@tanstack/react-table"
3
+ import AdvancedTableContext from "../Context/AdvancedTableContext"
4
+ import { TableHeaderCell } from "../Components/TableHeaderCell"
5
+ import { DataType } from "../Utilities/types"
6
+
7
+ type TableHeaderProps = {
8
+ headerId?: string
9
+ enableSorting?: boolean
10
+ sortIcon?: string | string[]
11
+ children?: React.ReactNode | React.ReactNode[]
12
+ }
13
+
14
+ export const TableHeader = ({
15
+ headerId,
16
+ enableSorting = false,
17
+ children,
18
+ sortIcon = ["arrow-up-short-wide", "arrow-down-short-wide"],
19
+ }: TableHeaderProps) => {
20
+ const {
21
+ table,
22
+ handleExpandOrCollapse,
23
+ loading,
24
+ enableToggleExpansion,
25
+ } = useContext(AdvancedTableContext)
26
+
27
+ return (
28
+ <>
29
+ <thead>
30
+ {/* Get the header groups (only one in this example) */}
31
+ {table.getHeaderGroups().map((headerGroup: HeaderGroup<DataType>) => (
32
+ <tr key={`${headerGroup.id}-headerGroup`}>
33
+ {headerGroup.headers.map(header => (
34
+ <TableHeaderCell
35
+ enableSorting={enableSorting}
36
+ enableToggleExpansion={enableToggleExpansion}
37
+ handleExpandOrCollapse={handleExpandOrCollapse}
38
+ header={header}
39
+ headerChildren={children}
40
+ headerId={headerId}
41
+ key={`${header.id}-header`}
42
+ loading={loading}
43
+ sortIcon={sortIcon}
44
+ />
45
+ ))}
46
+ </tr>
47
+ ))}
48
+ </thead>
49
+ </>
50
+ )
51
+ }
@@ -0,0 +1,77 @@
1
+ import { RowModel } from "@tanstack/react-table"
2
+ import { DataType, ExpandedStateObject } from "./types"
3
+
4
+ const filterExpandableRows = (expandedState: Record<string, boolean>) => {
5
+ for (const expandedRow in expandedState) {
6
+ if (expandedState[expandedRow] === false) {
7
+ delete expandedState[expandedRow]
8
+ }
9
+ }
10
+ return expandedState
11
+ }
12
+
13
+ export const updateExpandAndCollapseState = (
14
+ tableRows: RowModel<DataType>,
15
+ expanded: Record<string, boolean>,
16
+ targetParent: string
17
+ ) => {
18
+ const updateExpandedRows: Record<string, boolean> = {}
19
+ const rows = tableRows.flatRows
20
+ // Variable checks if all rows in a section have same expansion state or not
21
+ let isExpansionConsistent = true
22
+ const areRowsExpanded = new Set<boolean>()
23
+
24
+ // Update isExpansionConsistent variable
25
+ for (const row of rows) {
26
+ if (
27
+ row.getCanExpand() &&
28
+ (targetParent === undefined
29
+ ? row.depth === 0
30
+ : targetParent === row.parentId)
31
+ ) {
32
+ areRowsExpanded.add(row.getIsExpanded())
33
+ if (areRowsExpanded.size > 1) {
34
+ isExpansionConsistent = false
35
+ break
36
+ }
37
+ }
38
+ }
39
+
40
+ // The if statement runs only for row depth 0, the else statement for the rest
41
+ if (targetParent === undefined) {
42
+ rows.forEach(row => {
43
+ if (row.depth === 0) {
44
+ updateExpandedRows[row.id] = !isExpansionConsistent
45
+ ? true
46
+ : !row.getIsExpanded()
47
+ }
48
+ })
49
+ } else {
50
+ for (const row of rows) {
51
+ if (row.getCanExpand() && targetParent === row.parentId) {
52
+ updateExpandedRows[row.id] = !isExpansionConsistent
53
+ ? true
54
+ : !row.getIsExpanded()
55
+ }
56
+ }
57
+ }
58
+
59
+ return filterExpandableRows({
60
+ ...(expanded as ExpandedStateObject),
61
+ ...updateExpandedRows,
62
+ })
63
+ }
64
+
65
+ //Checking browser. Using this to add classname and css for browser specific issues with table borders
66
+ export const isChrome = () => {
67
+ const userAgent = navigator.userAgent.toLowerCase()
68
+ return userAgent.includes("chrome") && !userAgent.includes("edg")
69
+ }
70
+
71
+ // Logic for handling icons related props to allow for string or array of strings
72
+ export const displayIcon = (icon: string | string[]) => {
73
+ if (typeof icon === "string") {
74
+ return [icon, icon]
75
+ }
76
+ return icon
77
+ }