playbook_ui 15.4.0 → 15.5.0.pre.alpha.draggablefix12568
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/pb_advanced_table/docs/_advanced_table_column_styling.jsx +2 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_column_headers.jsx +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.jsx +3 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_infinite_scroll.jsx +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_inline_editing.jsx +3 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling.jsx +2 -1
- data/app/pb_kits/playbook/pb_copy_button/_copy_button.tsx +21 -8
- data/app/pb_kits/playbook/pb_copy_button/copy_button.html.erb +6 -2
- data/app/pb_kits/playbook/pb_copy_button/copy_button.rb +3 -0
- data/app/pb_kits/playbook/pb_copy_button/copy_button.test.jsx +24 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_button_variant.html.erb +9 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_button_variant.jsx +24 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_button_variant_rails.md +1 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_button_variant_react.md +1 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_default.html.erb +2 -2
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_default.jsx +1 -2
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_from.html.erb +2 -2
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_from.jsx +2 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_abbreviated.md +1 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_matching_decimals_rails.md +1 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_matching_decimals_react.md +1 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_negative.html.erb +10 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_negative.jsx +10 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_negative.md +1 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_no_symbol_rails.md +1 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_no_symbol_react.md +1 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_variants.html.erb +7 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_variants.jsx +7 -0
- data/app/pb_kits/playbook/pb_currency/docs/_description.md +2 -2
- data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +25 -11
- data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +44 -3
- data/app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.tsx +20 -13
- data/app/pb_kits/playbook/pb_date_range_inline/date_range_inline.rb +6 -4
- data/app/pb_kits/playbook/pb_date_range_inline/date_range_inline.test.js +17 -0
- data/app/pb_kits/playbook/pb_date_range_inline/docs/_date_range_inline_show_current_year.html.erb +4 -0
- data/app/pb_kits/playbook/pb_date_range_inline/docs/_date_range_inline_show_current_year.jsx +43 -0
- data/app/pb_kits/playbook/pb_date_range_inline/docs/_date_range_inline_show_current_year.md +1 -0
- data/app/pb_kits/playbook/pb_date_range_inline/docs/_description.md +1 -1
- data/app/pb_kits/playbook/pb_date_range_inline/docs/example.yml +3 -2
- data/app/pb_kits/playbook/pb_date_range_inline/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_date_stacked/_date_stacked.tsx +6 -4
- data/app/pb_kits/playbook/pb_date_stacked/date_stacked.html.erb +2 -3
- data/app/pb_kits/playbook/pb_date_stacked/date_stacked.rb +11 -5
- data/app/pb_kits/playbook/pb_date_stacked/date_stacked.test.js +26 -9
- data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_current_year.html.erb +12 -0
- data/app/pb_kits/playbook/pb_date_stacked/docs/{_date_stacked_not_current_year.jsx → _date_stacked_current_year.jsx} +6 -5
- data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_current_year.md +1 -0
- data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_default.html.erb +1 -1
- data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_date_stacked/docs/_description.md +1 -1
- data/app/pb_kits/playbook/pb_date_stacked/docs/example.yml +2 -2
- data/app/pb_kits/playbook/pb_date_stacked/docs/index.js +1 -1
- data/app/pb_kits/playbook/pb_date_time/_date_time.tsx +3 -0
- data/app/pb_kits/playbook/pb_date_time/date_time.html.erb +1 -0
- data/app/pb_kits/playbook/pb_date_time/date_time.rb +1 -0
- data/app/pb_kits/playbook/pb_date_time/docs/_date_time_show_current_year.html.erb +4 -0
- data/app/pb_kits/playbook/pb_date_time/docs/_date_time_show_current_year.jsx +14 -0
- data/app/pb_kits/playbook/pb_date_time/docs/_date_time_show_current_year_rails.md +1 -0
- data/app/pb_kits/playbook/pb_date_time/docs/_date_time_show_current_year_react.md +1 -0
- data/app/pb_kits/playbook/pb_date_time/docs/example.yml +3 -1
- data/app/pb_kits/playbook/pb_date_time/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_date_time_stacked/_date_time_stacked.tsx +3 -0
- data/app/pb_kits/playbook/pb_date_time_stacked/date_time_stacked.html.erb +2 -2
- data/app/pb_kits/playbook/pb_date_time_stacked/date_time_stacked.rb +2 -0
- data/app/pb_kits/playbook/pb_date_time_stacked/date_time_stacked.test.js +33 -0
- data/app/pb_kits/playbook/pb_date_time_stacked/docs/_date_time_stacked_show_current_year.html.erb +4 -0
- data/app/pb_kits/playbook/pb_date_time_stacked/docs/_date_time_stacked_show_current_year.jsx +22 -0
- data/app/pb_kits/playbook/pb_date_time_stacked/docs/_date_time_stacked_show_current_year.md +1 -0
- data/app/pb_kits/playbook/pb_date_time_stacked/docs/example.yml +3 -1
- data/app/pb_kits/playbook/pb_date_time_stacked/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_compound_components.html.erb +2 -2
- data/app/pb_kits/playbook/pb_draggable/context/index.tsx +122 -4
- data/app/pb_kits/playbook/pb_draggable/context/types.ts +6 -3
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_dropzone.jsx +179 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_dropzone.md +20 -0
- data/app/pb_kits/playbook/pb_draggable/docs/example.yml +3 -2
- data/app/pb_kits/playbook/pb_draggable/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_draggable/draggable.test.jsx +77 -1
- data/app/pb_kits/playbook/pb_dropdown/index.js +32 -14
- data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_alignment.jsx +2 -1
- data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_default.jsx +2 -1
- data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_orientation.jsx +2 -1
- data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_size.jsx +2 -1
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.tsx +31 -9
- data/app/pb_kits/playbook/pb_flex/_flex_item.tsx +12 -5
- data/app/pb_kits/playbook/pb_flex/docs/_flex_item_example.jsx +1 -0
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.jsx +4 -1
- data/app/pb_kits/playbook/pb_loading_inline/docs/_loading_inline_variant.jsx +1 -1
- data/app/pb_kits/playbook/pb_nav/_item.tsx +18 -4
- data/app/pb_kits/playbook/pb_nav/_nav.scss +30 -5
- data/app/pb_kits/playbook/pb_nav/_nav_item.test.js +192 -0
- data/app/pb_kits/playbook/pb_nav/_vertical_nav.scss +1 -1
- data/app/pb_kits/playbook/pb_nav/docs/_horizontal_nav_disabled.html.erb +21 -0
- data/app/pb_kits/playbook/pb_nav/docs/_horizontal_nav_disabled.jsx +113 -0
- data/app/pb_kits/playbook/pb_nav/docs/_horizontal_nav_disabled.md +1 -0
- data/app/pb_kits/playbook/pb_nav/docs/_vertical_nav_disabled.html.erb +30 -0
- data/app/pb_kits/playbook/pb_nav/docs/_vertical_nav_disabled.jsx +117 -0
- data/app/pb_kits/playbook/pb_nav/docs/_vertical_nav_disabled.md +1 -0
- data/app/pb_kits/playbook/pb_nav/docs/example.yml +4 -0
- data/app/pb_kits/playbook/pb_nav/docs/index.js +3 -1
- data/app/pb_kits/playbook/pb_nav/item.html.erb +6 -4
- data/app/pb_kits/playbook/pb_nav/item.rb +11 -2
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_description.md +3 -1
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_colors.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_default.md +1 -0
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_height.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_horizontal.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_legend.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_legend_non_clickable.jsx +1 -2
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_legend_position.html.erb +1 -1
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_legend_position.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_legend_position.md +11 -0
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_negative_numbers.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_secondary_y_axis.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_spline.jsx +1 -2
- data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_pb_bar_graph_stacked.jsx +1 -2
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_description.md +3 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_block_content.jsx +2 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_color_overrides.jsx +2 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_custom_tooltip.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_custom_tooltip.md +2 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_data_legend_position.jsx +2 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_data_with_labels.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_data_with_legend.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_default.md +1 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_inner_sizes.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_live_data.jsx +2 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_rounded.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_with_title.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_description.md +3 -1
- data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_pb_gauge_chart_color.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_pb_gauge_chart_color.md +2 -2
- data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_pb_gauge_chart_complex.jsx +2 -1
- data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_pb_gauge_chart_default.md +1 -0
- data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_pb_gauge_chart_full_circle.jsx +2 -1
- data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_pb_gauge_chart_height.jsx +2 -1
- data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_pb_gauge_chart_min_max.jsx +2 -1
- data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_pb_gauge_chart_units.jsx +2 -1
- data/app/pb_kits/playbook/pb_pb_line_graph/docs/_description.md +3 -1
- data/app/pb_kits/playbook/pb_pb_line_graph/docs/_pb_line_graph_colors.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_line_graph/docs/_pb_line_graph_default.md +1 -0
- data/app/pb_kits/playbook/pb_pb_line_graph/docs/_pb_line_graph_legend_position.html.erb +1 -1
- data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.jsx +4 -1
- data/app/pb_kits/playbook/pb_progress_step/_progress_step.scss +384 -262
- data/app/pb_kits/playbook/pb_progress_step/docs/_description.md +1 -5
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_color.html.erb +14 -0
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_color.jsx +29 -0
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_color.md +3 -0
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_custom_icon.jsx +31 -0
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_custom_icon.md +1 -0
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_default.html.erb +4 -1
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_default.jsx +14 -3
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_default.md +3 -0
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_tracker.md +3 -0
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_vertical.html.erb +1 -7
- data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_vertical.md +1 -0
- data/app/pb_kits/playbook/pb_progress_step/docs/example.yml +3 -0
- data/app/pb_kits/playbook/pb_progress_step/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_progress_step/progress_step.test.js +41 -0
- data/app/pb_kits/playbook/pb_radio/docs/_radio_react_hook.jsx +3 -1
- data/app/pb_kits/playbook/pb_select/docs/_select_react_hook.jsx +3 -1
- data/app/pb_kits/playbook/pb_table/_table.tsx +28 -26
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_sizing.jsx +4 -1
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +4 -0
- data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +1 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_react_hook.jsx +2 -1
- data/app/pb_kits/playbook/pb_user/docs/_user_font_options.jsx +1 -1
- data/app/pb_kits/playbook/utilities/_truncate.scss +2 -0
- data/app/pb_kits/playbook/utilities/globalProps.ts +26 -8
- data/app/pb_kits/playbook/utilities/test/globalProps/alignContent.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/alignItems.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/alignSelf.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/display.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/flex.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/flexDirection.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/flexGrow.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/flexShrink.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/flexWrap.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/justifyContent.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/justifySelf.test.js +18 -0
- data/app/pb_kits/playbook/utilities/test/globalProps/order.test.js +18 -0
- data/dist/chunks/_typeahead-6571n2UL.js +6 -0
- data/dist/chunks/lib-CgpqUb6l.js +29 -0
- data/dist/chunks/vendor.js +37 -1
- 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/version.rb +2 -2
- metadata +48 -11
- data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_not_current_year.html.erb +0 -5
- data/dist/chunks/_line_graph-r__oOO2H.js +0 -1
- data/dist/chunks/_typeahead-B7c52zVj.js +0 -6
- data/dist/chunks/_weekday_stacked-DgiIj2w3.js +0 -37
- data/dist/chunks/componentRegistry-DzmmLR2x.js +0 -1
- data/dist/chunks/lib-CRUXizZe.js +0 -29
- data/dist/chunks/pb_form_validation-CywJN0ej.js +0 -1
- data/dist/playbook-doc.js +0 -19
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<%= pb_rails("button", props: { text: "Open Complex Dialog", data:{"open-dialog": "dialog-complex"} }) %>
|
|
2
2
|
|
|
3
3
|
<%= pb_rails("dialog", props: { id:"dialog-complex", size: "lg", full_height: true }) do %>
|
|
4
|
-
|
|
4
|
+
<%= pb_form_with(scope: :example, method: :get, url: "", options: { remote: true }) do |form| %>
|
|
5
5
|
<%= pb_rails("dialog/dialog_header", props: { id: "dialog-complex" } ) do %>
|
|
6
6
|
<%= pb_rails("body", props: { text: "What do you need us to take care of?" }) %>
|
|
7
7
|
<% end %>
|
|
@@ -13,5 +13,5 @@
|
|
|
13
13
|
|
|
14
14
|
<% end %>
|
|
15
15
|
<%= pb_rails("dialog/dialog_footer", props: {cancel_button: "Back", confirm_button: "Send my Issue", confirm_button_id:"confirm-complex", id: "dialog-complex"}) %>
|
|
16
|
-
|
|
16
|
+
<% end %>
|
|
17
17
|
<% end %>
|
|
@@ -39,6 +39,56 @@ const reducer = (state: InitialStateType, action: ActionType) => {
|
|
|
39
39
|
|
|
40
40
|
return { ...state, items: newItems };
|
|
41
41
|
}
|
|
42
|
+
case 'REORDER_ITEMS_CROSS_CONTAINER': {
|
|
43
|
+
const { dragId, targetId, newContainer } = action.payload;
|
|
44
|
+
const newItems = [...state.items];
|
|
45
|
+
const draggedItem = newItems.find(item => item.id === dragId);
|
|
46
|
+
const draggedIndex = newItems.indexOf(draggedItem);
|
|
47
|
+
const targetIndex = newItems.findIndex(item => item.id === targetId);
|
|
48
|
+
|
|
49
|
+
// Update container temporarily so dropzone preview works correctly
|
|
50
|
+
const updatedItem = { ...draggedItem, container: newContainer };
|
|
51
|
+
|
|
52
|
+
newItems.splice(draggedIndex, 1);
|
|
53
|
+
newItems.splice(targetIndex, 0, updatedItem);
|
|
54
|
+
|
|
55
|
+
return { ...state, items: newItems };
|
|
56
|
+
}
|
|
57
|
+
case 'MOVE_TO_CONTAINER_END': {
|
|
58
|
+
const { dragId, newContainer } = action.payload;
|
|
59
|
+
const newItems = [...state.items];
|
|
60
|
+
const draggedItem = newItems.find(item => item.id === dragId);
|
|
61
|
+
const draggedIndex = newItems.indexOf(draggedItem);
|
|
62
|
+
|
|
63
|
+
// Update container temporarily so dropzone preview works correctly
|
|
64
|
+
const updatedItem = { ...draggedItem, container: newContainer };
|
|
65
|
+
|
|
66
|
+
// Remove from current position
|
|
67
|
+
newItems.splice(draggedIndex, 1);
|
|
68
|
+
|
|
69
|
+
// Find the last item in the target container and insert after it
|
|
70
|
+
const lastIndexInContainer = newItems.map(item => item.container).lastIndexOf(newContainer);
|
|
71
|
+
if (lastIndexInContainer === -1) {
|
|
72
|
+
// Container is empty, add to end
|
|
73
|
+
newItems.push(updatedItem);
|
|
74
|
+
} else {
|
|
75
|
+
// Insert after last item in container
|
|
76
|
+
newItems.splice(lastIndexInContainer + 1, 0, updatedItem);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { ...state, items: newItems };
|
|
80
|
+
}
|
|
81
|
+
case 'RESET_DRAG_CONTAINER': {
|
|
82
|
+
const { itemId, originalContainer } = action.payload;
|
|
83
|
+
return {
|
|
84
|
+
...state,
|
|
85
|
+
items: state.items.map(item =>
|
|
86
|
+
item.id === itemId
|
|
87
|
+
? { ...item, container: originalContainer }
|
|
88
|
+
: item
|
|
89
|
+
)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
42
92
|
default:
|
|
43
93
|
return state;
|
|
44
94
|
}
|
|
@@ -103,17 +153,47 @@ export const DraggableProvider = ({
|
|
|
103
153
|
if (state.dragData.originId !== providerId) return; // Ignore drag events from other providers
|
|
104
154
|
|
|
105
155
|
if (state.dragData.id !== id) {
|
|
106
|
-
|
|
156
|
+
// Check if this is a cross-container drag
|
|
157
|
+
const isCrossContainer = state.dragData.initialGroup !== container;
|
|
158
|
+
|
|
159
|
+
if (isCrossContainer) {
|
|
160
|
+
// Use cross-container reorder to update container temporarily for dropzone preview
|
|
161
|
+
dispatch({ type: 'REORDER_ITEMS_CROSS_CONTAINER', payload: { dragId: state.dragData.id, targetId: id, newContainer: container } });
|
|
162
|
+
} else {
|
|
163
|
+
// Same container: use normal reorder no need to be fancy nancy
|
|
164
|
+
dispatch({ type: 'REORDER_ITEMS', payload: { dragId: state.dragData.id, targetId: id } });
|
|
165
|
+
}
|
|
107
166
|
dispatch({ type: 'SET_DRAG_DATA', payload: { id: state.dragData.id, initialGroup: container, originId: providerId } });
|
|
108
167
|
}
|
|
109
168
|
if (onDragEnter) onDragEnter(id, container);
|
|
110
169
|
};
|
|
111
170
|
|
|
112
171
|
const handleDragEnd = () => {
|
|
172
|
+
const draggedItemId = state.dragData.id;
|
|
173
|
+
const originalContainer = state.dragData.initialGroup;
|
|
174
|
+
|
|
175
|
+
if (!draggedItemId) {
|
|
176
|
+
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
177
|
+
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
178
|
+
dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const draggedItem = state.items.find(item => item.id === draggedItemId);
|
|
183
|
+
const finalContainer = draggedItem ? draggedItem.container : originalContainer;
|
|
184
|
+
|
|
185
|
+
// Find items above and below in the same container
|
|
186
|
+
const itemsInContainer = state.items.filter(item => item.container === finalContainer);
|
|
187
|
+
const indexInContainer = itemsInContainer.findIndex(item => item.id === draggedItemId);
|
|
188
|
+
const itemAbove = indexInContainer > 0 ? itemsInContainer[indexInContainer - 1] : null;
|
|
189
|
+
const itemBelow = indexInContainer < itemsInContainer.length - 1 ? itemsInContainer[indexInContainer + 1] : null;
|
|
190
|
+
|
|
113
191
|
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
114
192
|
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
115
193
|
dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
|
|
116
|
-
|
|
194
|
+
|
|
195
|
+
// Pass enhanced info to onDragEnd callback to give dev more context
|
|
196
|
+
if (onDragEnd) onDragEnd(draggedItemId, finalContainer, originalContainer, itemAbove, itemBelow);
|
|
117
197
|
};
|
|
118
198
|
|
|
119
199
|
const changeCategory = (itemId: string, container: string) => {
|
|
@@ -123,10 +203,37 @@ export const DraggableProvider = ({
|
|
|
123
203
|
const handleDrop = (container: string) => {
|
|
124
204
|
if (state.dragData.originId !== providerId) return; // Ignore drop events from other providers
|
|
125
205
|
|
|
206
|
+
const draggedItemId = state.dragData.id;
|
|
207
|
+
const originalContainer = state.dragData.initialGroup;
|
|
208
|
+
|
|
209
|
+
if (!draggedItemId) return; // Guard against missing drag data when dropping too quickly
|
|
210
|
+
|
|
211
|
+
const draggedItem = state.items.find(item => item.id === draggedItemId);
|
|
212
|
+
|
|
213
|
+
if (!draggedItem) {
|
|
214
|
+
// Item not found in state - clear drag state and exit
|
|
215
|
+
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
216
|
+
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
217
|
+
dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Find items above and below in the same container (before changeCategory updates it)
|
|
222
|
+
const itemsInContainer = state.items.filter(item => item.container === container);
|
|
223
|
+
const indexInContainer = itemsInContainer.findIndex(item => item.id === draggedItemId);
|
|
224
|
+
const itemAbove = indexInContainer > 0 ? itemsInContainer[indexInContainer - 1] : null;
|
|
225
|
+
const itemBelow = indexInContainer < itemsInContainer.length - 1 ? itemsInContainer[indexInContainer + 1] : null;
|
|
226
|
+
|
|
126
227
|
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
127
228
|
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
128
|
-
changeCategory
|
|
129
|
-
|
|
229
|
+
// changeCategory will ensure the container is set correctly on drop for cross container and same container drops
|
|
230
|
+
changeCategory(draggedItemId, container);
|
|
231
|
+
|
|
232
|
+
// Pass enhanced info to onDrop callback so devs have more context
|
|
233
|
+
if (onDrop) {
|
|
234
|
+
const updatedItem = { ...draggedItem, container };
|
|
235
|
+
onDrop(draggedItemId, container, originalContainer, updatedItem, itemAbove, itemBelow);
|
|
236
|
+
}
|
|
130
237
|
};
|
|
131
238
|
|
|
132
239
|
const handleDragOver = (e: Event, container: string) => {
|
|
@@ -134,6 +241,17 @@ export const DraggableProvider = ({
|
|
|
134
241
|
|
|
135
242
|
e.preventDefault();
|
|
136
243
|
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: container });
|
|
244
|
+
|
|
245
|
+
// Check if we're dragging over a different container than where the item currently is
|
|
246
|
+
if (!state.dragData.id) return; // Guard against missing drag ID when dragging too quickly
|
|
247
|
+
|
|
248
|
+
const draggedItem = state.items.find(item => item.id === state.dragData.id);
|
|
249
|
+
if (draggedItem && draggedItem.container !== container) {
|
|
250
|
+
// This handles the case when dragging to empty space at bottom of container OR in empty container
|
|
251
|
+
dispatch({ type: 'MOVE_TO_CONTAINER_END', payload: { dragId: state.dragData.id, newContainer: container } });
|
|
252
|
+
dispatch({ type: 'SET_DRAG_DATA', payload: { id: state.dragData.id, initialGroup: container, originId: providerId } });
|
|
253
|
+
}
|
|
254
|
+
|
|
137
255
|
if (onDragOver) onDragOver(e, container);
|
|
138
256
|
};
|
|
139
257
|
|
|
@@ -19,7 +19,10 @@ export type ActionType =
|
|
|
19
19
|
| { type: 'SET_IS_DRAGGING'; payload: string }
|
|
20
20
|
| { type: 'SET_ACTIVE_CONTAINER'; payload: string }
|
|
21
21
|
| { type: 'CHANGE_CATEGORY'; payload: { itemId: string; container: string } }
|
|
22
|
-
| { type: 'REORDER_ITEMS'; payload: { dragId: string; targetId: string } }
|
|
22
|
+
| { type: 'REORDER_ITEMS'; payload: { dragId: string; targetId: string } }
|
|
23
|
+
| { type: 'REORDER_ITEMS_CROSS_CONTAINER'; payload: { dragId: string; targetId: string; newContainer: string } }
|
|
24
|
+
| { type: 'MOVE_TO_CONTAINER_END'; payload: { dragId: string; newContainer: string } }
|
|
25
|
+
| { type: 'RESET_DRAG_CONTAINER'; payload: { itemId: string; originalContainer: string } };
|
|
23
26
|
|
|
24
27
|
export interface DropZoneConfig {
|
|
25
28
|
type?: 'ghost' | 'outline' | 'shadow' | 'line';
|
|
@@ -33,8 +36,8 @@ export type ActionType =
|
|
|
33
36
|
onReorder: (items: ItemType[]) => void;
|
|
34
37
|
onDragStart?: (id: string, container: string) => void;
|
|
35
38
|
onDragEnter?: (id: string, container: string) => void;
|
|
36
|
-
onDragEnd?: () => void;
|
|
37
|
-
onDrop?: (
|
|
39
|
+
onDragEnd?: (draggedItemId: string, finalContainer: string, originalContainer: string, itemAbove: ItemType | null, itemBelow: ItemType | null) => void;
|
|
40
|
+
onDrop?: (draggedItemId: string, droppedContainer: string, originalContainer: string, item: ItemType, itemAbove: ItemType | null, itemBelow: ItemType | null) => void;
|
|
38
41
|
onDragOver?: (e: Event, container: string) => void;
|
|
39
42
|
dropZone?: DropZoneConfig | string; // Can accept string for backward compatibility
|
|
40
43
|
providerId?: string;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
import Flex from '../../pb_flex/_flex'
|
|
4
|
+
import Draggable from '../../pb_draggable/_draggable'
|
|
5
|
+
import { DraggableProvider } from '../../pb_draggable/context'
|
|
6
|
+
import Badge from '../../pb_badge/_badge'
|
|
7
|
+
import Title from '../../pb_title/_title'
|
|
8
|
+
import Caption from '../../pb_caption/_caption'
|
|
9
|
+
import Card from '../../pb_card/_card'
|
|
10
|
+
import FlexItem from '../../pb_flex/_flex_item'
|
|
11
|
+
import Avatar from '../../pb_avatar/_avatar'
|
|
12
|
+
import Body from '../../pb_body/_body'
|
|
13
|
+
|
|
14
|
+
// Initial groups to drag between
|
|
15
|
+
const containers = ["To Do", "In Progress", "Done"];
|
|
16
|
+
|
|
17
|
+
// Initial items to be dragged
|
|
18
|
+
const data = [
|
|
19
|
+
{
|
|
20
|
+
id: "11",
|
|
21
|
+
container: "To Do",
|
|
22
|
+
title: "Task 1",
|
|
23
|
+
description: "Bug fixes",
|
|
24
|
+
assignee_name: "Terry Miles",
|
|
25
|
+
assignee_img: "https://randomuser.me/api/portraits/men/44.jpg",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "12",
|
|
29
|
+
container: "To Do",
|
|
30
|
+
title: "Task 2",
|
|
31
|
+
description: "Documentation",
|
|
32
|
+
assignee_name: "Sophia Miles",
|
|
33
|
+
assignee_img: "https://randomuser.me/api/portraits/women/8.jpg",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "13",
|
|
37
|
+
container: "In Progress",
|
|
38
|
+
title: "Task 3",
|
|
39
|
+
description: "Add a variant",
|
|
40
|
+
assignee_name: "Alice Jones",
|
|
41
|
+
assignee_img: "https://randomuser.me/api/portraits/women/10.jpg",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "14",
|
|
45
|
+
container: "To Do",
|
|
46
|
+
title: "Task 4",
|
|
47
|
+
description: "Add jest tests",
|
|
48
|
+
assignee_name: "Mike James",
|
|
49
|
+
assignee_img: "https://randomuser.me/api/portraits/men/8.jpg",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "15",
|
|
53
|
+
container: "Done",
|
|
54
|
+
title: "Task 5",
|
|
55
|
+
description: "Alpha testing",
|
|
56
|
+
assignee_name: "James Guy",
|
|
57
|
+
assignee_img: "https://randomuser.me/api/portraits/men/18.jpg",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "16",
|
|
61
|
+
container: "In Progress",
|
|
62
|
+
title: "Task 6",
|
|
63
|
+
description: "Release",
|
|
64
|
+
assignee_name: "Sally Jones",
|
|
65
|
+
assignee_img: "https://randomuser.me/api/portraits/women/28.jpg",
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
const DraggableMultipleContainersDropzone = (props) => {
|
|
70
|
+
const [initialState, setInitialState] = useState(data);
|
|
71
|
+
|
|
72
|
+
const badgeProperties = (container) => {
|
|
73
|
+
switch (container) {
|
|
74
|
+
case "To Do":
|
|
75
|
+
return { text: "queue", color: "warning" };
|
|
76
|
+
case "In Progress":
|
|
77
|
+
return { text: "progress", color: "primary" };
|
|
78
|
+
default:
|
|
79
|
+
return { text: "done", color: "success" };
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<DraggableProvider
|
|
85
|
+
dropZone={{type: "outline"}}
|
|
86
|
+
initialItems={data}
|
|
87
|
+
onDragEnd={(draggedItemId, finalContainer, originalContainer, itemAbove, itemBelow) => {
|
|
88
|
+
console.log(`Dragged Item ID: ${draggedItemId}`);
|
|
89
|
+
console.log(`Final Container: ${finalContainer}`);
|
|
90
|
+
console.log(`Original Container: ${originalContainer}`);
|
|
91
|
+
console.log('Item Above:', itemAbove);
|
|
92
|
+
console.log('Item Below:', itemBelow);
|
|
93
|
+
}}
|
|
94
|
+
onDrop={(draggedItemId, droppedContainer, originalContainer, item, itemAbove, itemBelow) => {
|
|
95
|
+
console.log(`Dragged Item ID: ${draggedItemId}`);
|
|
96
|
+
console.log(`Dropped Container: ${droppedContainer}`);
|
|
97
|
+
console.log(`Original Container: ${originalContainer}`);
|
|
98
|
+
console.log('Dropped Item:', item);
|
|
99
|
+
console.log('Item Above:', itemAbove);
|
|
100
|
+
console.log('Item Below:', itemBelow);
|
|
101
|
+
}}
|
|
102
|
+
onReorder={(items) => setInitialState(items)}
|
|
103
|
+
>
|
|
104
|
+
<Flex
|
|
105
|
+
justifyContent="center"
|
|
106
|
+
{...props}
|
|
107
|
+
>
|
|
108
|
+
{containers?.map((container) => (
|
|
109
|
+
<Draggable.Container
|
|
110
|
+
container={container}
|
|
111
|
+
htmlOptions={{style:{ width: "200px", height: "70vh"}}}
|
|
112
|
+
key={container}
|
|
113
|
+
padding="sm"
|
|
114
|
+
>
|
|
115
|
+
<Caption textAlign="center">{container}</Caption>
|
|
116
|
+
<Flex
|
|
117
|
+
alignItems="stretch"
|
|
118
|
+
gap="sm"
|
|
119
|
+
orientation="column"
|
|
120
|
+
>
|
|
121
|
+
{initialState
|
|
122
|
+
.filter((item) => item.container === container)
|
|
123
|
+
.map(
|
|
124
|
+
({
|
|
125
|
+
assignee_img,
|
|
126
|
+
assignee_name,
|
|
127
|
+
description,
|
|
128
|
+
id,
|
|
129
|
+
title,
|
|
130
|
+
}) => (
|
|
131
|
+
<Draggable.Item
|
|
132
|
+
container={container}
|
|
133
|
+
dragId={id}
|
|
134
|
+
key={id}
|
|
135
|
+
>
|
|
136
|
+
<Card
|
|
137
|
+
padding="sm"
|
|
138
|
+
{...props}
|
|
139
|
+
>
|
|
140
|
+
<Flex justify="between">
|
|
141
|
+
<FlexItem>
|
|
142
|
+
<Flex>
|
|
143
|
+
<Avatar
|
|
144
|
+
imageUrl={assignee_img}
|
|
145
|
+
name={assignee_name}
|
|
146
|
+
size="xxs"
|
|
147
|
+
/>
|
|
148
|
+
<Title paddingLeft="xs"
|
|
149
|
+
size={4}
|
|
150
|
+
text={title}
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
</Flex>
|
|
154
|
+
</FlexItem>
|
|
155
|
+
<Badge
|
|
156
|
+
marginLeft="sm"
|
|
157
|
+
rounded
|
|
158
|
+
text={badgeProperties(container).text}
|
|
159
|
+
variant={badgeProperties(container).color}
|
|
160
|
+
{...props}
|
|
161
|
+
/>
|
|
162
|
+
</Flex>
|
|
163
|
+
<Body paddingTop="xs"
|
|
164
|
+
text={description}
|
|
165
|
+
{...props}
|
|
166
|
+
/>
|
|
167
|
+
</Card>
|
|
168
|
+
</Draggable.Item>
|
|
169
|
+
)
|
|
170
|
+
)}
|
|
171
|
+
</Flex>
|
|
172
|
+
</Draggable.Container>
|
|
173
|
+
))}
|
|
174
|
+
</Flex>
|
|
175
|
+
</DraggableProvider>
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export default DraggableMultipleContainersDropzone;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The multiple container functionality also supports customized dropzone styling as shown here.
|
|
2
|
+
|
|
3
|
+
In addition to this, the `onDrop` and `onDragEnd` event listeners provide several arguments to allow developers more context from the drag event.
|
|
4
|
+
|
|
5
|
+
The `onDrop` callback is triggered when an item is successfully dropped into a container. It provides the following arguments:
|
|
6
|
+
|
|
7
|
+
- `draggedItemId` - The ID of the item that was dragged
|
|
8
|
+
- `droppedContainer` - The container where the item was dropped
|
|
9
|
+
- `originalContainer` - The container where the drag started
|
|
10
|
+
- `item` - The complete item object with all properties (including the updated container)
|
|
11
|
+
- `itemAbove` - The item directly above the dropped item in the final position (null if at the top)
|
|
12
|
+
- `itemBelow` - The item directly below the dropped item in the final position (null if at the bottom)
|
|
13
|
+
|
|
14
|
+
The `onDragEnd` callback is triggered when a drag operation ends, whether it was dropped or cancelled. It provides the following arguments:
|
|
15
|
+
|
|
16
|
+
- `draggedItemId` - The ID of the item that was dragged
|
|
17
|
+
- `finalContainer` - The container where the item ended up (could be same as original if drag was cancelled)
|
|
18
|
+
- `originalContainer` - The container where the drag started
|
|
19
|
+
- `itemAbove` - The item directly above the dragged item in the final position (null if at the top)
|
|
20
|
+
- `itemBelow` - The item directly below the dragged item in the final position (null if at the bottom)
|
|
@@ -5,11 +5,12 @@ examples:
|
|
|
5
5
|
- draggable_with_selectable_list: Draggable with SelectableList Kit
|
|
6
6
|
- draggable_with_cards: Draggable with Cards
|
|
7
7
|
- draggable_with_table: Draggable with Table
|
|
8
|
-
- draggable_multiple_containers: Dragging Across Multiple Containers
|
|
9
8
|
- draggable_drop_zones: Draggable Drop Zones
|
|
10
9
|
- draggable_drop_zones_colors: Draggable Drop Zones Colors
|
|
11
10
|
- draggable_drop_zones_line: Draggable Drop Zones Line
|
|
12
11
|
- draggable_event_listeners: Draggable Event Listeners
|
|
12
|
+
- draggable_multiple_containers: Dragging Across Multiple Containers
|
|
13
|
+
- draggable_multiple_containers_dropzone: Dragging Across Multiple Containers with Dropzones
|
|
13
14
|
|
|
14
15
|
rails:
|
|
15
16
|
- draggable_default: Default
|
|
@@ -17,8 +18,8 @@ examples:
|
|
|
17
18
|
- draggable_with_selectable_list: Draggable with SelectableList Kit
|
|
18
19
|
- draggable_with_cards: Draggable with Cards
|
|
19
20
|
- draggable_with_table: Draggable with Table
|
|
20
|
-
- draggable_multiple_containers: Dragging Across Multiple Containers
|
|
21
21
|
- draggable_drop_zones: Draggable Drop Zones
|
|
22
22
|
- draggable_drop_zones_colors: Draggable Drop Zones Colors
|
|
23
23
|
- draggable_drop_zones_line: Draggable Drop Zones Line
|
|
24
24
|
- draggable_event_listeners: Draggable Event Listeners
|
|
25
|
+
- draggable_multiple_containers: Dragging Across Multiple Containers
|
|
@@ -7,4 +7,5 @@ export { default as DraggableWithTable } from './_draggable_with_table.jsx'
|
|
|
7
7
|
export { default as DraggableDropZones } from './_draggable_drop_zones.jsx'
|
|
8
8
|
export { default as DraggableDropZonesColors } from './_draggable_drop_zones_colors.jsx'
|
|
9
9
|
export { default as DraggableDropZonesLine } from './_draggable_drop_zones_line.jsx'
|
|
10
|
-
export { default as DraggableEventListeners } from './_draggable_event_listeners.jsx'
|
|
10
|
+
export { default as DraggableEventListeners } from './_draggable_event_listeners.jsx'
|
|
11
|
+
export { default as DraggableMultipleContainersDropzone } from './_draggable_multiple_containers_dropzone.jsx'
|
|
@@ -255,4 +255,80 @@ test("line dropZone with horizontal direction applies 'line_horizontal' class to
|
|
|
255
255
|
const container = kit.querySelector(".pb_draggable_container");
|
|
256
256
|
|
|
257
257
|
expect(container).toHaveClass("line_horizontal");
|
|
258
|
-
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Cross-container drag tests
|
|
261
|
+
const multiContainerData = [
|
|
262
|
+
{ id: "1", container: "To Do", text: "Task 1" },
|
|
263
|
+
{ id: "2", container: "To Do", text: "Task 2" },
|
|
264
|
+
{ id: "3", container: "In Progress", text: "Task 3" },
|
|
265
|
+
{ id: "4", container: "Done", text: "Task 4" },
|
|
266
|
+
];
|
|
267
|
+
|
|
268
|
+
const containers = ["To Do", "In Progress", "Done"];
|
|
269
|
+
|
|
270
|
+
const DraggableMultipleContainers = () => {
|
|
271
|
+
const [initialState, setInitialState] = useState(multiContainerData);
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
<div data-testid={testId}>
|
|
275
|
+
<DraggableProvider
|
|
276
|
+
dropZone={{ type: "outline" }}
|
|
277
|
+
initialItems={multiContainerData}
|
|
278
|
+
onReorder={(items) => setInitialState(items)}
|
|
279
|
+
>
|
|
280
|
+
{containers.map((container) => (
|
|
281
|
+
<Draggable.Container
|
|
282
|
+
container={container}
|
|
283
|
+
data={{testid:`container-${container}`}}
|
|
284
|
+
key={container}
|
|
285
|
+
>
|
|
286
|
+
{initialState
|
|
287
|
+
.filter((item) => item.container === container)
|
|
288
|
+
.map(({ id, text }) => (
|
|
289
|
+
<Draggable.Item
|
|
290
|
+
container={container}
|
|
291
|
+
data-testid={`item-${id}`}
|
|
292
|
+
dragId={id}
|
|
293
|
+
key={id}
|
|
294
|
+
>
|
|
295
|
+
{text}
|
|
296
|
+
</Draggable.Item>
|
|
297
|
+
))}
|
|
298
|
+
</Draggable.Container>
|
|
299
|
+
))}
|
|
300
|
+
</DraggableProvider>
|
|
301
|
+
</div>
|
|
302
|
+
);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
test("renders multiple containers with correct items", () => {
|
|
306
|
+
render(<DraggableMultipleContainers />);
|
|
307
|
+
|
|
308
|
+
const kit = screen.getByTestId(testId);
|
|
309
|
+
expect(kit).toBeInTheDocument();
|
|
310
|
+
|
|
311
|
+
containers.forEach((container) => {
|
|
312
|
+
const containerEl = kit.querySelector(`[data-testid="container-${container}"]`);
|
|
313
|
+
expect(containerEl).toBeInTheDocument();
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// Check items are in correct containers
|
|
317
|
+
expect(screen.getByText("Task 1")).toBeInTheDocument();
|
|
318
|
+
expect(screen.getByText("Task 2")).toBeInTheDocument();
|
|
319
|
+
expect(screen.getByText("Task 3")).toBeInTheDocument();
|
|
320
|
+
expect(screen.getByText("Task 4")).toBeInTheDocument();
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test("items have correct container association", () => {
|
|
324
|
+
const { container } = render(<DraggableMultipleContainers />);
|
|
325
|
+
|
|
326
|
+
// items rendered within their respective containers
|
|
327
|
+
const todoContainer = container.querySelector('[data-testid="container-To Do"]');
|
|
328
|
+
const inProgressContainer = container.querySelector('[data-testid="container-In Progress"]');
|
|
329
|
+
const doneContainer = container.querySelector('[data-testid="container-Done"]');
|
|
330
|
+
|
|
331
|
+
expect(todoContainer.querySelectorAll('.pb_draggable_item')).toHaveLength(2);
|
|
332
|
+
expect(inProgressContainer.querySelectorAll('.pb_draggable_item')).toHaveLength(1);
|
|
333
|
+
expect(doneContainer.querySelectorAll('.pb_draggable_item')).toHaveLength(1);
|
|
334
|
+
})
|
|
@@ -33,6 +33,8 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
33
33
|
this.formPillProps = this.element.dataset.formPillProps
|
|
34
34
|
? JSON.parse(this.element.dataset.formPillProps)
|
|
35
35
|
: {};
|
|
36
|
+
const baseInput = this.element.querySelector(DROPDOWN_INPUT);
|
|
37
|
+
this.wasOriginallyRequired = baseInput && baseInput.hasAttribute("required");
|
|
36
38
|
this.setDefaultValue();
|
|
37
39
|
this.bindEventListeners();
|
|
38
40
|
this.bindSearchInput();
|
|
@@ -126,7 +128,7 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
126
128
|
.label.toString()
|
|
127
129
|
.toLowerCase();
|
|
128
130
|
|
|
129
|
-
|
|
131
|
+
// hide or show option
|
|
130
132
|
const match = label.includes(lcTerm);
|
|
131
133
|
opt.style.display = match ? "" : "none";
|
|
132
134
|
if (match) hasMatch = true
|
|
@@ -356,17 +358,6 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
356
358
|
}
|
|
357
359
|
|
|
358
360
|
clearFormValidation(input) {
|
|
359
|
-
if (input.checkValidity()) {
|
|
360
|
-
const dropdownWrapperElement = input.closest(".dropdown_wrapper");
|
|
361
|
-
dropdownWrapperElement.classList.remove("error");
|
|
362
|
-
|
|
363
|
-
const errorLabelElement = dropdownWrapperElement.querySelector(
|
|
364
|
-
".pb_body_kit_negative"
|
|
365
|
-
);
|
|
366
|
-
if (errorLabelElement) {
|
|
367
|
-
errorLabelElement.remove();
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
361
|
if (this.isMultiSelect) {
|
|
371
362
|
if (this.selectedOptions.size > 0) {
|
|
372
363
|
const dropdownWrapperElement = input.closest(".dropdown_wrapper");
|
|
@@ -377,6 +368,19 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
377
368
|
if (errorLabelElement) {
|
|
378
369
|
errorLabelElement.remove();
|
|
379
370
|
}
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (input.checkValidity()) {
|
|
376
|
+
const dropdownWrapperElement = input.closest(".dropdown_wrapper");
|
|
377
|
+
dropdownWrapperElement.classList.remove("error");
|
|
378
|
+
|
|
379
|
+
const errorLabelElement = dropdownWrapperElement.querySelector(
|
|
380
|
+
".pb_body_kit_negative"
|
|
381
|
+
);
|
|
382
|
+
if (errorLabelElement) {
|
|
383
|
+
errorLabelElement.remove();
|
|
380
384
|
}
|
|
381
385
|
}
|
|
382
386
|
}
|
|
@@ -585,7 +589,9 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
585
589
|
// for multi_select, for each selectedOption, create a hidden input
|
|
586
590
|
const name = baseInput.getAttribute("name");
|
|
587
591
|
this.selectedOptions.forEach((raw) => {
|
|
588
|
-
const
|
|
592
|
+
const optionData = JSON.parse(raw);
|
|
593
|
+
// Use id if available, otherwise fall back to value
|
|
594
|
+
const id = optionData.id || optionData.value;
|
|
589
595
|
const inp = document.createElement("input");
|
|
590
596
|
inp.type = "hidden";
|
|
591
597
|
inp.name = name;
|
|
@@ -593,7 +599,19 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
593
599
|
inp.dataset.generated = "true";
|
|
594
600
|
baseInput.insertAdjacentElement("afterend", inp);
|
|
595
601
|
});
|
|
596
|
-
|
|
602
|
+
|
|
603
|
+
// For multi-select, remove required from base input when there are selections
|
|
604
|
+
// The generated inputs handle the form submission with actual values
|
|
605
|
+
// Restore required attribute when there are no selections (if it was originally required)
|
|
606
|
+
if (this.selectedOptions.size > 0) {
|
|
607
|
+
baseInput.value = "";
|
|
608
|
+
baseInput.removeAttribute("required");
|
|
609
|
+
} else {
|
|
610
|
+
baseInput.value = "";
|
|
611
|
+
if (this.wasOriginallyRequired) {
|
|
612
|
+
baseInput.setAttribute("required", "");
|
|
613
|
+
}
|
|
614
|
+
}
|
|
597
615
|
}
|
|
598
616
|
|
|
599
617
|
handleBackspaceClear() {
|