playbook_ui 16.8.0.pre.alpha.PLAY298616637 → 16.8.0.pre.alpha.play293416802

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_enable_toggle_expansion_rails.html.erb +62 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_enable_toggle_expansion_rails.md +7 -0
  4. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.jsx +12 -4
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.md +4 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.html.erb +16 -2
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.md +4 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_scroll_limitation.jsx +68 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_scroll_limitation.md +7 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.html.erb +16 -2
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.jsx +12 -5
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_rails.md +4 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_react.md +5 -3
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +2 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -0
  16. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +2 -42
  17. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +41 -29
  18. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +0 -12
  19. data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +0 -60
  20. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +1 -3
  21. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_dialog_submission.jsx +2 -2
  22. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +58 -0
  23. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +2 -0
  24. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +7 -1
  25. data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.tsx +100 -28
  26. data/app/pb_kits/playbook/pb_filter/Filter/FilterDouble.tsx +4 -1
  27. data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.tsx +4 -1
  28. data/app/pb_kits/playbook/pb_filter/Filter/InteractiveFilter.tsx +277 -0
  29. data/app/pb_kits/playbook/pb_filter/_filter.scss +108 -1
  30. data/app/pb_kits/playbook/pb_filter/docs/_filter_default.html.erb +5 -1
  31. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive.html.erb +116 -0
  32. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive.md +14 -0
  33. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive_react.jsx +153 -0
  34. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive_react.md +10 -0
  35. data/app/pb_kits/playbook/pb_filter/docs/example.yml +2 -0
  36. data/app/pb_kits/playbook/pb_filter/docs/index.js +2 -1
  37. data/app/pb_kits/playbook/pb_filter/filter.html.erb +85 -3
  38. data/app/pb_kits/playbook/pb_filter/filter.rb +71 -0
  39. data/app/pb_kits/playbook/pb_filter/filter.test.js +138 -0
  40. data/app/pb_kits/playbook/pb_filter/index.ts +352 -0
  41. data/app/pb_kits/playbook/pb_filter/kit.schema.json +6 -0
  42. data/app/pb_kits/playbook/pb_icon/_icon.scss +2 -1
  43. data/app/pb_kits/playbook/pb_select/select.rb +9 -0
  44. data/app/pb_kits/playbook/pb_table/docs/_table_sticky.html.erb +85 -83
  45. data/app/pb_kits/playbook/pb_table/docs/_table_sticky.jsx +88 -86
  46. data/app/pb_kits/playbook/pb_table/docs/_table_sticky.md +3 -1
  47. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_external_filter_rails.md +1 -1
  48. data/app/pb_kits/playbook/pb_text_input/_text_input.scss +37 -0
  49. data/app/pb_kits/playbook/pb_text_input/text_input.rb +9 -0
  50. data/app/pb_kits/playbook/pb_time_picker/_time_picker.scss +26 -3
  51. data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_default.md +3 -1
  52. data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler.html.erb +24 -0
  53. data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler_rails.md +6 -0
  54. data/app/pb_kits/playbook/pb_time_picker/docs/example.yml +1 -0
  55. data/app/pb_kits/playbook/pb_time_picker/index.ts +771 -30
  56. data/app/pb_kits/playbook/pb_time_picker/time_picker.html.erb +168 -1
  57. data/app/pb_kits/playbook/pb_time_picker/time_picker.rb +53 -38
  58. data/dist/chunks/{_pb_line_graph-BdDqs3Vu.js → _pb_line_graph-Cb55jfIQ.js} +1 -1
  59. data/dist/chunks/{_typeahead-B8k7RBsj.js → _typeahead-TVQIJBcl.js} +2 -2
  60. data/dist/chunks/{globalProps-DF0MuVPf.js → globalProps-Dgb9uSU9.js} +1 -1
  61. data/dist/chunks/lib-DUPzOYd7.js +29 -0
  62. data/dist/chunks/{lazysizes-B7xYodB-.js → time_picker_helper-Bx8nzyM8.js} +1 -1
  63. data/dist/chunks/vendor.js +5 -5
  64. data/dist/menu.yml +4 -4
  65. data/dist/playbook-rails-react-bindings.js +1 -1
  66. data/dist/playbook-rails.js +1 -1
  67. data/dist/playbook.css +1 -1
  68. data/lib/playbook/forms/builder/time_picker_field.rb +6 -3
  69. data/lib/playbook/version.rb +1 -1
  70. metadata +20 -8
  71. data/dist/chunks/lib-DsBJM_F3.js +0 -29
  72. /data/app/pb_kits/playbook/pb_time_picker/docs/{_time_picker_on_handler.md → _time_picker_on_handler_react.md} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7433137fdbca6402528b7760f24b18180f74ee7e365cf010286a3a8e80614b5
4
- data.tar.gz: fd6226655188651cbdc783e6acb77deff35ebcaaea75a03f040cf2466505d3e8
3
+ metadata.gz: 97c1fd925455a9e6eff978e1a8fdecfd468eac9a740da37bac70baba0657553b
4
+ data.tar.gz: 3238668211f24e47b266678d4423113c9a74dd7dc887b4861e71fa35dd395951
5
5
  SHA512:
6
- metadata.gz: 8e022be82d66109e4e13e67776667c0fa952b4fb25b9ff961deb80a4e9801e490de9fa256a9acd0a9a4e7456a44a55ba0707be8f88cca0ca4551f510d90ab6d3
7
- data.tar.gz: 9587bdc193b7be5422c15c21c8fec87a28cb7e1779ff566bac63d4c9bff0383ad0bc18062159667d447f972b44e99f6d43567892a04e62c1e08584cfe956bec9
6
+ metadata.gz: 9baa8b5e56bc75de858aca8789577215a16eea48faa6cf9c3aa70c90e5eec73094e573189081e3ad28a511b01a5fa7b8f48c58abc3839cdd83fd7c4783824fe6
7
+ data.tar.gz: 564a482162cb22c918abe00c9e009107d049494196fe7d9e1c79bd40ea8bfbdb7f21f3fc349ad69a5834fa47396e819eeabd39d09fb74b0d9715f746db2a1f34
@@ -0,0 +1,62 @@
1
+ <%
2
+ column_definitions = [
3
+ {
4
+ accessor: "year",
5
+ label: "Year",
6
+ cellAccessors: ["quarter", "month", "day"],
7
+ },
8
+ {
9
+ accessor: "newEnrollments",
10
+ label: "New Enrollments",
11
+ },
12
+ {
13
+ accessor: "scheduledMeetings",
14
+ label: "Scheduled Meetings",
15
+ },
16
+ {
17
+ accessor: "attendanceRate",
18
+ label: "Attendance Rate",
19
+ },
20
+ {
21
+ accessor: "completedClasses",
22
+ label: "Completed Classes",
23
+ },
24
+ {
25
+ accessor: "classCompletionRate",
26
+ label: "Class Completion Rate",
27
+ },
28
+ {
29
+ accessor: "graduatedStudents",
30
+ label: "Graduated Students",
31
+ }
32
+ ]
33
+
34
+ subrow_headers = ["Quarter", "Month", "Day"]
35
+ %>
36
+
37
+ <%= pb_rails("title", props: { size: 4, text: "Normal Structure", margin_bottom: "sm" }) %>
38
+
39
+ <%= pb_rails("advanced_table", props: {
40
+ id: "enable-toggle-expansion-normal",
41
+ table_data: @table_data,
42
+ column_definitions: column_definitions,
43
+ enable_toggle_expansion: "all"
44
+ }) %>
45
+
46
+ <%= pb_rails("title", props: { size: 4, text: "Subcomponent Structure", margin_top: "lg", margin_bottom: "sm" }) %>
47
+
48
+ <%= pb_rails("advanced_table", props: { id: "enable-toggle-expansion-subcomponents" }) do %>
49
+ <%= pb_rails("advanced_table/table_header", props: {
50
+ table_id: "enable-toggle-expansion-subcomponents",
51
+ table_data: @table_data,
52
+ column_definitions: column_definitions,
53
+ enable_toggle_expansion: "all"
54
+ }) %>
55
+ <%= pb_rails("advanced_table/table_body", props: {
56
+ table_id: "enable-toggle-expansion-subcomponents",
57
+ table_data: @table_data,
58
+ column_definitions: column_definitions,
59
+ subrow_headers: subrow_headers,
60
+ enable_toggle_expansion: "all"
61
+ }) %>
62
+ <% end %>
@@ -0,0 +1,7 @@
1
+ `enable_toggle_expansion` controls where AdvancedTable renders toggle-all expansion controls. It accepts `"header"`, `"all"`, or `"none"` and defaults to `"header"`.
2
+
3
+ When using the normal Rails structure, pass `enable_toggle_expansion` to `advanced_table`. The parent kit renders its own `table_header` and `table_body`, so the prop is passed down automatically.
4
+
5
+ When using the Rails subcomponent structure, pass `enable_toggle_expansion` directly to the subcomponents that need it. `advanced_table/table_header` uses it for the table header toggle-all button. **NOTE**: you must pass `table_data` to `advanced_table/table_header` as well so it can detect whether expandable rows exist. `advanced_table/table_body` uses it for nested subrow header toggle controls, such as when `subrow_headers` is present.
6
+
7
+ Use `"all"` when you want toggle-all controls in both the table header and subrow headers. Use `"header"` when you only want the table header toggle-all control. Use `"none"` to suppress the header toggle-all control.
@@ -1,13 +1,21 @@
1
1
  import React from "react"
2
2
  import AdvancedTable from '../../pb_advanced_table/_advanced_table'
3
- import MOCK_DATA from "./advanced_table_mock_data.json"
3
+
4
+ const tableData = Array.from({ length: 15 }, (_, index) => ({
5
+ year: String(2020 + index),
6
+ newEnrollments: String(20 + index),
7
+ scheduledMeetings: String(10 + index),
8
+ attendanceRate: `${50 + index}%`,
9
+ completedClasses: String(3 + index),
10
+ classCompletionRate: `${30 + index}%`,
11
+ graduatedStudents: String(19 + index),
12
+ }))
4
13
 
5
14
  const AdvancedTableStickyHeader = (props) => {
6
15
  const columnDefinitions = [
7
16
  {
8
17
  accessor: "year",
9
18
  label: "Year",
10
- cellAccessors: ["quarter", "month", "day"],
11
19
  },
12
20
  {
13
21
  accessor: "newEnrollments",
@@ -40,11 +48,11 @@ const AdvancedTableStickyHeader = (props) => {
40
48
  }
41
49
 
42
50
  return (
43
- <div>
51
+ <div style={{ maxHeight: "320px", overflowY: "auto" }}>
44
52
  <AdvancedTable
45
53
  columnDefinitions={columnDefinitions}
46
54
  responsive="none"
47
- tableData={MOCK_DATA}
55
+ tableData={tableData}
48
56
  tableProps={tableProps}
49
57
  {...props}
50
58
  />
@@ -1,3 +1,7 @@
1
1
  The `TableProps` prop can also be used to render a sticky header for the Advanced Table.
2
2
 
3
+ This doc example uses a scroll container with flat rows so sticky behavior is visible in the docs without expanding subrows. Scroll inside the preview to see the header stick.
4
+
5
+ This example builds flat table data inline for the docs preview. For typical `tableData` setup, see [Default (Required Props)](/kits/advanced_table/default/react#advanced_table_default).
6
+
3
7
  This doc example showcases how to set a sticky header for a nonresponsive table (see the `responsive` prop set to "none"). To achieve sticky header AND responsive functionality, see the "Sticky Header for Responsive Table" doc example below.
@@ -2,7 +2,6 @@
2
2
  {
3
3
  accessor: "year",
4
4
  label: "Year",
5
- cellAccessors: ["quarter", "month", "day"],
6
5
  },
7
6
  {
8
7
  accessor: "newEnrollments",
@@ -30,4 +29,19 @@
30
29
  }
31
30
  ] %>
32
31
 
33
- <%= pb_rails("advanced_table", props: { id: "sticky_header_table", table_data: @table_data, column_definitions: column_definitions, responsive: "none", table_props: { sticky: true }}) %>
32
+ <% table_data = 15.times.map do |index|
33
+ {
34
+ year: (2020 + index).to_s,
35
+ id: (2020 + index).to_s,
36
+ newEnrollments: (20 + index).to_s,
37
+ scheduledMeetings: (10 + index).to_s,
38
+ attendanceRate: "#{50 + index}%",
39
+ completedClasses: (3 + index).to_s,
40
+ classCompletionRate: "#{30 + index}%",
41
+ graduatedStudents: (19 + index).to_s,
42
+ }
43
+ end %>
44
+
45
+ <div style="max-height: 320px; overflow-y: auto;">
46
+ <%= pb_rails("advanced_table", props: { id: "sticky_header_table", table_data: table_data, column_definitions: column_definitions, responsive: "none", table_props: { sticky: true }}) %>
47
+ </div>
@@ -1,3 +1,7 @@
1
1
  The `table_props` prop can also be used to render a sticky header for the Advanced Table.
2
2
 
3
+ This doc example uses a scroll container with flat rows so sticky behavior is visible in the docs without expanding subrows. Scroll inside the preview to see the header stick.
4
+
5
+ This example builds flat table data inline for the docs preview. For typical `table_data` setup, see [Default (Required Props)](/kits/advanced_table/default/rails#advanced_table_beta).
6
+
3
7
  This doc example showcases how to set a sticky header for a nonresponsive table (see the `responsive` prop set to "none"). To achieve sticky header AND responsive functionality, see the "[Sticky Header for Responsive Table](https://playbook.powerapp.cloud/kits/advanced_table/react#sticky-header-for-responsive-table)" doc example below.
@@ -0,0 +1,68 @@
1
+ import React from "react"
2
+ import AdvancedTable from "../../pb_advanced_table/_advanced_table"
3
+ import Title from "../../pb_title/_title"
4
+
5
+ const COLUMN_COUNT = 10
6
+ const ROW_COUNT = 40
7
+
8
+ const columnDefinitions = [
9
+ {
10
+ accessor: "region",
11
+ label: "Region",
12
+ id: "region",
13
+ columnStyling: { minWidth: 160 },
14
+ },
15
+ ...Array.from({ length: COLUMN_COUNT }, (_, index) => ({
16
+ accessor: `metric${index + 1}`,
17
+ label: `Metric ${index + 1}`,
18
+ id: `metric${index + 1}`,
19
+ columnStyling: { minWidth: 180 },
20
+ })),
21
+ ]
22
+
23
+ const tableData = Array.from({ length: ROW_COUNT }, (_, row) => ({
24
+ region: `Region ${row + 1}`,
25
+ ...Object.fromEntries(
26
+ Array.from({ length: COLUMN_COUNT }, (_, col) => [
27
+ `metric${col + 1}`,
28
+ String((row + 1) * (col + 1)),
29
+ ])
30
+ ),
31
+ }))
32
+
33
+ const tableProps = { sticky: true }
34
+
35
+ const AdvancedTableStickyScrollLimitation = (props) => (
36
+ <div>
37
+ <Title
38
+ size={4}
39
+ text="Without maxHeight"
40
+ {...props}
41
+ />
42
+ <AdvancedTable
43
+ columnDefinitions={columnDefinitions}
44
+ responsive="none"
45
+ stickyLeftColumn={["region"]}
46
+ tableData={tableData}
47
+ tableProps={tableProps}
48
+ {...props}
49
+ />
50
+ <Title
51
+ paddingTop="sm"
52
+ size={4}
53
+ text="With maxHeight"
54
+ {...props}
55
+ />
56
+ <AdvancedTable
57
+ columnDefinitions={columnDefinitions}
58
+ maxHeight="sm"
59
+ responsive="none"
60
+ stickyLeftColumn={["region"]}
61
+ tableData={tableData}
62
+ tableProps={tableProps}
63
+ {...props}
64
+ />
65
+ </div>
66
+ )
67
+
68
+ export default AdvancedTableStickyScrollLimitation
@@ -0,0 +1,7 @@
1
+ `stickyLeftColumn` adds horizontal overflow to the table wrapper. Without `maxHeight`, the page scrolls vertically while the table scrolls horizontally — two scroll containers.
2
+
3
+ Sticky columns work in that setup, but the sticky header cannot stick to the page. Scroll down on the page, then scroll the first table horizontally to see the conflict.
4
+
5
+ The second table uses `maxHeight` so both axes share one scroll container. The header sticks to the top of the table box instead of the page.
6
+
7
+ For a typical implementation with subrows, see [Sticky Columns with Sticky Header](#sticky-columns-with-sticky-header).
@@ -2,7 +2,6 @@
2
2
  {
3
3
  accessor: "year",
4
4
  label: "Year",
5
- cellAccessors: ["quarter", "month", "day"],
6
5
  },
7
6
  {
8
7
  accessor: "newEnrollments",
@@ -30,4 +29,19 @@
30
29
  }
31
30
  ] %>
32
31
 
33
- <%= pb_rails("advanced_table", props: { id: "table_props_sticky_table", table_data: @table_data, column_definitions: column_definitions, max_height: "xs", table_props: { sticky: true }}) %>
32
+ <% table_data = 15.times.map do |index|
33
+ {
34
+ year: (2020 + index).to_s,
35
+ id: (2020 + index).to_s,
36
+ newEnrollments: (20 + index).to_s,
37
+ scheduledMeetings: (10 + index).to_s,
38
+ attendanceRate: "#{50 + index}%",
39
+ completedClasses: (3 + index).to_s,
40
+ classCompletionRate: "#{30 + index}%",
41
+ graduatedStudents: (19 + index).to_s,
42
+ }
43
+ end %>
44
+
45
+ <div style="max-height: 320px; overflow-y: auto;">
46
+ <%= pb_rails("advanced_table", props: { id: "table_props_sticky_table", table_data: table_data, column_definitions: column_definitions, table_props: { sticky: true }}) %>
47
+ </div>
@@ -1,13 +1,21 @@
1
1
  import React from "react"
2
2
  import AdvancedTable from '../../pb_advanced_table/_advanced_table'
3
- import MOCK_DATA from "./advanced_table_mock_data.json"
3
+
4
+ const tableData = Array.from({ length: 15 }, (_, index) => ({
5
+ year: String(2020 + index),
6
+ newEnrollments: String(20 + index),
7
+ scheduledMeetings: String(10 + index),
8
+ attendanceRate: `${50 + index}%`,
9
+ completedClasses: String(3 + index),
10
+ classCompletionRate: `${30 + index}%`,
11
+ graduatedStudents: String(19 + index),
12
+ }))
4
13
 
5
14
  const AdvancedTableTablePropsStickyHeader = (props) => {
6
15
  const columnDefinitions = [
7
16
  {
8
17
  accessor: "year",
9
18
  label: "Year",
10
- cellAccessors: ["quarter", "month", "day"],
11
19
  },
12
20
  {
13
21
  accessor: "newEnrollments",
@@ -40,11 +48,10 @@ const AdvancedTableTablePropsStickyHeader = (props) => {
40
48
  }
41
49
 
42
50
  return (
43
- <div>
51
+ <div style={{ maxHeight: "320px", overflowY: "auto" }}>
44
52
  <AdvancedTable
45
53
  columnDefinitions={columnDefinitions}
46
- maxHeight="xs"
47
- tableData={MOCK_DATA}
54
+ tableData={tableData}
48
55
  tableProps={tableProps}
49
56
  {...props}
50
57
  />
@@ -2,6 +2,10 @@ Create a sticky header that works for responsive Advanced Tables by setting `sti
2
2
 
3
3
  **NOTE**: This behavior requires a `max_height` to work. The header is sticky within the table container, allowing for it to work along with the first column stickiness of a responsive table on smaller screen sizes.
4
4
 
5
+ Scroll inside the table preview to see the header stick.
6
+
7
+ This example builds flat table data inline for the docs preview. For typical `table_data` setup, see [Default (Required Props)](/kits/advanced_table/default/rails#advanced_table_beta).
8
+
5
9
  Expand the table above to see this in action.
6
10
 
7
11
  A sticky header on a nonresponsive table is demonstrated in the ["Sticky Header"](https://playbook.powerapp.cloud/kits/advanced_table#sticky-header) doc example above.
@@ -1,7 +1,9 @@
1
- Create a sticky header that works for responsive Advanced Tables by setting `sticky: true` via `tableProps` and giving the AdvancedTable a `maxHeight` using our [Max Height](https://playbook.powerapp.cloud/global_props/max_height) global prop.
1
+ Create a sticky header that works for responsive Advanced Tables by setting `sticky: true` via `tableProps` and wrapping the table in a scroll container (or using `maxHeight`).
2
2
 
3
- **NOTE**: This behavior requires a `maxHeight` to work. The header is sticky within the table container, allowing for it to work along with the first column stickiness of a responsive table on smaller screen sizes.
3
+ **NOTE**: The header is sticky within the table scroll area. The live example uses flat rows so you can scroll inside the preview without expanding subrows.
4
4
 
5
- Expand the table above to see this in action.
5
+ This example builds flat table data inline for the docs preview. For typical `tableData` setup, see [Default (Required Props)](/kits/advanced_table/default/react#advanced_table_default).
6
+
7
+ Expand the table above to see responsive behavior in action.
6
8
 
7
9
  A sticky header on a nonresponsive table is demonstrated in the ["Sticky Header"](https://playbook.powerapp.cloud/kits/advanced_table/react#sticky-header) doc example above.
@@ -3,6 +3,7 @@ examples:
3
3
  - advanced_table_beta: Default (Required Props)
4
4
  - advanced_table_loading: Loading State
5
5
  - advanced_table_beta_subrow_headers: SubRow Headers
6
+ - advanced_table_enable_toggle_expansion_rails: Enable Toggle Expansion
6
7
  - advanced_table_collapsible_trail_rails: Collapsible Trail
7
8
  - advanced_table_table_props: Table Props
8
9
  - advanced_table_sticky_header_rails: Sticky Header
@@ -52,6 +53,7 @@ examples:
52
53
  - advanced_table_table_props_sticky_header: Sticky Header for Responsive Table
53
54
  - advanced_table_sticky_columns: Sticky Columns
54
55
  - advanced_table_sticky_columns_and_header: Sticky Columns with Sticky Header
56
+ - advanced_table_sticky_scroll_limitation: Sticky Header and Column Scroll Limitation
55
57
  - advanced_table_responsive: Responsive Tables
56
58
  - advanced_table_custom_cell: Custom Components for Cells
57
59
  - advanced_table_with_custom_header: Custom Header Cell
@@ -27,6 +27,7 @@ export { default as AdvancedTableFullscreen } from './_advanced_table_fullscreen
27
27
  export { default as AdvancedTableStickyColumns } from './_advanced_table_sticky_columns.jsx'
28
28
  export { default as AdvancedTableStickyHeader } from './_advanced_table_sticky_header.jsx'
29
29
  export { default as AdvancedTableStickyColumnsAndHeader } from './_advanced_table_sticky_columns_and_header.jsx'
30
+ export { default as AdvancedTableStickyScrollLimitation } from './_advanced_table_sticky_scroll_limitation.jsx'
30
31
  export { default as AdvancedTableExpandByDepth } from './_advanced_table_expand_by_depth.jsx'
31
32
  export { default as AdvancedTableColumnBorderColor} from './_advanced_table_column_border_color.jsx'
32
33
  export { default as AdvancedTableColumnVisibility } from './_advanced_table_column_visibility.jsx'
@@ -12,41 +12,6 @@ import Caption from '../pb_caption/_caption'
12
12
  import Body from '../pb_body/_body'
13
13
  import colors from "../tokens/exports/_colors.module.scss"
14
14
 
15
- function isValidDateInstance(value: Date): boolean {
16
- return !Number.isNaN(value.getTime())
17
- }
18
-
19
- function normalizeDefaultDate<T>(defaultDate: T): T {
20
- if (defaultDate instanceof Date) {
21
- return (isValidDateInstance(defaultDate) ? defaultDate : '') as unknown as T
22
- }
23
- if (Array.isArray(defaultDate)) {
24
- const normalized = defaultDate.filter(
25
- (d) => !(d instanceof Date) || isValidDateInstance(d)
26
- )
27
- return (normalized.length ? normalized : '') as unknown as T
28
- }
29
- return defaultDate
30
- }
31
-
32
- function serializeDefaultDateForFilterReset(defaultDate: unknown): string | undefined {
33
- if (defaultDate === '' || defaultDate == null) return undefined
34
- if (Array.isArray(defaultDate)) {
35
- const parts = defaultDate.map((d) => {
36
- if (d == null || d === '') return ''
37
- if (d instanceof Date) {
38
- return isValidDateInstance(d) ? d.toISOString() : ''
39
- }
40
- return String(d)
41
- }).filter(Boolean)
42
- return parts.length ? parts.join(',') : undefined
43
- }
44
- if (defaultDate instanceof Date) {
45
- return isValidDateInstance(defaultDate) ? defaultDate.toISOString() : undefined
46
- }
47
- return String(defaultDate)
48
- }
49
-
50
15
  type DatePickerProps = {
51
16
  allowInput?: boolean,
52
17
  aria?: { [key: string]: string },
@@ -148,12 +113,7 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
148
113
  } = props
149
114
 
150
115
  const ariaProps = buildAriaProps(aria)
151
- const normalizedDefaultDate = normalizeDefaultDate(defaultDate)
152
- const filterResetDefaultSerialized = serializeDefaultDateForFilterReset(normalizedDefaultDate)
153
- const dataProps = buildDataProps({
154
- ...data,
155
- ...(filterResetDefaultSerialized ? { 'default-value': filterResetDefaultSerialized } : {}),
156
- })
116
+ const dataProps = buildDataProps(data)
157
117
  const htmlProps = buildHtmlProps(htmlOptions)
158
118
  const inputAriaProps = buildAriaProps(inputAria)
159
119
  const inputDataProps = buildDataProps(inputData)
@@ -176,7 +136,7 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
176
136
  datePickerHelper({
177
137
  allowInput,
178
138
  customQuickPickDates,
179
- defaultDate: normalizedDefaultDate,
139
+ defaultDate,
180
140
  disableDate,
181
141
  disableRange,
182
142
  disableWeekdays,
@@ -1,11 +1,8 @@
1
- <% date_picker_root_attrs = {
2
- class: object.classname + object.error_class,
3
- 'data-pb-date-picker' => true,
4
- 'data-validation-message' => object.validation_message,
5
- }
6
- date_picker_root_attrs['data-default-value'] = object.serialized_default_date_for_dom if object.serialized_default_date_for_dom.present?
7
- %>
8
- <%= pb_content_tag(:div, date_picker_root_attrs) do %>
1
+ <%= pb_content_tag(:div,
2
+ class: object.classname + object.error_class,
3
+ 'data-pb-date-picker' => true,
4
+ 'data-validation-message' => object.validation_message,
5
+ ) do %>
9
6
  <div class="input_wrapper">
10
7
  <% if !object.hide_label && object.label %>
11
8
  <label for="<%= object.picker_id %>">
@@ -82,42 +79,57 @@
82
79
 
83
80
  <%= javascript_tag do %>
84
81
  (function() {
82
+ const initQuickPickChangeListener = (input) => {
83
+ if (!<%= object.selection_type == "quickpick" %>) return
84
+ if (input.dataset.quickpickInitialized) return
85
+
86
+ input.dataset.quickpickInitialized = "true"
87
+ input.addEventListener("change", ({ target }) => {
88
+ const startDate = document.getElementById("<%= object.start_date_id %>")
89
+ const endDate = document.getElementById("<%= object.end_date_id %>")
90
+ const splittedValue = target.value.split(" to ")
91
+ startDate.value = splittedValue[0]
92
+ endDate.value = splittedValue[1] ? splittedValue[1] : splittedValue[0]
93
+ })
94
+ }
95
+
85
96
  const loadDatePicker = () => {
86
- const input = document.getElementById("<%= object.picker_id %>");
87
- if (input && !input._flatpickr) {
88
- datePickerHelper(<%= object.date_picker_config %>, "<%= object.scroll_container %>")
97
+ const input = document.getElementById("<%= object.picker_id %>")
98
+
99
+ if (!input || input._flatpickr) return true
100
+ if (typeof window.datePickerHelper !== "function") return false
89
101
 
90
- if (<%= object.selection_type == "quickpick" %>) {
91
- document.getElementById("<%= object.picker_id %>").addEventListener("change", ({ target }) => {
92
- const startDate = document.getElementById("<%= object.start_date_id %>")
93
- const endDate = document.getElementById("<%= object.end_date_id %>")
94
- const splittedValue = target.value.split(" to ")
95
- startDate.value = splittedValue[0]
96
- endDate.value = splittedValue[1] ? splittedValue[1] : splittedValue[0]
97
- })
98
- }
102
+ window.datePickerHelper(<%= object.date_picker_config %>, "<%= object.scroll_container %>")
103
+ initQuickPickChangeListener(input)
104
+
105
+ return true
106
+ }
107
+
108
+ let attempts = 0
109
+ const retryLoad = () => {
110
+ if (loadDatePicker()) return
111
+
112
+ if (attempts++ < 20) {
113
+ setTimeout(retryLoad, 100)
99
114
  }
100
115
  }
101
116
 
102
- // Try to initialize immediately if DOM is ready
103
117
  if (document.readyState === "loading") {
104
- window.addEventListener("DOMContentLoaded", loadDatePicker)
118
+ window.addEventListener("DOMContentLoaded", retryLoad)
105
119
  } else {
106
- loadDatePicker()
120
+ retryLoad()
107
121
  }
108
122
 
109
123
  // For dynamically added content (modals, etc.), check again after a brief delay
110
124
  setTimeout(() => {
111
- const input = document.getElementById("<%= object.picker_id %>");
125
+ const input = document.getElementById("<%= object.picker_id %>")
112
126
  if (input && !input._flatpickr) {
113
- loadDatePicker();
127
+ retryLoad()
114
128
  }
115
- }, 100);
129
+ }, 100)
116
130
 
117
131
  if (<%= !object.custom_event_type.empty? %>) {
118
- window.addEventListener("<%= object.custom_event_type %>", () => {
119
- loadDatePicker()
120
- })
132
+ window.addEventListener("<%= object.custom_event_type %>", retryLoad)
121
133
  }
122
134
  })()
123
135
  <% end %>
@@ -145,18 +145,6 @@ module Playbook
145
145
  def angle_down_path
146
146
  "app/pb_kits/playbook/utilities/icons/angle-down.svg"
147
147
  end
148
-
149
- # Serialized business default for opt-in smart filter reset (Nitro / data-default-value).
150
- def serialized_default_date_for_dom
151
- case default_date
152
- when nil, ""
153
- nil
154
- when Array
155
- default_date.compact_blank.map(&:to_s).join(",")
156
- else
157
- default_date.to_s.presence
158
- end
159
- end
160
148
  end
161
149
  end
162
150
  end
@@ -40,66 +40,6 @@ describe('DatePicker Kit', () => {
40
40
  expect(kit).toHaveClass('pb_date_picker_kit mb_sm')
41
41
  })
42
42
 
43
- test('exposes data-default-value on kit root when defaultDate is set', () => {
44
- const testId = 'datepicker-def-attr'
45
- render(
46
- <DatePicker
47
- data={{ testid: testId }}
48
- defaultDate={DEFAULT_DATE}
49
- pickerId="date-picker-def-attr"
50
- />
51
- )
52
- const kit = screen.getByTestId(testId)
53
- expect(kit).toHaveAttribute('data-default-value', DEFAULT_DATE.toISOString())
54
- })
55
-
56
- test('omits data-default-value when defaultDate is empty', () => {
57
- const testId = 'datepicker-no-def-attr'
58
- render(
59
- <DatePicker
60
- data={{ testid: testId }}
61
- defaultDate=""
62
- pickerId="date-picker-no-def-attr"
63
- />
64
- )
65
- const kit = screen.getByTestId(testId)
66
- expect(kit).not.toHaveAttribute('data-default-value')
67
- })
68
-
69
- test('renders without error when defaultDate is an invalid Date', () => {
70
- const testId = 'datepicker-invalid-date'
71
- const invalidDate = new Date('UndefinedT00:00')
72
-
73
- expect(() => {
74
- render(
75
- <DatePicker
76
- data={{ testid: testId }}
77
- defaultDate={invalidDate}
78
- pickerId="date-picker-invalid-date"
79
- />
80
- )
81
- }).not.toThrow()
82
-
83
- const kit = screen.getByTestId(testId)
84
- expect(kit).not.toHaveAttribute('data-default-value')
85
- })
86
-
87
- test('omits data-default-value when defaultDate is constructed from undefined', () => {
88
- const testId = 'datepicker-undefined-date'
89
- const invalidDate = new Date(undefined + 'T00:00')
90
-
91
- render(
92
- <DatePicker
93
- data={{ testid: testId }}
94
- defaultDate={invalidDate}
95
- pickerId="date-picker-undefined-date"
96
- />
97
- )
98
-
99
- const kit = screen.getByTestId(testId)
100
- expect(kit).not.toHaveAttribute('data-default-value')
101
- })
102
-
103
43
  test('inLine alone adds inline-date-picker class and inline control icons, not the calendar icon', () => {
104
44
  const testId = 'datepicker-inline-only'
105
45
  render(
@@ -278,9 +278,7 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
278
278
  // Default Date + Min/Max Date Initialization Helper Functions section ----/
279
279
  const toDateObject = (dateValue: any): Date | null => {
280
280
  if (!dateValue) return null
281
- if (dateValue instanceof Date) {
282
- return isNaN(dateValue.getTime()) ? null : dateValue
283
- }
281
+ if (dateValue instanceof Date) return dateValue
284
282
  if (typeof dateValue === 'string') {
285
283
  const parsed = new Date(dateValue)
286
284
  return isNaN(parsed.getTime()) ? null : parsed
@@ -36,10 +36,10 @@ const DatePickerDialogSubmission = () => {
36
36
  <Dialog.Body>
37
37
  <DatePicker
38
38
  defaultDate={dateFixed || undefined}
39
- key={`fixed-${pickerInstance}`}
39
+ key={"fixed-" + pickerInstance}
40
40
  label="Date"
41
41
  onChange={(dateStr) => setDateFixed(dateStr || "")}
42
- pickerId={`datePickerFixed-${pickerInstance}`}
42
+ pickerId={"datePickerFixed-" + pickerInstance}
43
43
  staticPosition={false}
44
44
  />
45
45
  </Dialog.Body>