playbook_ui 14.20.0 → 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 (80) 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/TableHeaderCell.tsx +1 -1
  5. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +58 -2
  6. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +1 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +16 -4
  8. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +7 -3
  9. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +42 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +13 -3
  11. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +16 -8
  12. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +16 -1
  13. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +61 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.md +6 -2
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.md +1 -1
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.html.erb +33 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.jsx +0 -1
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +57 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md +5 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_scrollbar_none.html.erb +33 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_scrollbar_none.jsx +53 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.html.erb +137 -0
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.md +3 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.html.erb +40 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.md +1 -0
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +8 -2
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +3 -1
  28. data/app/pb_kits/playbook/pb_advanced_table/index.js +157 -12
  29. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.html.erb +23 -0
  30. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.rb +19 -0
  31. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +4 -0
  32. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +4 -11
  33. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +10 -6
  34. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +2 -48
  35. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate_rails.md +1 -0
  36. data/app/pb_kits/playbook/pb_checkbox/index.js +56 -0
  37. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_date_display.html.erb +13 -0
  38. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +17 -58
  39. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +12 -3
  40. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.jsx +42 -0
  41. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.md +1 -0
  42. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +2 -0
  43. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +2 -1
  44. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +108 -2
  45. data/app/pb_kits/playbook/pb_dropdown/index.js +24 -0
  46. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +14 -10
  47. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +26 -15
  48. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +4 -0
  49. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.html.erb +4 -0
  50. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.jsx +15 -0
  51. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.md +1 -0
  52. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.jsx +1 -1
  53. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +4 -3
  54. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  55. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  56. data/app/pb_kits/playbook/pb_popover/index.ts +9 -4
  57. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.html.erb +12 -0
  58. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.jsx +31 -0
  59. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.md +1 -0
  60. data/app/pb_kits/playbook/pb_select/docs/example.yml +2 -0
  61. data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
  62. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +3 -51
  63. data/app/pb_kits/playbook/pb_table/styles/_mobile_collapse.scss +1 -1
  64. data/dist/chunks/_typeahead-CoOpeYom.js +22 -0
  65. data/dist/chunks/_weekday_stacked-B_jpa2Rz.js +45 -0
  66. data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
  67. data/dist/chunks/lib-D7Va7yqa.js +29 -0
  68. data/dist/chunks/{pb_form_validation-D1Bwm-op.js → pb_form_validation-DSkdRDMf.js} +1 -1
  69. data/dist/chunks/vendor.js +1 -1
  70. data/dist/menu.yml +1 -1
  71. data/dist/playbook-doc.js +2 -2
  72. data/dist/playbook-rails-react-bindings.js +1 -1
  73. data/dist/playbook-rails.js +1 -1
  74. data/dist/playbook.css +1 -1
  75. data/lib/playbook/version.rb +2 -2
  76. metadata +29 -7
  77. data/dist/chunks/_typeahead-MUu4QW0I.js +0 -22
  78. data/dist/chunks/_weekday_stacked-CZJor-EY.js +0 -45
  79. data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
  80. data/dist/chunks/lib-DFF1N868.js +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df6a61095071691d0b05f1fbec7ec814d97410e945a2c9eeb88df6b7aee7f17d
4
- data.tar.gz: d01d8fd76b9a504da0600a42d869c7de35fcfac17ce0bfa449459356f74c3089
3
+ metadata.gz: 62d1fd85a95adbd0877d0fafb8043652c3c585d26feb6138109572ad00513512
4
+ data.tar.gz: 1dbc06be5519944fdc7a1caff8c3e7cff9efa505f058d5890b5a708173916cfd
5
5
  SHA512:
6
- metadata.gz: a95beeddd9ec8ad5f6684eaff098098230c6f8d21e4b1037b7c56a51f2b87bbb67ab004a9c66843ca556f3c54bfda704cf69c27295678db816692b01814eadbd
7
- data.tar.gz: ac4605915f1fce8c69d50fa1faf599bb4e2ec9a90faafc8f17e959787d2a0f831c4720597f186d78602b635165ea5309f47222aaa6887494f781d73178a4d4e9
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;
@@ -128,7 +128,7 @@ const isToggleExpansionEnabled =
128
128
 
129
129
  let justifyHeader:justifyTypes;
130
130
 
131
- if (header?.index === 0 && hasAnySubRows || (header?.index === 0 && inlineRowLoading)) {
131
+ if (header?.index === 0 && hasAnySubRows || (header?.index === 0 && inlineRowLoading) || (header?.index === 0 && isToggleExpansionEnabled)) {
132
132
  justifyHeader = enableSorting ? "between" : "start";
133
133
  } else {
134
134
  justifyHeader = isLeafColumn ? "end" : "center";
@@ -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
@@ -33,6 +33,16 @@
33
33
  }
34
34
  }
35
35
 
36
+ @mixin scrollbar-styling {
37
+ &::-webkit-scrollbar {
38
+ width: 8px;
39
+ }
40
+
41
+ -ms-overflow-style: none !important;
42
+ scrollbar-width: thin !important;
43
+ scrollbar-color: #00000033 transparent !important;
44
+ }
45
+
36
46
  [id$="-span"] {
37
47
  word-wrap: normal;
38
48
  }
@@ -87,6 +97,16 @@
87
97
  }
88
98
  }
89
99
 
100
+ &.advanced-table-hide-scrollbar {
101
+ &::-webkit-scrollbar {
102
+ display: none !important;
103
+ }
104
+
105
+ -ms-overflow-style: none !important;
106
+ scrollbar-width: none !important;
107
+ }
108
+
109
+
90
110
  .row-selection-actions-card {
91
111
  border-bottom-right-radius: 0px !important;
92
112
  border-bottom-left-radius: 0px !important;
@@ -226,30 +246,37 @@
226
246
  &.advanced-table-max-height-xs {
227
247
  max-height: 320px;
228
248
  overflow-y: auto;
249
+ @include scrollbar-styling;
229
250
  }
230
251
  &.advanced-table-max-height-sm {
231
252
  max-height: 480px;
232
253
  overflow-y: auto;
254
+ @include scrollbar-styling;
233
255
  }
234
256
  &.advanced-table-max-height-md {
235
257
  max-height: 768px;
236
258
  overflow-y: auto;
259
+ @include scrollbar-styling;
237
260
  }
238
261
  &.advanced-table-max-height-lg {
239
262
  max-height: 1024px;
240
263
  overflow-y: auto;
264
+ @include scrollbar-styling;
241
265
  }
242
266
  &.advanced-table-max-height-xl {
243
267
  max-height: 1280px;
244
268
  overflow-y: auto;
269
+ @include scrollbar-styling;
245
270
  }
246
271
  &.advanced-table-max-height-xxl {
247
272
  max-height: 1440px;
248
273
  overflow-y: auto;
274
+ @include scrollbar-styling;
249
275
  }
250
276
  &.advanced-table-max-height-xxxl {
251
277
  max-height: 1920px;
252
278
  overflow-y: auto;
279
+ @include scrollbar-styling;
253
280
  }
254
281
 
255
282
  // Fullscreen
@@ -368,6 +395,10 @@
368
395
  box-shadow: 1px 0px 0px 0px var(--column-border-color) !important;
369
396
  }
370
397
 
398
+ .pb_table_td:nth-child(2) {
399
+ box-shadow: inset 1px 0px 0px 0px var(--column-border-color) !important;
400
+ }
401
+
371
402
  // Color for collapsible trail
372
403
  .collapsible-trail {
373
404
  background-color: $border_light !important;
@@ -532,6 +563,7 @@
532
563
  // Sticky Left Columns Styling
533
564
  &[class*="advanced-table-sticky-left-columns"] {
534
565
  overflow-x: scroll;
566
+ @include scrollbar-styling;
535
567
  .sticky-left {
536
568
  position: sticky !important;
537
569
  z-index: 2;
@@ -551,6 +583,7 @@
551
583
  &[class*="advanced-table-responsive-scroll"] {
552
584
  overflow-x: auto;
553
585
  width: 100%;
586
+ @include scrollbar-styling;
554
587
 
555
588
  // These are the responsive borders that should NOT inherit the custom color
556
589
  @include advanced-table-sticky-mixin(
@@ -564,6 +597,10 @@
564
597
  box-shadow: $shadow_deep !important;
565
598
  }
566
599
 
600
+ .pb_table_td:nth-child(2) {
601
+ box-shadow: 0 0 0 0 !important;
602
+ }
603
+
567
604
  .pb_advanced_table_header,
568
605
  .pb_advanced_table_body {
569
606
  th.sticky-left,
@@ -580,6 +617,11 @@
580
617
  }
581
618
  }
582
619
 
620
+ // Row Pinning - additional inline styles in RegularTableView.tsx
621
+ .pinned-row {
622
+ box-shadow: 0 4px 10px 0 rgba($shadow, 0.16) !important;
623
+ }
624
+
583
625
  &.dark {
584
626
  // Override default border color for dark mode
585
627
  --column-border-color: #{$border_dark};
@@ -2,7 +2,7 @@ import React, { useRef, useEffect, useState, useCallback } from "react";
2
2
  import classnames from "classnames";
3
3
 
4
4
  import { GenericObject } from "../types";
5
- import { Row, RowSelectionState } from "@tanstack/react-table";
5
+ import { Row, RowSelectionState, RowPinningState } from "@tanstack/react-table";
6
6
 
7
7
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from "../utilities/props";
8
8
  import { globalProps, GlobalProps } from "../utilities/globalProps";
@@ -51,8 +51,13 @@ type AdvancedTableProps = {
51
51
  onRowToggleClick?: (arg: Row<GenericObject>) => void
52
52
  onToggleExpansionClick?: (arg: Row<GenericObject>) => void
53
53
  pagination?: boolean,
54
- paginationProps?: GenericObject
54
+ paginationProps?: GenericObject,
55
+ pinnedRows?: {
56
+ value?: RowPinningState;
57
+ onChange?: (value: RowPinningState) => void;
58
+ };
55
59
  responsive?: "scroll" | "none",
60
+ scrollBarNone?: boolean,
56
61
  selectableRows?: boolean,
57
62
  showActionsBar?: boolean,
58
63
  sortControl?: GenericObject
@@ -91,7 +96,9 @@ const AdvancedTable = (props: AdvancedTableProps) => {
91
96
  onToggleExpansionClick,
92
97
  pagination = false,
93
98
  paginationProps,
99
+ pinnedRows,
94
100
  responsive = "scroll",
101
+ scrollBarNone= false,
95
102
  showActionsBar = true,
96
103
  selectableRows,
97
104
  sortControl,
@@ -136,6 +143,7 @@ const AdvancedTable = (props: AdvancedTableProps) => {
136
143
  tableOptions,
137
144
  onRowSelectionChange,
138
145
  columnVisibilityControl,
146
+ pinnedRows,
139
147
  });
140
148
 
141
149
  // Initialize table actions
@@ -241,10 +249,11 @@ const AdvancedTable = (props: AdvancedTableProps) => {
241
249
  maxHeight ? `advanced-table-max-height-${maxHeight}` : '',
242
250
  {
243
251
  'advanced-table-fullscreen': isFullscreen,
244
- 'advanced-table-allow-fullscreen': allowFullScreen
252
+ 'advanced-table-allow-fullscreen': allowFullScreen,
245
253
  },
246
254
  {'advanced-table-sticky-left-columns': stickyLeftColumn && stickyLeftColumn.length > 0},
247
255
  columnGroupBorderColor ? `column-group-border-${columnGroupBorderColor}` : '',
256
+ scrollBarNone ? 'advanced-table-hide-scrollbar' : '',
248
257
  globalProps(props),
249
258
  className
250
259
  );
@@ -302,6 +311,7 @@ const AdvancedTable = (props: AdvancedTableProps) => {
302
311
  isFullscreen={isFullscreen}
303
312
  loading={loading}
304
313
  onExpandByDepthClick={onExpandByDepthClick}
314
+ pinnedRows={pinnedRows}
305
315
  responsive={responsive}
306
316
  selectableRows={selectableRows}
307
317
  setExpanded={setExpanded}
@@ -1,10 +1,18 @@
1
1
  <%= pb_content_tag do %>
2
- <%= pb_rails("table", props: { size: "sm", data_table: true, number_spacing:"tabular", responsive:"none", dark: dark, classname: object.loading ? "content-loading" : "" }.merge(object.table_props)) do %>
3
- <% if content.present? %>
4
- <% content.presence %>
5
- <% else %>
6
- <%= pb_rails("advanced_table/table_header", props: { column_definitions: object.column_definitions, enable_toggle_expansion: object.enable_toggle_expansion, responsive: object.responsive, loading: object.loading, selectable_rows: object.selectable_rows }) %>
7
- <%= pb_rails("advanced_table/table_body", props: { id: object.id, table_data: object.table_data, column_definitions: object.column_definitions, responsive: object.responsive, loading: object.loading, selectable_rows: object.selectable_rows, enable_toggle_expansion: object.enable_toggle_expansion }) %>
8
- <% end %>
9
- <% end %>
2
+ <% if object.id && object.selectable_rows && object.show_actions_bar %>
3
+ <%= pb_rails("advanced_table/table_action_bar", props: {
4
+ actions: object.actions,
5
+ is_visible: false,
6
+ selected_count: 0
7
+ }) %>
8
+ <% end %>
9
+
10
+ <%= pb_rails("table", props: { size: "sm", data_table: true, number_spacing:"tabular", responsive:"none", dark: dark, classname: object.loading ? "content-loading" : "" }.merge(object.table_props)) do %>
11
+ <% if content.present? %>
12
+ <% content.presence %>
13
+ <% else %>
14
+ <%= pb_rails("advanced_table/table_header", props: { column_definitions: object.column_definitions, enable_toggle_expansion: object.enable_toggle_expansion, responsive: object.responsive, loading: object.loading, selectable_rows: object.selectable_rows, show_actions_bar: object.show_actions_bar }) %>
15
+ <%= pb_rails("advanced_table/table_body", props: { id: object.id, table_data: object.table_data, column_definitions: object.column_definitions, responsive: object.responsive, loading: object.loading, selectable_rows: object.selectable_rows, enable_toggle_expansion: object.enable_toggle_expansion }) %>
16
+ <% end %>
17
+ <% end %>
10
18
  <% end %>
@@ -25,9 +25,15 @@ module Playbook
25
25
  default: "auto"
26
26
  prop :selectable_rows, type: Playbook::Props::Boolean,
27
27
  default: false
28
+ prop :show_actions_bar, type: Playbook::Props::Boolean,
29
+ default: true
30
+ prop :actions, type: Playbook::Props::Array,
31
+ default: []
32
+ prop :scroll_bar_none, type: Playbook::Props::Boolean,
33
+ default: false
28
34
 
29
35
  def classname
30
- additional_classes = [responsive_classname, max_height_classname]
36
+ additional_classes = [responsive_classname, max_height_classname, hide_scroll_bar_class]
31
37
  additional_classes << "column-group-border-#{column_group_border_color}" if column_group_border_color != "none"
32
38
  generate_classname("pb_advanced_table", *additional_classes, separator: " ")
33
39
  end
@@ -40,6 +46,10 @@ module Playbook
40
46
  max_height.present? ? "advanced-table-max-height-#{max_height}" : ""
41
47
  end
42
48
 
49
+ def hide_scroll_bar_class
50
+ scroll_bar_none ? "advanced-table-hide-scrollbar " : ""
51
+ end
52
+
43
53
  def selected_rows
44
54
  @selected_rows ||= []
45
55
  end
@@ -47,6 +57,11 @@ module Playbook
47
57
  def selected_rows_length
48
58
  selected_rows.length
49
59
  end
60
+
61
+ def is_action_bar_visible
62
+ # Action bar visibility is controlled by JS based on selection
63
+ false
64
+ end
50
65
  end
51
66
  end
52
67
  end