playbook_ui 14.19.0.pre.alpha.play2125phonenumberinputcountrysearcherrorstylefix7698 → 14.19.0.pre.rc.0

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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +1 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +21 -304
  4. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +1 -5
  5. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +1 -6
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.md +6 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_no_subrows_react.jsx → _advanced_table_selectable_rows_no_subrows.jsx} +2 -2
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows_rails.md +1 -5
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_rails.md +2 -3
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +5 -6
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -3
  12. data/app/pb_kits/playbook/pb_advanced_table/index.js +11 -228
  13. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +1 -9
  14. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +3 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +2 -1
  16. data/app/pb_kits/playbook/pb_avatar/_avatar.scss +0 -4
  17. data/app/pb_kits/playbook/pb_avatar/_avatar.tsx +0 -3
  18. data/app/pb_kits/playbook/pb_avatar/avatar.html.erb +3 -3
  19. data/app/pb_kits/playbook/pb_avatar/avatar.rb +0 -2
  20. data/app/pb_kits/playbook/pb_avatar/avatar.test.js +0 -18
  21. data/app/pb_kits/playbook/pb_avatar/docs/example.yml +0 -2
  22. data/app/pb_kits/playbook/pb_avatar/docs/index.js +0 -1
  23. data/app/pb_kits/playbook/pb_card/card.html.erb +1 -1
  24. data/app/pb_kits/playbook/pb_card/card.rb +0 -12
  25. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_error.html.erb +2 -2
  26. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +1 -4
  27. data/app/pb_kits/playbook/pb_draggable/docs/index.js +1 -2
  28. data/app/pb_kits/playbook/pb_draggable/draggable.rb +1 -9
  29. data/app/pb_kits/playbook/pb_draggable/draggable_container.rb +1 -11
  30. data/app/pb_kits/playbook/pb_draggable/draggable_item.rb +1 -11
  31. data/app/pb_kits/playbook/pb_draggable/index.js +142 -141
  32. data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableItem.tsx +5 -33
  33. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +0 -5
  34. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +16 -5
  35. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_error.html.erb +2 -5
  36. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.jsx +64 -17
  37. data/app/pb_kits/playbook/pb_dropdown/docs/{_dropdown_with_autocomplete_with_subcomponents.jsx → _dropdown_with_autocomplete_and_custom_display.jsx} +25 -11
  38. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_and_custom_display.md +1 -0
  39. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_hook.jsx +79 -0
  40. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +4 -7
  41. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +2 -2
  42. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +2 -2
  43. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +0 -4
  44. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +1 -45
  45. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +0 -10
  46. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.rb +0 -3
  47. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +2 -12
  48. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +1 -3
  49. data/app/pb_kits/playbook/pb_dropdown/index.js +0 -57
  50. data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +0 -26
  51. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownContainer.tsx +2 -1
  52. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +4 -4
  53. data/app/pb_kits/playbook/pb_empty_state/_empty_state.scss +1 -8
  54. data/app/pb_kits/playbook/pb_empty_state/docs/example.yml +1 -5
  55. data/app/pb_kits/playbook/pb_filter/docs/example.yml +0 -1
  56. data/app/pb_kits/playbook/pb_form_group/_error_state_mixin.scss +18 -22
  57. data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.scss +3 -0
  58. data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.tsx +72 -0
  59. data/app/pb_kits/playbook/pb_gantt_chart/docs/_gantt_chart_default.jsx +53 -0
  60. data/app/pb_kits/playbook/pb_gantt_chart/docs/example.yml +7 -0
  61. data/app/pb_kits/playbook/pb_gantt_chart/docs/index.js +1 -0
  62. data/app/pb_kits/playbook/pb_gantt_chart/gantt_chart.test.jsx +19 -0
  63. data/app/pb_kits/playbook/pb_line_graph/docs/example.yml +0 -1
  64. data/app/pb_kits/playbook/pb_line_graph/docs/index.js +0 -1
  65. data/app/pb_kits/playbook/pb_message/_message.tsx +0 -3
  66. data/app/pb_kits/playbook/pb_message/docs/example.yml +0 -2
  67. data/app/pb_kits/playbook/pb_message/docs/index.js +0 -1
  68. data/app/pb_kits/playbook/pb_message/message.html.erb +1 -2
  69. data/app/pb_kits/playbook/pb_message/message.rb +0 -1
  70. data/app/pb_kits/playbook/pb_overlay/_overlay.scss +1 -2
  71. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.jsx +1 -1
  72. data/app/pb_kits/playbook/pb_overlay/subcomponents/_overlay_token.tsx +4 -5
  73. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +8 -21
  74. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +1 -3
  75. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +0 -2
  76. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +0 -1
  77. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +0 -3
  78. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +0 -19
  79. data/app/pb_kits/playbook/pb_popover/docs/example.yml +0 -1
  80. data/app/pb_kits/playbook/pb_popover/index.ts +1 -13
  81. data/app/pb_kits/playbook/pb_popover/popover.rb +0 -2
  82. data/app/pb_kits/playbook/pb_select/_select.scss +0 -10
  83. data/app/pb_kits/playbook/pb_select/docs/_select_error.html.erb +1 -1
  84. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_click.jsx +7 -7
  85. data/app/pb_kits/playbook/pb_table/subcomponents/_table_row.tsx +5 -5
  86. data/app/pb_kits/playbook/pb_text_input/_text_input.scss +2 -4
  87. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.html.erb +1 -1
  88. data/app/pb_kits/playbook/pb_textarea/docs/_textarea_error.html.erb +1 -5
  89. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.html.erb +1 -8
  90. data/app/pb_kits/playbook/pb_user/_user.tsx +0 -3
  91. data/app/pb_kits/playbook/pb_user/docs/example.yml +0 -2
  92. data/app/pb_kits/playbook/pb_user/docs/index.js +0 -1
  93. data/app/pb_kits/playbook/pb_user/user.html.erb +1 -2
  94. data/app/pb_kits/playbook/pb_user/user.rb +0 -1
  95. data/dist/chunks/_typeahead-BX8IifKY.js +22 -0
  96. data/dist/chunks/_weekday_stacked-DfMD7HJz.js +45 -0
  97. data/dist/chunks/{lib-DwFasxbk.js → lib-96_ZmvAo.js} +1 -1
  98. data/dist/chunks/{pb_form_validation-nnXW3T-3.js → pb_form_validation-Vv2TqXVC.js} +1 -1
  99. data/dist/chunks/vendor.js +1 -1
  100. data/dist/menu.yml +14 -6
  101. data/dist/playbook-doc.js +2 -2
  102. data/dist/playbook-rails-react-bindings.js +1 -1
  103. data/dist/playbook-rails.js +1 -1
  104. data/dist/playbook.css +1 -1
  105. data/lib/playbook/version.rb +2 -2
  106. metadata +23 -58
  107. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color.jsx +0 -80
  108. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color.md +0 -3
  109. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color_rails.html.erb +0 -58
  110. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color_rails.md +0 -3
  111. data/app/pb_kits/playbook/pb_advanced_table/flat_advanced_table.js +0 -106
  112. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_grayscale.html.erb +0 -5
  113. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_grayscale.jsx +0 -16
  114. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones.html.erb +0 -64
  115. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors.html.erb +0 -55
  116. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors_rails.md +0 -1
  117. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_line.html.erb +0 -55
  118. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_line_rails.md +0 -5
  119. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_rails.md +0 -5
  120. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_event_listeners.jsx +0 -59
  121. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_event_listeners_react.md +0 -1
  122. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.html.erb +0 -28
  123. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_with_subcomponents.html.erb +0 -58
  124. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_with_subcomponents.md +0 -1
  125. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_external_control.md +0 -1
  126. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search.jsx +0 -61
  127. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search.md +0 -2
  128. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search_rails.html.erb +0 -52
  129. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search_rails.md +0 -2
  130. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_alignment.html.erb +0 -27
  131. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_default.html.erb +0 -7
  132. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_orientation.html.erb +0 -12
  133. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_size.html.erb +0 -23
  134. data/app/pb_kits/playbook/pb_empty_state/empty_state.html.erb +0 -19
  135. data/app/pb_kits/playbook/pb_empty_state/empty_state.rb +0 -123
  136. data/app/pb_kits/playbook/pb_filter/docs/_filter_within_turbo_frames.html.erb +0 -41
  137. data/app/pb_kits/playbook/pb_filter/docs/_filter_within_turbo_frames.md +0 -1
  138. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_pb_styles.jsx +0 -52
  139. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_pb_styles.md +0 -1
  140. data/app/pb_kits/playbook/pb_line_graph/lineGraphTheme.ts +0 -110
  141. data/app/pb_kits/playbook/pb_message/docs/_message_grayscale.html.erb +0 -9
  142. data/app/pb_kits/playbook/pb_message/docs/_message_grayscale.jsx +0 -21
  143. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.html.erb +0 -10
  144. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.jsx +0 -20
  145. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.md +0 -1
  146. data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.html.erb +0 -46
  147. data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.md +0 -1
  148. data/app/pb_kits/playbook/pb_user/docs/_user_grayscale.html.erb +0 -6
  149. data/app/pb_kits/playbook/pb_user/docs/_user_grayscale.jsx +0 -16
  150. data/dist/chunks/_typeahead-BQV04mOl.js +0 -22
  151. data/dist/chunks/_weekday_stacked-CVwWr8B2.js +0 -45
  152. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_rails.html.erb → _advanced_table_selectable_rows.html.erb} +0 -0
  153. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_no_subrows_rails.html.erb → _advanced_table_selectable_rows_no_subrows.html.erb} +0 -0
  154. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows.md → _advanced_table_selectable_rows_react.md} +0 -0
  155. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_drop_zones_react.md → _draggable_drop_zones.md} +0 -0
  156. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_drop_zones_colors_react.md → _draggable_drop_zones_colors.md} +0 -0
  157. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_drop_zones_line_react.md → _draggable_drop_zones_line.md} +0 -0
  158. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_event_listeners_rails.md → _draggable_event_listeners.md} +0 -0
@@ -1,26 +1,24 @@
1
1
  import PbEnhancedElement from "../pb_enhanced_element";
2
2
 
3
- const DRAGGABLE_SELECTOR = "[data-pb-draggable]";
3
+ const DRAGGABLE_SELECTOR = "[data-pb-draggable]";
4
4
  const DRAGGABLE_CONTAINER = ".pb_draggable_container";
5
- const NEEDS_CLONE = ["shadow", "outline", "line"]; // clone only for these types
6
5
 
7
6
  export default class PbDraggable extends PbEnhancedElement {
8
- static get selector() { return DRAGGABLE_SELECTOR; }
7
+ static get selector() {
8
+ return DRAGGABLE_SELECTOR;
9
+ }
9
10
 
10
11
  connect() {
11
12
  this.state = {
12
- items: [],
13
- dragData: { id: "", initialGroup: "" },
14
- isDragging: "",
15
- activeContainer: "",
13
+ items: [],
14
+ dragData: { id: "", initialGroup: "" },
15
+ isDragging: "",
16
+ activeContainer: ""
16
17
  };
17
18
 
18
- this.draggedItem = null;
19
+ this.draggedItem = null;
19
20
  this.draggedItemId = null;
20
- this.dragGhost = null;
21
21
  this.hasMultipleContainers = false;
22
- this.dragZoneType = "";
23
- this.dragZoneColor = "";
24
22
 
25
23
  document.addEventListener("DOMContentLoaded", () => this.bindEventListeners());
26
24
  }
@@ -28,12 +26,13 @@ export default class PbDraggable extends PbEnhancedElement {
28
26
  setState(newState) {
29
27
  this.state = { ...this.state, ...newState };
30
28
  if (newState.items) {
31
- this.element.dispatchEvent(new CustomEvent("pb-draggable-reorder", {
29
+ const customEvent = new CustomEvent('pb-draggable-reorder', {
32
30
  detail: {
33
31
  reorderedItems: this.state.items,
34
- containerId: this.element.querySelector(DRAGGABLE_CONTAINER).id,
35
- },
36
- }));
32
+ containerId: this.element.querySelector(DRAGGABLE_CONTAINER).id
33
+ }
34
+ });
35
+ this.element.dispatchEvent(customEvent);
37
36
  }
38
37
  }
39
38
 
@@ -44,102 +43,71 @@ export default class PbDraggable extends PbEnhancedElement {
44
43
 
45
44
  // Needed to prevent images within draggable items from being independently draggable
46
45
  // Needed if using Image kit in draggable items
47
- this.element.querySelectorAll(".pb_draggable_item img")
48
- .forEach(img => img.setAttribute("draggable", "false"));
49
-
50
- this.element.querySelectorAll(".pb_draggable_item")
51
- .forEach(item => {
52
- item.addEventListener("dragstart", this.handleDragStart.bind(this));
53
- item.addEventListener("dragend", this.handleDragEnd.bind(this));
54
- item.addEventListener("dragenter", this.handleDragEnter.bind(this));
55
- });
46
+ this.element.querySelectorAll(".pb_draggable_item img").forEach(img => {
47
+ img.setAttribute("draggable", "false");
48
+ });
56
49
 
57
- containers.forEach(c => {
58
- c.addEventListener("dragover", this.handleDragOver.bind(this));
59
- c.addEventListener("drop", this.handleDrop.bind(this));
50
+ this.element.querySelectorAll(".pb_draggable_item").forEach(item => {
51
+ item.addEventListener("dragstart", this.handleDragStart.bind(this));
52
+ item.addEventListener("dragend", this.handleDragEnd.bind(this));
53
+ item.addEventListener("dragenter", this.handleDragEnter.bind(this));
54
+ });
55
+
56
+ containers.forEach(container => {
57
+ container.addEventListener("dragover", this.handleDragOver.bind(this));
58
+ container.addEventListener("drop", this.handleDrop.bind(this));
60
59
  });
61
60
  }
62
61
 
63
- /* ---------------- DRAG START ---------------- */
64
62
  handleDragStart(event) {
65
63
  // Needed to prevent images within draggable items from being independently draggable
66
64
  // Needed if using Image kit in draggable items
67
- if (event.target.tagName.toLowerCase() === "img") {
65
+ if (event.target.tagName.toLowerCase() === 'img') {
68
66
  event.preventDefault();
69
67
  return;
70
68
  }
71
69
 
72
- const container = event.target.closest(DRAGGABLE_CONTAINER);
73
- this.draggedItem = event.target;
70
+ const container = event.target.closest(DRAGGABLE_CONTAINER);
71
+ this.draggedItem = event.target;
74
72
  this.draggedItemId = event.target.id;
75
- this.dragZoneType = this.element.dataset.dropZoneType || "";
76
- this.dragZoneColor = this.element.dataset.dropZoneColor || "";
77
73
 
78
74
  this.setState({
79
- dragData: { id: this.draggedItemId, initialGroup: container.id },
80
- isDragging: this.draggedItemId,
75
+ dragData: { id: this.draggedItemId, initialGroup: container.id },
76
+ isDragging: this.draggedItemId
81
77
  });
82
78
 
83
- this.draggedItem.classList.add(
84
- "is_dragging",
85
- `drop_zone_${this.dragZoneType}`,
86
- `drop_zone_color_${this.dragZoneColor}`,
87
- );
88
-
79
+ event.target.classList.add("is_dragging");
89
80
  if (event.dataTransfer) {
90
- event.dataTransfer.effectAllowed = "move";
91
- event.dataTransfer.setData("text/plain", this.draggedItemId);
92
-
93
- /* ---------- custom ghost clone (shadow + outline only) ---------- */
94
- if (NEEDS_CLONE.includes(this.dragZoneType)) {
95
- const ghost = this.draggedItem.cloneNode(true);
96
- ghost.classList.remove(
97
- "is_dragging",
98
- `drop_zone_${this.dragZoneType}`,
99
- `drop_zone_color_${this.dragZoneColor}`,
100
- );
101
- const { width, height } = this.draggedItem.getBoundingClientRect();
102
- Object.assign(ghost.style, {
103
- border: "none",
104
- width: `${width}px`,
105
- height: `${height}px`,
106
- position: "absolute",
107
- top: "-9999px",
108
- left: "-9999px",
109
- boxSizing: "border-box",
110
- zIndex: "9999",
111
- });
112
- document.body.appendChild(ghost);
113
- this.dragGhost = ghost;
114
- event.dataTransfer.setDragImage(ghost, width / 2, height / 2);
115
- }
116
- /* ---------------------------------------------------------------- */
81
+ event.dataTransfer.effectAllowed = 'move';
82
+ event.dataTransfer.setData('text/plain', this.draggedItemId);
117
83
  }
118
84
 
119
- if (this.dragZoneType !== "line") {
120
- requestAnimationFrame(() => (event.target.style.opacity = "0.5"));
121
- }
85
+ setTimeout(() => {
86
+ event.target.style.opacity = '0.5';
87
+ }, 0);
122
88
  }
123
89
 
124
- /* ---------------- DRAG ENTER ---------------- */
125
90
  handleDragEnter(event) {
126
91
  if (!this.draggedItem || event.target === this.draggedItem) return;
127
- this.hasMultipleContainers
128
- ? this.handleMultiContainerDragEnter(event)
129
- : this.handleSingleContainerDragEnter(event);
92
+
93
+ if (this.hasMultipleContainers) {
94
+ this.handleMultiContainerDragEnter(event);
95
+ } else {
96
+ this.handleSingleContainerDragEnter(event);
97
+ }
130
98
  }
131
99
 
132
100
  handleSingleContainerDragEnter(event) {
133
- const targetItem = event.target.closest(".pb_draggable_item");
134
- // If we're entering a container directly or there's no target item
101
+ const targetItem = event.target.closest('.pb_draggable_item');
135
102
  if (!targetItem) return;
136
103
 
137
104
  const container = targetItem.parentNode;
138
- const items = Array.from(container.children);
139
- const fromIdx = items.indexOf(this.draggedItem);
140
- const toIdx = items.indexOf(targetItem);
105
+ const items = Array.from(container.children);
106
+
107
+ const draggedIndex = items.indexOf(this.draggedItem);
108
+ const targetIndex = items.indexOf(targetItem);
141
109
 
142
- if (fromIdx > toIdx) {
110
+ if (draggedIndex > targetIndex) {
143
111
  container.insertBefore(this.draggedItem, targetItem);
144
112
  } else {
145
113
  container.insertBefore(this.draggedItem, targetItem.nextSibling);
@@ -148,113 +116,146 @@ export default class PbDraggable extends PbEnhancedElement {
148
116
 
149
117
  handleMultiContainerDragEnter(event) {
150
118
  const targetContainer = event.target.closest(DRAGGABLE_CONTAINER);
151
- const targetItem = event.target.closest(".pb_draggable_item");
119
+ const targetItem = event.target.closest('.pb_draggable_item');
120
+
152
121
  if (!targetContainer) return;
153
122
 
123
+ // If we're entering a container directly or there's no target item
154
124
  if (!targetItem) {
155
- const last = targetContainer.querySelector(".pb_draggable_item:last-child");
156
- last
157
- ? targetContainer.insertBefore(this.draggedItem, last.nextSibling)
158
- : targetContainer.appendChild(this.draggedItem);
125
+ const lastItem = targetContainer.querySelector('.pb_draggable_item:last-child');
126
+ if (lastItem) {
127
+ targetContainer.insertBefore(this.draggedItem, lastItem.nextSibling);
128
+ } else {
129
+ targetContainer.appendChild(this.draggedItem);
130
+ }
159
131
  return;
160
132
  }
161
133
 
162
- const items = Array.from(targetContainer.children);
163
- this.setState({ items: items.map(i => ({ id: i.id, container: targetContainer.id })) });
134
+ const container = targetItem.parentNode;
135
+ const items = Array.from(container.children);
136
+
137
+ const newItems = [...items].map(item => ({
138
+ id: item.id,
139
+ container: container.id
140
+ }));
141
+
142
+ this.setState({ items: newItems });
164
143
 
165
- const midY = targetItem.getBoundingClientRect().top +
166
- targetItem.getBoundingClientRect().height / 2;
144
+ const rect = targetItem.getBoundingClientRect();
145
+ const middleY = rect.top + rect.height / 2;
167
146
 
168
- if (event.clientY < midY) {
169
- targetContainer.insertBefore(this.draggedItem, targetItem);
147
+ if (event.clientY < middleY) {
148
+ container.insertBefore(this.draggedItem, targetItem);
170
149
  } else {
171
- targetContainer.insertBefore(this.draggedItem, targetItem.nextSibling);
150
+ container.insertBefore(this.draggedItem, targetItem.nextSibling);
172
151
  }
173
152
  }
174
153
 
175
- /* ---------------- DRAG OVER ---------------- */
176
154
  handleDragOver(event) {
177
155
  event.preventDefault();
178
156
  event.stopPropagation();
179
- this.hasMultipleContainers
180
- ? this.handleMultiContainerDragOver(event)
181
- : this.handleSingleContainerDragOver(event);
157
+
158
+ if (this.hasMultipleContainers) {
159
+ this.handleMultiContainerDragOver(event);
160
+ } else {
161
+ this.handleSingleContainerDragOver(event);
162
+ }
182
163
  }
183
164
 
184
165
  handleSingleContainerDragOver(event) {
185
166
  const container = event.target.closest(DRAGGABLE_CONTAINER);
186
- if (container) container.classList.add("active_container");
167
+ if (container) {
168
+ container.classList.add("active_container");
169
+ }
187
170
  }
188
171
 
189
172
  handleMultiContainerDragOver(event) {
190
- const container = event.target.matches(DRAGGABLE_CONTAINER)
191
- ? event.target
192
- : event.target.closest(DRAGGABLE_CONTAINER);
193
- if (!container) return;
194
-
195
- this.setState({ activeContainer: container.id });
196
- container.classList.add("active_container");
197
-
198
- const last = container.querySelector(".pb_draggable_item:last-child");
199
- if (!last || event.clientY > last.getBoundingClientRect().bottom) {
200
- if (this.draggedItem && this.draggedItem.parentNode !== container) {
201
- container.appendChild(this.draggedItem);
173
+ let container;
174
+ if (event.target.matches(DRAGGABLE_CONTAINER)) {
175
+ container = event.target;
176
+ } else {
177
+ container = event.target.closest(DRAGGABLE_CONTAINER);
178
+ }
179
+
180
+ if (container) {
181
+ this.setState({ activeContainer: container.id });
182
+ container.classList.add("active_container");
183
+
184
+ // If dragging over empty container or below last item
185
+ const lastItem = container.querySelector('.pb_draggable_item:last-child');
186
+ if (!lastItem || (lastItem && event.clientY > lastItem.getBoundingClientRect().bottom)) {
187
+ if (this.draggedItem && this.draggedItem.parentNode !== container) {
188
+ container.appendChild(this.draggedItem);
189
+ }
202
190
  }
203
191
  }
204
192
  }
205
193
 
206
- /* ---------------- DROP ---------------- */
207
194
  handleDrop(event) {
208
195
  event.preventDefault();
209
196
  event.stopPropagation();
210
197
 
211
- const container = event.target.matches(DRAGGABLE_CONTAINER)
212
- ? event.target
213
- : event.target.closest(DRAGGABLE_CONTAINER);
198
+ let container;
199
+ if (event.target.matches(DRAGGABLE_CONTAINER)) {
200
+ container = event.target;
201
+ } else {
202
+ container = event.target.closest(DRAGGABLE_CONTAINER);
203
+ }
204
+
214
205
  if (!container || !this.draggedItem) return;
215
206
 
216
207
  container.classList.remove("active_container");
217
- this.draggedItem.style.opacity = "1";
208
+ this.draggedItem.style.opacity = '1';
218
209
 
219
210
  // Handle empty containers
220
- if (this.hasMultipleContainers && !container.querySelector(".pb_draggable_item")) {
211
+ if (this.hasMultipleContainers && !container.querySelector('.pb_draggable_item')) {
221
212
  container.appendChild(this.draggedItem);
222
213
  }
223
214
 
224
215
  // Updated order of items as an array of item IDs
225
- const reorderedItems = Array.from(this.element.querySelectorAll(".pb_draggable_item"))
226
- .map(i => ({ id: i.id, container: i.closest(DRAGGABLE_CONTAINER).id }));
227
-
228
- container.dataset.reorderedItems = JSON.stringify(reorderedItems);
229
- this.element.dispatchEvent(new CustomEvent("pb-draggable-reorder", {
230
- detail: { reorderedItems, containerId: container.id },
216
+ const reorderedItems = Array.from(
217
+ this.element.querySelectorAll('.pb_draggable_item')
218
+ ).map(item => ({
219
+ id: item.id,
220
+ container: item.closest(DRAGGABLE_CONTAINER).id
231
221
  }));
232
222
 
233
- this.setState({ items: reorderedItems, isDragging: "", activeContainer: "" });
234
- this.draggedItem = null;
223
+ // Store reordered items in a data attribute on the container
224
+ container.setAttribute("data-reordered-items", JSON.stringify(reorderedItems));
225
+
226
+ const customEvent = new CustomEvent('pb-draggable-reorder', {
227
+ detail: {
228
+ reorderedItems,
229
+ containerId: container.id,
230
+ }
231
+ });
232
+
233
+ this.element.dispatchEvent(customEvent);
234
+
235
+ this.setState({
236
+ items: reorderedItems,
237
+ isDragging: "",
238
+ activeContainer: ""
239
+ });
240
+
241
+ this.draggedItem = null;
235
242
  this.draggedItemId = null;
236
243
  }
237
244
 
238
- /* ---------------- DRAG END ---------------- */
239
245
  handleDragEnd(event) {
240
- event.target.classList.remove(
241
- "is_dragging",
242
- `drop_zone_${this.dragZoneType}`,
243
- `drop_zone_color_${this.dragZoneColor}`,
244
- );
245
- event.target.style.opacity = "1";
246
-
247
- if (this.dragGhost) {
248
- document.body.removeChild(this.dragGhost);
249
- this.dragGhost = null;
250
- }
251
-
252
- this.setState({ isDragging: "", activeContainer: "" });
246
+ event.target.classList.remove("is_dragging");
247
+ event.target.style.opacity = '1';
253
248
 
254
- this.element.querySelectorAll(DRAGGABLE_CONTAINER)
255
- .forEach(c => c.classList.remove("active_container"));
249
+ this.setState({
250
+ isDragging: "",
251
+ activeContainer: ""
252
+ });
256
253
 
257
- this.draggedItem = null;
254
+ this.draggedItem = null;
258
255
  this.draggedItemId = null;
256
+
257
+ this.element.querySelectorAll(DRAGGABLE_CONTAINER).forEach(container => {
258
+ container.classList.remove("active_container");
259
+ });
259
260
  }
260
261
  }
@@ -8,7 +8,6 @@ import {
8
8
  } from "../../utilities/props";
9
9
  import { globalProps } from "../../utilities/globalProps";
10
10
  import { DraggableContext } from "../context";
11
- import { noop } from '../../utilities/object'
12
11
 
13
12
  type DraggableItemProps = {
14
13
  aria?: { [key: string]: string };
@@ -18,13 +17,6 @@ type DraggableItemProps = {
18
17
  data?: { [key: string]: string };
19
18
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
20
19
  id?: string;
21
- onDrag?: () => void,
22
- onDragEnd?: () => void,
23
- onDragEnter?: () => void,
24
- onDragLeave?: () => void,
25
- onDragOver?: () => void,
26
- onDragStart?: () => void,
27
- onDrop?: () => void,
28
20
  dragId?: string;
29
21
  tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'div' | 'tr' | 'th' | 'td' | 'thead' | 'col' | 'tbody',
30
22
  };
@@ -39,14 +31,7 @@ const DraggableItem = (props: DraggableItemProps) => {
39
31
  htmlOptions = {},
40
32
  id,
41
33
  dragId,
42
- tag="div",
43
- onDrag = noop,
44
- onDragEnd = noop,
45
- onDragEnter = noop,
46
- onDragLeave = noop,
47
- onDragOver = noop,
48
- onDragStart = noop,
49
- onDrop = noop,
34
+ tag="div"
50
35
  } = props;
51
36
 
52
37
  const {
@@ -76,7 +61,7 @@ const DraggableItem = (props: DraggableItemProps) => {
76
61
  );
77
62
 
78
63
  // Enhanced drag start handler that preserves dimensions
79
- const handleDragStartWithCustom = (e: React.DragEvent) => {
64
+ const onDragStart = (e: React.DragEvent) => {
80
65
  if (dropZone !== 'ghost' && itemRef.current) {
81
66
  // Create a clone for the drag image
82
67
  const clone = itemRef.current.cloneNode(true) as HTMLElement;
@@ -111,9 +96,6 @@ const DraggableItem = (props: DraggableItemProps) => {
111
96
 
112
97
  // Call the original handler
113
98
  handleDragStart(dragId, container);
114
-
115
- // Custom event handler
116
- onDragStart()
117
99
  };
118
100
 
119
101
  return (
@@ -125,19 +107,9 @@ const DraggableItem = (props: DraggableItemProps) => {
125
107
  draggable
126
108
  id={id}
127
109
  key={dragId}
128
- onDrag={onDrag}
129
- onDragEnd={() => {
130
- handleDragEnd()
131
- onDragEnd()
132
- }}
133
- onDragEnter={() => {
134
- handleDragEnter(dragId, container)
135
- onDragEnter()
136
- }}
137
- onDragLeave={onDragLeave}
138
- onDragOver={onDragOver}
139
- onDragStart={handleDragStartWithCustom}
140
- onDrop={onDrop}
110
+ onDragEnd={() => handleDragEnd()}
111
+ onDragEnter={() => handleDragEnter(dragId, container)}
112
+ onDragStart={onDragStart}
141
113
  ref={itemRef}
142
114
  >
143
115
  {children}
@@ -41,11 +41,6 @@
41
41
  outline: unset;
42
42
  transition: box-shadow 0.15s ease-in-out;
43
43
  }
44
- &:focus-within {
45
- box-shadow: 0px 0px 0 1px $primary !important;
46
- outline: unset;
47
- transition: box-shadow 0.15s ease-in-out;
48
- }
49
44
 
50
45
  &[class*="_select_only"] {
51
46
  box-shadow: inset 0 -11px 20px rgba($primary, 0.05);
@@ -36,6 +36,7 @@ type DropdownProps = {
36
36
  onSelect?: (arg: GenericObject) => null;
37
37
  options: GenericObject;
38
38
  separators?: boolean;
39
+ triggerRef?: any;
39
40
  variant?: "default" | "subtle";
40
41
  };
41
42
 
@@ -64,6 +65,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
64
65
  onSelect,
65
66
  options,
66
67
  separators = true,
68
+ triggerRef,
67
69
  variant = "default",
68
70
  } = props;
69
71
 
@@ -89,7 +91,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
89
91
  const [focusedOptionIndex, setFocusedOptionIndex] = useState(-1);
90
92
 
91
93
  const dropdownRef = useRef(null);
92
- const inputRef = useRef<HTMLInputElement>(null);
94
+ const inputRef = useRef(null);
93
95
  const inputWrapperRef = useRef(null);
94
96
  const dropdownContainerRef = useRef(null);
95
97
 
@@ -97,7 +99,15 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
97
99
  separateChildComponents(children);
98
100
 
99
101
  useEffect(() => {
100
- // Handle clicks outside the dropdown
102
+ // Set the parent element of the trigger to relative to allow for absolute positioning of the dropdown
103
+ //Only needed for when useDropdown hook used with external trigger
104
+ if (triggerRef?.current) {
105
+ const parentElement = triggerRef.current.parentNode;
106
+ if (parentElement) {
107
+ parentElement.style.position = 'relative';
108
+ }
109
+ }
110
+ // Handle clicks outside the dropdown
101
111
  const handleClick = handleClickOutside({
102
112
  inputWrapperRef,
103
113
  dropdownContainerRef,
@@ -157,7 +167,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
157
167
  };
158
168
 
159
169
  const handleWrapperClick = () => {
160
- autocomplete && inputRef?.current?.focus();
170
+ autocomplete && inputRef.current.focus();
161
171
  toggleDropdown();
162
172
  };
163
173
 
@@ -192,7 +202,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
192
202
  {...htmlProps}
193
203
  className={classes}
194
204
  id={id}
195
- style={{position: "relative"}}
205
+ style={triggerRef ? { position: "absolute" } : { position: "relative" }}
196
206
  >
197
207
  <DropdownContext.Provider
198
208
  value={{
@@ -215,7 +225,8 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
215
225
  setIsDropDownClosed,
216
226
  setIsInputFocused,
217
227
  setSelected,
218
- toggleDropdown
228
+ toggleDropdown,
229
+ triggerRef
219
230
  }}
220
231
  >
221
232
  {label &&
@@ -1,4 +1,4 @@
1
- <%
1
+ <%
2
2
  options = [
3
3
  { label: 'United States', value: 'United States', id: 'us' },
4
4
  { label: 'Canada', value: 'Canada', id: 'ca' },
@@ -6,7 +6,4 @@
6
6
  ]
7
7
  %>
8
8
 
9
- <%= pb_rails("dropdown", props: {
10
- error: raw(pb_rails("icon", props: { icon: "warning" }) + " Please make a valid selection"),
11
- options: options
12
- }) %>
9
+ <%= pb_rails("dropdown", props: { error: "Please make a valid selection", options: options }) %>
@@ -1,39 +1,86 @@
1
1
  import React from 'react'
2
2
 
3
3
  import Dropdown from '../../pb_dropdown/_dropdown'
4
+ import Badge from '../../pb_badge/_badge'
5
+ import FlexItem from '../../pb_flex/_flex_item'
6
+ import User from '../../pb_user/_user'
4
7
 
5
8
  const DropdownWithAutocomplete = (props) => {
6
9
 
7
10
  const options = [
8
11
  {
9
- label: "United States",
10
- value: "United States",
11
- areaCode: "+1",
12
- icon: "🇺🇸",
13
- id: "us"
12
+ label: "Jasper Furniss",
13
+ value: "Jasper Furniss",
14
+ territory: "PHL",
15
+ title: "Lead UX Engineer",
16
+ id: "jasper-furniss",
17
+ status: "Offline"
14
18
  },
15
19
  {
16
- label: "United Kingdom",
17
- value: "United Kingdom",
18
- areaCode: "+44",
19
- icon: "🇬🇧",
20
- id: "gb"
20
+ label: "Ramon Ruiz",
21
+ value: "Ramon Ruiz",
22
+ territory: "PHL",
23
+ title: "Senior UX Designer",
24
+ id: "ramon-ruiz",
25
+ status: "Away"
21
26
  },
22
27
  {
23
- label: "Pakistan",
24
- value: "Pakistan",
25
- areaCode: "+92",
26
- icon: "🇵🇰",
27
- id: "pk"
28
+ label: "Carlos Lima",
29
+ value: "Carlos Lima",
30
+ territory: "PHL",
31
+ title: "Nitro Developer",
32
+ id: "carlos-lima",
33
+ status: "Online"
34
+ },
35
+ {
36
+ label: "Courtney Long",
37
+ value: "Courtney Long",
38
+ territory: "PHL",
39
+ title: "Lead UX Designer",
40
+ id: "courtney-long",
41
+ status: "Online"
28
42
  }
29
- ]
43
+ ];
44
+
30
45
 
31
46
  return (
32
47
  <div>
33
48
  <Dropdown autocomplete
34
49
  options={options}
35
50
  {...props}
36
- />
51
+ >
52
+ {options.map((option) => (
53
+ <Dropdown.Option key={option.id}
54
+ option={option}
55
+ >
56
+ <>
57
+ <FlexItem>
58
+ <User
59
+ align="left"
60
+ avatar
61
+ name={option.label}
62
+ orientation="horizontal"
63
+ territory={option.territory}
64
+ title={option.title}
65
+ />
66
+ </FlexItem>
67
+ <FlexItem>
68
+ <Badge
69
+ rounded
70
+ text={option.status}
71
+ variant={`${
72
+ option.status === "Offline"
73
+ ? "neutral"
74
+ : option.status === "Online"
75
+ ? "success"
76
+ : "warning"
77
+ }`}
78
+ />
79
+ </FlexItem>
80
+ </>
81
+ </Dropdown.Option>
82
+ ))}
83
+ </Dropdown>
37
84
  </div>
38
85
  )
39
86
  }