playbook_ui 15.6.0.pre.rc.4 → 15.7.0.pre.alpha.PLAY2675dropdownquickpickcustomquickpickdates13330
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/_playbook.scss +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +3 -2
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +4 -0
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +95 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_background_colors_rails.html.erb +43 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_background_colors_rails.md +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_background_control_rails.html.erb +11 -5
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_background_control_rails.md +7 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_background.jsx +54 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_background.md +9 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_background_multi.jsx +80 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_background_multi.md +3 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +4 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +3 -1
- data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +2 -2
- data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +57 -0
- data/app/pb_kits/playbook/pb_bar_graph/_bar_graph.tsx +6 -0
- data/app/pb_kits/playbook/pb_card/docs/_card_header.md +1 -1
- data/app/pb_kits/playbook/pb_card/docs/_card_highlight.md +1 -1
- data/app/pb_kits/playbook/pb_circle_chart/_circle_chart.tsx +6 -0
- data/app/pb_kits/playbook/pb_collapsible/__snapshots__/collapsible.test.js.snap +2 -2
- data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleIcon.tsx +10 -8
- data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_icons.jsx +0 -1
- data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_state.jsx +0 -3
- data/app/pb_kits/playbook/pb_contact/_contact.tsx +51 -24
- data/app/pb_kits/playbook/pb_contact/contact.html.erb +53 -19
- data/app/pb_kits/playbook/pb_contact/contact.rb +11 -1
- data/app/pb_kits/playbook/pb_contact/contact.test.js +76 -0
- data/app/pb_kits/playbook/pb_contact/docs/_contact_unstyled.html.erb +33 -0
- data/app/pb_kits/playbook/pb_contact/docs/_contact_unstyled.jsx +46 -0
- data/app/pb_kits/playbook/pb_contact/docs/_contact_unstyled_rails.md +2 -0
- data/app/pb_kits/playbook/pb_contact/docs/_contact_unstyled_react.md +2 -0
- data/app/pb_kits/playbook/pb_contact/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_contact/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +24 -0
- data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +197 -7
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern_rails.html.erb +23 -14
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern_rails.md +1 -1
- data/app/pb_kits/playbook/pb_dialog/_dialog.tsx +2 -1
- data/app/pb_kits/playbook/pb_dialog/dialog.html.erb +1 -1
- data/app/pb_kits/playbook/pb_dialog/dialog.rb +1 -0
- data/app/pb_kits/playbook/pb_dialog/dialog.test.jsx +14 -0
- data/app/pb_kits/playbook/pb_dialog/dialog_header.html.erb +5 -4
- data/app/pb_kits/playbook/pb_dialog/dialog_header.rb +2 -0
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_closeable.html.erb +24 -0
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_closeable.jsx +60 -0
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_closeable.md +3 -0
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_overflow_visible.html.erb +71 -0
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_overflow_visible.jsx +57 -0
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_overflow_visible_rails.md +1 -0
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_overflow_visible_react.md +1 -0
- data/app/pb_kits/playbook/pb_dialog/docs/example.yml +4 -0
- data/app/pb_kits/playbook/pb_dialog/docs/index.js +3 -1
- data/app/pb_kits/playbook/pb_distribution_bar/docs/_distribution_bar_custom_colors.md +1 -1
- data/app/pb_kits/playbook/pb_draggable/context/index.tsx +316 -15
- data/app/pb_kits/playbook/pb_draggable/context/types.ts +1 -1
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +13 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.html.erb +7 -5
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_custom.jsx +56 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_custom.md +10 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_custom_rails.html.erb +64 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_custom_rails.md +10 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_default_dates.html.erb +19 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_rails.html.erb +12 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_rails.md +26 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_range_end_rails.html.erb +19 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_range_end_rails.md +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_with_date_pickers_default_rails.html.erb +30 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_with_date_pickers_default_rails.md +3 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_with_date_pickers_rails.html.erb +29 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_quickpick_with_date_pickers_rails.md +13 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.html.erb +3 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +7 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +4 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +44 -5
- data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +121 -0
- data/app/pb_kits/playbook/pb_dropdown/index.js +171 -3
- data/app/pb_kits/playbook/pb_dropdown/quickpick/index.ts +85 -9
- data/app/pb_kits/playbook/pb_dropdown/quickpick_helper.rb +156 -0
- data/app/pb_kits/playbook/pb_filter/Filter/FilterBackground.tsx +3 -3
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +1 -1
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +2 -1
- data/app/pb_kits/playbook/pb_form/docs/_form_with_required_indicator.html.erb +14 -0
- data/app/pb_kits/playbook/pb_form/docs/_form_with_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_form/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_gauge/_gauge.tsx +6 -0
- data/app/pb_kits/playbook/pb_line_graph/_line_graph.tsx +6 -0
- data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.html.erb +2 -2
- data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.jsx +3 -2
- data/app/pb_kits/playbook/pb_radio/docs/_radio_error.md +1 -1
- data/app/pb_kits/playbook/pb_select/_select.tsx +8 -3
- data/app/pb_kits/playbook/pb_select/docs/_select_error.md +1 -1
- data/app/pb_kits/playbook/pb_select/docs/_select_input_options.html.erb +16 -0
- data/app/pb_kits/playbook/pb_select/docs/_select_input_options.jsx +30 -0
- data/app/pb_kits/playbook/pb_select/docs/_select_input_options.md +1 -0
- data/app/pb_kits/playbook/pb_select/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_select/select.html.erb +2 -2
- data/app/pb_kits/playbook/pb_select/select.rb +3 -1
- data/app/pb_kits/playbook/pb_select/select.test.js +23 -0
- data/app/pb_kits/playbook/pb_table/_table.tsx +187 -33
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant.jsx +134 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant.md +34 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_rails.html.erb +101 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_rails.md +33 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination.jsx +180 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination.md +3 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination_rails.html.erb +122 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination_rails.md +3 -0
- data/app/pb_kits/playbook/pb_table/docs/example.yml +4 -0
- data/app/pb_kits/playbook/pb_table/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_table/table.html.erb +68 -12
- data/app/pb_kits/playbook/pb_table/table.rb +22 -3
- data/app/pb_kits/playbook/pb_table/table.test.js +143 -0
- data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +15 -3
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.md +1 -1
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_required_indicator.html.erb +6 -0
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_required_indicator.jsx +25 -0
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_text_input/docs/example.yml +3 -0
- data/app/pb_kits/playbook/pb_text_input/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +6 -0
- data/app/pb_kits/playbook/pb_text_input/text_input.rb +2 -0
- data/app/pb_kits/playbook/pb_text_input/text_input.test.js +16 -0
- data/app/pb_kits/playbook/pb_textarea/docs/_textarea_error.md +1 -1
- data/app/pb_kits/playbook/pb_time_picker/_time_picker.scss +296 -0
- data/app/pb_kits/playbook/pb_time_picker/_time_picker.tsx +822 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_24_hour.html.erb +2 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_24_hour.jsx +16 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_24_hour.md +1 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_default.html.erb +1 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_default.jsx +13 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_default.md +1 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_default_time.html.erb +4 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_default_time.jsx +29 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_default_time.md +1 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_disabled.html.erb +13 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_disabled.jsx +23 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_error.html.erb +5 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_error.jsx +15 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_input_options.html.erb +14 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_label.html.erb +2 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_label.jsx +15 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_min_max_time.html.erb +42 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_min_max_time.jsx +52 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_min_max_time.md +1 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler.jsx +45 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler.md +1 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_timezone.html.erb +3 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_timezone.jsx +21 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_timezone.md +1 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/example.yml +24 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/index.js +9 -0
- data/app/pb_kits/playbook/pb_time_picker/index.ts +40 -0
- data/app/pb_kits/playbook/pb_time_picker/time_picker.html.erb +1 -0
- data/app/pb_kits/playbook/pb_time_picker/time_picker.rb +80 -0
- data/app/pb_kits/playbook/pb_time_picker/time_picker.test.jsx +114 -0
- data/app/pb_kits/playbook/pb_time_picker/time_picker_helper.ts +662 -0
- data/app/pb_kits/playbook/pb_timeline/_item.tsx +3 -0
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.html.erb +60 -0
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.jsx +118 -0
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.md +1 -0
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_date.md +1 -1
- data/app/pb_kits/playbook/pb_timeline/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_timeline/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_timeline/item.html.erb +1 -1
- data/app/pb_kits/playbook/pb_timeline/item.rb +2 -0
- data/app/pb_kits/playbook/pb_timeline/label.html.erb +2 -1
- data/app/pb_kits/playbook/pb_timeline/label.rb +2 -0
- data/app/pb_kits/playbook/pb_timeline/subcomponents/Label.tsx +3 -0
- data/app/pb_kits/playbook/pb_timeline/timeline.test.js +51 -0
- data/app/pb_kits/playbook/tokens/_colors.scss +2 -1
- data/app/pb_kits/playbook/utilities/deprecated.ts +73 -0
- data/app/pb_kits/playbook/utilities/globalProps.ts +1 -0
- data/dist/chunks/_typeahead-Ckz1ce-2.js +6 -0
- data/dist/chunks/lib-DxDBrGZX.js +29 -0
- data/dist/chunks/vendor.js +3 -3
- data/dist/menu.yml +16 -9
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/forms/builder/collection_select_field.rb +9 -1
- data/lib/playbook/forms/builder/form_field_builder.rb +13 -2
- data/lib/playbook/forms/builder/select_field.rb +9 -1
- data/lib/playbook/forms/builder/time_picker_field.rb +24 -0
- data/lib/playbook/forms/builder/time_zone_select_field.rb +9 -1
- data/lib/playbook/forms/builder.rb +1 -0
- data/lib/playbook/pb_doc_helper.rb +3 -0
- data/lib/playbook/pb_kit_helper.rb +35 -0
- data/lib/playbook/version.rb +2 -2
- metadata +89 -4
- data/dist/chunks/_typeahead-BXM7QUuy.js +0 -6
- data/dist/chunks/lib-CgpqUb6l.js +0 -29
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useReducer, useContext, useEffect, useMemo } from "react";
|
|
1
|
+
import React, { createContext, useReducer, useContext, useEffect, useMemo, useRef } from "react";
|
|
2
2
|
import { InitialStateType, ActionType, DraggableProviderType } from "./types";
|
|
3
3
|
|
|
4
4
|
const initialState: InitialStateType = {
|
|
@@ -92,6 +92,35 @@ const reducer = (state: InitialStateType, action: ActionType) => {
|
|
|
92
92
|
return { ...state, items: newItems };
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
// Reset item back to its original container and position (e.g., when drag ends without valid drop)
|
|
96
|
+
case "RESET_DRAG_CONTAINER": {
|
|
97
|
+
const { itemId, originalContainer, originalIndex } = action.payload;
|
|
98
|
+
const newItems = [...state.items];
|
|
99
|
+
const draggedItem = newItems.find(item => item && item.id === itemId);
|
|
100
|
+
|
|
101
|
+
if (!draggedItem) return state;
|
|
102
|
+
|
|
103
|
+
const currentIndex = newItems.indexOf(draggedItem);
|
|
104
|
+
|
|
105
|
+
// Remove from current position
|
|
106
|
+
newItems.splice(currentIndex, 1);
|
|
107
|
+
|
|
108
|
+
// Restore container property and insert at original index
|
|
109
|
+
const restoredItem = { ...draggedItem, container: originalContainer };
|
|
110
|
+
|
|
111
|
+
// Insert at original index, or at end if index is invalid
|
|
112
|
+
if (originalIndex !== undefined && originalIndex >= 0) {
|
|
113
|
+
newItems.splice(originalIndex, 0, restoredItem);
|
|
114
|
+
} else {
|
|
115
|
+
newItems.push(restoredItem);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
...state,
|
|
120
|
+
items: newItems
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
95
124
|
default:
|
|
96
125
|
return state;
|
|
97
126
|
}
|
|
@@ -119,6 +148,29 @@ export const DraggableProvider = ({
|
|
|
119
148
|
enableCrossContainerPreview = false,
|
|
120
149
|
}: DraggableProviderType) => {
|
|
121
150
|
const [state, dispatch] = useReducer(reducer, initialState);
|
|
151
|
+
|
|
152
|
+
// Track drag state for global listener
|
|
153
|
+
const dragStateRef = useRef<{
|
|
154
|
+
isDragging: boolean;
|
|
155
|
+
draggedItemId: string;
|
|
156
|
+
originalContainer: string;
|
|
157
|
+
originalIndex: number;
|
|
158
|
+
currentContainer: string;
|
|
159
|
+
dropOccurred: boolean;
|
|
160
|
+
}>({
|
|
161
|
+
isDragging: false,
|
|
162
|
+
draggedItemId: '',
|
|
163
|
+
originalContainer: '',
|
|
164
|
+
originalIndex: -1,
|
|
165
|
+
currentContainer: '',
|
|
166
|
+
dropOccurred: false,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Track current state for use in gated event listeners (avoid stale closures)
|
|
170
|
+
const stateRef = useRef(state);
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
stateRef.current = state;
|
|
173
|
+
}, [state]);
|
|
122
174
|
|
|
123
175
|
// Parse dropZone prop - handle both string format (backward compatibility) and object format
|
|
124
176
|
let dropZoneType = 'ghost';
|
|
@@ -148,7 +200,209 @@ export const DraggableProvider = ({
|
|
|
148
200
|
onReorder(state.items);
|
|
149
201
|
}, [state.items]);
|
|
150
202
|
|
|
203
|
+
// Monitor for failed drops by detecting mouse/pointer release during drag (this is needed for cross container preview)
|
|
204
|
+
useEffect(() => {
|
|
205
|
+
if (!enableCrossContainerPreview) return;
|
|
206
|
+
|
|
207
|
+
// Allow drops anywhere on the document by preventing default dragover
|
|
208
|
+
const handleGlobalDragOver = (e: DragEvent) => {
|
|
209
|
+
if (dragStateRef.current.isDragging) {
|
|
210
|
+
e.preventDefault();
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// Handle drops anywhere on the document (including non-container areas)
|
|
215
|
+
const handleGlobalDrop = (e: DragEvent) => {
|
|
216
|
+
if (!dragStateRef.current.isDragging) return;
|
|
217
|
+
|
|
218
|
+
// If a container already handled the drop, don't process again
|
|
219
|
+
if (dragStateRef.current.dropOccurred) return;
|
|
220
|
+
|
|
221
|
+
e.preventDefault();
|
|
222
|
+
|
|
223
|
+
// If we reach here, it means the drop was NOT on a valid container
|
|
224
|
+
// (otherwise the container's handleDrop would have set dropOccurred = true)
|
|
225
|
+
// So we should ALWAYS reset to original container for invalid drops
|
|
226
|
+
const originalContainer = dragStateRef.current.originalContainer;
|
|
227
|
+
|
|
228
|
+
dispatch({
|
|
229
|
+
type: 'RESET_DRAG_CONTAINER',
|
|
230
|
+
payload: {
|
|
231
|
+
itemId: dragStateRef.current.draggedItemId,
|
|
232
|
+
originalContainer: originalContainer,
|
|
233
|
+
originalIndex: dragStateRef.current.originalIndex,
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
238
|
+
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
239
|
+
dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
|
|
240
|
+
|
|
241
|
+
// Clear drag state
|
|
242
|
+
dragStateRef.current = {
|
|
243
|
+
isDragging: false,
|
|
244
|
+
draggedItemId: '',
|
|
245
|
+
originalContainer: '',
|
|
246
|
+
originalIndex: -1,
|
|
247
|
+
currentContainer: '',
|
|
248
|
+
dropOccurred: false,
|
|
249
|
+
};
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const handleGlobalMouseUp = () => {
|
|
253
|
+
// If we're dragging and mouse is released, wait a bit to see if drop occurs
|
|
254
|
+
if (dragStateRef.current.isDragging) {
|
|
255
|
+
setTimeout(() => {
|
|
256
|
+
const currentContainer = dragStateRef.current.currentContainer;
|
|
257
|
+
|
|
258
|
+
// If drop still hasn't occurred, check if item is in a different container
|
|
259
|
+
if (dragStateRef.current.isDragging && !dragStateRef.current.dropOccurred) {
|
|
260
|
+
// If item is in a different container than original, treat it as a successful drop
|
|
261
|
+
if (currentContainer && currentContainer !== dragStateRef.current.originalContainer) {
|
|
262
|
+
// Trigger onDrop callback with the current container
|
|
263
|
+
if (onDrop) {
|
|
264
|
+
const draggedItem = stateRef.current.items.find(item => item && item.id === dragStateRef.current.draggedItemId);
|
|
265
|
+
const updatedItem = draggedItem ? { ...draggedItem, container: currentContainer } : null;
|
|
266
|
+
const itemsInContainer = stateRef.current.items.filter(item => item && item.container === currentContainer);
|
|
267
|
+
const indexInContainer = itemsInContainer.findIndex(item => item && item.id === dragStateRef.current.draggedItemId);
|
|
268
|
+
const itemAbove = indexInContainer > 0 ? itemsInContainer[indexInContainer - 1] : null;
|
|
269
|
+
const itemBelow = indexInContainer < itemsInContainer.length - 1 ? itemsInContainer[indexInContainer + 1] : null;
|
|
270
|
+
|
|
271
|
+
onDrop(
|
|
272
|
+
dragStateRef.current.draggedItemId,
|
|
273
|
+
currentContainer,
|
|
274
|
+
dragStateRef.current.originalContainer,
|
|
275
|
+
updatedItem,
|
|
276
|
+
itemAbove,
|
|
277
|
+
itemBelow
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
dispatch({
|
|
282
|
+
type: 'RESET_DRAG_CONTAINER',
|
|
283
|
+
payload: {
|
|
284
|
+
itemId: dragStateRef.current.draggedItemId,
|
|
285
|
+
originalContainer: dragStateRef.current.originalContainer,
|
|
286
|
+
originalIndex: dragStateRef.current.originalIndex,
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
291
|
+
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
292
|
+
dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
|
|
293
|
+
|
|
294
|
+
// Clear drag state
|
|
295
|
+
dragStateRef.current = {
|
|
296
|
+
isDragging: false,
|
|
297
|
+
draggedItemId: '',
|
|
298
|
+
originalContainer: '',
|
|
299
|
+
originalIndex: -1,
|
|
300
|
+
currentContainer: '',
|
|
301
|
+
dropOccurred: false,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
}, 50); // Small delay to let drop event fire if it's going to
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
// Detect when drag leaves document boundaries
|
|
309
|
+
const handleDragLeave = (e: DragEvent) => {
|
|
310
|
+
// Check if we're leaving the document (relatedTarget will be null)
|
|
311
|
+
if (!e.relatedTarget && dragStateRef.current.isDragging && !dragStateRef.current.dropOccurred) {
|
|
312
|
+
// Drag left the document: reset to original container immediately
|
|
313
|
+
dispatch({
|
|
314
|
+
type: 'RESET_DRAG_CONTAINER',
|
|
315
|
+
payload: {
|
|
316
|
+
itemId: dragStateRef.current.draggedItemId,
|
|
317
|
+
originalContainer: dragStateRef.current.originalContainer,
|
|
318
|
+
originalIndex: dragStateRef.current.originalIndex,
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
322
|
+
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
323
|
+
dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
|
|
324
|
+
|
|
325
|
+
// Clear drag state
|
|
326
|
+
dragStateRef.current = {
|
|
327
|
+
isDragging: false,
|
|
328
|
+
draggedItemId: '',
|
|
329
|
+
originalContainer: '',
|
|
330
|
+
originalIndex: -1,
|
|
331
|
+
currentContainer: '',
|
|
332
|
+
dropOccurred: false,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
document.addEventListener('dragover', handleGlobalDragOver);
|
|
338
|
+
document.addEventListener('drop', handleGlobalDrop);
|
|
339
|
+
document.addEventListener('dragleave', handleDragLeave);
|
|
340
|
+
document.addEventListener('mouseup', handleGlobalMouseUp);
|
|
341
|
+
document.addEventListener('pointerup', handleGlobalMouseUp);
|
|
342
|
+
|
|
343
|
+
return () => {
|
|
344
|
+
document.removeEventListener('dragover', handleGlobalDragOver);
|
|
345
|
+
document.removeEventListener('drop', handleGlobalDrop);
|
|
346
|
+
document.removeEventListener('dragleave', handleDragLeave);
|
|
347
|
+
document.removeEventListener('mouseup', handleGlobalMouseUp);
|
|
348
|
+
document.removeEventListener('pointerup', handleGlobalMouseUp);
|
|
349
|
+
};
|
|
350
|
+
}, [enableCrossContainerPreview]);
|
|
351
|
+
|
|
352
|
+
// Detect when dragging stops (isDragging goes from truthy to empty)
|
|
353
|
+
const prevIsDraggingRef = useRef(state.isDragging);
|
|
354
|
+
|
|
355
|
+
useEffect(() => {
|
|
356
|
+
if (!enableCrossContainerPreview) return;
|
|
357
|
+
|
|
358
|
+
const wasDragging = prevIsDraggingRef.current;
|
|
359
|
+
const isNowDragging = state.isDragging;
|
|
360
|
+
|
|
361
|
+
// Drag just ended (was dragging, now not)
|
|
362
|
+
if (wasDragging && !isNowDragging) {
|
|
363
|
+
|
|
364
|
+
// If drop didn't occur, reset to original container
|
|
365
|
+
if (!dragStateRef.current.dropOccurred && dragStateRef.current.draggedItemId) {
|
|
366
|
+
dispatch({
|
|
367
|
+
type: 'RESET_DRAG_CONTAINER',
|
|
368
|
+
payload: {
|
|
369
|
+
itemId: dragStateRef.current.draggedItemId,
|
|
370
|
+
originalContainer: dragStateRef.current.originalContainer,
|
|
371
|
+
originalIndex: dragStateRef.current.originalIndex,
|
|
372
|
+
},
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Clear drag state
|
|
377
|
+
dragStateRef.current = {
|
|
378
|
+
isDragging: false,
|
|
379
|
+
draggedItemId: '',
|
|
380
|
+
originalContainer: '',
|
|
381
|
+
originalIndex: -1,
|
|
382
|
+
currentContainer: '',
|
|
383
|
+
dropOccurred: false,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
prevIsDraggingRef.current = isNowDragging;
|
|
388
|
+
}, [state.isDragging, enableCrossContainerPreview]);
|
|
389
|
+
|
|
151
390
|
const handleDragStart = (id: string, container: string) => {
|
|
391
|
+
// Track drag in ref for global listener
|
|
392
|
+
if (enableCrossContainerPreview) {
|
|
393
|
+
// Find the original index of the item
|
|
394
|
+
const originalIndex = state.items.findIndex(item => item && item.id === id);
|
|
395
|
+
|
|
396
|
+
dragStateRef.current = {
|
|
397
|
+
isDragging: true,
|
|
398
|
+
draggedItemId: id,
|
|
399
|
+
originalContainer: container,
|
|
400
|
+
originalIndex: originalIndex,
|
|
401
|
+
currentContainer: container,
|
|
402
|
+
dropOccurred: false,
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
|
|
152
406
|
dispatch({ type: 'SET_DRAG_DATA', payload: { id: id, initialGroup: container, originId: providerId } });
|
|
153
407
|
dispatch({ type: 'SET_IS_DRAGGING', payload: id });
|
|
154
408
|
if (onDragStart) onDragStart(id, container);
|
|
@@ -181,6 +435,10 @@ export const DraggableProvider = ({
|
|
|
181
435
|
newContainer: container,
|
|
182
436
|
},
|
|
183
437
|
});
|
|
438
|
+
// Update current container in ref
|
|
439
|
+
if (enableCrossContainerPreview) {
|
|
440
|
+
dragStateRef.current.currentContainer = container;
|
|
441
|
+
}
|
|
184
442
|
} else {
|
|
185
443
|
// Same container: keep original behavior
|
|
186
444
|
dispatch({
|
|
@@ -193,7 +451,10 @@ export const DraggableProvider = ({
|
|
|
193
451
|
dispatch({type: "REORDER_ITEMS", payload: { dragId: state.dragData.id, targetId: id }});
|
|
194
452
|
}
|
|
195
453
|
|
|
196
|
-
|
|
454
|
+
// When enableCrossContainerPreview is true, preserve the original initialGroup
|
|
455
|
+
// Otherwise, update it to track the current container
|
|
456
|
+
const newInitialGroup = enableCrossContainerPreview ? state.dragData.initialGroup : container;
|
|
457
|
+
dispatch({type: "SET_DRAG_DATA",payload: {id: state.dragData.id, initialGroup: newInitialGroup, originId: providerId}});
|
|
197
458
|
}
|
|
198
459
|
if (onDragEnter) onDragEnter(id, container);
|
|
199
460
|
};
|
|
@@ -202,17 +463,29 @@ export const DraggableProvider = ({
|
|
|
202
463
|
const draggedItemId = state.dragData.id;
|
|
203
464
|
const originalContainer = state.dragData.initialGroup;
|
|
204
465
|
|
|
466
|
+
// If enableCrossContainerPreview is true and no drop occurred, reset item to original container
|
|
467
|
+
if (enableCrossContainerPreview && !dragStateRef.current.dropOccurred && draggedItemId && originalContainer) {
|
|
468
|
+
dispatch({ type: 'RESET_DRAG_CONTAINER', payload: { itemId: draggedItemId, originalContainer, originalIndex: dragStateRef.current.originalIndex } });
|
|
469
|
+
}
|
|
470
|
+
|
|
205
471
|
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
206
472
|
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
207
473
|
dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
|
|
474
|
+
|
|
475
|
+
// Only call onDragEnd if drop didn't already occur (for enableCrossContainerPreview)
|
|
476
|
+
// If drop occurred, handleDrop or global drop handler already called onDragEnd
|
|
477
|
+
if (enableCrossContainerPreview && dragStateRef.current.dropOccurred) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
|
|
208
481
|
if (onDragEnd) {
|
|
209
482
|
if (!enableCrossContainerPreview) {
|
|
210
483
|
onDragEnd();
|
|
211
484
|
} else {
|
|
212
|
-
const draggedItem =
|
|
485
|
+
const draggedItem = stateRef.current.items.find(item => item && item.id === draggedItemId);
|
|
213
486
|
const finalContainer = draggedItem ? draggedItem.container : originalContainer;
|
|
214
487
|
|
|
215
|
-
const itemsInContainer =
|
|
488
|
+
const itemsInContainer = stateRef.current.items.filter(item => item && item.container === finalContainer);
|
|
216
489
|
const indexInContainer = itemsInContainer.findIndex(item => item && item.id === draggedItemId);
|
|
217
490
|
const itemAbove = indexInContainer > 0 ? itemsInContainer[indexInContainer - 1] : null;
|
|
218
491
|
const itemBelow = indexInContainer < itemsInContainer.length - 1 ? itemsInContainer[indexInContainer + 1] : null;
|
|
@@ -237,32 +510,58 @@ export const DraggableProvider = ({
|
|
|
237
510
|
|
|
238
511
|
const draggedItemId = state.dragData.id;
|
|
239
512
|
const originalContainer = state.dragData.initialGroup;
|
|
513
|
+
|
|
514
|
+
// Mark drop as successful in ref for global listener
|
|
515
|
+
if (enableCrossContainerPreview) {
|
|
516
|
+
dragStateRef.current.dropOccurred = true;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Gather data for callbacks BEFORE clearing state
|
|
520
|
+
const isCrossContainer = container !== originalContainer;
|
|
521
|
+
let callbackData = null;
|
|
522
|
+
|
|
523
|
+
if (enableCrossContainerPreview) {
|
|
524
|
+
const draggedItem = stateRef.current.items.find(item => item && item.id === draggedItemId);
|
|
525
|
+
const updatedItem = draggedItem ? { ...draggedItem, container } : null;
|
|
526
|
+
const itemsInContainer = stateRef.current.items.filter(item => item && item.container === container);
|
|
527
|
+
const indexInContainer = itemsInContainer.findIndex(item => item && item.id === draggedItemId);
|
|
528
|
+
const itemAbove = indexInContainer > 0 ? itemsInContainer[indexInContainer - 1] : null;
|
|
529
|
+
const itemBelow = indexInContainer < itemsInContainer.length - 1 ? itemsInContainer[indexInContainer + 1] : null;
|
|
530
|
+
|
|
531
|
+
callbackData = { updatedItem, itemAbove, itemBelow };
|
|
532
|
+
}
|
|
240
533
|
|
|
241
534
|
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
242
535
|
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
536
|
+
dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
|
|
243
537
|
changeCategory(state.dragData.id, container);
|
|
538
|
+
|
|
244
539
|
if (onDrop) {
|
|
245
540
|
if (!enableCrossContainerPreview) {
|
|
246
541
|
onDrop(container);
|
|
247
542
|
} else {
|
|
248
|
-
const draggedItem = state.items.find(item => item && item.id === draggedItemId);
|
|
249
|
-
const updatedItem = draggedItem ? { ...draggedItem, container } : null;
|
|
250
|
-
|
|
251
|
-
const itemsInContainer = state.items.filter(item => item && item.container === container);
|
|
252
|
-
const indexInContainer = itemsInContainer.findIndex(item => item && item.id === draggedItemId);
|
|
253
|
-
const itemAbove = indexInContainer > 0 ? itemsInContainer[indexInContainer - 1] : null;
|
|
254
|
-
const itemBelow = indexInContainer < itemsInContainer.length - 1 ? itemsInContainer[indexInContainer + 1] : null;
|
|
255
|
-
|
|
256
543
|
onDrop(
|
|
257
544
|
draggedItemId,
|
|
258
545
|
container,
|
|
259
546
|
originalContainer,
|
|
260
|
-
updatedItem,
|
|
261
|
-
itemAbove,
|
|
262
|
-
itemBelow
|
|
547
|
+
callbackData.updatedItem,
|
|
548
|
+
callbackData.itemAbove,
|
|
549
|
+
callbackData.itemBelow
|
|
263
550
|
);
|
|
264
551
|
}
|
|
265
552
|
}
|
|
553
|
+
|
|
554
|
+
// Trigger onDragEnd ONLY for cross-container drops (dragend doesn't fire reliably in that case)
|
|
555
|
+
// For same-container drops, handleDragEnd will be called normally
|
|
556
|
+
if (enableCrossContainerPreview && isCrossContainer && onDragEnd && callbackData) {
|
|
557
|
+
onDragEnd(
|
|
558
|
+
draggedItemId,
|
|
559
|
+
container,
|
|
560
|
+
originalContainer,
|
|
561
|
+
callbackData.itemAbove,
|
|
562
|
+
callbackData.itemBelow
|
|
563
|
+
);
|
|
564
|
+
}
|
|
266
565
|
};
|
|
267
566
|
|
|
268
567
|
const handleDragOver = (e: Event, container: string) => {
|
|
@@ -281,6 +580,8 @@ export const DraggableProvider = ({
|
|
|
281
580
|
type: "MOVE_TO_CONTAINER_END",
|
|
282
581
|
payload: { dragId: state.dragData.id, newContainer: container },
|
|
283
582
|
});
|
|
583
|
+
// Update current container in ref
|
|
584
|
+
dragStateRef.current.currentContainer = container;
|
|
284
585
|
}
|
|
285
586
|
}
|
|
286
587
|
|
|
@@ -23,7 +23,7 @@ export type ActionType =
|
|
|
23
23
|
| { type: 'REORDER_ITEMS'; payload: { dragId: string; targetId: string } }
|
|
24
24
|
| { type: 'REORDER_ITEMS_CROSS_CONTAINER'; payload: { dragId: string; targetId: string; newContainer: string } }
|
|
25
25
|
| { type: 'MOVE_TO_CONTAINER_END'; payload: { dragId: string; newContainer: string } }
|
|
26
|
-
| { type: 'RESET_DRAG_CONTAINER'; payload: { itemId: string; originalContainer: string } };
|
|
26
|
+
| { type: 'RESET_DRAG_CONTAINER'; payload: { itemId: string; originalContainer: string, originalIndex: number } };
|
|
27
27
|
|
|
28
28
|
export interface DropZoneConfig {
|
|
29
29
|
type?: 'ghost' | 'outline' | 'shadow' | 'line';
|
|
@@ -20,12 +20,23 @@ import {
|
|
|
20
20
|
handleClickOutside,
|
|
21
21
|
} from "./utilities";
|
|
22
22
|
|
|
23
|
+
type CustomQuickPickDate = {
|
|
24
|
+
label: string;
|
|
25
|
+
value: string[] | { timePeriod: string; amount: number };
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type CustomQuickPickDates = {
|
|
29
|
+
override?: boolean;
|
|
30
|
+
dates: CustomQuickPickDate[];
|
|
31
|
+
};
|
|
32
|
+
|
|
23
33
|
type DropdownProps = {
|
|
24
34
|
aria?: { [key: string]: string };
|
|
25
35
|
autocomplete?: boolean;
|
|
26
36
|
blankSelection?: string;
|
|
27
37
|
children?: React.ReactChild[] | React.ReactChild | React.ReactElement[];
|
|
28
38
|
className?: string;
|
|
39
|
+
customQuickPickDates?: CustomQuickPickDates;
|
|
29
40
|
formPillProps?: GenericObject;
|
|
30
41
|
dark?: boolean;
|
|
31
42
|
data?: { [key: string]: string };
|
|
@@ -63,6 +74,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
|
63
74
|
blankSelection = '',
|
|
64
75
|
children,
|
|
65
76
|
className,
|
|
77
|
+
customQuickPickDates,
|
|
66
78
|
dark = false,
|
|
67
79
|
data = {},
|
|
68
80
|
defaultValue = {},
|
|
@@ -95,7 +107,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
|
95
107
|
// ------------- Quick Pick ---------------------------------
|
|
96
108
|
// Use QuickPick options when variant is "quickpick"
|
|
97
109
|
const dropdownOptions = variant === "quickpick"
|
|
98
|
-
? getQuickPickOptions(rangeEndsToday)
|
|
110
|
+
? getQuickPickOptions(rangeEndsToday, customQuickPickDates)
|
|
99
111
|
: (options || []);
|
|
100
112
|
// ----------------------------------------------------------
|
|
101
113
|
|
|
@@ -20,12 +20,14 @@
|
|
|
20
20
|
|
|
21
21
|
%>
|
|
22
22
|
|
|
23
|
-
<%= pb_rails("dropdown", props: {options: options}) %>
|
|
23
|
+
<%= pb_rails("dropdown", props: {id: "country-dropdown", options: options}) %>
|
|
24
24
|
|
|
25
25
|
<script>
|
|
26
26
|
document.addEventListener("pb:dropdown:selected", (e) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
if (e.target.id === "country-dropdown") {
|
|
28
|
+
const option = e.detail;
|
|
29
|
+
const dropdown = e.target;
|
|
30
|
+
console.log("Selected option:", option);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
31
33
|
</script>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import Dropdown from "../_dropdown"
|
|
3
|
+
|
|
4
|
+
const DropdownQuickpickCustom = (props) => (
|
|
5
|
+
<div>
|
|
6
|
+
<Dropdown
|
|
7
|
+
customQuickPickDates={{
|
|
8
|
+
dates: [
|
|
9
|
+
// Allow Playbook to handle the logic...
|
|
10
|
+
{
|
|
11
|
+
label: "Last 15 months",
|
|
12
|
+
value: {
|
|
13
|
+
timePeriod: "months",
|
|
14
|
+
amount: 15,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
// Or, be explicit with an exact date range for more control...
|
|
18
|
+
{
|
|
19
|
+
label: "First Week of June 2022",
|
|
20
|
+
value: ["06/01/2022", "06/07/2022"],
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
}}
|
|
24
|
+
label="Date Range"
|
|
25
|
+
marginBottom="sm"
|
|
26
|
+
onSelect={(selectedItem) => console.log(selectedItem)}
|
|
27
|
+
variant="quickpick"
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
<Dropdown
|
|
31
|
+
customQuickPickDates={{
|
|
32
|
+
dates: [
|
|
33
|
+
{
|
|
34
|
+
label: "Last 15 months",
|
|
35
|
+
value: {
|
|
36
|
+
timePeriod: "months",
|
|
37
|
+
amount: 15,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
label: "First Week of June 2022",
|
|
42
|
+
value: ["06/01/2022", "06/07/2022"],
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
override: false,
|
|
46
|
+
}}
|
|
47
|
+
label="Date Range - Append to Defaults"
|
|
48
|
+
onSelect={(selectedItem) => console.log(selectedItem)}
|
|
49
|
+
variant="quickpick"
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
</div>
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
export default DropdownQuickpickCustom
|
|
56
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
|
|
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"]`)
|
|
5
|
+
- An object with `timePeriod` and `amount` properties for dynamic date calculations:
|
|
6
|
+
- The `timePeriod` property accepts `"days"`, `"weeks"`, `"months"`, `"quarters"`, or `"years"`, representing past time periods calculated from today.
|
|
7
|
+
- The `amount` property accepts any number.
|
|
8
|
+
|
|
9
|
+
**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,64 @@
|
|
|
1
|
+
<%= pb_rails("dropdown", props: {
|
|
2
|
+
custom_quick_pick_dates: {
|
|
3
|
+
dates: [
|
|
4
|
+
# Allow Playbook to handle the logic...
|
|
5
|
+
{
|
|
6
|
+
label: "Last 15 months",
|
|
7
|
+
value: {
|
|
8
|
+
time_period: "months",
|
|
9
|
+
amount: 15
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
# Or, be explicit with an exact date range for more control...
|
|
13
|
+
{
|
|
14
|
+
label: "First Week of June 2022",
|
|
15
|
+
value: ["06/01/2022", "06/07/2022"]
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
id: "date-range-quickpick-custom",
|
|
20
|
+
label: "Date Range",
|
|
21
|
+
margin_bottom: "sm",
|
|
22
|
+
variant: "quickpick"
|
|
23
|
+
}) %>
|
|
24
|
+
|
|
25
|
+
<%= pb_rails("dropdown", props: {
|
|
26
|
+
custom_quick_pick_dates: {
|
|
27
|
+
override: false,
|
|
28
|
+
dates: [
|
|
29
|
+
{
|
|
30
|
+
label: "Last 15 months",
|
|
31
|
+
value: {
|
|
32
|
+
time_period: "months",
|
|
33
|
+
amount: 15
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
label: "First Week of June 2022",
|
|
38
|
+
value: ["06/01/2022", "06/07/2022"]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
id: "date-range-quickpick-custom-append-to-defaults",
|
|
43
|
+
label: "Date Range - Append to Defaults",
|
|
44
|
+
variant: "quickpick"
|
|
45
|
+
}) %>
|
|
46
|
+
|
|
47
|
+
<script>
|
|
48
|
+
const dropdown1 = document.getElementById("date-range-quickpick-custom");
|
|
49
|
+
if (dropdown1) {
|
|
50
|
+
dropdown1.addEventListener("pb:dropdown:selected", (e) => {
|
|
51
|
+
const option = e.detail;
|
|
52
|
+
console.log("Selected option:", option);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const dropdown2 = document.getElementById("date-range-quickpick-custom-append-to-defaults");
|
|
57
|
+
if (dropdown2) {
|
|
58
|
+
dropdown2.addEventListener("pb:dropdown:selected", (e) => {
|
|
59
|
+
const option = e.detail;
|
|
60
|
+
console.log("Selected option:", option);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
|
|
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"]`)
|
|
5
|
+
- An object with `time_period` and `amount` properties for dynamic date calculations:
|
|
6
|
+
- The `time_period` property accepts `"days"`, `"weeks"`, `"months"`, `"quarters"`, or `"years"`, representing past time periods calculated from today.
|
|
7
|
+
- The `amount` property accepts any number.
|
|
8
|
+
|
|
9
|
+
**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,19 @@
|
|
|
1
|
+
|
|
2
|
+
<%= pb_rails("dropdown", props: {
|
|
3
|
+
id: "date-range-with-default",
|
|
4
|
+
label: "Date Range",
|
|
5
|
+
variant: "quickpick",
|
|
6
|
+
default_value: "This Year"
|
|
7
|
+
}) %>
|
|
8
|
+
|
|
9
|
+
<script>
|
|
10
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
11
|
+
const dropdown = document.getElementById("date-range-with-default");
|
|
12
|
+
if (dropdown) {
|
|
13
|
+
dropdown.addEventListener("pb:dropdown:selected", (e) => {
|
|
14
|
+
const option = e.detail;
|
|
15
|
+
console.log("Selected option:", option);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
</script>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<%= pb_rails("dropdown", props: {id: "date-range-quickpick-1", label: "Date Range", variant: "quickpick"}) %>
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
<script>
|
|
5
|
+
const dropdown = document.getElementById("date-range-quickpick-1");
|
|
6
|
+
if (dropdown) {
|
|
7
|
+
dropdown.addEventListener("pb:dropdown:selected", (e) => {
|
|
8
|
+
const option = e.detail;
|
|
9
|
+
console.log("Selected option:", option);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
</script>
|