playbook_ui 14.20.0.pre.rc.2 → 14.21.0.pre.alpha.PLAY2140upgraderailsdependency8110

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +1 -1
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +116 -49
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +61 -35
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +37 -23
  6. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +58 -2
  7. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +1 -1
  8. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +16 -4
  9. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +7 -3
  10. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +48 -19
  11. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +13 -3
  12. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +16 -8
  13. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +16 -1
  14. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +61 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.md +6 -2
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.jsx +1 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.md +3 -1
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.md +1 -1
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.html.erb +33 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.jsx +0 -1
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +57 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md +5 -0
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_scrollbar_none.html.erb +33 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_scrollbar_none.jsx +53 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.html.erb +137 -0
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.md +3 -0
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.html.erb +40 -0
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.md +1 -0
  29. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +8 -2
  30. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +3 -1
  31. data/app/pb_kits/playbook/pb_advanced_table/index.js +157 -12
  32. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.html.erb +23 -0
  33. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.rb +19 -0
  34. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +4 -0
  35. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +4 -11
  36. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +10 -6
  37. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +2 -48
  38. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate_rails.md +1 -0
  39. data/app/pb_kits/playbook/pb_checkbox/index.js +56 -0
  40. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_date_display.html.erb +13 -0
  41. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +17 -58
  42. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +1 -1
  43. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +86 -19
  44. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.jsx +42 -0
  45. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.md +1 -0
  46. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.html.erb +31 -0
  47. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.md +5 -0
  48. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.jsx +56 -0
  49. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.md +3 -0
  50. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.jsx +58 -0
  51. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.md +3 -0
  52. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.html.erb +20 -0
  53. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.md +1 -0
  54. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.html.erb +19 -0
  55. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.md +3 -0
  56. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.html.erb +20 -0
  57. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.jsx +57 -0
  58. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.md +1 -0
  59. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.html.erb +50 -0
  60. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.jsx +105 -0
  61. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.html.erb +22 -0
  62. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.jsx +67 -0
  63. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +13 -1
  64. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +6 -0
  65. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -3
  66. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +16 -2
  67. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +108 -2
  68. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +34 -13
  69. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +3 -1
  70. data/app/pb_kits/playbook/pb_dropdown/hooks/useHandleOnKeydown.tsx +0 -6
  71. data/app/pb_kits/playbook/pb_dropdown/index.js +357 -40
  72. data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +39 -12
  73. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +26 -18
  74. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +96 -19
  75. data/app/pb_kits/playbook/pb_dropdown/subcomponents/MultiSelectTriggerDisplay.tsx +58 -0
  76. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +1 -0
  77. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -0
  78. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +4 -0
  79. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.html.erb +4 -0
  80. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.jsx +15 -0
  81. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.md +1 -0
  82. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.jsx +1 -1
  83. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +4 -3
  84. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  85. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  86. data/app/pb_kits/playbook/pb_popover/index.ts +9 -4
  87. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.html.erb +12 -0
  88. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.jsx +31 -0
  89. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.md +1 -0
  90. data/app/pb_kits/playbook/pb_select/docs/example.yml +2 -0
  91. data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
  92. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +3 -51
  93. data/app/pb_kits/playbook/pb_table/styles/_mobile_collapse.scss +1 -1
  94. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +73 -3
  95. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.jsx +23 -0
  96. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.md +1 -0
  97. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +1 -0
  98. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
  99. data/dist/chunks/_typeahead-CoOpeYom.js +22 -0
  100. data/dist/chunks/_weekday_stacked-B_jpa2Rz.js +45 -0
  101. data/dist/chunks/lib-D7Va7yqa.js +29 -0
  102. data/dist/chunks/{pb_form_validation-WWvUXPKD.js → pb_form_validation-DSkdRDMf.js} +1 -1
  103. data/dist/chunks/vendor.js +1 -1
  104. data/dist/menu.yml +1 -1
  105. data/dist/playbook-doc.js +2 -2
  106. data/dist/playbook-rails-react-bindings.js +1 -1
  107. data/dist/playbook-rails.js +1 -1
  108. data/dist/playbook.css +1 -1
  109. data/lib/playbook/kit_base.rb +3 -3
  110. data/lib/playbook/version.rb +2 -2
  111. metadata +48 -7
  112. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.html.erb +0 -10
  113. data/dist/chunks/_typeahead-B9-s4j4U.js +0 -22
  114. data/dist/chunks/_weekday_stacked-CvzpmXD5.js +0 -45
  115. data/dist/chunks/lib-B20MXZcW.js +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 550eb9cf8486549b50d70381987dc8b6df78f8aa7dea1524b5e2b9d7142966e6
4
- data.tar.gz: 8ad49a6bd0a8b792998a24292872458ff0af0b0fd65c98c93aec4b37b40ffa3d
3
+ metadata.gz: 62d1fd85a95adbd0877d0fafb8043652c3c585d26feb6138109572ad00513512
4
+ data.tar.gz: 1dbc06be5519944fdc7a1caff8c3e7cff9efa505f058d5890b5a708173916cfd
5
5
  SHA512:
6
- metadata.gz: 3c12a7c65488cb05d4652474347af12ccaf4ae4cdf3e5631cdd38d55d449533807f44ced11e23b163ba2f194f4b016216c189730f6c92050e889497a54b6a443
7
- data.tar.gz: 7a92df587607e3ba5944e69d790a6433bde32b15d3c1626004e2e34d0eeb3489a14d468dc6322d73391bdf0acecf5581f137d371d387f1d0e2b49b9928758a6a
6
+ metadata.gz: 22e8527f0a707b044948444679cdd130afd72e28d8d08f8d6387dc55775c47588719f518a288c673fcb03d35727b71b17ac6afc5f799a363c8a8154419b189fa
7
+ data.tar.gz: 2443dcb9395c05af0d8cd88a4b47a811407c82643fee4fc5474911249b457383e495546743f9065264bef323244c314bb2a1457b475ffb3444c5cb413f66f3ae
@@ -47,7 +47,7 @@ export const CustomCell = ({
47
47
  <Flex
48
48
  alignItems="center"
49
49
  columnGap="xs"
50
- justify={!hasAnySubRows && !inlineRowLoading ? "end" : "start"}
50
+ justify={"start"}
51
51
  orientation="row"
52
52
  >
53
53
  {
@@ -19,6 +19,71 @@ type RegularTableViewProps = {
19
19
  subRowHeaders?: string[]
20
20
  }
21
21
 
22
+ // Helper function for Table Rendering
23
+ const TableCellRenderer = ({
24
+ row,
25
+ collapsibleTrail = true,
26
+ loading = false,
27
+ stickyLeftColumn,
28
+ columnPinning
29
+ }: {
30
+ row: Row<GenericObject>
31
+ collapsibleTrail?: boolean
32
+ loading?: boolean | string
33
+ stickyLeftColumn?: string[]
34
+ columnPinning: { left: string[] }
35
+ }) => {
36
+ return (
37
+ <>
38
+ {row.getVisibleCells().map((cell: Cell<GenericObject, unknown>, i: number) => {
39
+ const isPinnedLeft = columnPinning.left.includes(cell.column.id);
40
+ const isLastCell = (() => {
41
+ const parent = cell.column.parent;
42
+ if (!parent) {
43
+ const last = row.getVisibleCells().at(-1);
44
+ return last?.column.id === cell.column.id;
45
+ }
46
+
47
+ const visibleSiblings = parent.columns.filter(col => col.getIsVisible());
48
+ return visibleSiblings.at(-1)?.id === cell.column.id;
49
+ })();
50
+
51
+ const { column } = cell;
52
+
53
+ return (
54
+ <td
55
+ align="right"
56
+ className={classnames(
57
+ `${cell.id}-cell position_relative`,
58
+ isChrome() ? "chrome-styles" : "",
59
+ isPinnedLeft && 'pinned-left',
60
+ stickyLeftColumn && stickyLeftColumn.length > 0 && isPinnedLeft && 'sticky-left',
61
+ isLastCell && 'last-cell',
62
+ )}
63
+ key={`${cell.id}-data`}
64
+ style={{
65
+ left: isPinnedLeft
66
+ ? i === 1 // Accounting for set min-width for first column
67
+ ? '180px'
68
+ : `${column.getStart("left")}px`
69
+ : undefined,
70
+ }}
71
+ >
72
+ {collapsibleTrail && i === 0 && row.depth > 0 && renderCollapsibleTrail(row.depth)}
73
+ <span id={`${cell.id}-span`}>
74
+ {loading ? (
75
+ <LoadingCell />
76
+ ) : (
77
+ flexRender(cell.column.columnDef.cell, cell.getContext())
78
+ )}
79
+ </span>
80
+ </td>
81
+ );
82
+ })}
83
+ </>
84
+ )
85
+ }
86
+
22
87
  export const RegularTableView = ({
23
88
  collapsibleTrail = true,
24
89
  subRowHeaders,
@@ -28,11 +93,14 @@ export const RegularTableView = ({
28
93
  handleExpandOrCollapse,
29
94
  inlineRowLoading,
30
95
  loading,
31
- responsive,
32
96
  table,
33
97
  selectableRows,
34
98
  hasAnySubRows,
35
- stickyLeftColumn
99
+ stickyLeftColumn,
100
+ pinnedRows,
101
+ headerHeight,
102
+ rowHeight,
103
+ sampleRowRef,
36
104
  } = useContext(AdvancedTableContext)
37
105
 
38
106
 
@@ -50,9 +118,44 @@ export const RegularTableView = ({
50
118
  const columnPinning = table.getState().columnPinning || { left: [] };
51
119
  const columnDefinitions = table.options.meta?.columnDefinitions || [];
52
120
 
121
+ // Row pinning
122
+ function PinnedRow({ row }: { row: Row<any> }) {
123
+ return (
124
+ <tr
125
+ className={classnames(
126
+ `pinned-row`,
127
+ )}
128
+ style={{
129
+ backgroundColor: 'white',
130
+ position: 'sticky',
131
+ top:
132
+ row.getIsPinned() === 'top'
133
+ ? `${row.getPinnedIndex() * rowHeight + headerHeight}px`
134
+ : undefined,
135
+ zIndex: '3'
136
+ }}
137
+ >
138
+ <TableCellRenderer
139
+ collapsibleTrail={collapsibleTrail}
140
+ columnPinning={columnPinning}
141
+ loading={loading}
142
+ row={row}
143
+ stickyLeftColumn={stickyLeftColumn}
144
+ />
145
+ </tr>
146
+ )
147
+ }
148
+
149
+ const totalRows = pinnedRows ? table.getCenterRows() : table.getRowModel().rows
150
+
53
151
  return (
54
152
  <>
55
- {table.getRowModel().rows.map((row: Row<GenericObject>) => {
153
+ {pinnedRows && table.getTopRows().map((row: Row<GenericObject>) => (
154
+ <PinnedRow key={row.id}
155
+ row={row}
156
+ />
157
+ ))}
158
+ {totalRows.map((row: Row<GenericObject>, rowIndex: number) => {
56
159
  const isExpandable = row.getIsExpanded();
57
160
  const isFirstChildofSubrow = row.depth > 0 && row.index === 0;
58
161
  const rowHasNoChildren = row.original?.children && !row.original.children.length ? true : false;
@@ -60,6 +163,7 @@ export const RegularTableView = ({
60
163
  const isDataLoading = isExpandable && (inlineRowLoading && rowHasNoChildren) && (row.depth < columnDefinitions[0]?.cellAccessors?.length);
61
164
  const rowBackground = isExpandable && ((!inlineRowLoading && row.getCanExpand()) || (inlineRowLoading && rowHasNoChildren));
62
165
  const rowColor = row.getIsSelected() ? "bg-row-selection" : rowBackground ? "bg-silver" : "bg-white";
166
+ const isFirstRegularRow = rowIndex === 0 && !row.getIsPinned();
63
167
 
64
168
  return (
65
169
  <React.Fragment key={`${row.index}-${row.id}-${row.depth}-row`}>
@@ -77,6 +181,7 @@ export const RegularTableView = ({
77
181
  <tr
78
182
  className={`${rowColor} ${row.depth > 0 ? `depth-sub-row-${row.depth}` : ""}`}
79
183
  id={`${row.index}-${row.id}-${row.depth}-row`}
184
+ ref={isFirstRegularRow ? sampleRowRef : null}
80
185
  >
81
186
  {/* Render custom checkbox column when we want selectableRows for non-expanding tables */}
82
187
  {selectableRows && !hasAnySubRows && (
@@ -90,51 +195,13 @@ export const RegularTableView = ({
90
195
  />
91
196
  </td>
92
197
  )}
93
-
94
- {row.getVisibleCells().map((cell: Cell<GenericObject, unknown>, i: number) => {
95
- const isPinnedLeft = columnPinning.left.includes(cell.column.id);
96
- const isLastCell = (() => {
97
- const parent = cell.column.parent;
98
- if (!parent) {
99
- const last = row.getVisibleCells().at(-1);
100
- return last?.column.id === cell.column.id;
101
- }
102
-
103
- const visibleSiblings = parent.columns.filter(col => col.getIsVisible());
104
- return visibleSiblings.at(-1)?.id === cell.column.id;
105
- })();
106
-
107
- const { column } = cell;
108
- return (
109
- <td
110
- align="right"
111
- className={classnames(
112
- `${cell.id}-cell position_relative`,
113
- isChrome() ? "chrome-styles" : "",
114
- isPinnedLeft && 'pinned-left',
115
- stickyLeftColumn && stickyLeftColumn.length > 0 && isPinnedLeft && 'sticky-left',
116
- isLastCell && 'last-cell',
117
- )}
118
- key={`${cell.id}-data`}
119
- style={{
120
- left: isPinnedLeft
121
- ? i === 1 //Accounting for set min-width for first column
122
- ? '180px'
123
- : `${column.getStart("left")}px`
124
- : undefined,
125
- }}
126
- >
127
- {collapsibleTrail && i === 0 && row.depth > 0 && renderCollapsibleTrail(row.depth)}
128
- <span id={`${cell.id}-span`}>
129
- {loading ? (
130
- <LoadingCell />
131
- ) : (
132
- flexRender(cell.column.columnDef.cell, cell.getContext())
133
- )}
134
- </span>
135
- </td>
136
- );
137
- })}
198
+ <TableCellRenderer
199
+ collapsibleTrail={collapsibleTrail}
200
+ columnPinning={columnPinning}
201
+ loading={loading}
202
+ row={row}
203
+ stickyLeftColumn={stickyLeftColumn}
204
+ />
138
205
  </tr>
139
206
 
140
207
  {/* Display LoadingInline if Row Data is querying and there are no children already */}
@@ -154,4 +221,4 @@ export const RegularTableView = ({
154
221
  );
155
222
  }
156
223
 
157
- export default RegularTableView;
224
+ export default RegularTableView;
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useRef, useContext } from "react";
1
+ import React, { useEffect, useRef, useContext, useState } from "react";
2
2
 
3
3
  import AdvancedTableContext from "../Context/AdvancedTableContext";
4
4
  import { buildVisibilityTree } from "../Utilities/VisibilityTree";
@@ -7,13 +7,11 @@ import Card from "../../pb_card/_card";
7
7
  import Caption from "../../pb_caption/_caption";
8
8
  import Flex from "../../pb_flex/_flex";
9
9
  import FlexItem from "../../pb_flex/_flex_item";
10
- import Dropdown from "../../pb_dropdown/_dropdown";
11
- import DropdownContainer from "../../pb_dropdown/subcomponents/DropdownContainer";
12
- import DropdownTrigger from "../../pb_dropdown/subcomponents/DropdownTrigger";
13
10
  import Icon from "../../pb_icon/_icon";
14
11
  import Checkbox from "../../pb_checkbox/_checkbox";
15
12
  import SectionSeparator from "../../pb_section_separator/_section_separator";
16
13
  import Tooltip from "../../pb_tooltip/_tooltip";
14
+ import PbReactPopover from "../../pb_popover/_popover";
17
15
 
18
16
  import {
19
17
  showActionBar,
@@ -56,11 +54,24 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
56
54
  const col = table.getColumn(id);
57
55
  const show = col.getIsVisible();
58
56
 
57
+ const handleVisibilityChange = () => {
58
+ col.toggleVisibility();
59
+ if (columnVisibilityControl?.onColumnVisibilityChange) {
60
+ const updatedVisibilityState = {
61
+ ...table.getAllColumns().reduce((acc: { [x: string]: any; }, col: { id: string | number; getIsVisible: () => any; }) => {
62
+ acc[col.id] = col.getIsVisible();
63
+ return acc;
64
+ }, {}),
65
+ };
66
+ columnVisibilityControl?.onColumnVisibilityChange(updatedVisibilityState);
67
+ }
68
+ };
69
+
59
70
  return (
60
71
  <Checkbox
61
72
  checked={show}
62
73
  key={id}
63
- onChange={() => col.toggleVisibility()}
74
+ onChange={handleVisibilityChange}
64
75
  paddingBottom="xs"
65
76
  text={label}
66
77
  />
@@ -80,16 +91,24 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
80
91
  const allOn = visibleArray.every(Boolean);
81
92
  const someOn = visibleArray.some(Boolean);
82
93
 
94
+ const handleGroupVisibilityChange = () => {
95
+ leaves.forEach((id) => table.getColumn(id).toggleVisibility(!allOn));
96
+ if (columnVisibilityControl?.onColumnVisibilityChange) {
97
+ const updatedVisibilityState = {
98
+ ...table.getAllColumns().reduce((acc: { [x: string]: any; }, col: { id: string | number; getIsVisible: () => any; }) => {
99
+ acc[col.id] = col.getIsVisible();
100
+ return acc;
101
+ }, {}),
102
+ };
103
+ columnVisibilityControl?.onColumnVisibilityChange(updatedVisibilityState);
104
+ }
105
+ };
83
106
  return (
84
107
  <>
85
108
  <Checkbox
86
109
  checked={allOn}
87
110
  indeterminate={!allOn && someOn}
88
- onChange={() =>
89
- leaves.forEach((id) =>
90
- table.getColumn(id).toggleVisibility(!allOn),
91
- )
92
- }
111
+ onChange={handleGroupVisibilityChange}
93
112
  paddingBottom="xs"
94
113
  text={node.label}
95
114
  />
@@ -113,7 +132,28 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
113
132
  hideActionBar(cardRef.current);
114
133
  }
115
134
  }
116
- }, [isVisible]);
135
+ }, [isVisible, type]);
136
+
137
+ const [showPopover, setShowPopover] = useState(false)
138
+
139
+ const togglePopover = () => setShowPopover((prev) => !prev)
140
+ const handleShouldClose = (shouldClose: boolean) =>
141
+ setShowPopover(!shouldClose)
142
+
143
+ const popoverReference = (
144
+ <Tooltip
145
+ placement="top"
146
+ text="Column Configuration"
147
+ >
148
+ <div onClick={togglePopover}>
149
+ <Icon
150
+ color="primary"
151
+ cursor="pointer"
152
+ icon="sliders-h"
153
+ />
154
+ </div>
155
+ </Tooltip>
156
+ )
117
157
 
118
158
  return (
119
159
  <Card
@@ -139,30 +179,17 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
139
179
  <FlexItem>{actions}</FlexItem>
140
180
  </>
141
181
  ) : (
142
- <Dropdown
143
- className="column-visibility-dropdown-wrapper"
144
- options={columnDefinitions}
182
+ <PbReactPopover
183
+ closeOnClick="outside"
184
+ placement="bottom-end"
185
+ reference={popoverReference}
186
+ shouldClosePopover={handleShouldClose}
187
+ show={showPopover}
188
+ zIndex={3}
145
189
  >
146
- <DropdownTrigger>
147
- <Tooltip
148
- placement='top'
149
- text="Column Configuration"
150
- zIndex={10}
151
- >
152
- <Icon
153
- color="primary"
154
- cursor="pointer"
155
- icon="sliders-h"
156
- />
157
- </Tooltip>
158
- </DropdownTrigger>
159
- <DropdownContainer
160
- className="column-visibility-dropdown"
161
- paddingTop="sm"
162
- >
163
- <>
190
+ <>
164
191
  <Caption
165
- paddingBottom="sm"
192
+ paddingY="sm"
166
193
  text="Columns Config"
167
194
  textAlign="center"
168
195
  />
@@ -177,8 +204,7 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
177
204
  </Flex>
178
205
  ))}
179
206
  </>
180
- </DropdownContainer>
181
- </Dropdown>
207
+ </PbReactPopover>
182
208
  )}
183
209
  </Flex>
184
210
  </Card>
@@ -1,4 +1,4 @@
1
- import React, { useContext } from "react"
1
+ import React, { useContext, useState } from "react"
2
2
  import classnames from "classnames"
3
3
  import { flexRender, Header, Table, RowModel } from "@tanstack/react-table"
4
4
 
@@ -8,10 +8,8 @@ import { GlobalProps } from "../../utilities/globalProps"
8
8
 
9
9
  import Flex from "../../pb_flex/_flex"
10
10
  import Checkbox from "../../pb_checkbox/_checkbox"
11
- import Dropdown from "../../pb_dropdown/_dropdown"
12
- import DropdownTrigger from "../../pb_dropdown/subcomponents/DropdownTrigger"
13
- import DropdownOption from "../../pb_dropdown/subcomponents/DropdownOption"
14
- import DropdownContainer from "../../pb_dropdown/subcomponents/DropdownContainer"
11
+ import SectionSeparator from "../../pb_section_separator/_section_separator"
12
+ import PbReactPopover from "../../pb_popover/_popover";
15
13
  import Icon from "../../pb_icon/_icon"
16
14
 
17
15
  import { SortIconButton } from "./SortIconButton"
@@ -130,12 +128,26 @@ const isToggleExpansionEnabled =
130
128
 
131
129
  let justifyHeader:justifyTypes;
132
130
 
133
- if (header?.index === 0 && hasAnySubRows || (header?.index === 0 && inlineRowLoading)) {
131
+ if (header?.index === 0 && hasAnySubRows || (header?.index === 0 && inlineRowLoading) || (header?.index === 0 && isToggleExpansionEnabled)) {
134
132
  justifyHeader = enableSorting ? "between" : "start";
135
133
  } else {
136
134
  justifyHeader = isLeafColumn ? "end" : "center";
137
135
  }
138
136
 
137
+ const [showPopover, setShowPopover] = useState(false)
138
+
139
+ const togglePopover = () => setShowPopover((prev) => !prev)
140
+ const handleShouldClose = (shouldClose: boolean) =>
141
+ setShowPopover(!shouldClose)
142
+
143
+ const popoverReference = (
144
+ <div className="gray-icon toggle-all-icon"
145
+ onClick={togglePopover}
146
+ >
147
+ <Icon icon={displayIcon(toggleExpansionIcon)[0]} />
148
+ </div>
149
+ )
150
+
139
151
  const handleExpandDepth = (depth: number) => {
140
152
  if (onExpandByDepthClick) {
141
153
  const flatRows = table?.getRowModel().flatRows
@@ -191,31 +203,33 @@ const isToggleExpansionEnabled =
191
203
  <ToggleIconButton onClick={handleExpandOrCollapse} />
192
204
  )}
193
205
  {isToggleExpansionEnabled && hasAnySubRows && expandByDepth && (
194
- <Dropdown className="expand-by-depth-dropdown-wrapper"
195
- options={expandByDepth}
196
- >
197
- <DropdownTrigger className="gray-icon toggle-all-icon">
198
- <Icon icon={displayIcon(toggleExpansionIcon)[0]} />
199
- </DropdownTrigger>
200
- <DropdownContainer className="expand-by-depth-dropdown">
201
- {expandByDepth.map((option:{ [key: string]: any }, index: number) => (
202
- <DropdownOption
203
- key={index}
204
- option={option}
205
- padding="none"
206
+
207
+ <PbReactPopover
208
+ closeOnClick="any"
209
+ placement="bottom-start"
210
+ reference={popoverReference}
211
+ shouldClosePopover={handleShouldClose}
212
+ show={showPopover}
213
+ zIndex={3}
206
214
  >
215
+ {expandByDepth.map((option:{ [key: string]: any }, index: number) => (
216
+ <>
207
217
  <Flex
208
218
  alignItems="center"
219
+ className="pb-advanced-table-popover-option"
220
+ cursor="pointer"
209
221
  htmlOptions={{onClick: () => {handleExpandDepth(option.depth)} }}
210
222
  paddingX="sm"
211
223
  paddingY="xs"
212
224
  >
213
225
  {option.label}
214
- </Flex>
215
- </DropdownOption>
216
- ))}
217
- </DropdownContainer>
218
- </Dropdown>
226
+ </Flex>
227
+ {index !== expandByDepth.length - 1 && <SectionSeparator/>}
228
+ </>
229
+ ))}
230
+ </PbReactPopover>
231
+
232
+
219
233
  )}
220
234
 
221
235
  {isToggleExpansionEnabledLoading &&(
@@ -1,4 +1,4 @@
1
- import React, { createContext, useRef, useMemo, useEffect } from 'react';
1
+ import React, { createContext, useRef, useMemo, useEffect, useState, useCallback } from 'react';
2
2
  import { useVirtualizer } from '@tanstack/react-virtual';
3
3
 
4
4
  import { Row } from "@tanstack/react-table";
@@ -23,6 +23,54 @@ export const AdvancedTableProvider = ({ children, ...props }: {
23
23
 
24
24
  const table = props.table;
25
25
  const isVirtualized = props.virtualizedRows || props.enableVirtualization;
26
+
27
+ // Pinned Row: height calculations for Header and Row
28
+ const headerRef = useRef(null);
29
+ const sampleRowRef = useRef(null);
30
+
31
+ const [headerHeight, setHeaderHeight] = useState(44);
32
+ const [rowHeight, setRowHeight] = useState(38);
33
+
34
+ const measureHeights = useCallback(() => {
35
+ if (headerRef.current) {
36
+ const headerRect = headerRef.current.getBoundingClientRect();
37
+ if (headerRect.height > 0) {
38
+ setHeaderHeight(headerRect.height);
39
+ }
40
+ }
41
+ if (sampleRowRef.current) {
42
+ const rowRect = sampleRowRef.current.getBoundingClientRect();
43
+ if (rowRect.height > 0) {
44
+ setRowHeight(rowRect.height);
45
+ }
46
+ }
47
+ }, []);
48
+
49
+ useEffect(() => {
50
+ const resizeObserver = new ResizeObserver(() => {
51
+ measureHeights();
52
+ });
53
+
54
+ if (headerRef.current) {
55
+ resizeObserver.observe(headerRef.current);
56
+ }
57
+
58
+ if (sampleRowRef.current) {
59
+ resizeObserver.observe(sampleRowRef.current);
60
+ }
61
+
62
+ const timeoutId = setTimeout(measureHeights, 100);
63
+
64
+ return () => {
65
+ resizeObserver.disconnect();
66
+ clearTimeout(timeoutId);
67
+ };
68
+ }, [measureHeights]);
69
+
70
+ useEffect(() => {
71
+ measureHeights();
72
+ }, [table?.getRowModel().rows.length, measureHeights]);
73
+
26
74
 
27
75
  // Create a flattened data array that includes ALL components for virtualization
28
76
  const flattenedItems = useMemo(() => {
@@ -132,7 +180,15 @@ export const AdvancedTableProvider = ({ children, ...props }: {
132
180
  virtualizer: isVirtualized ? virtualizer : null,
133
181
  flattenedItems,
134
182
  virtualizedRows: isVirtualized,
135
- enableVirtualization: isVirtualized
183
+ enableVirtualization: isVirtualized,
184
+ rowPinning: props.rowPinning,
185
+ setRowPinning: props.setRowPinning,
186
+ keepPinnedRows: props.keepPinnedRows,
187
+ headerHeight,
188
+ rowHeight,
189
+ headerRef,
190
+ sampleRowRef,
191
+ measureHeights,
136
192
  };
137
193
 
138
194
  return (
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect } from 'react';
2
- import { Row } from "@tanstack/react-table";
2
+ import { Row, RowPinningState } from "@tanstack/react-table";
3
3
  import { GenericObject } from "../../types";
4
4
  import { updateExpandAndCollapseState } from "../Utilities/ExpansionControlHelpers";
5
5
 
@@ -6,7 +6,8 @@ import {
6
6
  getPaginationRowModel,
7
7
  getSortedRowModel,
8
8
  RowSelectionState,
9
- Row
9
+ Row,
10
+ RowPinningState
10
11
  } from "@tanstack/react-table";
11
12
  import { GenericObject } from "../../types";
12
13
  import { createColumnHelper } from "@tanstack/react-table";
@@ -23,11 +24,14 @@ interface UseTableStateProps {
23
24
  loading?: boolean | string;
24
25
  pagination?: boolean;
25
26
  paginationProps?: GenericObject;
27
+ pinnedRows?: {
28
+ value?: RowPinningState;
29
+ onChange?: (value: RowPinningState) => void;
30
+ };
26
31
  virtualizedRows?: boolean;
27
32
  tableOptions?: GenericObject;
28
33
  onRowSelectionChange?: (arg: RowSelectionState) => void;
29
34
  columnVisibilityControl?: GenericObject;
30
-
31
35
  }
32
36
 
33
37
  export function useTableState({
@@ -43,18 +47,24 @@ export function useTableState({
43
47
  paginationProps,
44
48
  virtualizedRows = false,
45
49
  tableOptions,
46
- columnVisibilityControl
50
+ columnVisibilityControl,
51
+ pinnedRows,
47
52
  }: UseTableStateProps) {
48
53
  // Create a local state for expanded and setExpanded if expandedControl not used
49
54
  const [localExpanded, setLocalExpanded] = useState({});
50
55
  const [loadingStateRowCount, setLoadingStateRowCount] = useState(initialLoadingRowsCount);
51
56
  const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
52
57
  const [localColumnVisibility, setLocalColumnVisibility] = useState({});
58
+ const [localRowPinning, setLocalRowPinning] = useState<RowPinningState>({
59
+ top: [],
60
+ });
53
61
  // Determine whether to use the prop or the local state
54
62
  const expanded = expandedControl ? expandedControl.value : localExpanded;
55
63
  const setExpanded = expandedControl ? expandedControl.onChange : setLocalExpanded;
56
64
  const columnVisibility = (columnVisibilityControl && columnVisibilityControl.value) ? columnVisibilityControl.value : localColumnVisibility;
57
65
  const setColumnVisibility = (columnVisibilityControl && columnVisibilityControl.onChange) ? columnVisibilityControl.onChange : setLocalColumnVisibility;
66
+ const rowPinning = pinnedRows && pinnedRows.value || localRowPinning;
67
+ const setRowPinning = (pinnedRows && pinnedRows.onChange) ? pinnedRows.onChange : setLocalRowPinning;
58
68
 
59
69
  // Virtualized data handling (chunked loading)
60
70
  const fetchSize = 20; // Number of rows per "page"
@@ -115,6 +125,7 @@ export function useTableState({
115
125
  ...(sortControl && { sorting }),
116
126
  ...(selectableRows && { rowSelection }),
117
127
  ...(columnVisibility && { columnVisibility }),
128
+ ...(pinnedRows && { rowPinning }),
118
129
  },
119
130
  }), [
120
131
  expanded,
@@ -123,6 +134,7 @@ export function useTableState({
123
134
  selectableRows,
124
135
  rowSelection,
125
136
  columnVisibility,
137
+ rowPinning,
126
138
  ]);
127
139
 
128
140
  // Pagination configuration
@@ -153,7 +165,7 @@ export function useTableState({
153
165
  enableSortingRemoval: false,
154
166
  sortDescFirst: true,
155
167
  onRowSelectionChange: setRowSelection,
156
- getRowId: selectableRows ? row => row.id : undefined,
168
+ getRowId: (selectableRows || pinnedRows) ? row => row.id : undefined,
157
169
  onColumnVisibilityChange: setColumnVisibility,
158
170
  meta: {
159
171
  columnDefinitions
@@ -39,7 +39,8 @@ export const TableHeader = ({
39
39
  hasAnySubRows,
40
40
  showActionsBar,
41
41
  selectableRows,
42
- responsive
42
+ responsive,
43
+ headerRef
43
44
  } = useContext(AdvancedTableContext)
44
45
 
45
46
  const classes = classnames(
@@ -62,8 +63,11 @@ export const TableHeader = ({
62
63
  id={id}
63
64
  >
64
65
  {/* Get the header groups (only one in this example) */}
65
- {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>) => (
66
- <tr key={`${headerGroup.id}-headerGroup`}>
66
+ {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>, index: number) => (
67
+ <tr
68
+ key={`${headerGroup.id}-headerGroup`}
69
+ ref={index === 0 ? headerRef : null}
70
+ >
67
71
  {!hasAnySubRows && selectableRows && (
68
72
  <th className={customCellClassnames}>
69
73
  <Checkbox