playbook_ui 14.8.0 → 14.9.0.pre.alpha.PBNTR702stickyleftcolrails4806

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +2 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +61 -17
  4. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.html.erb +1 -1
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta_sort.html.erb +1 -1
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell_rails.html.erb +53 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell_rails.md +5 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination.jsx +50 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination.md +1 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination_with_props.jsx +57 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination_with_props.md +5 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_pagination_mock_data.json +5600 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +3 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +3 -1
  16. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +15 -0
  17. data/app/pb_kits/playbook/pb_background/_background.tsx +8 -2
  18. data/app/pb_kits/playbook/pb_button/_button.scss +6 -0
  19. data/app/pb_kits/playbook/pb_button/_button.tsx +1 -3
  20. data/app/pb_kits/playbook/pb_button/_button_mixins.scss +15 -0
  21. data/app/pb_kits/playbook/pb_button/button.rb +1 -1
  22. data/app/pb_kits/playbook/pb_button/docs/_button_default.html.erb +1 -0
  23. data/app/pb_kits/playbook/pb_button/docs/_button_default.jsx +8 -0
  24. data/app/pb_kits/playbook/pb_button/docs/_button_default.md +1 -1
  25. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +2 -2
  26. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +0 -4
  27. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +84 -7
  28. data/app/pb_kits/playbook/pb_collapsible/_collapsible.tsx +3 -1
  29. data/app/pb_kits/playbook/pb_currency/_currency.tsx +7 -3
  30. data/app/pb_kits/playbook/pb_currency/currency.html.erb +2 -2
  31. data/app/pb_kits/playbook/pb_currency/currency.rb +17 -1
  32. data/app/pb_kits/playbook/pb_currency/currency.test.js +40 -3
  33. data/app/pb_kits/playbook/pb_currency/docs/_currency_negative.html.erb +4 -0
  34. data/app/pb_kits/playbook/pb_currency/docs/_currency_negative.jsx +16 -0
  35. data/app/pb_kits/playbook/pb_currency/docs/example.yml +2 -0
  36. data/app/pb_kits/playbook/pb_currency/docs/index.js +1 -0
  37. data/app/pb_kits/playbook/pb_drawer/_drawer.scss +1 -0
  38. data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +159 -45
  39. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +31 -0
  40. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.md +6 -0
  41. data/app/pb_kits/playbook/pb_drawer/docs/example.yml +1 -1
  42. data/app/pb_kits/playbook/pb_drawer/docs/index.js +1 -0
  43. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +1 -0
  44. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +0 -1
  45. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.rb +0 -4
  46. data/app/pb_kits/playbook/pb_dropdown/utilities/subComponentHelper.tsx +13 -2
  47. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +2 -2
  48. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_loading.html.erb +1 -1
  49. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +63 -12
  50. data/app/pb_kits/playbook/pb_image/_image.tsx +3 -1
  51. data/app/pb_kits/playbook/pb_layout/_layout.tsx +6 -3
  52. data/app/pb_kits/playbook/pb_overlay/_overlay.tsx +3 -1
  53. data/app/pb_kits/playbook/pb_pagination/_pagination.tsx +2 -2
  54. data/app/pb_kits/playbook/pb_progress_simple/_progress_simple.tsx +5 -3
  55. data/app/pb_kits/playbook/pb_progress_simple/progress_simple.html.erb +3 -2
  56. data/app/pb_kits/playbook/pb_progress_simple/progress_simple.rb +5 -0
  57. data/app/pb_kits/playbook/pb_section_separator/_section_separator.tsx +3 -1
  58. data/app/pb_kits/playbook/pb_selectable_card/docs/_selectable_card_default.html.erb +2 -1
  59. data/app/pb_kits/playbook/pb_table/_table.tsx +109 -25
  60. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns.html.erb +95 -0
  61. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns.jsx +87 -0
  62. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_react.md +2 -0
  63. data/app/pb_kits/playbook/pb_table/docs/index.js +1 -0
  64. data/app/pb_kits/playbook/pb_table/index.ts +100 -26
  65. data/app/pb_kits/playbook/pb_table/styles/_all.scss +2 -0
  66. data/app/pb_kits/playbook/pb_table/styles/_scroll.scss +4 -0
  67. data/app/pb_kits/playbook/pb_table/styles/_sticky_columns.scss +18 -0
  68. data/app/pb_kits/playbook/pb_table/table.html.erb +1 -1
  69. data/app/pb_kits/playbook/pb_table/table.rb +17 -2
  70. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_children.html.erb +47 -0
  71. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_children.jsx +59 -0
  72. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +3 -0
  73. data/app/pb_kits/playbook/pb_typeahead/index.ts +29 -3
  74. data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +5 -2
  75. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +4 -0
  76. data/app/pb_kits/playbook/tokens/_height.scss +19 -0
  77. data/app/pb_kits/playbook/tokens/exports/_height.module.scss +37 -0
  78. data/app/pb_kits/playbook/utilities/_height.scss +33 -0
  79. data/app/pb_kits/playbook/utilities/_max_width.scss +29 -9
  80. data/app/pb_kits/playbook/utilities/_min_width.scss +6 -2
  81. data/app/pb_kits/playbook/utilities/_width.scss +45 -0
  82. data/app/pb_kits/playbook/utilities/globalPropNames.mjs +1 -1
  83. data/app/pb_kits/playbook/utilities/globalProps.ts +37 -4
  84. data/dist/chunks/_typeahead-CCDoUmRR.js +22 -0
  85. data/dist/chunks/_weekday_stacked-CxjKLoMr.js +45 -0
  86. data/dist/chunks/{lib-BC6ESsxG.js → lib-CVPInSs5.js} +2 -2
  87. data/dist/chunks/{pb_form_validation-B_Z9rEbg.js → pb_form_validation-CDLJ5eAG.js} +1 -1
  88. data/dist/chunks/vendor.js +1 -1
  89. data/dist/menu.yml +321 -0
  90. data/dist/playbook-doc.js +1 -1
  91. data/dist/playbook-rails-react-bindings.js +1 -1
  92. data/dist/playbook-rails.js +1 -1
  93. data/dist/playbook.css +1 -1
  94. data/lib/playbook/classnames.rb +4 -0
  95. data/lib/playbook/forms/builder/typeahead_field.rb +13 -0
  96. data/lib/playbook/height.rb +29 -0
  97. data/lib/playbook/kit_base.rb +16 -1
  98. data/lib/playbook/max_height.rb +29 -0
  99. data/lib/playbook/min_height.rb +29 -0
  100. data/lib/playbook/spacing.rb +21 -0
  101. data/lib/playbook/version.rb +2 -2
  102. metadata +32 -9
  103. data/dist/chunks/_typeahead-D0PihN_3.js +0 -22
  104. data/dist/chunks/_weekday_stacked-uMIX8f-A.js +0 -45
@@ -1,7 +1,9 @@
1
1
  import React from 'react'
2
2
  import classnames from 'classnames'
3
3
  import { buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
4
- import { globalProps } from '../utilities/globalProps'
4
+ import { globalProps, GlobalProps } from '../utilities/globalProps'
5
+
6
+ type ModifiedGlobalProps = Omit<GlobalProps, 'width'>
5
7
 
6
8
  type ProgressSimpleProps = {
7
9
  align?: "left" | "center" | "right",
@@ -16,7 +18,7 @@ type ProgressSimpleProps = {
16
18
  value: number,
17
19
  variant?: "default" | "positive" | "negative" | "warning",
18
20
  width: string,
19
- }
21
+ } & ModifiedGlobalProps
20
22
 
21
23
  const ProgressSimple = (props: ProgressSimpleProps): React.ReactElement => {
22
24
  const {
@@ -56,7 +58,7 @@ const ProgressSimple = (props: ProgressSimpleProps): React.ReactElement => {
56
58
  )
57
59
 
58
60
  return (
59
- <div
61
+ <div
60
62
  {...dataProps}
61
63
  {...htmlProps}
62
64
  className={wrapperClass}
@@ -1,9 +1,10 @@
1
- <%= content_tag(:div, class: object.wrapper_classname) do %>
1
+ <%= content_tag(:div,
2
+ class: object.wrapper_classname,
3
+ style: object.style) do %>
2
4
  <%= content_tag(:div,
3
5
  id: object.id,
4
6
  data: object.data_values,
5
7
  class: object.classname,
6
- style: object.style,
7
8
  **combined_html_options) do %>
8
9
  <%= content_tag(:div, "",
9
10
  class: "progress_simple_value",
@@ -21,6 +21,11 @@ module Playbook
21
21
  values: %w[default positive negative warning],
22
22
  default: "default"
23
23
 
24
+ # Explicitly defining the width prop here so the local prop takes precedence over global width prop
25
+ def width
26
+ prop(:width)
27
+ end
28
+
24
29
  def number_value
25
30
  validate_required_progress_props
26
31
 
@@ -2,7 +2,7 @@ import React from 'react'
2
2
  import classnames from 'classnames'
3
3
 
4
4
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
5
- import { globalProps } from '../utilities/globalProps'
5
+ import { globalProps, globalInlineProps } from '../utilities/globalProps'
6
6
 
7
7
  import Caption from '../pb_caption/_caption'
8
8
 
@@ -38,6 +38,7 @@ const SectionSeparator = (props: SectionSeparatorProps): React.ReactElement => {
38
38
  const dataProps = buildDataProps(data)
39
39
  const htmlProps = buildHtmlProps(htmlOptions)
40
40
  const classes = classnames(buildCss('pb_section_separator_kit', variant, orientation, lineStyle === "dashed" ? lineStyle : ""), globalProps(props), className)
41
+ const dynamicInlineProps = globalInlineProps(props)
41
42
 
42
43
  return (
43
44
 
@@ -47,6 +48,7 @@ const SectionSeparator = (props: SectionSeparatorProps): React.ReactElement => {
47
48
  {...htmlProps}
48
49
  className={classes}
49
50
  id={id}
51
+ style={dynamicInlineProps}
50
52
  >
51
53
  {
52
54
  children && children ||
@@ -6,6 +6,7 @@
6
6
  value: "selected_with_icon",
7
7
  checked: true,
8
8
  icon: true,
9
+
9
10
  }) do %>
10
11
  Selected, with icon
11
12
  <% end %>
@@ -36,4 +37,4 @@
36
37
  Disabled
37
38
  <% end %>
38
39
 
39
- </div>
40
+ </div>
@@ -1,14 +1,14 @@
1
1
  import React, { useEffect } from 'react'
2
2
  import classnames from 'classnames'
3
3
  import { buildAriaProps, buildDataProps, buildHtmlProps } from '../utilities/props'
4
- import { globalProps, GlobalProps } from '../utilities/globalProps'
4
+ import { globalProps, GlobalProps, globalInlineProps } from '../utilities/globalProps'
5
5
  import PbTable from '.'
6
6
  import {
7
- TableHead,
8
- TableHeader,
9
- TableBody,
10
- TableRow,
11
- TableCell,
7
+ TableHead,
8
+ TableHeader,
9
+ TableBody,
10
+ TableRow,
11
+ TableCell,
12
12
  } from "./subcomponents";
13
13
 
14
14
  type TableProps = {
@@ -28,6 +28,7 @@ type TableProps = {
28
28
  singleLine?: boolean,
29
29
  size?: "sm" | "md" | "lg",
30
30
  sticky?: boolean,
31
+ stickyLeftcolumn?: string[],
31
32
  striped?: boolean,
32
33
  tag?: "table" | "div",
33
34
  verticalBorder?: boolean,
@@ -51,6 +52,7 @@ const Table = (props: TableProps): React.ReactElement => {
51
52
  singleLine = false,
52
53
  size = 'sm',
53
54
  sticky = false,
55
+ stickyLeftcolumn = [],
54
56
  striped = false,
55
57
  tag = 'table',
56
58
  verticalBorder = false,
@@ -64,6 +66,7 @@ const Table = (props: TableProps): React.ReactElement => {
64
66
  const spaceCssName = outerPadding !== 'none' ? 'space_' : ''
65
67
  const outerPaddingCss = outerPadding ? `outer_padding_${spaceCssName}${outerPadding}` : ''
66
68
  const isTableTag = tag === 'table'
69
+ const dynamicInlineProps = globalInlineProps(props)
67
70
 
68
71
  const classNames = classnames(
69
72
  'pb_table',
@@ -76,6 +79,7 @@ const Table = (props: TableProps): React.ReactElement => {
76
79
  'single-line': singleLine,
77
80
  'no-hover': disableHover,
78
81
  'sticky-header': sticky,
82
+ 'sticky-left-column': stickyLeftcolumn,
79
83
  'striped': striped,
80
84
  [outerPaddingCss]: outerPadding !== '',
81
85
  },
@@ -85,6 +89,56 @@ const Table = (props: TableProps): React.ReactElement => {
85
89
  className
86
90
  )
87
91
 
92
+ useEffect(() => {
93
+ const handleStickyColumns = () => {
94
+ let accumulatedWidth = 0;
95
+
96
+ stickyLeftcolumn.forEach((colId, index) => {
97
+ const isLastColumn = index === stickyLeftcolumn.length - 1;
98
+ const header = document.querySelector(`th[id="${colId}"]`);
99
+ const cells = document.querySelectorAll(`td[id="${colId}"]`);
100
+
101
+ if (header) {
102
+ header.classList.add('sticky');
103
+ (header as HTMLElement).style.left = `${accumulatedWidth}px`;
104
+
105
+ if (!isLastColumn) {
106
+ header.classList.add('with-border');
107
+ header.classList.remove('sticky-shadow');
108
+ } else {
109
+ header.classList.remove('with-border');
110
+ header.classList.add('sticky-shadow');
111
+ }
112
+
113
+ accumulatedWidth += (header as HTMLElement).offsetWidth;
114
+ }
115
+
116
+ cells.forEach((cell) => {
117
+ cell.classList.add('sticky');
118
+ (cell as HTMLElement).style.left = `${accumulatedWidth - (header as HTMLElement).offsetWidth}px`;
119
+
120
+ if (!isLastColumn) {
121
+ cell.classList.add('with-border');
122
+ cell.classList.remove('sticky-shadow');
123
+ } else {
124
+ cell.classList.remove('with-border');
125
+ cell.classList.add('sticky-shadow');
126
+ }
127
+ });
128
+ });
129
+ };
130
+
131
+ setTimeout(() => {
132
+ handleStickyColumns();
133
+ }, 10);
134
+
135
+ window.addEventListener('resize', handleStickyColumns);
136
+
137
+ return () => {
138
+ window.removeEventListener('resize', handleStickyColumns);
139
+ };
140
+ }, [stickyLeftcolumn]);
141
+
88
142
  useEffect(() => {
89
143
  const instance = new PbTable()
90
144
  instance.connect()
@@ -92,26 +146,56 @@ const Table = (props: TableProps): React.ReactElement => {
92
146
 
93
147
  return (
94
148
  <>
95
- {isTableTag ? (
96
- <table
97
- {...ariaProps}
98
- {...dataProps}
99
- {...htmlProps}
100
- className={classNames}
101
- id={id}
102
- >
103
- {children}
104
- </table>
105
- ) : (
106
- <div
107
- {...ariaProps}
108
- {...dataProps}
109
- {...htmlProps}
110
- className={classNames}
111
- id={id}
112
- >
113
- {children}
149
+ {responsive === 'scroll' ? (
150
+ <div className='table-responsive-scroll'>
151
+ {isTableTag ? (
152
+ <table
153
+ {...ariaProps}
154
+ {...dataProps}
155
+ {...htmlProps}
156
+ className={classNames}
157
+ id={id}
158
+ style={dynamicInlineProps}
159
+ >
160
+ {children}
161
+ </table>
162
+ ) : (
163
+ <div
164
+ {...ariaProps}
165
+ {...dataProps}
166
+ {...htmlProps}
167
+ className={classNames}
168
+ id={id}
169
+ style={dynamicInlineProps}
170
+ >
171
+ {children}
172
+ </div>
173
+ )}
114
174
  </div>
175
+ ) : (
176
+ isTableTag ? (
177
+ <table
178
+ {...ariaProps}
179
+ {...dataProps}
180
+ {...htmlProps}
181
+ className={classNames}
182
+ id={id}
183
+ style={dynamicInlineProps}
184
+ >
185
+ {children}
186
+ </table>
187
+ ) : (
188
+ <div
189
+ {...ariaProps}
190
+ {...dataProps}
191
+ {...htmlProps}
192
+ className={classNames}
193
+ id={id}
194
+ style={dynamicInlineProps}
195
+ >
196
+ {children}
197
+ </div>
198
+ )
115
199
  )}
116
200
  </>
117
201
  )
@@ -0,0 +1,95 @@
1
+ <%= pb_rails("table", props: { size: "md", responsive: "scroll", sticky_left_column: ["1", "2", "3"] }) do %>
2
+ <thead>
3
+ <tr>
4
+ <th id="1">Column 1</th>
5
+ <th id="2">Column 2</th>
6
+ <th id="3">Column 3</th>
7
+ <th>Column 4</th>
8
+ <th>Column 5</th>
9
+ <th>Column 6</th>
10
+ <th>Column 7</th>
11
+ <th>Column 8</th>
12
+ <th>Column 9</th>
13
+ <th>Column 10</th>
14
+ <th>Column 11</th>
15
+ <th>Column 12</th>
16
+ <th>Column 13</th>
17
+ <th>Column 14</th>
18
+ <th>Column 15</th>
19
+ </tr>
20
+ </thead>
21
+ <tbody>
22
+ <tr>
23
+ <td id="1">Value 1</td>
24
+ <td id="2">Value 2</td>
25
+ <td id="3">Value 3</td>
26
+ <td>Value 4</td>
27
+ <td>Value 5</td>
28
+ <td>Column 6</td>
29
+ <td>Column 7</td>
30
+ <td>Column 8</td>
31
+ <td>Column 9</td>
32
+ <td>Column 10</td>
33
+ <td>Column 11</td>
34
+ <td>Column 12</td>
35
+ <td>Column 13</td>
36
+ <td>Column 14</td>
37
+ <td>Column 15</td>
38
+
39
+ </tr>
40
+ <tr>
41
+ <td id="1">Value 1</td>
42
+ <td id="2">Value 2</td>
43
+ <td id="3">Value 3</td>
44
+ <td>Value 4</td>
45
+ <td>Value 5</td>
46
+ <td>Column 6</td>
47
+ <td>Column 7</td>
48
+ <td>Column 8</td>
49
+ <td>Column 9</td>
50
+ <td>Column 10</td>
51
+ <td>Column 11</td>
52
+ <td>Column 12</td>
53
+ <td>Column 13</td>
54
+ <td>Column 14</td>
55
+ <td>Column 15</td>
56
+
57
+ </tr>
58
+ <tr>
59
+ <td id="1">Value 1</td>
60
+ <td id="2">Value 2</td>
61
+ <td id="3">Value 3</td>
62
+ <td>Value 4</td>
63
+ <td>Value 5</td>
64
+ <td>Column 6</td>
65
+ <td>Column 7</td>
66
+ <td>Column 8</td>
67
+ <td>Column 9</td>
68
+ <td>Column 10</td>
69
+ <td>Column 11</td>
70
+ <td>Column 12</td>
71
+ <td>Column 13</td>
72
+ <td>Column 14</td>
73
+ <td>Column 15</td>
74
+
75
+ </tr>
76
+ <tr>
77
+ <td id="1">Value 1</td>
78
+ <td id="2">Value 2</td>
79
+ <td id="3">Value 3</td>
80
+ <td>Value 4</td>
81
+ <td>Value 5</td>
82
+ <td>Column 6</td>
83
+ <td>Column 7</td>
84
+ <td>Column 8</td>
85
+ <td>Column 9</td>
86
+ <td>Column 10</td>
87
+ <td>Column 11</td>
88
+ <td>Column 12</td>
89
+ <td>Column 13</td>
90
+ <td>Column 14</td>
91
+ <td>Column 15</td>
92
+
93
+ </tr>
94
+ </tbody>
95
+ <% end %>
@@ -0,0 +1,87 @@
1
+ import React from 'react'
2
+ import Table from '../_table'
3
+
4
+ const TableStickyLeftColumns = () => {
5
+ return (
6
+ <Table
7
+ responsive="scroll"
8
+ size="md"
9
+ stickyLeftcolumn={["1", "2", "3"]}
10
+ >
11
+ <thead>
12
+ <tr>
13
+ <th id="1">{'Column 1'}</th>
14
+ <th id="2">{'Column 2'}</th>
15
+ <th id="3">{'Column 3'}</th>
16
+ <th>{'Column 4'}</th>
17
+ <th>{'Column 5'}</th>
18
+ <th>{'Column 6'}</th>
19
+ <th>{'Column 7'}</th>
20
+ <th>{'Column 8'}</th>
21
+ <th>{'Column 9'}</th>
22
+ <th>{'Column 10'}</th>
23
+ <th>{'Column 11'}</th>
24
+ <th>{'Column 12'}</th>
25
+ <th>{'Column 13'}</th>
26
+ <th>{'Column 14'}</th>
27
+ <th>{'Column 15'}</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <tr>
32
+ <td id="1">{'Value 1'}</td>
33
+ <td id="2">{'Value 2'}</td>
34
+ <td id="3">{'Value 3'}</td>
35
+ <td>{'Value 4'}</td>
36
+ <td>{'Value 5'}</td>
37
+ <td>{'Value 6'}</td>
38
+ <td>{'Value 7'}</td>
39
+ <td>{'Value 8'}</td>
40
+ <td>{'Value 9'}</td>
41
+ <td>{'Value 10'}</td>
42
+ <td>{'Value 11'}</td>
43
+ <td>{'Value 12'}</td>
44
+ <td>{'Value 13'}</td>
45
+ <td>{'Value 14'}</td>
46
+ <td>{'Value 15'}</td>
47
+ </tr>
48
+ <tr>
49
+ <td id="1">{'Value 1'}</td>
50
+ <td id="2">{'Value 2'}</td>
51
+ <td id="3">{'Value 3'}</td>
52
+ <td>{'Value 4'}</td>
53
+ <td>{'Value 5'}</td>
54
+ <td>{'Value 6'}</td>
55
+ <td>{'Value 7'}</td>
56
+ <td>{'Value 8'}</td>
57
+ <td>{'Value 9'}</td>
58
+ <td>{'Value 10'}</td>
59
+ <td>{'Value 11'}</td>
60
+ <td>{'Value 12'}</td>
61
+ <td>{'Value 13'}</td>
62
+ <td>{'Value 14'}</td>
63
+ <td>{'Value 15'}</td>
64
+ </tr>
65
+ <tr>
66
+ <td id="1">{'Value 1'}</td>
67
+ <td id="2">{'Value 2'}</td>
68
+ <td id="3">{'Value 3'}</td>
69
+ <td>{'Value 4'}</td>
70
+ <td>{'Value 5'}</td>
71
+ <td>{'Value 6'}</td>
72
+ <td>{'Value 7'}</td>
73
+ <td>{'Value 8'}</td>
74
+ <td>{'Value 9'}</td>
75
+ <td>{'Value 10'}</td>
76
+ <td>{'Value 11'}</td>
77
+ <td>{'Value 12'}</td>
78
+ <td>{'Value 13'}</td>
79
+ <td>{'Value 14'}</td>
80
+ <td>{'Value 15'}</td>
81
+ </tr>
82
+ </tbody>
83
+ </Table>
84
+ )
85
+ }
86
+
87
+ export default TableStickyLeftColumns
@@ -0,0 +1,2 @@
1
+ The `stickyLeftColumn` prop expects an array of the column ids you want to be sticky. Make sure to add the corresponding id to the `<th>` and `<td>`.
2
+ If you are using the sub-component variant, then you will pass the id to `<Table.Header>` and `<Table.Cell>`
@@ -25,3 +25,4 @@ export { default as TableDiv } from './_table_div.jsx'
25
25
  export { default as TableWithSubcomponents } from './_table_with_subcomponents.jsx'
26
26
  export { default as TableWithSubcomponentsAsDivs } from './_table_with_subcomponents_as_divs.jsx'
27
27
  export { default as TableOuterPadding } from './_table_outer_padding.jsx'
28
+ export { default as TableStickyLeftColumns } from './_table_sticky_left_columns.jsx'
@@ -1,32 +1,106 @@
1
1
  import PbEnhancedElement from '../pb_enhanced_element'
2
2
 
3
3
  export default class PbTable extends PbEnhancedElement {
4
- static get selector(): string {
5
- return '.table-responsive-collapse'
6
- }
7
-
8
- connect(): void {
9
- const tables = document.querySelectorAll('.table-responsive-collapse');
10
-
11
- // Each Table
12
- [].forEach.call(tables, (table: HTMLTableElement) => {
13
- // Header Titles
14
- const headers: string[] = [];
15
- [].forEach.call(table.querySelectorAll('th'), (header: HTMLTableCellElement) => {
16
- const colSpan = header.colSpan
17
- for (let i = 0; i < colSpan; i++) {
18
- headers.push(header.textContent.replace(/\r?\n|\r/, ''));
4
+ private stickyLeftColumns: string[] = [];
5
+ private handleStickyColumnsRef: () => void;
6
+
7
+ static get selector(): string {
8
+ return '.table-responsive-collapse'
9
+ }
10
+
11
+ connect(): void {
12
+ const tables = document.querySelectorAll('.table-responsive-collapse');
13
+ // Each Table
14
+ [].forEach.call(tables, (table: HTMLTableElement) => {
15
+ // Header Titles
16
+ const headers: string[] = [];
17
+ [].forEach.call(table.querySelectorAll('th'), (header: HTMLTableCellElement) => {
18
+ const colSpan = header.colSpan
19
+ for (let i = 0; i < colSpan; i++) {
20
+ headers.push(header.textContent.replace(/\r?\n|\r/, ''));
21
+ }
22
+ });
23
+ // for each row in tbody
24
+ [].forEach.call(table.querySelectorAll('tbody tr'), (row: HTMLTableRowElement) => {
25
+ // for each cell
26
+ [].forEach.call(row.cells, (cell: HTMLTableCellElement, headerIndex: number) => {
27
+ // apply the attribute
28
+ cell.setAttribute('data-title', headers[headerIndex])
29
+ })
30
+ })
31
+ });
32
+
33
+ // New sticky columns logic
34
+ this.initStickyColumns();
35
+ }
36
+
37
+ private initStickyColumns(): void {
38
+ // Find tables with sticky-left-column class
39
+ const tables = document.querySelectorAll('.sticky-left-column');
40
+
41
+ tables.forEach((table) => {
42
+ // Extract sticky left column IDs by looking at the component's class
43
+ const classList = Array.from(table.classList);
44
+
45
+ // Look for classes in the format sticky-left-column-{ids}
46
+ const stickyColumnClass = classList.find(cls => cls.startsWith('sticky-columns-'));
47
+ if (stickyColumnClass) {
48
+ // Extract the IDs from the class name
49
+ this.stickyLeftColumns = stickyColumnClass
50
+ .replace('sticky-columns-', '')
51
+ .split('-');
52
+
53
+ if (this.stickyLeftColumns.length > 0) {
54
+ this.handleStickyColumnsRef = this.handleStickyColumns.bind(this);
55
+ this.handleStickyColumns();
56
+ window.addEventListener('resize', this.handleStickyColumnsRef);
57
+ }
19
58
  }
20
59
  });
60
+ }
21
61
 
22
- // for each row in tbody
23
- [].forEach.call(table.querySelectorAll('tbody tr'), (row: HTMLTableRowElement) => {
24
- // for each cell
25
- [].forEach.call(row.cells, (cell: HTMLTableCellElement, headerIndex: number) => {
26
- // apply the attribute
27
- cell.setAttribute('data-title', headers[headerIndex])
28
- })
29
- })
30
- })
31
- }
32
- }
62
+ private handleStickyColumns(): void {
63
+ let accumulatedWidth = 0;
64
+
65
+ this.stickyLeftColumns.forEach((colId, index) => {
66
+ const isLastColumn = index === this.stickyLeftColumns.length - 1;
67
+ const header = document.querySelector(`th[id="${colId}"]`);
68
+ const cells = document.querySelectorAll(`td[id="${colId}"]`);
69
+
70
+ if (header) {
71
+ header.classList.add('sticky');
72
+ (header as HTMLElement).style.left = `${accumulatedWidth}px`;
73
+
74
+ if (!isLastColumn) {
75
+ header.classList.add('with-border');
76
+ header.classList.remove('sticky-shadow');
77
+ } else {
78
+ header.classList.remove('with-border');
79
+ header.classList.add('sticky-shadow');
80
+ }
81
+
82
+ accumulatedWidth += (header as HTMLElement).offsetWidth;
83
+ }
84
+
85
+ cells.forEach((cell) => {
86
+ cell.classList.add('sticky');
87
+ (cell as HTMLElement).style.left = `${accumulatedWidth - (header as HTMLElement).offsetWidth}px`;
88
+
89
+ if (!isLastColumn) {
90
+ cell.classList.add('with-border');
91
+ cell.classList.remove('sticky-shadow');
92
+ } else {
93
+ cell.classList.remove('with-border');
94
+ cell.classList.add('sticky-shadow');
95
+ }
96
+ });
97
+ });
98
+ }
99
+
100
+ // Cleanup method to remove event listener
101
+ disconnect(): void {
102
+ if (this.handleStickyColumnsRef) {
103
+ window.removeEventListener('resize', this.handleStickyColumnsRef);
104
+ }
105
+ }
106
+ }
@@ -20,3 +20,5 @@
20
20
  @import "table_header";
21
21
  @import "striped";
22
22
  @import "outer_padding";
23
+ @import "sticky_columns";
24
+ @import "scroll";
@@ -0,0 +1,4 @@
1
+ .table-responsive-scroll {
2
+ display: block;
3
+ overflow-x: auto;
4
+ }
@@ -0,0 +1,18 @@
1
+ @import "../../tokens/colors";
2
+
3
+ [class^="pb_table"] {
4
+ .sticky {
5
+ position: sticky !important;
6
+ left: 0;
7
+ z-index: 1;
8
+ background-color: white;
9
+ }
10
+
11
+ .with-border {
12
+ border-right: 1px solid $border_light !important;
13
+ }
14
+
15
+ .sticky-shadow {
16
+ box-shadow: 4px 0 10px rgba(60, 106, 172, 0.16) !important;
17
+ }
18
+ }
@@ -18,4 +18,4 @@
18
18
  <%= content.presence %>
19
19
  <% end %>
20
20
  <% end %>
21
- <% end %>
21
+ <% end %>