playbook_ui 14.18.0 → 14.18.1.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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_circle_chart/_circle_chart.tsx +1 -1
  3. data/app/pb_kits/playbook/pb_circle_chart/circleChart.test.js +2 -2
  4. data/app/pb_kits/playbook/pb_circle_chart/circleChartTheme.ts +53 -0
  5. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_block.html.erb +2 -2
  6. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_block.jsx +1 -1
  7. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_colors.html.erb +1 -1
  8. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_colors.jsx +1 -1
  9. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_custom_tooltip.html.erb +1 -1
  10. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_custom_tooltip.jsx +1 -1
  11. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_default.html.erb +1 -1
  12. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_default.jsx +1 -1
  13. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_legend_position.html.erb +1 -1
  14. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_legend_position.jsx +1 -1
  15. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_live_data.jsx +2 -2
  16. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_pb_styles.jsx +38 -0
  17. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_pb_styles.md +1 -0
  18. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_rounded.html.erb +1 -1
  19. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_rounded.jsx +1 -1
  20. data/app/pb_kits/playbook/pb_circle_chart/docs/example.yml +2 -3
  21. data/app/pb_kits/playbook/pb_circle_chart/docs/index.js +2 -1
  22. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +12 -0
  23. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +12 -0
  24. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +50 -1
  25. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_error.jsx +4 -1
  26. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_rails.md +4 -0
  27. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_range_limit.md +1 -1
  28. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_react.md +5 -1
  29. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern.jsx +34 -0
  30. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern.md +14 -0
  31. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern_rails.html.erb +20 -0
  32. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern_rails.md +14 -0
  33. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +2 -0
  34. data/app/pb_kits/playbook/pb_date_picker/docs/index.js +1 -0
  35. data/app/pb_kits/playbook/pb_date_picker/plugins/quickPick.tsx +10 -0
  36. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones.html.erb +43 -0
  37. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors.html.erb +55 -0
  38. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors_rails.md +1 -0
  39. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +2 -1
  40. data/app/pb_kits/playbook/pb_draggable/draggable.rb +9 -1
  41. data/app/pb_kits/playbook/pb_draggable/index.js +139 -142
  42. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_error.jsx +4 -1
  43. data/app/pb_kits/playbook/pb_filter/docs/_filter_within_turbo_frames.html.erb +41 -0
  44. data/app/pb_kits/playbook/pb_filter/docs/_filter_within_turbo_frames.md +1 -0
  45. data/app/pb_kits/playbook/pb_filter/docs/example.yml +1 -0
  46. data/app/pb_kits/playbook/pb_form_group/_error_state_mixin.scss +22 -18
  47. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_pb_styles.jsx +0 -1
  48. data/app/pb_kits/playbook/pb_gauge/gaugeTheme.ts +3 -1
  49. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_pb_styles.jsx +52 -0
  50. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_pb_styles.md +1 -0
  51. data/app/pb_kits/playbook/pb_line_graph/docs/example.yml +1 -0
  52. data/app/pb_kits/playbook/pb_line_graph/docs/index.js +1 -0
  53. data/app/pb_kits/playbook/pb_line_graph/lineGraphTheme.ts +110 -0
  54. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +13 -0
  55. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +3 -1
  56. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.html.erb +10 -0
  57. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.jsx +20 -0
  58. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.md +1 -0
  59. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_validation.jsx +8 -1
  60. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +2 -0
  61. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  62. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  63. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +19 -0
  64. data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.html.erb +46 -0
  65. data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.md +1 -0
  66. data/app/pb_kits/playbook/pb_popover/docs/example.yml +1 -0
  67. data/app/pb_kits/playbook/pb_popover/index.ts +13 -1
  68. data/app/pb_kits/playbook/pb_popover/popover.rb +2 -0
  69. data/app/pb_kits/playbook/pb_select/docs/_select_error.jsx +7 -2
  70. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.jsx +9 -1
  71. data/app/pb_kits/playbook/pb_textarea/docs/_textarea_error.jsx +7 -1
  72. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.jsx +6 -2
  73. data/dist/chunks/{_typeahead-C_FX7o_S.js → _typeahead-D8CsVBZO.js} +3 -3
  74. data/dist/chunks/_weekday_stacked-CHQsoCdP.js +45 -0
  75. data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
  76. data/dist/chunks/lib-BmTAc7Nc.js +29 -0
  77. data/dist/chunks/{pb_form_validation-BRjyJrKh.js → pb_form_validation-BWjy4bFn.js} +1 -1
  78. data/dist/chunks/vendor.js +1 -1
  79. data/dist/playbook-doc.js +2 -2
  80. data/dist/playbook-rails-react-bindings.js +1 -1
  81. data/dist/playbook-rails.js +1 -1
  82. data/dist/playbook.css +1 -1
  83. data/lib/playbook/version.rb +2 -2
  84. metadata +29 -9
  85. data/dist/chunks/_weekday_stacked-B4RLTeDo.js +0 -45
  86. data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
  87. data/dist/chunks/lib-ySl8uEpT.js +0 -29
  88. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_drop_zones_colors.md → _draggable_drop_zones_colors_react.md} +0 -0
  89. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_drop_zones.md → _draggable_drop_zones_react.md} +0 -0
@@ -0,0 +1,55 @@
1
+ <% initial_items = [
2
+ {
3
+ id: "141",
4
+ url: "https://unsplash.it/500/400/?image=633",
5
+ },
6
+ {
7
+ id: "142",
8
+ url: "https://unsplash.it/500/400/?image=634",
9
+ },
10
+ {
11
+ id: "143",
12
+ url: "https://unsplash.it/500/400/?image=637",
13
+ },
14
+ ] %>
15
+
16
+ <% next_init_items = [
17
+ {
18
+ id: "151",
19
+ url: "https://unsplash.it/500/400/?image=633",
20
+ },
21
+ {
22
+ id: "152",
23
+ url: "https://unsplash.it/500/400/?image=634",
24
+ },
25
+ {
26
+ id: "153",
27
+ url: "https://unsplash.it/500/400/?image=637",
28
+ },
29
+ ] %>
30
+
31
+ <%= pb_rails("draggable", props: {initial_items: initial_items, drop_zone_type: "shadow", drop_zone_color: "primary"}) do %>
32
+ <%= pb_rails("draggable/draggable_container") do %>
33
+ <%= pb_rails("flex", props: { gap: "sm" }) do %>
34
+ <% initial_items.each do |item| %>
35
+ <%= pb_rails("draggable/draggable_item", props:{drag_id: item[:id]}) do %>
36
+ <%= pb_rails("image", props: { alt: item[:id], size: "md", url: item[:url] }) %>
37
+ <% end %>
38
+ <% end %>
39
+ <% end %>
40
+ <% end %>
41
+ <% end %>
42
+
43
+ <br/>
44
+
45
+ <%= pb_rails("draggable", props: {initial_items: next_init_items, drop_zone_type: "outline", drop_zone_color: "purple"}) do %>
46
+ <%= pb_rails("draggable/draggable_container") do %>
47
+ <%= pb_rails("flex", props: { gap: "sm" }) do %>
48
+ <% initial_items.each do |item| %>
49
+ <%= pb_rails("draggable/draggable_item", props:{drag_id: item[:id]}) do %>
50
+ <%= pb_rails("image", props: { alt: item[:id], size: "md", url: item[:url] }) %>
51
+ <% end %>
52
+ <% end %>
53
+ <% end %>
54
+ <% end %>
55
+ <% end %>
@@ -0,0 +1 @@
1
+ The default `color` for Draggable kit drop zones is "neutral", with "primary" or "purple" as additional options.
@@ -17,5 +17,6 @@ examples:
17
17
  - draggable_with_cards: Draggable with Cards
18
18
  - draggable_with_table: Draggable with Table
19
19
  - draggable_multiple_containers: Dragging Across Multiple Containers
20
+ - draggable_drop_zones: Draggable Drop Zones
21
+ - draggable_drop_zones_colors: Draggable Drop Zones Colors
20
22
  - draggable_event_listeners: Draggable Event Listeners
21
-
@@ -5,9 +5,17 @@ module Playbook
5
5
  class Draggable < ::Playbook::KitBase
6
6
  prop :initial_items, type: Playbook::Props::Array,
7
7
  default: []
8
+ prop :drop_zone_type, type: Playbook::Props::Enum,
9
+ values: %w[ghost shadow outline line],
10
+ default: "ghost"
11
+ prop :drop_zone_color, type: Playbook::Props::Enum,
12
+ values: %w[neutral primary purple],
13
+ default: "neutral"
8
14
 
9
15
  def data
10
- Hash(prop(:data)).merge(pb_draggable: true)
16
+ Hash(prop(:data)).merge(pb_draggable: true,
17
+ drop_zone_type: drop_zone_type,
18
+ drop_zone_color: drop_zone_color)
11
19
  end
12
20
 
13
21
  def classname
@@ -1,24 +1,26 @@
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
5
6
 
6
7
  export default class PbDraggable extends PbEnhancedElement {
7
- static get selector() {
8
- return DRAGGABLE_SELECTOR;
9
- }
8
+ static get selector() { return DRAGGABLE_SELECTOR; }
10
9
 
11
10
  connect() {
12
11
  this.state = {
13
- items: [],
14
- dragData: { id: "", initialGroup: "" },
15
- isDragging: "",
16
- activeContainer: ""
12
+ items: [],
13
+ dragData: { id: "", initialGroup: "" },
14
+ isDragging: "",
15
+ activeContainer: "",
17
16
  };
18
17
 
19
- this.draggedItem = null;
18
+ this.draggedItem = null;
20
19
  this.draggedItemId = null;
20
+ this.dragGhost = null;
21
21
  this.hasMultipleContainers = false;
22
+ this.dragZoneType = "";
23
+ this.dragZoneColor = "";
22
24
 
23
25
  document.addEventListener("DOMContentLoaded", () => this.bindEventListeners());
24
26
  }
@@ -26,13 +28,12 @@ export default class PbDraggable extends PbEnhancedElement {
26
28
  setState(newState) {
27
29
  this.state = { ...this.state, ...newState };
28
30
  if (newState.items) {
29
- const customEvent = new CustomEvent('pb-draggable-reorder', {
31
+ this.element.dispatchEvent(new CustomEvent("pb-draggable-reorder", {
30
32
  detail: {
31
33
  reorderedItems: this.state.items,
32
- containerId: this.element.querySelector(DRAGGABLE_CONTAINER).id
33
- }
34
- });
35
- this.element.dispatchEvent(customEvent);
34
+ containerId: this.element.querySelector(DRAGGABLE_CONTAINER).id,
35
+ },
36
+ }));
36
37
  }
37
38
  }
38
39
 
@@ -43,71 +44,100 @@ export default class PbDraggable extends PbEnhancedElement {
43
44
 
44
45
  // Needed to prevent images within draggable items from being independently draggable
45
46
  // Needed if using Image kit in draggable items
46
- this.element.querySelectorAll(".pb_draggable_item img").forEach(img => {
47
- img.setAttribute("draggable", "false");
48
- });
49
-
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
- });
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
+ });
55
56
 
56
- containers.forEach(container => {
57
- container.addEventListener("dragover", this.handleDragOver.bind(this));
58
- container.addEventListener("drop", this.handleDrop.bind(this));
57
+ containers.forEach(c => {
58
+ c.addEventListener("dragover", this.handleDragOver.bind(this));
59
+ c.addEventListener("drop", this.handleDrop.bind(this));
59
60
  });
60
61
  }
61
62
 
63
+ /* ---------------- DRAG START ---------------- */
62
64
  handleDragStart(event) {
63
65
  // Needed to prevent images within draggable items from being independently draggable
64
66
  // Needed if using Image kit in draggable items
65
- if (event.target.tagName.toLowerCase() === 'img') {
67
+ if (event.target.tagName.toLowerCase() === "img") {
66
68
  event.preventDefault();
67
69
  return;
68
70
  }
69
71
 
70
- const container = event.target.closest(DRAGGABLE_CONTAINER);
71
- this.draggedItem = event.target;
72
+ const container = event.target.closest(DRAGGABLE_CONTAINER);
73
+ this.draggedItem = event.target;
72
74
  this.draggedItemId = event.target.id;
75
+ this.dragZoneType = this.element.dataset.dropZoneType || "";
76
+ this.dragZoneColor = this.element.dataset.dropZoneColor || "";
73
77
 
74
78
  this.setState({
75
- dragData: { id: this.draggedItemId, initialGroup: container.id },
76
- isDragging: this.draggedItemId
79
+ dragData: { id: this.draggedItemId, initialGroup: container.id },
80
+ isDragging: this.draggedItemId,
77
81
  });
78
82
 
79
- event.target.classList.add("is_dragging");
83
+ this.draggedItem.classList.add(
84
+ "is_dragging",
85
+ `drop_zone_${this.dragZoneType}`,
86
+ `drop_zone_color_${this.dragZoneColor}`,
87
+ );
88
+
80
89
  if (event.dataTransfer) {
81
- event.dataTransfer.effectAllowed = 'move';
82
- event.dataTransfer.setData('text/plain', this.draggedItemId);
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
+ /* ---------------------------------------------------------------- */
83
117
  }
84
118
 
85
- setTimeout(() => {
86
- event.target.style.opacity = '0.5';
87
- }, 0);
119
+ requestAnimationFrame(() => (event.target.style.opacity = "0.5"));
88
120
  }
89
121
 
122
+ /* ---------------- DRAG ENTER ---------------- */
90
123
  handleDragEnter(event) {
91
124
  if (!this.draggedItem || event.target === this.draggedItem) return;
92
-
93
- if (this.hasMultipleContainers) {
94
- this.handleMultiContainerDragEnter(event);
95
- } else {
96
- this.handleSingleContainerDragEnter(event);
97
- }
125
+ this.hasMultipleContainers
126
+ ? this.handleMultiContainerDragEnter(event)
127
+ : this.handleSingleContainerDragEnter(event);
98
128
  }
99
129
 
100
130
  handleSingleContainerDragEnter(event) {
101
- const targetItem = event.target.closest('.pb_draggable_item');
131
+ const targetItem = event.target.closest(".pb_draggable_item");
132
+ // If we're entering a container directly or there's no target item
102
133
  if (!targetItem) return;
103
134
 
104
135
  const container = targetItem.parentNode;
105
- const items = Array.from(container.children);
136
+ const items = Array.from(container.children);
137
+ const fromIdx = items.indexOf(this.draggedItem);
138
+ const toIdx = items.indexOf(targetItem);
106
139
 
107
- const draggedIndex = items.indexOf(this.draggedItem);
108
- const targetIndex = items.indexOf(targetItem);
109
-
110
- if (draggedIndex > targetIndex) {
140
+ if (fromIdx > toIdx) {
111
141
  container.insertBefore(this.draggedItem, targetItem);
112
142
  } else {
113
143
  container.insertBefore(this.draggedItem, targetItem.nextSibling);
@@ -116,146 +146,113 @@ export default class PbDraggable extends PbEnhancedElement {
116
146
 
117
147
  handleMultiContainerDragEnter(event) {
118
148
  const targetContainer = event.target.closest(DRAGGABLE_CONTAINER);
119
- const targetItem = event.target.closest('.pb_draggable_item');
120
-
149
+ const targetItem = event.target.closest(".pb_draggable_item");
121
150
  if (!targetContainer) return;
122
151
 
123
- // If we're entering a container directly or there's no target item
124
152
  if (!targetItem) {
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
- }
153
+ const last = targetContainer.querySelector(".pb_draggable_item:last-child");
154
+ last
155
+ ? targetContainer.insertBefore(this.draggedItem, last.nextSibling)
156
+ : targetContainer.appendChild(this.draggedItem);
131
157
  return;
132
158
  }
133
159
 
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 });
160
+ const items = Array.from(targetContainer.children);
161
+ this.setState({ items: items.map(i => ({ id: i.id, container: targetContainer.id })) });
143
162
 
144
- const rect = targetItem.getBoundingClientRect();
145
- const middleY = rect.top + rect.height / 2;
163
+ const midY = targetItem.getBoundingClientRect().top +
164
+ targetItem.getBoundingClientRect().height / 2;
146
165
 
147
- if (event.clientY < middleY) {
148
- container.insertBefore(this.draggedItem, targetItem);
166
+ if (event.clientY < midY) {
167
+ targetContainer.insertBefore(this.draggedItem, targetItem);
149
168
  } else {
150
- container.insertBefore(this.draggedItem, targetItem.nextSibling);
169
+ targetContainer.insertBefore(this.draggedItem, targetItem.nextSibling);
151
170
  }
152
171
  }
153
172
 
173
+ /* ---------------- DRAG OVER ---------------- */
154
174
  handleDragOver(event) {
155
175
  event.preventDefault();
156
176
  event.stopPropagation();
157
-
158
- if (this.hasMultipleContainers) {
159
- this.handleMultiContainerDragOver(event);
160
- } else {
161
- this.handleSingleContainerDragOver(event);
162
- }
177
+ this.hasMultipleContainers
178
+ ? this.handleMultiContainerDragOver(event)
179
+ : this.handleSingleContainerDragOver(event);
163
180
  }
164
181
 
165
182
  handleSingleContainerDragOver(event) {
166
183
  const container = event.target.closest(DRAGGABLE_CONTAINER);
167
- if (container) {
168
- container.classList.add("active_container");
169
- }
184
+ if (container) container.classList.add("active_container");
170
185
  }
171
186
 
172
187
  handleMultiContainerDragOver(event) {
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
- }
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);
190
200
  }
191
201
  }
192
202
  }
193
203
 
204
+ /* ---------------- DROP ---------------- */
194
205
  handleDrop(event) {
195
206
  event.preventDefault();
196
207
  event.stopPropagation();
197
208
 
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
-
209
+ const container = event.target.matches(DRAGGABLE_CONTAINER)
210
+ ? event.target
211
+ : event.target.closest(DRAGGABLE_CONTAINER);
205
212
  if (!container || !this.draggedItem) return;
206
213
 
207
214
  container.classList.remove("active_container");
208
- this.draggedItem.style.opacity = '1';
215
+ this.draggedItem.style.opacity = "1";
209
216
 
210
217
  // Handle empty containers
211
- if (this.hasMultipleContainers && !container.querySelector('.pb_draggable_item')) {
218
+ if (this.hasMultipleContainers && !container.querySelector(".pb_draggable_item")) {
212
219
  container.appendChild(this.draggedItem);
213
220
  }
214
221
 
215
222
  // Updated order of items as an array of item IDs
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
221
- }));
222
-
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);
223
+ const reorderedItems = Array.from(this.element.querySelectorAll(".pb_draggable_item"))
224
+ .map(i => ({ id: i.id, container: i.closest(DRAGGABLE_CONTAINER).id }));
234
225
 
235
- this.setState({
236
- items: reorderedItems,
237
- isDragging: "",
238
- activeContainer: ""
239
- });
226
+ container.dataset.reorderedItems = JSON.stringify(reorderedItems);
227
+ this.element.dispatchEvent(new CustomEvent("pb-draggable-reorder", {
228
+ detail: { reorderedItems, containerId: container.id },
229
+ }));
240
230
 
241
- this.draggedItem = null;
231
+ this.setState({ items: reorderedItems, isDragging: "", activeContainer: "" });
232
+ this.draggedItem = null;
242
233
  this.draggedItemId = null;
243
234
  }
244
235
 
236
+ /* ---------------- DRAG END ---------------- */
245
237
  handleDragEnd(event) {
246
- event.target.classList.remove("is_dragging");
247
- event.target.style.opacity = '1';
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
+ }
248
249
 
249
- this.setState({
250
- isDragging: "",
251
- activeContainer: ""
252
- });
250
+ this.setState({ isDragging: "", activeContainer: "" });
253
251
 
254
- this.draggedItem = null;
255
- this.draggedItemId = null;
252
+ this.element.querySelectorAll(DRAGGABLE_CONTAINER)
253
+ .forEach(c => c.classList.remove("active_container"));
256
254
 
257
- this.element.querySelectorAll(DRAGGABLE_CONTAINER).forEach(container => {
258
- container.classList.remove("active_container");
259
- });
255
+ this.draggedItem = null;
256
+ this.draggedItemId = null;
260
257
  }
261
258
  }
@@ -1,9 +1,12 @@
1
1
  import React, { useState } from 'react'
2
2
  import Dropdown from '../../pb_dropdown/_dropdown'
3
+ import Icon from '../../pb_icon/_icon'
3
4
 
4
5
  const DropdownError = (props) => {
5
6
  const [selectedOption, setSelectedOption] = useState()
6
- const error = selectedOption?.value ? null : "Please make a valid selection"
7
+ const error = selectedOption?.value ? null : (<>
8
+ <Icon icon="warning" /> Please make a valid selection
9
+ </>)
7
10
  const options = [
8
11
  {
9
12
  label: "United States",
@@ -0,0 +1,41 @@
1
+ <%=
2
+ pb_rails("filter", props: {
3
+ id: "filter_within_trubo_frames",
4
+ position: "top",
5
+ filters: [
6
+ { name: "name", value: "John Wick" },
7
+ { name: "city", value: "San Francisco"}
8
+ ],
9
+ sort_menu: [
10
+ { item: "Popularity", link: "?q[sorts]=managers_popularity+asc", active: true, direction: "desc" },
11
+ { item: "Mananger's Title", link: "?q[sorts]=managers_title+asc", active: false },
12
+ { item: "Manager's Name", link: "?q[sorts]=managers_name+asc", active: false },
13
+ ],
14
+ template: "default",
15
+ results: 1,
16
+ popover_props: { append_to: "parent" },
17
+ }) do
18
+ %>
19
+ <%
20
+ example_collection = [
21
+ OpenStruct.new(name: "USA", value: 1),
22
+ OpenStruct.new(name: "Canada", value: 2),
23
+ OpenStruct.new(name: "Brazil", value: 3),
24
+ OpenStruct.new(name: "Philippines", value: 4),
25
+ OpenStruct.new(name: "A galaxy far far away, like really far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far away...", value: 5)
26
+ ]
27
+ %>
28
+ <%= pb_rails("form", props: { form_system_options: { scope: :example, method: :get } }) do |form| %>
29
+ <%= form.text_field :example_text_field, props: { label: true } %>
30
+ <%= form.collection_select :example_collection_select, example_collection, :value, :name, props: {max_width: "sm", label: true } %>
31
+
32
+ <%= form.actions do |action| %>
33
+ <%= action.submit props: {
34
+ text: "Apply",
35
+ data: {
36
+ disable_with: "pb_rails('icon', props: { icon: 'spinner', spin: true, fixed_width: true })Searching...".html_safe
37
+ },}%>
38
+ <%= action.button props: { type: "reset", text: "Clear", variant: "secondary" } %>
39
+ <% end %>
40
+ <% end %>
41
+ <% end %>
@@ -0,0 +1 @@
1
+ By default, the filter popover attaches to the `<body>`. To attach it elsewhere, like inside a Turbo Frame, pass the `append_to` prop through `popover_props`. Set it to `"parent"` to place the tooltip inside its parent element, or pass any CSS selector (`#id` or `.class`) to specify a custom container.
@@ -11,6 +11,7 @@ examples:
11
11
  - filter_max_height: Max Height for Popover Inside of Filter
12
12
  - filter_placement: Filter Placement
13
13
  - filter_popover_props: Popover Props
14
+ - filter_within_turbo_frames: Within Turbo Frames
14
15
 
15
16
  react:
16
17
  - filter_default: Default
@@ -23,35 +23,39 @@
23
23
  @mixin error-state-right-side-select-kit {
24
24
  &:has(.pb_text_input_kit:not(.error)):has(.pb_text_input_kit_label):has(.pb_select_kit_wrapper.error),
25
25
  &:has(.pb_text_input_kit.error):has(.pb_text_input_kit_label):has(.pb_select_kit_wrapper) {
26
- align-items: flex-start;
27
-
28
- .pb_select_kit_wrapper {
29
- padding-top: $space_md;
30
- margin-top: 2px;
26
+ &:not(:has(.pb_phone_number_input)) {
27
+ align-items: flex-start;
31
28
 
32
- .pb_select_kit_caret {
29
+ .pb_select_kit_wrapper {
33
30
  padding-top: $space_md;
31
+ margin-top: 2px;
32
+
33
+ .pb_select_kit_caret {
34
+ padding-top: $space_md;
35
+ }
34
36
  }
35
- }
36
37
 
37
- .pb_select_kit_wrapper.error {
38
- padding-top: $space_md;
39
- margin-top: 2px;
38
+ .pb_select_kit_wrapper.error {
39
+ padding-top: $space_md;
40
+ margin-top: 2px;
40
41
 
41
- .pb_select_kit_caret {
42
- padding-top: $space_xl;
42
+ .pb_select_kit_caret {
43
+ padding-top: $space_xl;
44
+ }
43
45
  }
44
46
  }
45
47
  }
46
48
  }
47
49
 
48
50
  @mixin error-state-left-side-select-kit {
49
- &:has(.pb_select_kit_label):has(.pb_select_kit_wrapper):has(.pb_phone_number_input):has(.pb_text_input_kit.error) {
50
- align-items: flex-start;
51
+ &:has(.pb_select_kit_label):has(.pb_select_kit_wrapper):has(.pb_text_input_kit.error) {
52
+ &:not(:has(.pb_phone_number_input)) {
53
+ align-items: flex-start;
51
54
 
52
- .pb_text_input_kit.error {
53
- padding-top: $space_md;
54
- margin-top: 2px;
55
+ .pb_text_input_kit.error {
56
+ padding-top: $space_md;
57
+ margin-top: 2px;
58
+ }
55
59
  }
56
60
  }
57
- }
61
+ }
@@ -11,7 +11,6 @@ SolidGauge(Highcharts);
11
11
  const data = [{ name: "Name", y: 45 }]
12
12
 
13
13
  const baseOptions = {
14
- title: { text: "" },
15
14
  series: [{ data: data }],
16
15
  };
17
16
 
@@ -2,6 +2,7 @@ import colors from '../tokens/exports/_colors.module.scss'
2
2
  import typography from '../tokens/exports/_typography.module.scss'
3
3
 
4
4
  const gaugeTheme = {
5
+ title: { text: "" },
5
6
  chart: {
6
7
  type: "solidgauge",
7
8
  events: {
@@ -77,7 +78,8 @@ const gaugeTheme = {
77
78
  y: -26,
78
79
  },
79
80
  },
80
- }
81
+ },
82
+ credits: { enabled: false }
81
83
  }
82
84
 
83
85
  export default gaugeTheme;