playbook_ui 14.18.0.pre.alpha.dropdownautocomplete7493 → 14.18.0.pre.alpha.play1736highchartslinegraphdefaultrebuild7431

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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +21 -304
  3. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +1 -5
  4. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +1 -6
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.md +6 -0
  6. 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
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows_rails.md +1 -5
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_rails.md +2 -3
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +5 -6
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -3
  11. data/app/pb_kits/playbook/pb_advanced_table/index.js +11 -228
  12. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +1 -9
  13. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +3 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +2 -1
  15. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_error.html.erb +2 -2
  16. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +1 -2
  17. data/app/pb_kits/playbook/pb_draggable/draggable.rb +1 -9
  18. data/app/pb_kits/playbook/pb_draggable/index.js +142 -139
  19. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +0 -5
  20. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +16 -5
  21. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_error.html.erb +2 -5
  22. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.jsx +64 -17
  23. data/app/pb_kits/playbook/pb_dropdown/docs/{_dropdown_with_autocomplete_with_subcomponents.jsx → _dropdown_with_autocomplete_and_custom_display.jsx} +25 -11
  24. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_and_custom_display.md +1 -0
  25. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_hook.jsx +79 -0
  26. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +4 -7
  27. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +2 -2
  28. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +2 -2
  29. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +0 -4
  30. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +1 -45
  31. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +0 -10
  32. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.rb +0 -3
  33. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +2 -12
  34. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +1 -3
  35. data/app/pb_kits/playbook/pb_dropdown/index.js +0 -57
  36. data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +0 -26
  37. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownContainer.tsx +2 -1
  38. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +4 -4
  39. data/app/pb_kits/playbook/pb_filter/docs/example.yml +0 -1
  40. data/app/pb_kits/playbook/pb_form_group/_error_state_mixin.scss +18 -22
  41. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_pb_styles.jsx +1 -1
  42. data/app/pb_kits/playbook/pb_line_graph/lineGraphTheme.js +49 -0
  43. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +0 -13
  44. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +1 -3
  45. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +0 -2
  46. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +0 -1
  47. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +0 -3
  48. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +0 -19
  49. data/app/pb_kits/playbook/pb_popover/docs/example.yml +0 -1
  50. data/app/pb_kits/playbook/pb_popover/index.ts +1 -13
  51. data/app/pb_kits/playbook/pb_popover/popover.rb +0 -2
  52. data/app/pb_kits/playbook/pb_select/docs/_select_error.html.erb +1 -1
  53. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.html.erb +1 -1
  54. data/app/pb_kits/playbook/pb_textarea/docs/_textarea_error.html.erb +1 -5
  55. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.html.erb +1 -8
  56. data/dist/chunks/{_typeahead-D8CsVBZO.js → _typeahead-0GuhDCLl.js} +2 -2
  57. data/dist/chunks/_weekday_stacked-DGgA3ilU.js +45 -0
  58. data/dist/chunks/{lib-BmTAc7Nc.js → lib-C8GLwWXp.js} +1 -1
  59. data/dist/chunks/{pb_form_validation-BWjy4bFn.js → pb_form_validation-Eul4XODx.js} +1 -1
  60. data/dist/chunks/vendor.js +1 -1
  61. data/dist/playbook-doc.js +1 -1
  62. data/dist/playbook-rails-react-bindings.js +1 -1
  63. data/dist/playbook-rails.js +1 -1
  64. data/dist/playbook.css +1 -1
  65. data/lib/playbook/version.rb +1 -1
  66. metadata +16 -38
  67. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color.jsx +0 -80
  68. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color.md +0 -3
  69. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color_rails.html.erb +0 -58
  70. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color_rails.md +0 -3
  71. data/app/pb_kits/playbook/pb_advanced_table/flat_advanced_table.js +0 -106
  72. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones.html.erb +0 -43
  73. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors.html.erb +0 -55
  74. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors_rails.md +0 -1
  75. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.html.erb +0 -28
  76. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_with_subcomponents.html.erb +0 -58
  77. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_with_subcomponents.md +0 -1
  78. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_external_control.md +0 -1
  79. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search.jsx +0 -61
  80. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search.md +0 -2
  81. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search_rails.html.erb +0 -52
  82. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search_rails.md +0 -2
  83. data/app/pb_kits/playbook/pb_filter/docs/_filter_within_turbo_frames.html.erb +0 -41
  84. data/app/pb_kits/playbook/pb_filter/docs/_filter_within_turbo_frames.md +0 -1
  85. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_pb_styles.md +0 -1
  86. data/app/pb_kits/playbook/pb_line_graph/lineGraphTheme.ts +0 -110
  87. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.html.erb +0 -10
  88. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.jsx +0 -20
  89. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.md +0 -1
  90. data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.html.erb +0 -46
  91. data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.md +0 -1
  92. data/dist/chunks/_weekday_stacked-Da8b-KUp.js +0 -45
  93. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_rails.html.erb → _advanced_table_selectable_rows.html.erb} +0 -0
  94. /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
  95. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows.md → _advanced_table_selectable_rows_react.md} +0 -0
  96. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_drop_zones_react.md → _draggable_drop_zones.md} +0 -0
  97. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_drop_zones_colors_react.md → _draggable_drop_zones_colors.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"]; // 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,100 +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
- requestAnimationFrame(() => (event.target.style.opacity = "0.5"));
85
+ setTimeout(() => {
86
+ event.target.style.opacity = '0.5';
87
+ }, 0);
120
88
  }
121
89
 
122
- /* ---------------- DRAG ENTER ---------------- */
123
90
  handleDragEnter(event) {
124
91
  if (!this.draggedItem || event.target === this.draggedItem) return;
125
- this.hasMultipleContainers
126
- ? this.handleMultiContainerDragEnter(event)
127
- : this.handleSingleContainerDragEnter(event);
92
+
93
+ if (this.hasMultipleContainers) {
94
+ this.handleMultiContainerDragEnter(event);
95
+ } else {
96
+ this.handleSingleContainerDragEnter(event);
97
+ }
128
98
  }
129
99
 
130
100
  handleSingleContainerDragEnter(event) {
131
- const targetItem = event.target.closest(".pb_draggable_item");
132
- // If we're entering a container directly or there's no target item
101
+ const targetItem = event.target.closest('.pb_draggable_item');
133
102
  if (!targetItem) return;
134
103
 
135
104
  const container = targetItem.parentNode;
136
- const items = Array.from(container.children);
137
- const fromIdx = items.indexOf(this.draggedItem);
138
- const toIdx = items.indexOf(targetItem);
105
+ const items = Array.from(container.children);
139
106
 
140
- if (fromIdx > toIdx) {
107
+ const draggedIndex = items.indexOf(this.draggedItem);
108
+ const targetIndex = items.indexOf(targetItem);
109
+
110
+ if (draggedIndex > targetIndex) {
141
111
  container.insertBefore(this.draggedItem, targetItem);
142
112
  } else {
143
113
  container.insertBefore(this.draggedItem, targetItem.nextSibling);
@@ -146,113 +116,146 @@ export default class PbDraggable extends PbEnhancedElement {
146
116
 
147
117
  handleMultiContainerDragEnter(event) {
148
118
  const targetContainer = event.target.closest(DRAGGABLE_CONTAINER);
149
- const targetItem = event.target.closest(".pb_draggable_item");
119
+ const targetItem = event.target.closest('.pb_draggable_item');
120
+
150
121
  if (!targetContainer) return;
151
122
 
123
+ // If we're entering a container directly or there's no target item
152
124
  if (!targetItem) {
153
- const last = targetContainer.querySelector(".pb_draggable_item:last-child");
154
- last
155
- ? targetContainer.insertBefore(this.draggedItem, last.nextSibling)
156
- : 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
+ }
157
131
  return;
158
132
  }
159
133
 
160
- const items = Array.from(targetContainer.children);
161
- 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 });
162
143
 
163
- const midY = targetItem.getBoundingClientRect().top +
164
- targetItem.getBoundingClientRect().height / 2;
144
+ const rect = targetItem.getBoundingClientRect();
145
+ const middleY = rect.top + rect.height / 2;
165
146
 
166
- if (event.clientY < midY) {
167
- targetContainer.insertBefore(this.draggedItem, targetItem);
147
+ if (event.clientY < middleY) {
148
+ container.insertBefore(this.draggedItem, targetItem);
168
149
  } else {
169
- targetContainer.insertBefore(this.draggedItem, targetItem.nextSibling);
150
+ container.insertBefore(this.draggedItem, targetItem.nextSibling);
170
151
  }
171
152
  }
172
153
 
173
- /* ---------------- DRAG OVER ---------------- */
174
154
  handleDragOver(event) {
175
155
  event.preventDefault();
176
156
  event.stopPropagation();
177
- this.hasMultipleContainers
178
- ? this.handleMultiContainerDragOver(event)
179
- : this.handleSingleContainerDragOver(event);
157
+
158
+ if (this.hasMultipleContainers) {
159
+ this.handleMultiContainerDragOver(event);
160
+ } else {
161
+ this.handleSingleContainerDragOver(event);
162
+ }
180
163
  }
181
164
 
182
165
  handleSingleContainerDragOver(event) {
183
166
  const container = event.target.closest(DRAGGABLE_CONTAINER);
184
- if (container) container.classList.add("active_container");
167
+ if (container) {
168
+ container.classList.add("active_container");
169
+ }
185
170
  }
186
171
 
187
172
  handleMultiContainerDragOver(event) {
188
- const container = event.target.matches(DRAGGABLE_CONTAINER)
189
- ? event.target
190
- : event.target.closest(DRAGGABLE_CONTAINER);
191
- if (!container) return;
192
-
193
- this.setState({ activeContainer: container.id });
194
- container.classList.add("active_container");
195
-
196
- const last = container.querySelector(".pb_draggable_item:last-child");
197
- if (!last || event.clientY > last.getBoundingClientRect().bottom) {
198
- if (this.draggedItem && this.draggedItem.parentNode !== container) {
199
- 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
+ }
200
190
  }
201
191
  }
202
192
  }
203
193
 
204
- /* ---------------- DROP ---------------- */
205
194
  handleDrop(event) {
206
195
  event.preventDefault();
207
196
  event.stopPropagation();
208
197
 
209
- const container = event.target.matches(DRAGGABLE_CONTAINER)
210
- ? event.target
211
- : 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
+
212
205
  if (!container || !this.draggedItem) return;
213
206
 
214
207
  container.classList.remove("active_container");
215
- this.draggedItem.style.opacity = "1";
208
+ this.draggedItem.style.opacity = '1';
216
209
 
217
210
  // Handle empty containers
218
- if (this.hasMultipleContainers && !container.querySelector(".pb_draggable_item")) {
211
+ if (this.hasMultipleContainers && !container.querySelector('.pb_draggable_item')) {
219
212
  container.appendChild(this.draggedItem);
220
213
  }
221
214
 
222
215
  // Updated order of items as an array of item IDs
223
- const reorderedItems = Array.from(this.element.querySelectorAll(".pb_draggable_item"))
224
- .map(i => ({ id: i.id, container: i.closest(DRAGGABLE_CONTAINER).id }));
225
-
226
- container.dataset.reorderedItems = JSON.stringify(reorderedItems);
227
- this.element.dispatchEvent(new CustomEvent("pb-draggable-reorder", {
228
- 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
229
221
  }));
230
222
 
231
- this.setState({ items: reorderedItems, isDragging: "", activeContainer: "" });
232
- 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;
233
242
  this.draggedItemId = null;
234
243
  }
235
244
 
236
- /* ---------------- DRAG END ---------------- */
237
245
  handleDragEnd(event) {
238
- event.target.classList.remove(
239
- "is_dragging",
240
- `drop_zone_${this.dragZoneType}`,
241
- `drop_zone_color_${this.dragZoneColor}`,
242
- );
243
- event.target.style.opacity = "1";
244
-
245
- if (this.dragGhost) {
246
- document.body.removeChild(this.dragGhost);
247
- this.dragGhost = null;
248
- }
249
-
250
- this.setState({ isDragging: "", activeContainer: "" });
246
+ event.target.classList.remove("is_dragging");
247
+ event.target.style.opacity = '1';
251
248
 
252
- this.element.querySelectorAll(DRAGGABLE_CONTAINER)
253
- .forEach(c => c.classList.remove("active_container"));
249
+ this.setState({
250
+ isDragging: "",
251
+ activeContainer: ""
252
+ });
254
253
 
255
- this.draggedItem = null;
254
+ this.draggedItem = null;
256
255
  this.draggedItemId = null;
256
+
257
+ this.element.querySelectorAll(DRAGGABLE_CONTAINER).forEach(container => {
258
+ container.classList.remove("active_container");
259
+ });
257
260
  }
258
261
  }
@@ -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
  }
@@ -1,13 +1,15 @@
1
- import React from 'react'
1
+ import React, { useState } from 'react'
2
2
 
3
- import Dropdown from '../_dropdown'
3
+ import Dropdown from '../../pb_dropdown/_dropdown'
4
4
  import Badge from '../../pb_badge/_badge'
5
- import Flex from '../../pb_flex/_flex'
6
5
  import FlexItem from '../../pb_flex/_flex_item'
6
+ import Avatar from '../../pb_avatar/_avatar'
7
7
  import User from '../../pb_user/_user'
8
8
 
9
9
 
10
- const DropdownWithAutocompleteWithSubcomponents = (props) => {
10
+ const DropdownWithAutocompleteAndCustomDisplay = (props) => {
11
+ const [selectedOption, setSelectedOption] = useState();
12
+
11
13
  const options = [
12
14
  {
13
15
  label: "Jasper Furniss",
@@ -43,21 +45,34 @@ const DropdownWithAutocompleteWithSubcomponents = (props) => {
43
45
  }
44
46
  ];
45
47
 
48
+ const CustomDisplay = () => {
49
+ return (
50
+ <>
51
+ {
52
+ selectedOption && (
53
+ <Avatar
54
+ name={selectedOption.label}
55
+ size="xs"
56
+ />
57
+ )
58
+ }
59
+ </>
60
+ )
61
+ };
46
62
 
47
63
  return (
48
64
  <div>
49
65
  <Dropdown autocomplete
66
+ onSelect={(selectedItem) => setSelectedOption(selectedItem)}
50
67
  options={options}
51
68
  {...props}
52
69
  >
70
+ <Dropdown.Trigger customDisplay={<CustomDisplay/>} />
53
71
  {options.map((option) => (
54
72
  <Dropdown.Option key={option.id}
55
73
  option={option}
56
74
  >
57
- <Flex
58
- align="center"
59
- justify="between"
60
- >
75
+ <>
61
76
  <FlexItem>
62
77
  <User
63
78
  align="left"
@@ -70,7 +85,6 @@ const DropdownWithAutocompleteWithSubcomponents = (props) => {
70
85
  </FlexItem>
71
86
  <FlexItem>
72
87
  <Badge
73
- dark
74
88
  rounded
75
89
  text={option.status}
76
90
  variant={`${
@@ -82,7 +96,7 @@ const DropdownWithAutocompleteWithSubcomponents = (props) => {
82
96
  }`}
83
97
  />
84
98
  </FlexItem>
85
- </Flex>
99
+ </>
86
100
  </Dropdown.Option>
87
101
  ))}
88
102
  </Dropdown>
@@ -90,4 +104,4 @@ const DropdownWithAutocompleteWithSubcomponents = (props) => {
90
104
  )
91
105
  }
92
106
 
93
- export default DropdownWithAutocompleteWithSubcomponents
107
+ export default DropdownWithAutocompleteAndCustomDisplay