playbook_ui 18.2.0.pre.rc.2 → 18.2.0.pre.rc.3

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_background/_background.tsx +3 -1
  3. data/app/pb_kits/playbook/pb_background/kit.schema.json +1 -0
  4. data/app/pb_kits/playbook/pb_caption/_caption.tsx +3 -1
  5. data/app/pb_kits/playbook/pb_caption/kit.schema.json +1 -0
  6. data/app/pb_kits/playbook/pb_container/_container.tsx +3 -1
  7. data/app/pb_kits/playbook/pb_container/kit.schema.json +1 -0
  8. data/app/pb_kits/playbook/pb_detail/_detail.tsx +3 -1
  9. data/app/pb_kits/playbook/pb_detail/kit.schema.json +1 -0
  10. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +6 -5
  11. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_custom.md +7 -2
  12. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_custom_rails.md +7 -2
  13. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_enable_time.html.erb +33 -0
  14. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_enable_time.jsx +42 -0
  15. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_enable_time.md +24 -0
  16. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +2 -0
  17. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +1 -0
  18. data/app/pb_kits/playbook/pb_dropdown/index.js +19 -10
  19. data/app/pb_kits/playbook/pb_dropdown/quickpick/index.ts +60 -18
  20. data/app/pb_kits/playbook/pb_dropdown/quickpick_helper.rb +92 -3
  21. data/app/pb_kits/playbook/pb_dropdown/utilities/index.ts +8 -1
  22. data/app/pb_kits/playbook/pb_dropdown/utilities/quickpickDateSync.ts +137 -0
  23. data/app/pb_kits/playbook/pb_filter/Filter/InteractiveFilter.tsx +1 -1
  24. data/app/pb_kits/playbook/pb_highlight/_highlight.tsx +3 -1
  25. data/app/pb_kits/playbook/pb_highlight/kit.schema.json +1 -0
  26. data/app/pb_kits/playbook/pb_map/docs/_map_default.md +3 -3
  27. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/MoreExtensionsDropdown.tsx +10 -3
  28. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/Toolbar.tsx +16 -1
  29. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_playground.json +2 -3
  30. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_playground.overrides.json +2 -3
  31. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_attributes.jsx +1 -5
  32. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_default.jsx +1 -5
  33. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_default.md +2 -3
  34. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_focus.jsx +1 -5
  35. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_height.jsx +3 -13
  36. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_inline.jsx +1 -5
  37. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_label.jsx +2 -3
  38. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_markdown_support.jsx +1 -2
  39. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_min_height.jsx +3 -13
  40. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_preview.jsx +1 -5
  41. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_required_indicator.jsx +1 -5
  42. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_simple.jsx +1 -5
  43. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_sticky.jsx +1 -5
  44. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_templates.jsx +1 -5
  45. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_more_extensions.jsx +3 -8
  46. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_more_extensions.md +1 -1
  47. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_default.md +2 -2
  48. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.test.js +2 -1
  49. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor_advanced.test.js +7 -5
  50. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor_rails.js +15 -4
  51. data/app/pb_kits/playbook/pb_table/_table.tsx +70 -197
  52. data/app/pb_kits/playbook/pb_table/index.ts +53 -122
  53. data/app/pb_kits/playbook/pb_table/styles/_sticky_columns.scss +26 -3
  54. data/app/pb_kits/playbook/pb_table/utilities/stickyColumns.test.ts +266 -0
  55. data/app/pb_kits/playbook/pb_table/utilities/stickyColumns.ts +145 -0
  56. data/app/pb_kits/playbook/utilities/test/globalProps/onClick.test.js +10 -0
  57. data/dist/ai/all-schemas.json +5 -0
  58. data/dist/ai/forms.json +1 -1
  59. data/dist/ai/index.json +2 -2
  60. data/dist/ai/kits/background.schema.json +1 -0
  61. data/dist/ai/kits/caption.schema.json +1 -0
  62. data/dist/ai/kits/container.schema.json +1 -0
  63. data/dist/ai/kits/detail.schema.json +1 -0
  64. data/dist/ai/kits/highlight.schema.json +1 -0
  65. data/dist/ai/playgrounds/rich_text_editor.json +1 -1
  66. data/dist/chunks/{_detail-BqqzPTNr.js → _detail-Cy54syJC.js} +2 -2
  67. data/dist/chunks/{_pb_line_graph-BGyCJjgG.js → _pb_line_graph-Du7xE9vl.js} +1 -1
  68. data/dist/chunks/_table-BCqp1PAO.js +1 -0
  69. data/dist/chunks/_typeahead-CXZH3KvV.js +1 -0
  70. data/dist/chunks/{globalProps-K1DCn3il.js → globalProps-B120NbSJ.js} +1 -1
  71. data/dist/chunks/{lib-7vm9BMqp.js → lib-Buo6zHEw.js} +1 -1
  72. data/dist/chunks/quickpickDateSync-DLDx4zce.js +1 -0
  73. data/dist/chunks/{time_picker_helper-BZutIzB3.js → time_picker_helper-CYGg0UQ0.js} +1 -1
  74. data/dist/chunks/vendor.js +2 -2
  75. data/dist/playbook-rails-react-bindings.js +1 -1
  76. data/dist/playbook-rails.js +1 -1
  77. data/dist/playbook.css +1 -1
  78. data/lib/playbook/version.rb +1 -1
  79. metadata +16 -9
  80. data/dist/chunks/_table-CEZU0qUK.js +0 -1
  81. data/dist/chunks/_typeahead-C7iPR5ZF.js +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbc2a1ba01cca1bd4a5b48488fafecee3697e273fd940d942a9de5de93a76921
4
- data.tar.gz: e8cf1cc4ec63bd1957d455ed4766db51865e0f42b9369ae59065f89bb7d78946
3
+ metadata.gz: 1c86866d416fa61cd6ef95462feacdaab4821a38f7512d171709d74ae355ca79
4
+ data.tar.gz: 881dc11beb08455d597c2fef659070af84626c562597566f69fcdb773a61f5e7
5
5
  SHA512:
6
- metadata.gz: f5af4f9cf873c44ba0c76176e17130f0cf77fbd9c526ccea6041a70b0e1da2951a16da702259a01d16df03628a30402bcc1fdc47f32675af28aaf16f1fdb8ffb
7
- data.tar.gz: 598126c77b37bd8885bfeb8fa1ebcc30d5f30adab8dcd92b46ea71ce8b038314dda4e774d3fea789ba3e7462ff5ea83276bd10229ce43efaa767e33fe5c430c4
6
+ metadata.gz: 2a6e88281370f5ce11a7467aab89ed9db923a593f34748c39f43143488daa0f92b9f55b8eb9c1636c2f2c64215a3b092cdd5fbc3702315cc9612ef9cfe2327b0
7
+ data.tar.gz: 398a941db88d54157eb9ca15fb952d290961fc05074a7c62ec0e6246cf315ae9d75da943f31d57b6c654d99652f32036b33c4dc1fda9bd3b2454e1cf524dae50
@@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react'
2
2
  import classnames from 'classnames'
3
3
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
4
4
  import { GlobalProps, globalProps, globalInlineProps } from '../utilities/globalProps'
5
+ import { GlobalEventProps, globalEventProps } from '../utilities/globalEventProps'
5
6
 
6
7
  type BackgroundColors = 'gradient' |
7
8
  'dark' |'light' | 'white' | 'success' | 'warning' | 'error' | 'info' | 'neutral' | 'primary' | 'shadow' |
@@ -35,7 +36,7 @@ type BackgroundProps = {
35
36
  padding?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl',
36
37
  tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'div' | 'tr' | 'th' | 'td' | 'thead' | 'col',
37
38
  transition?: 'fade' | 'blur' | 'scale',
38
- } & GlobalProps
39
+ } & GlobalProps & GlobalEventProps
39
40
 
40
41
  type ResponsiveProp<T> = T | {
41
42
  xs?: T,
@@ -166,6 +167,7 @@ const Background = (props: BackgroundProps): React.ReactElement => {
166
167
  {...ariaProps}
167
168
  {...dataProps}
168
169
  {...htmlProps}
170
+ {...globalEventProps(props)}
169
171
  alt={alt}
170
172
  className={classes}
171
173
  id={id}
@@ -221,6 +221,7 @@
221
221
  }
222
222
  },
223
223
  "globalProps": true,
224
+ "globalEventProps": true,
224
225
  "usage": {
225
226
  "react": {
226
227
  "import": "import { Background } from 'playbook-ui'",
@@ -2,6 +2,7 @@ import React from 'react'
2
2
  import classnames from 'classnames'
3
3
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
4
4
  import { deprecatedProps, globalProps, GlobalProps } from '../utilities/globalProps'
5
+ import { GlobalEventProps, globalEventProps } from '../utilities/globalEventProps'
5
6
 
6
7
  type CaptionProps = {
7
8
  aria?: {[key: string]: string},
@@ -15,7 +16,7 @@ type CaptionProps = {
15
16
  tag?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "div" | "caption",
16
17
  text?: string,
17
18
  variant?: null | "link",
18
- } & GlobalProps;
19
+ } & GlobalProps & GlobalEventProps;
19
20
 
20
21
  const Caption = (props: CaptionProps): React.ReactElement => {
21
22
  if (props.variant) deprecatedProps() //variant prop is deprecated, use color instead
@@ -62,6 +63,7 @@ const Caption = (props: CaptionProps): React.ReactElement => {
62
63
  {...ariaProps}
63
64
  {...dataProps}
64
65
  {...htmlProps}
66
+ {...globalEventProps(props)}
65
67
  className={css}
66
68
  id={id}
67
69
  >
@@ -78,6 +78,7 @@
78
78
  }
79
79
  },
80
80
  "globalProps": true,
81
+ "globalEventProps": true,
81
82
  "usage": {
82
83
  "react": {
83
84
  "import": "import { Caption } from 'playbook-ui'",
@@ -2,6 +2,7 @@ import React from 'react'
2
2
  import classnames from 'classnames'
3
3
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
4
4
  import { globalProps, GlobalProps } from '../utilities/globalProps'
5
+ import { GlobalEventProps, globalEventProps } from '../utilities/globalEventProps'
5
6
 
6
7
  type ContainerProps = {
7
8
  aria?: { [key: string]: string },
@@ -11,7 +12,7 @@ type ContainerProps = {
11
12
  htmlOptions?: { [key: string]: string | number | boolean | (() => void) | ((event: any) => void) | any },
12
13
  tag?: "div" | "span" | "a" | "button" | "option" | "table" | "tbody" | "thead" | "tfoot" | "tr" | "td" | "th" | "img" | "section" | "article" | "main" | "header" | "footer" | "nav" | "aside"
13
14
  id?: string,
14
- } & GlobalProps
15
+ } & GlobalProps & GlobalEventProps
15
16
 
16
17
  const Container = (props: ContainerProps): React.ReactElement => {
17
18
  const {
@@ -36,6 +37,7 @@ const Container = (props: ContainerProps): React.ReactElement => {
36
37
  {...ariaProps}
37
38
  {...dataProps}
38
39
  {...htmlProps}
40
+ {...globalEventProps(props)}
39
41
  className={classes}
40
42
  id={id}
41
43
  >
@@ -39,6 +39,7 @@
39
39
  }
40
40
  },
41
41
  "globalProps": true,
42
+ "globalEventProps": true,
42
43
  "usage": {
43
44
  "react": {
44
45
  "import": "import { Container } from 'playbook-ui'",
@@ -2,6 +2,7 @@ import React from 'react'
2
2
  import classnames from 'classnames'
3
3
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
4
4
  import { globalProps, GlobalProps } from '../utilities/globalProps'
5
+ import { globalEventProps, GlobalEventProps } from '../utilities/globalEventProps'
5
6
 
6
7
  type DetailProps = {
7
8
  aria?: { [key: string]: string },
@@ -15,7 +16,7 @@ type DetailProps = {
15
16
  id?: string,
16
17
  tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'div',
17
18
  text?: string,
18
- } & GlobalProps
19
+ } & GlobalProps & GlobalEventProps
19
20
 
20
21
  const Detail = (props: DetailProps): React.ReactElement => {
21
22
  const {
@@ -48,6 +49,7 @@ const Detail = (props: DetailProps): React.ReactElement => {
48
49
  {...ariaProps}
49
50
  {...dataProps}
50
51
  {...htmlProps}
52
+ {...globalEventProps(props)}
51
53
  className={classes}
52
54
  id={id}
53
55
  >
@@ -65,6 +65,7 @@
65
65
  }
66
66
  },
67
67
  "globalProps": true,
68
+ "globalEventProps": true,
68
69
  "usage": {
69
70
  "react": {
70
71
  "import": "import { Detail } from 'playbook-ui'",
@@ -20,6 +20,7 @@ import {
20
20
  separateChildComponents,
21
21
  prepareSubcomponents,
22
22
  handleClickOutside,
23
+ setQuickPickDateOnPicker,
23
24
  } from "./utilities";
24
25
 
25
26
  import { DialogContext } from "../pb_dialog/_dialog_context";
@@ -87,7 +88,7 @@ const asyncOptionValue = (option: GenericObject) => option.value ?? option.id ??
87
88
 
88
89
  type CustomQuickPickDate = {
89
90
  label: string;
90
- value: string[] | { timePeriod: string; amount: number };
91
+ value: Array<Date | string> | { timePeriod: string; amount: number };
91
92
  };
92
93
 
93
94
  type CustomQuickPickDates = {
@@ -594,12 +595,12 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
594
595
 
595
596
  if (controlsStartId) {
596
597
  const startPicker = (document.querySelector(`#${controlsStartId}`) as HTMLElement & { _flatpickr?: any })?._flatpickr;
597
- startPicker?.setDate(start, true);
598
+ setQuickPickDateOnPicker(startPicker, start, "start");
598
599
  }
599
600
 
600
601
  if (controlsEndId) {
601
602
  const endPicker = (document.querySelector(`#${controlsEndId}`) as HTMLElement & { _flatpickr?: any })?._flatpickr;
602
- endPicker?.setDate(end, true);
603
+ setQuickPickDateOnPicker(endPicker, end, "end");
603
604
  }
604
605
  }
605
606
  }
@@ -711,12 +712,12 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
711
712
  setTimeout(() => {
712
713
  if (controlsStartId) {
713
714
  const startPicker = (document.querySelector(`#${controlsStartId}`) as HTMLElement & { _flatpickr?: any })?._flatpickr;
714
- startPicker?.setDate(start, true);
715
+ setQuickPickDateOnPicker(startPicker, start, "start");
715
716
  }
716
717
 
717
718
  if (controlsEndId) {
718
719
  const endPicker = (document.querySelector(`#${controlsEndId}`) as HTMLElement & { _flatpickr?: any })?._flatpickr;
719
- endPicker?.setDate(end, true);
720
+ setQuickPickDateOnPicker(endPicker, end, "end");
720
721
  }
721
722
  }, 0);
722
723
  }
@@ -1,10 +1,15 @@
1
1
  The `customQuickPickDates` prop allows for defining custom quick pick date options for the dropdown. The prop accepts an object with two properties: `dates` and `override`.
2
2
 
3
3
  **The `dates` property** accepts an array of objects. Each object has `label` and `value` properties. The `label` is what will be displayed in the dropdown menu. The `value` property defines the date range that will be selected, and can be:
4
- - An array of two date strings representing a specific range (e.g., `["06/01/2022", "06/07/2022"]`)
4
+ - An array of two date strings (or `Date` objects) representing a specific range (e.g., `["06/01/2022", "06/07/2022"]`).
5
+ - **Date-only** strings get start-of-day / end-of-day when synced to `enableTime` DatePickers.
6
+ - **Timed** strings use the same formats as Rails QuickPick customs:
7
+ - US `m/d/Y` + time (optional `:SS`, optional `AM`/`PM`) — wall-clock; emit offset-less `YYYY-MM-DDTHH:MM:SS`
8
+ - Offset-less `YYYY-MM-DDTHH:MM:SS` — wall-clock; emit offset-less
9
+ - ISO-8601 with `Z` or numeric offset — absolute instant; emit keeps offset/`Z` so `new Date(iso)` preserves the instant
10
+ - `Date` objects keep their authored time (including intentional midnight / `23:59:00`).
5
11
  - An object with `timePeriod` and `amount` properties for dynamic date calculations:
6
12
  - The `timePeriod` property accepts `"days"`, `"weeks"`, `"months"`, `"quarters"`, or `"years"`, representing past time periods calculated from today.
7
13
  - The `amount` property accepts any number.
8
14
 
9
15
  **The `override` property** is a boolean that controls whether custom dates replace or append to the default quick pick options. Default is `true` (replaces defaults). Set to `false` to append your custom dates to the default quick pick options.
10
-
@@ -1,10 +1,15 @@
1
1
  The `custom_quick_pick_dates` prop allows for defining custom quick pick date options for the dropdown. The prop accepts an object with two properties: `dates` and `override`.
2
2
 
3
3
  **The `dates` property** accepts an array of objects. Each object has `label` and `value` properties. The `label` is what will be displayed in the dropdown menu. The `value` property defines the date range that will be selected, and can be:
4
- - An array of two date strings representing a specific range (e.g., `["06/01/2022", "06/07/2022"]`)
4
+ - An array of two date strings representing a specific range (e.g., `["06/01/2022", "06/07/2022"]`).
5
+ - **Date-only** strings stay date-only on the option payload (SOD/EOD applied at sync when `enable_time`).
6
+ - **Timed** strings use the same formats as React QuickPick customs:
7
+ - US `m/d/Y` + time (optional `:SS`, optional `AM`/`PM`) — wall-clock (e.g. `"06/01/2022 9:30 AM"`); emit offset-less `YYYY-MM-DDTHH:MM:SS`
8
+ - Offset-less `YYYY-MM-DDTHH:MM:SS` — wall-clock (e.g. `"2026-03-08T02:30:00"`); emit offset-less
9
+ - ISO-8601 with `Z` or numeric offset — absolute instant; emit keeps offset/`Z` (e.g. `…+00:00` / `…-05:00`) so JS `new Date(iso)` preserves the same instant
10
+ - Wall-clock and absolute emit differ on purpose: offset-less keeps the authored clock face; offset-bearing strings keep the absolute instant across Rails ↔ React. Unsupported timed free text raises.
5
11
  - An object with `time_period` and `amount` properties for dynamic date calculations:
6
12
  - The `time_period` property accepts `"days"`, `"weeks"`, `"months"`, `"quarters"`, or `"years"`, representing past time periods calculated from today.
7
13
  - The `amount` property accepts any number.
8
14
 
9
15
  **The `override` property** is a boolean that controls whether custom dates replace or append to the default quick pick options. Default is `true` (replaces defaults). Set to `false` to append your custom dates to the default quick pick options.
10
-
@@ -0,0 +1,33 @@
1
+ <%= pb_rails("dropdown", props: {
2
+ id: "dropdown-quickpick-enable-time",
3
+ label: "Date Range",
4
+ name: "date_range_enable_time",
5
+ margin_bottom: "sm",
6
+ variant: "quickpick",
7
+ controls_start_id: "start-date-picker-enable-time",
8
+ controls_end_id: "end-date-picker-enable-time",
9
+ start_date_id: "quickpick_enable_time_start_date",
10
+ start_date_name: "start_date_enable_time",
11
+ end_date_id: "quickpick_enable_time_end_date",
12
+ end_date_name: "end_date_enable_time"
13
+ }) %>
14
+
15
+ <%= pb_rails("date_picker", props: {
16
+ picker_id: "start-date-picker-enable-time",
17
+ label: "Start Date",
18
+ name: "start_date_picker_enable_time",
19
+ placeholder: "Select Start Date",
20
+ enable_time: true,
21
+ close_on_select: false,
22
+ sync_start_with: "dropdown-quickpick-enable-time"
23
+ }) %>
24
+
25
+ <%= pb_rails("date_picker", props: {
26
+ picker_id: "end-date-picker-enable-time",
27
+ label: "End Date",
28
+ name: "end_date_picker_enable_time",
29
+ placeholder: "Select End Date",
30
+ enable_time: true,
31
+ close_on_select: false,
32
+ sync_end_with: "dropdown-quickpick-enable-time"
33
+ }) %>
@@ -0,0 +1,42 @@
1
+ import React from "react";
2
+ import Dropdown from "../../pb_dropdown/_dropdown";
3
+ import DatePicker from "../../pb_date_picker/_date_picker";
4
+
5
+ const DropdownQuickpickEnableTime = (props) => {
6
+ return (
7
+ <>
8
+ <Dropdown
9
+ {...props}
10
+ controlsEndId="end-date-picker-enable-time"
11
+ controlsStartId="start-date-picker-enable-time"
12
+ id="dropdown-quickpick-enable-time"
13
+ label="Range"
14
+ marginBottom="sm"
15
+ placeholder="Select a Date Range"
16
+ variant="quickpick"
17
+ />
18
+
19
+ <DatePicker
20
+ {...props}
21
+ enableTime
22
+ initializeOnce
23
+ label="Start Date"
24
+ pickerId="start-date-picker-enable-time"
25
+ placeholder="Select a Start Date"
26
+ syncStartWith="dropdown-quickpick-enable-time"
27
+ />
28
+
29
+ <DatePicker
30
+ {...props}
31
+ enableTime
32
+ initializeOnce
33
+ label="End Date"
34
+ pickerId="end-date-picker-enable-time"
35
+ placeholder="Select an End Date"
36
+ syncEndWith="dropdown-quickpick-enable-time"
37
+ />
38
+ </>
39
+ );
40
+ };
41
+
42
+ export default DropdownQuickpickEnableTime;
@@ -0,0 +1,24 @@
1
+ When linked DatePickers use `enable_time` / `enableTime`, QuickPick presets that do not include an explicit time apply **start of day** (12:00 AM) to the start picker and **end of day** (11:59 PM) to the end picker. That matches DatePicker minute precision and inclusive datetime filters for ranges like Today and Yesterday.
2
+
3
+ **Supported timed custom formats (Rails and React — same contract):**
4
+
5
+ | Format | Example | Semantics |
6
+ |--------|---------|-----------|
7
+ | US `m/d/Y` + time (optional `:SS`, optional `AM`/`PM`) | `"06/01/2022 9:30 AM"` | Wall-clock — literal hour/minute/second labels |
8
+ | Offset-less ISO datetime (`T` separator) | `"2026-03-08T02:30:00"` | Wall-clock — same as above (not server-TZ) |
9
+ | ISO-8601 with `Z` or numeric offset | `"2026-03-08T07:30:00Z"`, `"2026-03-08T02:30:00-05:00"` | Absolute instant |
10
+
11
+ **Emit (Rails and React — same contract):**
12
+
13
+ | Input kind | Emit |
14
+ |------------|------|
15
+ | Wall-clock (US `m/d/Y` + time, or offset-less `YYYY-MM-DDTHH:MM:SS`) | Offset-less `YYYY-MM-DDTHH:MM:SS` — authored clock face |
16
+ | Absolute (`Z` or numeric offset) | Keeps offset / `Z` (e.g. `…Z` or `…±HH:MM`) so `parseQuickPickDateTime` / `new Date(iso)` preserve the same instant |
17
+
18
+ React also accepts `Date` objects (times kept as authored, including intentional midnight / `23:59:00`).
19
+
20
+ Date-only custom strings (e.g. `"06/01/2022"`) still get SOD/EOD at sync when `enableTime` is on. Other free-text / undocumented timed strings are not supported.
21
+
22
+ On Rails, wall-clock customs go to the option payload as offset-less datetimes; absolute customs keep their offset so linked `enableTime` DatePickers sync to the correct instant (not a misread local wall-clock).
23
+
24
+ Alternate configuration: QuickPick + Time can also be handled by a Date-only QuickPick (Dropdown QuickPick + two DatePickers without time selection) paired with two TimePickers for start + end time selection in the same form.
@@ -36,6 +36,7 @@ examples:
36
36
  - dropdown_quickpick_custom_rails: Quick Pick Variant (Custom Quick Pick Dates)
37
37
  - dropdown_quickpick_with_date_pickers_rails: Quick Pick with Date Pickers
38
38
  - dropdown_quickpick_with_date_pickers_default_rails: Quick Pick with Date Pickers (Default Value)
39
+ - dropdown_quickpick_enable_time: Quick Pick with Date Pickers (Enable Time)
39
40
  - dropdown_required_indicator: Required Indicator
40
41
  - dropdown_disabled: Disabled Input
41
42
  - dropdown_grouped_options: Grouped Options
@@ -86,6 +87,7 @@ examples:
86
87
  - dropdown_quickpick_default_dates: Quick Pick Variant (Default Dates)
87
88
  - dropdown_quickpick_custom: Quick Pick Variant (Custom Quick Pick Dates)
88
89
  - dropdown_quickpick_with_date_pickers: Quick Pick Variant with Date Pickers
90
+ - dropdown_quickpick_enable_time: Quick Pick with Date Pickers (Enable Time)
89
91
  - dropdown_required_indicator: Required Indicator
90
92
  - dropdown_disabled: Disabled Input
91
93
  - dropdown_grouped_options: Grouped Options
@@ -47,3 +47,4 @@ export { default as DropdownAsyncMultiSelect } from './_dropdown_async_multi_sel
47
47
  export { default as DropdownAsyncRichResults } from './_dropdown_async_rich_results.jsx'
48
48
  export { default as DropdownAsyncInitialOptions } from './_dropdown_async_initial_options.jsx'
49
49
  export { default as DropdownExternalSearch } from './_dropdown_external_search.jsx'
50
+ export { default as DropdownQuickpickEnableTime } from './_dropdown_quickpick_enable_time.jsx'
@@ -2,6 +2,7 @@ import PbEnhancedElement from "../pb_enhanced_element";
2
2
  import { PbDropdownKeyboard } from "./keyboard_accessibility";
3
3
  import { setArrowVisibility, toggleVisibility } from "../utilities/domHelpers";
4
4
  import { subscribeFloatingKitReposition, positionDropdownPortalToWrapper } from "../utilities/floatingPortalHosts";
5
+ import { setQuickPickDateOnPicker } from "./utilities/quickpickDateSync";
5
6
 
6
7
  const DROPDOWN_SELECTOR = "[data-pb-dropdown]";
7
8
  const TRIGGER_SELECTOR = "[data-dropdown-trigger]";
@@ -1313,11 +1314,11 @@ export default class PbDropdown extends PbEnhancedElement {
1313
1314
  const syncDatePickers = () => {
1314
1315
  if (controlsStartId) {
1315
1316
  const startPicker = document.querySelector(`#${CSS.escape(controlsStartId)}`)?._flatpickr;
1316
- if (startPicker) startPicker.setDate(optionData.formatted_start_date, true, "m/d/Y");
1317
+ setQuickPickDateOnPicker(startPicker, optionData.formatted_start_date, "start");
1317
1318
  }
1318
1319
  if (controlsEndId) {
1319
1320
  const endPicker = document.querySelector(`#${CSS.escape(controlsEndId)}`)?._flatpickr;
1320
- if (endPicker) endPicker.setDate(optionData.formatted_end_date, true, "m/d/Y");
1321
+ setQuickPickDateOnPicker(endPicker, optionData.formatted_end_date, "end");
1321
1322
  }
1322
1323
  };
1323
1324
  syncDatePickers();
@@ -1447,10 +1448,10 @@ export default class PbDropdown extends PbEnhancedElement {
1447
1448
  `#${controlsStartId}`,
1448
1449
  )?._flatpickr;
1449
1450
  if (startPicker) {
1450
- startPicker.setDate(
1451
+ setQuickPickDateOnPicker(
1452
+ startPicker,
1451
1453
  optionData.formatted_start_date,
1452
- true,
1453
- "m/d/Y",
1454
+ "start",
1454
1455
  );
1455
1456
  }
1456
1457
  }
@@ -1460,7 +1461,11 @@ export default class PbDropdown extends PbEnhancedElement {
1460
1461
  `#${controlsEndId}`,
1461
1462
  )?._flatpickr;
1462
1463
  if (endPicker) {
1463
- endPicker.setDate(optionData.formatted_end_date, true, "m/d/Y");
1464
+ setQuickPickDateOnPicker(
1465
+ endPicker,
1466
+ optionData.formatted_end_date,
1467
+ "end",
1468
+ );
1464
1469
  }
1465
1470
  }
1466
1471
  } else if (startDateId || endDateId) {
@@ -1793,10 +1798,10 @@ export default class PbDropdown extends PbEnhancedElement {
1793
1798
  `#${controlsStartId}`,
1794
1799
  )?._flatpickr;
1795
1800
  if (startPicker) {
1796
- startPicker.setDate(
1801
+ setQuickPickDateOnPicker(
1802
+ startPicker,
1797
1803
  optionData.formatted_start_date,
1798
- true,
1799
- "m/d/Y",
1804
+ "start",
1800
1805
  );
1801
1806
  }
1802
1807
  }
@@ -1806,7 +1811,11 @@ export default class PbDropdown extends PbEnhancedElement {
1806
1811
  `#${controlsEndId}`,
1807
1812
  )?._flatpickr;
1808
1813
  if (endPicker) {
1809
- endPicker.setDate(optionData.formatted_end_date, true, "m/d/Y");
1814
+ setQuickPickDateOnPicker(
1815
+ endPicker,
1816
+ optionData.formatted_end_date,
1817
+ "end",
1818
+ );
1810
1819
  }
1811
1820
  }
1812
1821
  };
@@ -2,6 +2,13 @@
2
2
  // This provides date range options similar to the DatePicker QuickPick functionality
3
3
 
4
4
  import DateTime from '../../pb_kit/dateTime';
5
+ import {
6
+ endOfDay,
7
+ parseQuickPickDateOnly,
8
+ parseQuickPickDateTime,
9
+ startOfDay,
10
+ stringHasExplicitTime,
11
+ } from '../utilities/quickpickDateSync';
5
12
 
6
13
  type QuickPickOption = {
7
14
  label: string;
@@ -13,7 +20,7 @@ type QuickPickOption = {
13
20
 
14
21
  type CustomQuickPickDate = {
15
22
  label: string;
16
- value: string[] | { timePeriod: string; amount: number };
23
+ value: Array<Date | string> | { timePeriod: string; amount: number };
17
24
  };
18
25
 
19
26
  type CustomQuickPickDates = {
@@ -21,6 +28,11 @@ type CustomQuickPickDates = {
21
28
  dates: CustomQuickPickDate[];
22
29
  };
23
30
 
31
+ const toQuickPickRange = (start: Date, end: Date): Date[] => [
32
+ startOfDay(start),
33
+ endOfDay(end),
34
+ ];
35
+
24
36
  // Helper function to calculate date range from timePeriod and amount
25
37
  const calculateDateRange = (timePeriod: string, amount: number): Date[] => {
26
38
  const endDate = new Date();
@@ -45,7 +57,7 @@ const calculateDateRange = (timePeriod: string, amount: number): Date[] => {
45
57
  default:
46
58
  throw new Error('Invalid time period');
47
59
  }
48
- return [startDate, endDate];
60
+ return toQuickPickRange(startDate, endDate);
49
61
  };
50
62
 
51
63
  // Helper to format date for display
@@ -57,13 +69,32 @@ const formatDate = (date: Date) => {
57
69
  return `${month}/${day}/${year}`;
58
70
  };
59
71
 
72
+ // Date objects keep their authored time (including midnight / 23:59:00).
73
+ // Date-only strings get SOD/EOD; timed strings keep their parsed time.
74
+ const parseCustomDateBoundary = (value: Date | string): Date => {
75
+ if (value instanceof Date) return value;
76
+ if (stringHasExplicitTime(value)) {
77
+ return parseQuickPickDateTime(value) ?? new Date(value);
78
+ }
79
+ return parseQuickPickDateOnly(value) ?? new Date(value);
80
+ };
81
+
82
+ const boundaryHasExplicitTime = (value: Date | string): boolean =>
83
+ value instanceof Date || stringHasExplicitTime(value);
84
+
60
85
  // Helper to create a QuickPickOption from a custom date
61
86
  const createOptionFromCustomDate = (customDate: CustomQuickPickDate): QuickPickOption => {
62
87
  let dateRange: Date[];
63
-
88
+
64
89
  if (Array.isArray(customDate.value)) {
65
- // Explicit date range as string array
66
- dateRange = customDate.value.map((dateStr: string) => new Date(dateStr));
90
+ const startRaw = parseCustomDateBoundary(customDate.value[0]);
91
+ const endRaw = parseCustomDateBoundary(customDate.value[1]);
92
+ const startHasTime = boundaryHasExplicitTime(customDate.value[0]);
93
+ const endHasTime = boundaryHasExplicitTime(customDate.value[1]);
94
+ dateRange = [
95
+ startHasTime ? startRaw : startOfDay(startRaw),
96
+ endHasTime ? endRaw : endOfDay(endRaw),
97
+ ];
67
98
  } else {
68
99
  // Calculate from timePeriod and amount
69
100
  dateRange = calculateDateRange(
@@ -81,6 +112,17 @@ const createOptionFromCustomDate = (customDate: CustomQuickPickDate): QuickPickO
81
112
  };
82
113
  };
83
114
 
115
+ const option = (label: string, start: Date, end: Date, id: string): QuickPickOption => {
116
+ const value = toQuickPickRange(start, end);
117
+ return {
118
+ label,
119
+ value,
120
+ formattedStartDate: formatDate(value[0]),
121
+ formattedEndDate: formatDate(value[1]),
122
+ id,
123
+ };
124
+ };
125
+
84
126
  // Helper to get QuickPick options with date ranges
85
127
  const getQuickPickOptions = (rangeEndsToday = false, customQuickPickDates?: CustomQuickPickDates): QuickPickOption[] => {
86
128
  const today = new Date();
@@ -107,30 +149,30 @@ const getQuickPickOptions = (rangeEndsToday = false, customQuickPickDates?: Cust
107
149
  const lastYearEndDate = DateTime.getPreviousYearEndDate(new Date());
108
150
 
109
151
  const defaultOptions: QuickPickOption[] = [
110
- { label: 'Today', value: [today, today], id: 'quickpick-today' },
111
- { label: 'Yesterday', value: [yesterday, yesterday], formattedStartDate: `${formatDate(yesterday)}`, formattedEndDate: `${formatDate(yesterday)}`, id: 'quickpick-yesterday' },
112
- { label: 'This Week', value: [thisWeekStartDate, thisWeekEndDate], formattedStartDate: `${formatDate(thisWeekStartDate)}`, formattedEndDate: `${formatDate(thisWeekEndDate)}`, id: 'quickpick-this-week' },
113
- { label: 'This Month', value: [thisMonthStartDate, thisMonthEndDate], formattedStartDate: `${formatDate(thisMonthStartDate)}`, formattedEndDate: `${formatDate(thisMonthEndDate)}`, id: 'quickpick-this-month' },
114
- { label: 'This Quarter', value: [thisQuarterStartDate, thisQuarterEndDate], formattedStartDate: `${formatDate(thisQuarterStartDate)}`, formattedEndDate: `${formatDate(thisQuarterEndDate)}`, id: 'quickpick-this-quarter' },
115
- { label: 'This Year', value: [thisYearStartDate, thisYearEndDate], formattedStartDate: `${formatDate(thisYearStartDate)}`, formattedEndDate: `${formatDate(thisYearEndDate)}`, id: 'quickpick-this-year' },
116
- { label: 'Last Week', value: [lastWeekStartDate, lastWeekEndDate], formattedStartDate: `${formatDate(lastWeekStartDate)}`, formattedEndDate: `${formatDate(lastWeekEndDate)}`, id: 'quickpick-last-week' },
117
- { label: 'Last Month', value: [lastMonthStartDate, lastMonthEndDate], formattedStartDate: `${formatDate(lastMonthStartDate)}`, formattedEndDate: `${formatDate(lastMonthEndDate)}`, id: 'quickpick-last-month' },
118
- { label: 'Last Quarter', value: [lastQuarterStartDate, lastQuarterEndDate], formattedStartDate: `${formatDate(lastQuarterStartDate)}`, formattedEndDate: `${formatDate(lastQuarterEndDate)}`, id: 'quickpick-last-quarter' },
119
- { label: 'Last Year', value: [lastYearStartDate, lastYearEndDate], formattedStartDate: `${formatDate(lastYearStartDate)}`, formattedEndDate: `${formatDate(lastYearEndDate)}`, id: 'quickpick-last-year' },
152
+ option('Today', today, today, 'quickpick-today'),
153
+ option('Yesterday', yesterday, yesterday, 'quickpick-yesterday'),
154
+ option('This Week', thisWeekStartDate, thisWeekEndDate, 'quickpick-this-week'),
155
+ option('This Month', thisMonthStartDate, thisMonthEndDate, 'quickpick-this-month'),
156
+ option('This Quarter', thisQuarterStartDate, thisQuarterEndDate, 'quickpick-this-quarter'),
157
+ option('This Year', thisYearStartDate, thisYearEndDate, 'quickpick-this-year'),
158
+ option('Last Week', lastWeekStartDate, lastWeekEndDate, 'quickpick-last-week'),
159
+ option('Last Month', lastMonthStartDate, lastMonthEndDate, 'quickpick-last-month'),
160
+ option('Last Quarter', lastQuarterStartDate, lastQuarterEndDate, 'quickpick-last-quarter'),
161
+ option('Last Year', lastYearStartDate, lastYearEndDate, 'quickpick-last-year'),
120
162
  ];
121
163
 
122
164
  // Handle customQuickPickDates and override logic
123
165
  if (customQuickPickDates && customQuickPickDates.dates && customQuickPickDates.dates.length > 0) {
124
166
  const customOptions = customQuickPickDates.dates.map(createOptionFromCustomDate);
125
-
167
+
126
168
  if (customQuickPickDates.override === false) {
127
169
  return [...defaultOptions, ...customOptions];
128
170
  }
129
-
171
+
130
172
  return customOptions;
131
173
  }
132
174
 
133
175
  return defaultOptions;
134
176
  };
135
177
 
136
- export default getQuickPickOptions
178
+ export default getQuickPickOptions