playbook_ui 16.8.0.pre.alpha.play301316889 → 16.8.0.pre.alpha.tablewidths16466

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.jsx +4 -12
  3. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.md +0 -4
  4. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.html.erb +2 -16
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.md +0 -4
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.html.erb +2 -16
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.jsx +5 -12
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_rails.md +0 -4
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_react.md +3 -5
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +0 -2
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +0 -1
  12. data/app/pb_kits/playbook/pb_card/_card.tsx +1 -1
  13. data/app/pb_kits/playbook/pb_card/card.html.erb +1 -1
  14. data/app/pb_kits/playbook/pb_currency/_currency.tsx +6 -9
  15. data/app/pb_kits/playbook/pb_currency/currency.rb +10 -5
  16. data/app/pb_kits/playbook/pb_currency/currency.test.js +1 -44
  17. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +2 -42
  18. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +26 -44
  19. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +0 -12
  20. data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +0 -60
  21. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +9 -11
  22. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_dialog_submission.jsx +2 -2
  23. data/app/pb_kits/playbook/pb_draggable/_draggable.scss +0 -19
  24. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards_rails.md +0 -2
  25. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards_react.md +0 -1
  26. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.md +0 -2
  27. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_react.md +1 -3
  28. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.md +1 -3
  29. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_react.md +1 -3
  30. data/app/pb_kits/playbook/pb_draggable/draggable.test.jsx +0 -16
  31. data/app/pb_kits/playbook/pb_draggable/draggable_container.html.erb +1 -3
  32. data/app/pb_kits/playbook/pb_draggable/draggable_item.html.erb +0 -1
  33. data/app/pb_kits/playbook/pb_draggable/index.js +7 -149
  34. data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableContainer.tsx +0 -1
  35. data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableItem.tsx +1 -67
  36. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +0 -58
  37. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +0 -2
  38. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +1 -7
  39. data/app/pb_kits/playbook/pb_filter/docs/_filter_default.html.erb +1 -5
  40. data/app/pb_kits/playbook/pb_filter/docs/_filter_no_background.html.erb +1 -1
  41. data/app/pb_kits/playbook/pb_icon/_icon.scss +1 -2
  42. data/app/pb_kits/playbook/pb_icon/docs/_icon_fa_kit.html.erb +1 -0
  43. data/app/pb_kits/playbook/pb_icon/docs/_icon_fa_kit.jsx +21 -0
  44. data/app/pb_kits/playbook/pb_icon/docs/_icon_fa_kit.md +7 -0
  45. data/app/pb_kits/playbook/pb_icon/docs/example.yml +2 -0
  46. data/app/pb_kits/playbook/pb_icon/docs/index.js +1 -0
  47. data/app/pb_kits/playbook/pb_list/_list_item.tsx +1 -4
  48. data/app/pb_kits/playbook/pb_list/item.html.erb +1 -1
  49. data/app/pb_kits/playbook/pb_message/_message.scss +1 -1
  50. data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_default.jsx +1 -1
  51. data/app/pb_kits/playbook/pb_pb_circle_chart/docs/example.yml +0 -2
  52. data/app/pb_kits/playbook/pb_pb_circle_chart/docs/index.js +1 -2
  53. data/app/pb_kits/playbook/pb_popover/docs/_popover_list.jsx +11 -9
  54. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/ToolbarDropdown.tsx +24 -12
  55. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_playground.json +1 -4
  56. data/app/pb_kits/playbook/pb_select/select.rb +0 -9
  57. data/app/pb_kits/playbook/pb_table/docs/_table_sticky.html.erb +83 -85
  58. data/app/pb_kits/playbook/pb_table/docs/_table_sticky.jsx +86 -88
  59. data/app/pb_kits/playbook/pb_table/docs/_table_sticky.md +1 -3
  60. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_external_filter_rails.md +1 -1
  61. data/app/pb_kits/playbook/pb_text_input/_text_input.scss +0 -37
  62. data/app/pb_kits/playbook/pb_text_input/text_input.rb +0 -9
  63. data/app/pb_kits/playbook/pb_time_picker/_time_picker.scss +3 -26
  64. data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_default.md +1 -3
  65. data/app/pb_kits/playbook/pb_time_picker/docs/example.yml +0 -1
  66. data/app/pb_kits/playbook/pb_time_picker/index.ts +30 -771
  67. data/app/pb_kits/playbook/pb_time_picker/time_picker.html.erb +1 -168
  68. data/app/pb_kits/playbook/pb_time_picker/time_picker.rb +38 -53
  69. data/app/pb_kits/playbook/utilities/icons/allicons.tsx +0 -38
  70. data/dist/chunks/{_pb_line_graph-5ED4uF6R.js → _pb_line_graph-BgsTI0CL.js} +1 -1
  71. data/dist/chunks/{_typeahead-sW4KcDqp.js → _typeahead-D2TWdJTn.js} +2 -2
  72. data/dist/chunks/{globalProps-CNMeQljP.js → globalProps-DOB47YGB.js} +1 -1
  73. data/dist/chunks/{time_picker_helper-Bx8nzyM8.js → lazysizes-B7xYodB-.js} +1 -1
  74. data/dist/chunks/lib-BzglXly2.js +29 -0
  75. data/dist/chunks/vendor.js +4 -4
  76. data/dist/menu.yml +131 -71
  77. data/dist/playbook-rails-react-bindings.js +1 -1
  78. data/dist/playbook-rails.js +1 -1
  79. data/dist/playbook.css +1 -1
  80. data/lib/playbook/forms/builder/time_picker_field.rb +3 -6
  81. data/lib/playbook/version.rb +1 -1
  82. metadata +12 -20
  83. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_enable_toggle_expansion_rails.html.erb +0 -62
  84. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_enable_toggle_expansion_rails.md +0 -7
  85. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_scroll_limitation.jsx +0 -68
  86. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_scroll_limitation.md +0 -7
  87. data/app/pb_kits/playbook/pb_draggable/touchDrag.test.js +0 -38
  88. data/app/pb_kits/playbook/pb_draggable/utilities/touchDrag.ts +0 -173
  89. data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_centered_data.html.erb +0 -90
  90. data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_centered_data.jsx +0 -100
  91. data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_centered_data.md +0 -1
  92. data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler.html.erb +0 -24
  93. data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler_rails.md +0 -6
  94. data/dist/chunks/lib-DD2WQ9Er.js +0 -29
  95. /data/app/pb_kits/playbook/pb_time_picker/docs/{_time_picker_on_handler_react.md → _time_picker_on_handler.md} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: edb2d6b1943796215222f43d5a667089909a292040708c227c91967e72f6f0bc
4
- data.tar.gz: 1762487740450da1b7b322409360bdaefb03cf1c4b7f14b500817a5374453fd2
3
+ metadata.gz: 0f46fd7de41487efa37647c36cc3d1d55e2260ccda34ff0f094dc4f3c21608c4
4
+ data.tar.gz: 60e1b0388423c2a75088ba9210b0e9456c27fb7a7b5822b5753f1c46f1abfa53
5
5
  SHA512:
6
- metadata.gz: e5e4c4a11408e787aa02ecf02ae3a815b92eb4c8010b1da263ae2a266da889d6b0364d38ee2471b58c9be08df653ee84d2999deed123f4979df84b15fe8c7c72
7
- data.tar.gz: 3b23460679cd966247435ff055de878cdaceab02e5b6279bc8c8cb6bfd0071718f77bcfb82c710d4cdc7ed72a7607d272a78305d48b1b6bb079cc6f6559c735e
6
+ metadata.gz: 236bb6ec1f254c88d37bfa99aa2bb530aba234550a5635bfd19c9bb76fe0240bf818ccd4f2b859424662c2e15d1f31cae47d0831e172a9c2926e1eaa4cf3ade7
7
+ data.tar.gz: 63776f5d3b77b41da7a95ad4d67e89d244a0981fb8cc2220c3fc8996f5506eb2b4f94cf30989d848afc83d2104dbe17092e00851e4b4cd46ebd5a63985ddb543
@@ -1,21 +1,13 @@
1
1
  import React from "react"
2
2
  import AdvancedTable from '../../pb_advanced_table/_advanced_table'
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
- }))
3
+ import MOCK_DATA from "./advanced_table_mock_data.json"
13
4
 
14
5
  const AdvancedTableStickyHeader = (props) => {
15
6
  const columnDefinitions = [
16
7
  {
17
8
  accessor: "year",
18
9
  label: "Year",
10
+ cellAccessors: ["quarter", "month", "day"],
19
11
  },
20
12
  {
21
13
  accessor: "newEnrollments",
@@ -48,11 +40,11 @@ const AdvancedTableStickyHeader = (props) => {
48
40
  }
49
41
 
50
42
  return (
51
- <div style={{ maxHeight: "320px", overflowY: "auto" }}>
43
+ <div>
52
44
  <AdvancedTable
53
45
  columnDefinitions={columnDefinitions}
54
46
  responsive="none"
55
- tableData={tableData}
47
+ tableData={MOCK_DATA}
56
48
  tableProps={tableProps}
57
49
  {...props}
58
50
  />
@@ -1,7 +1,3 @@
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
-
7
3
  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,6 +2,7 @@
2
2
  {
3
3
  accessor: "year",
4
4
  label: "Year",
5
+ cellAccessors: ["quarter", "month", "day"],
5
6
  },
6
7
  {
7
8
  accessor: "newEnrollments",
@@ -29,19 +30,4 @@
29
30
  }
30
31
  ] %>
31
32
 
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>
33
+ <%= pb_rails("advanced_table", props: { id: "sticky_header_table", table_data: @table_data, column_definitions: column_definitions, responsive: "none", table_props: { sticky: true }}) %>
@@ -1,7 +1,3 @@
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
-
7
3
  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.
@@ -2,6 +2,7 @@
2
2
  {
3
3
  accessor: "year",
4
4
  label: "Year",
5
+ cellAccessors: ["quarter", "month", "day"],
5
6
  },
6
7
  {
7
8
  accessor: "newEnrollments",
@@ -29,19 +30,4 @@
29
30
  }
30
31
  ] %>
31
32
 
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>
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 }}) %>
@@ -1,21 +1,13 @@
1
1
  import React from "react"
2
2
  import AdvancedTable from '../../pb_advanced_table/_advanced_table'
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
- }))
3
+ import MOCK_DATA from "./advanced_table_mock_data.json"
13
4
 
14
5
  const AdvancedTableTablePropsStickyHeader = (props) => {
15
6
  const columnDefinitions = [
16
7
  {
17
8
  accessor: "year",
18
9
  label: "Year",
10
+ cellAccessors: ["quarter", "month", "day"],
19
11
  },
20
12
  {
21
13
  accessor: "newEnrollments",
@@ -48,10 +40,11 @@ const AdvancedTableTablePropsStickyHeader = (props) => {
48
40
  }
49
41
 
50
42
  return (
51
- <div style={{ maxHeight: "320px", overflowY: "auto" }}>
43
+ <div>
52
44
  <AdvancedTable
53
45
  columnDefinitions={columnDefinitions}
54
- tableData={tableData}
46
+ maxHeight="xs"
47
+ tableData={MOCK_DATA}
55
48
  tableProps={tableProps}
56
49
  {...props}
57
50
  />
@@ -2,10 +2,6 @@ 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
-
9
5
  Expand the table above to see this in action.
10
6
 
11
7
  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,9 +1,7 @@
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`).
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.
2
2
 
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.
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.
4
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
-
7
- Expand the table above to see responsive behavior in action.
5
+ Expand the table above to see this in action.
8
6
 
9
7
  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,7 +3,6 @@ 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
7
6
  - advanced_table_collapsible_trail_rails: Collapsible Trail
8
7
  - advanced_table_table_props: Table Props
9
8
  - advanced_table_sticky_header_rails: Sticky Header
@@ -53,7 +52,6 @@ examples:
53
52
  - advanced_table_table_props_sticky_header: Sticky Header for Responsive Table
54
53
  - advanced_table_sticky_columns: Sticky Columns
55
54
  - advanced_table_sticky_columns_and_header: Sticky Columns with Sticky Header
56
- - advanced_table_sticky_scroll_limitation: Sticky Header and Column Scroll Limitation
57
55
  - advanced_table_responsive: Responsive Tables
58
56
  - advanced_table_custom_cell: Custom Components for Cells
59
57
  - advanced_table_with_custom_header: Custom Header Cell
@@ -27,7 +27,6 @@ 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'
31
30
  export { default as AdvancedTableExpandByDepth } from './_advanced_table_expand_by_depth.jsx'
32
31
  export { default as AdvancedTableColumnBorderColor} from './_advanced_table_column_border_color.jsx'
33
32
  export { default as AdvancedTableColumnVisibility } from './_advanced_table_column_visibility.jsx'
@@ -162,7 +162,7 @@ const Card = (props: CardPropTypes): React.ReactElement => {
162
162
  {
163
163
  dragHandle ? (
164
164
  <Flex>
165
- <span className="card_draggable_handle pb_draggable_handle">
165
+ <span className="card_draggable_handle">
166
166
  <Icon
167
167
  icon="grip-dots-vertical"
168
168
  paddingRight="xs"
@@ -4,7 +4,7 @@
4
4
  <% if object.draggable_item %>
5
5
  <%= pb_rails("flex", props: { align: "center" }) do %>
6
6
  <% if object.drag_handle %>
7
- <span class="card_draggable_handle pb_draggable_handle">
7
+ <span classname="card_draggable_handle">
8
8
  <%= pb_rails("icon", props: { icon: "grip-dots-vertical", padding_right: "xs" }) %>
9
9
  </span>
10
10
  <% end %>
@@ -59,13 +59,12 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
59
59
  commaSeparator = false,
60
60
  } = props
61
61
 
62
- const isAmountEmpty = (value: string | number): boolean => (
63
- value === '' || value == null || (typeof value === 'string' && value.trim() === '')
64
- )
65
-
66
62
  // Convert numeric input to string format
67
63
  const convertAmount = (input: string | number): string => {
68
64
  if (typeof input === 'number') {
65
+ if (input === 0 && !nullDisplay) {
66
+ return ""
67
+ }
69
68
  return input.toFixed(2)
70
69
  }
71
70
  return input
@@ -82,9 +81,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
82
81
  variantClass = '_bold'
83
82
  }
84
83
 
85
- const [wholePart, decimalPart = '00'] = currencyAmount ? currencyAmount.split('.') : ['', '00']
86
- const decimal = (decimalPart || '00').padEnd(2, '0').slice(0, 2)
87
- const whole = currencyAmount === '' ? '' : (wholePart === '' ? '0' : wholePart)
84
+ const [whole, decimal = '00'] = currencyAmount.split('.')
88
85
  const ariaProps = buildAriaProps(aria)
89
86
  const dataProps = buildDataProps(data)
90
87
  const htmlProps = buildHtmlProps(htmlOptions)
@@ -138,7 +135,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
138
135
  <Caption dark={dark}>{label}</Caption>
139
136
  <div className={`pb_currency_wrapper${variantClass || emphasizedClass}`}>
140
137
  {unstyled ? (
141
- nullDisplay && isAmountEmpty(amount) ? (
138
+ nullDisplay && !amount ? (
142
139
  <div>{nullDisplay}</div>
143
140
  ) : (
144
141
  <>
@@ -151,7 +148,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
151
148
  </>
152
149
  )
153
150
  ) : (
154
- nullDisplay && isAmountEmpty(amount) ? (
151
+ nullDisplay && !amount ? (
155
152
  <Title
156
153
  className="pb_currency_value"
157
154
  dark={dark}
@@ -68,7 +68,7 @@ module Playbook
68
68
  end
69
69
 
70
70
  def title_text
71
- if null_display && amount.blank?
71
+ if null_display
72
72
  null_display
73
73
  elsif swap_negative
74
74
  absolute_amount(abbr_or_format_amount)
@@ -125,7 +125,14 @@ module Playbook
125
125
  # Convert numeric input to string format
126
126
  def convert_amount(input)
127
127
  if input.is_a?(Numeric)
128
- Kernel.format("%.2f", input)
128
+ if input.zero? && null_display.nil?
129
+ ""
130
+ else
131
+ format("%.2f", input)
132
+ end
133
+ # Handle string representations of zero
134
+ elsif input.to_s.strip.match?(/^-?0+(\.0+)?$/) && null_display.nil?
135
+ ""
129
136
  else
130
137
  input.to_s
131
138
  end
@@ -135,7 +142,6 @@ module Playbook
135
142
  return "" if currency_amount.blank?
136
143
 
137
144
  value = currency_amount.split(".").first
138
- value = "0" if value.blank?
139
145
  if comma_separator
140
146
  number_with_delimiter(value.gsub(",", ""))
141
147
  else
@@ -146,8 +152,7 @@ module Playbook
146
152
  def decimal_value
147
153
  return "00" if currency_amount.blank?
148
154
 
149
- fraction = currency_amount.split(".")[1] || "00"
150
- fraction.ljust(2, "0")[0, 2]
155
+ currency_amount.split(".")[1] || "00"
151
156
  end
152
157
 
153
158
  def units_element
@@ -178,48 +178,5 @@ test('handles numeric amounts correctly', () => {
178
178
  expect(screen.getByTestId('test-numeric-no-symbol')).toHaveTextContent('400.50')
179
179
  expect(screen.getByTestId('test-numeric-medium-size')).toHaveTextContent('$500.55')
180
180
  expect(screen.getByTestId('test-numeric-negative')).toHaveTextContent('-$600.70')
181
- expect(screen.getByTestId('test-numeric-null')).toHaveTextContent('$0.00')
182
- })
183
-
184
- test('renders zero values with leading digit', () => {
185
- render(
186
- <>
187
- <Currency
188
- amount="0"
189
- data={{ testid: 'test-string-zero' }}
190
- />
191
- <Currency
192
- amount={0}
193
- data={{ testid: 'test-numeric-zero' }}
194
- />
195
- </>
196
- )
197
-
198
- expect(screen.getByTestId('test-string-zero')).toHaveTextContent('$0.00')
199
- expect(screen.getByTestId('test-numeric-zero')).toHaveTextContent('$0.00')
200
- })
201
-
202
- test('normalizes string zero with single decimal digit to .00', () => {
203
- render(
204
- <Currency
205
- amount="0.0"
206
- commaSeparator
207
- data={{ testid: 'test-string-zero-single-decimal' }}
208
- />
209
- )
210
-
211
- expect(screen.getByTestId('test-string-zero-single-decimal')).toHaveTextContent('$0.00')
212
- })
213
-
214
- test('nullDisplay only applies when amount is empty', () => {
215
- render(
216
- <Currency
217
- amount="-.53"
218
- data={{ testid: 'test-null-display-negative' }}
219
- nullDisplay="$0.00"
220
- />
221
- )
222
-
223
- expect(screen.getByTestId('test-null-display-negative')).toHaveTextContent('-$')
224
- expect(screen.getByTestId('test-null-display-negative')).not.toHaveTextContent('$0.00')
181
+ expect(screen.getByTestId('test-numeric-null')).toHaveTextContent('$.00')
225
182
  })
@@ -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,57 +79,42 @@
82
79
 
83
80
  <%= javascript_tag do %>
84
81
  (function() {
85
- const initQuickPickChangeListener = (input) => {
86
- if (!<%= object.selection_type == "quickpick" %>) return
87
- if (input.dataset.quickpickInitialized) return
88
-
89
- input.dataset.quickpickInitialized = "true"
90
- input.addEventListener("change", ({ target }) => {
91
- const startDate = document.getElementById("<%= object.start_date_id %>")
92
- const endDate = document.getElementById("<%= object.end_date_id %>")
93
- const splittedValue = target.value.split(" to ")
94
- startDate.value = splittedValue[0]
95
- endDate.value = splittedValue[1] ? splittedValue[1] : splittedValue[0]
96
- })
97
- }
98
-
99
82
  const loadDatePicker = () => {
100
- const input = document.getElementById("<%= object.picker_id %>")
101
-
102
- if (!input || input._flatpickr) return true
103
- if (typeof window.datePickerHelper !== "function") return false
104
-
105
- window.datePickerHelper(<%= object.date_picker_config %>, "<%= object.scroll_container %>")
106
- initQuickPickChangeListener(input)
107
-
108
- return true
109
- }
110
-
111
- let attempts = 0
112
- const retryLoad = () => {
113
- if (loadDatePicker()) return
83
+ const input = document.getElementById("<%= object.picker_id %>");
84
+ if (input && !input._flatpickr) {
85
+ datePickerHelper(<%= object.date_picker_config %>, "<%= object.scroll_container %>")
114
86
 
115
- if (attempts++ < 20) {
116
- setTimeout(retryLoad, 100)
87
+ if (<%= object.selection_type == "quickpick" %>) {
88
+ document.getElementById("<%= object.picker_id %>").addEventListener("change", ({ target }) => {
89
+ const startDate = document.getElementById("<%= object.start_date_id %>")
90
+ const endDate = document.getElementById("<%= object.end_date_id %>")
91
+ const splittedValue = target.value.split(" to ")
92
+ startDate.value = splittedValue[0]
93
+ endDate.value = splittedValue[1] ? splittedValue[1] : splittedValue[0]
94
+ })
95
+ }
117
96
  }
118
97
  }
119
98
 
99
+ // Try to initialize immediately if DOM is ready
120
100
  if (document.readyState === "loading") {
121
- window.addEventListener("DOMContentLoaded", retryLoad)
101
+ window.addEventListener("DOMContentLoaded", loadDatePicker)
122
102
  } else {
123
- retryLoad()
103
+ loadDatePicker()
124
104
  }
125
105
 
126
106
  // For dynamically added content (modals, etc.), check again after a brief delay
127
107
  setTimeout(() => {
128
- const input = document.getElementById("<%= object.picker_id %>")
108
+ const input = document.getElementById("<%= object.picker_id %>");
129
109
  if (input && !input._flatpickr) {
130
- retryLoad()
110
+ loadDatePicker();
131
111
  }
132
- }, 100)
112
+ }, 100);
133
113
 
134
114
  if (<%= !object.custom_event_type.empty? %>) {
135
- window.addEventListener("<%= object.custom_event_type %>", retryLoad)
115
+ window.addEventListener("<%= object.custom_event_type %>", () => {
116
+ loadDatePicker()
117
+ })
136
118
  }
137
119
  })()
138
120
  <% 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(