playbook_ui 14.18.0.pre.alpha.play2034zonesandcolors7407 → 14.18.0.pre.alpha.play2042addturbosupporttopopoverkit7423
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +12 -0
- data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +12 -0
- data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +50 -1
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_rails.md +4 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_range_limit.md +1 -1
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_react.md +5 -1
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern.jsx +34 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern.md +14 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern_rails.html.erb +20 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern_rails.md +14 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_date_picker/plugins/quickPick.tsx +10 -0
- data/app/pb_kits/playbook/pb_draggable/docs/example.yml +1 -2
- data/app/pb_kits/playbook/pb_draggable/draggable.rb +1 -9
- data/app/pb_kits/playbook/pb_draggable/index.js +142 -139
- data/app/pb_kits/playbook/pb_filter/docs/_filter_within_turbo_frames.html.erb +41 -0
- data/app/pb_kits/playbook/pb_filter/docs/_filter_within_turbo_frames.md +1 -0
- data/app/pb_kits/playbook/pb_filter/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.html.erb +46 -0
- data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.md +1 -0
- data/app/pb_kits/playbook/pb_popover/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_popover/index.ts +13 -1
- data/app/pb_kits/playbook/pb_popover/popover.rb +2 -0
- data/dist/chunks/{_typeahead-CvkGr9xV.js → _typeahead-COZRQUuU.js} +1 -1
- data/dist/chunks/_weekday_stacked-BRT0ul9R.js +45 -0
- data/dist/chunks/{lib-yWHJ_8mm.js → lib-ClNg0TLS.js} +1 -1
- data/dist/chunks/{pb_form_validation-CFPfX89U.js → pb_form_validation-Btrgnox1.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +16 -11
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones.html.erb +0 -43
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors.html.erb +0 -55
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors_rails.md +0 -1
- data/dist/chunks/_weekday_stacked-B-ran-L1.js +0 -45
- /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_drop_zones_react.md → _draggable_drop_zones.md} +0 -0
- /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
|
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() {
|
7
|
+
static get selector() {
|
8
|
+
return DRAGGABLE_SELECTOR;
|
9
|
+
}
|
9
10
|
|
10
11
|
connect() {
|
11
12
|
this.state = {
|
12
|
-
items:
|
13
|
-
dragData:
|
14
|
-
isDragging:
|
15
|
-
activeContainer: ""
|
13
|
+
items: [],
|
14
|
+
dragData: { id: "", initialGroup: "" },
|
15
|
+
isDragging: "",
|
16
|
+
activeContainer: ""
|
16
17
|
};
|
17
18
|
|
18
|
-
this.draggedItem
|
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
|
-
|
29
|
+
const customEvent = new CustomEvent('pb-draggable-reorder', {
|
32
30
|
detail: {
|
33
31
|
reorderedItems: this.state.items,
|
34
|
-
containerId:
|
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
|
-
|
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
|
-
|
58
|
-
|
59
|
-
|
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() ===
|
65
|
+
if (event.target.tagName.toLowerCase() === 'img') {
|
68
66
|
event.preventDefault();
|
69
67
|
return;
|
70
68
|
}
|
71
69
|
|
72
|
-
const container
|
73
|
-
this.draggedItem
|
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:
|
80
|
-
isDragging: this.draggedItemId
|
75
|
+
dragData: { id: this.draggedItemId, initialGroup: container.id },
|
76
|
+
isDragging: this.draggedItemId
|
81
77
|
});
|
82
78
|
|
83
|
-
|
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 =
|
91
|
-
event.dataTransfer.setData(
|
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
|
-
|
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
|
-
|
126
|
-
|
127
|
-
|
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(
|
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
|
137
|
-
const fromIdx = items.indexOf(this.draggedItem);
|
138
|
-
const toIdx = items.indexOf(targetItem);
|
105
|
+
const items = Array.from(container.children);
|
139
106
|
|
140
|
-
|
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
|
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
|
154
|
-
|
155
|
-
|
156
|
-
|
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
|
161
|
-
|
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
|
164
|
-
|
144
|
+
const rect = targetItem.getBoundingClientRect();
|
145
|
+
const middleY = rect.top + rect.height / 2;
|
165
146
|
|
166
|
-
if (event.clientY <
|
167
|
-
|
147
|
+
if (event.clientY < middleY) {
|
148
|
+
container.insertBefore(this.draggedItem, targetItem);
|
168
149
|
} else {
|
169
|
-
|
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
|
-
|
178
|
-
|
179
|
-
|
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)
|
167
|
+
if (container) {
|
168
|
+
container.classList.add("active_container");
|
169
|
+
}
|
185
170
|
}
|
186
171
|
|
187
172
|
handleMultiContainerDragOver(event) {
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
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
|
-
|
210
|
-
|
211
|
-
|
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 =
|
208
|
+
this.draggedItem.style.opacity = '1';
|
216
209
|
|
217
210
|
// Handle empty containers
|
218
|
-
if (this.hasMultipleContainers && !container.querySelector(
|
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(
|
224
|
-
.
|
225
|
-
|
226
|
-
|
227
|
-
|
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
|
-
|
232
|
-
|
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
|
-
|
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.
|
253
|
-
|
249
|
+
this.setState({
|
250
|
+
isDragging: "",
|
251
|
+
activeContainer: ""
|
252
|
+
});
|
254
253
|
|
255
|
-
this.draggedItem
|
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
|
}
|
@@ -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.
|
@@ -0,0 +1,46 @@
|
|
1
|
+
<%= pb_rails("flex", props: {
|
2
|
+
dark: true,
|
3
|
+
orientation: "row",
|
4
|
+
vertical: "center",
|
5
|
+
margin_bottom: "md"
|
6
|
+
}) do %>
|
7
|
+
<%= pb_rails("body", props: { text: "Click info for more details" }) %>
|
8
|
+
|
9
|
+
<%= pb_rails("circle_icon_button", props: {
|
10
|
+
variant: "secondary",
|
11
|
+
icon: "info",
|
12
|
+
id: "append-to-popover-1"
|
13
|
+
}) %>
|
14
|
+
<%= pb_rails("popover", props: {
|
15
|
+
trigger_element_id: "append-to-popover-1",
|
16
|
+
tooltip_id: "append-to-tooltip-1",
|
17
|
+
offset: true,
|
18
|
+
position: "top",
|
19
|
+
append_to: "parent",
|
20
|
+
}) do %>
|
21
|
+
I'm a popover. I have been appended to my parent element.
|
22
|
+
<% end %>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<%= pb_rails("flex", props: {
|
26
|
+
dark: true,
|
27
|
+
orientation: "row",
|
28
|
+
vertical: "center"
|
29
|
+
}) do %>
|
30
|
+
<%= pb_rails("body", props: { text: "Click info for more details" }) %>
|
31
|
+
|
32
|
+
<%= pb_rails("circle_icon_button", props: {
|
33
|
+
variant: "secondary",
|
34
|
+
icon: "info",
|
35
|
+
id: "append-to-popover-2"
|
36
|
+
}) %>
|
37
|
+
<%= pb_rails("popover", props: {
|
38
|
+
trigger_element_id: "append-to-popover-2",
|
39
|
+
tooltip_id: "append-to-tooltip-2",
|
40
|
+
offset: true,
|
41
|
+
position: "top",
|
42
|
+
append_to: ".kit-show-wrapper",
|
43
|
+
}) do %>
|
44
|
+
I'm a popover. I have been appended to the .kit-show-wrapper.
|
45
|
+
<% end %>
|
46
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
By default, the popover tooltip attaches to the `<body>`. To attach it elsewhere, use the `append_to` prop. 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.
|
@@ -13,7 +13,15 @@ export default class PbPopover extends PbEnhancedElement {
|
|
13
13
|
}
|
14
14
|
|
15
15
|
moveTooltip() {
|
16
|
-
|
16
|
+
let container: HTMLElement | null;
|
17
|
+
|
18
|
+
if (this.appendTo === "parent") {
|
19
|
+
container = this.element.parentElement;
|
20
|
+
} else if (this.appendTo) {
|
21
|
+
container = document.querySelector(this.appendTo);
|
22
|
+
}
|
23
|
+
|
24
|
+
(container || document.body).appendChild(this.tooltip);
|
17
25
|
}
|
18
26
|
|
19
27
|
connect() {
|
@@ -108,4 +116,8 @@ export default class PbPopover extends PbEnhancedElement {
|
|
108
116
|
get closeOnClick() {
|
109
117
|
return this.element.dataset.pbPopoverCloseOnClick
|
110
118
|
}
|
119
|
+
|
120
|
+
get appendTo() {
|
121
|
+
return this.element.dataset.pbPopoverAppendTo;
|
122
|
+
}
|
111
123
|
}
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module Playbook
|
4
4
|
module PbPopover
|
5
5
|
class Popover < Playbook::KitBase
|
6
|
+
prop :append_to, type: Playbook::Props::String, default: "body"
|
6
7
|
prop :position, type: Playbook::Props::Enum,
|
7
8
|
values: %w[top bottom left right top-start top-end bottom-start bottom-end right-start right-end left-start left-end],
|
8
9
|
default: "left"
|
@@ -47,6 +48,7 @@ module Playbook
|
|
47
48
|
|
48
49
|
def data
|
49
50
|
Hash(values[:data]).merge(
|
51
|
+
pb_popover_append_to: append_to,
|
50
52
|
pb_popover_kit: true,
|
51
53
|
pb_popover_position: position,
|
52
54
|
pb_popover_trigger_element_id: trigger_element_id,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{jsx as jsx$1,Fragment,jsxs}from"react/jsx-runtime";import*as React from"react";import React__default,{createContext,useReducer,useRef,useState,useEffect,useMemo,useContext,createElement,forwardRef,useLayoutEffect,useCallback,useImperativeHandle,Component,Fragment as Fragment$1}from"react";import{s as getDefaultExportFromCjs,y as filter,z as omit,u as useCollapsible,A as get,k as getAllIcons,r as commonjsGlobal,x as colors$1,v as highchartsTheme,B as merge,t as highchartsDarkTheme,C as offset$2,E as shift$2,F as flip$2,G as computePosition$1,H as arrow$3,I as createCoords$1,J as round$1,K as max$1,L as min$1,M as rectToClientRect$1,N as getAugmentedNamespace,O as createPopper,Q as uniqueId,S as typography,T as cloneDeep,m as isEmpty$1,U as isString}from"./lib-
|
1
|
+
import{jsx as jsx$1,Fragment,jsxs}from"react/jsx-runtime";import*as React from"react";import React__default,{createContext,useReducer,useRef,useState,useEffect,useMemo,useContext,createElement,forwardRef,useLayoutEffect,useCallback,useImperativeHandle,Component,Fragment as Fragment$1}from"react";import{s as getDefaultExportFromCjs,y as filter,z as omit,u as useCollapsible,A as get,k as getAllIcons,r as commonjsGlobal,x as colors$1,v as highchartsTheme,B as merge,t as highchartsDarkTheme,C as offset$2,E as shift$2,F as flip$2,G as computePosition$1,H as arrow$3,I as createCoords$1,J as round$1,K as max$1,L as min$1,M as rectToClientRect$1,N as getAugmentedNamespace,O as createPopper,Q as uniqueId,S as typography,T as cloneDeep,m as isEmpty$1,U as isString}from"./lib-ClNg0TLS.js";import*as ReactDOM from"react-dom";import ReactDOM__default,{createPortal}from"react-dom";import{TrixEditor}from"react-trix";import Trix from"trix";import require$$0 from"react-is";const initialState={items:[],dragData:{id:"",initialGroup:""},isDragging:"",activeContainer:""};const reducer=(state,action)=>{switch(action.type){case"SET_ITEMS":return{...state,items:action.payload};case"SET_DRAG_DATA":return{...state,dragData:action.payload};case"SET_IS_DRAGGING":return{...state,isDragging:action.payload};case"SET_ACTIVE_CONTAINER":return{...state,activeContainer:action.payload};case"CHANGE_CATEGORY":return{...state,items:state.items.map((item=>item.id===action.payload.itemId?{...item,container:action.payload.container}:item))};case"REORDER_ITEMS":{const{dragId:dragId,targetId:targetId}=action.payload;const newItems=[...state.items];const draggedItem=newItems.find((item=>item.id===dragId));const targetItem=newItems.find((item=>item.id===targetId));if(!draggedItem||!targetItem||draggedItem.container!==targetItem.container){return state}if(dragId===targetId){return state}const draggedIndex=newItems.findIndex((item=>item.id===dragId));const targetIndex=newItems.findIndex((item=>item.id===targetId));if(draggedIndex===-1||targetIndex===-1){return state}newItems.splice(draggedIndex,1);newItems.splice(targetIndex,0,draggedItem);return{...state,items:newItems}}default:return state}};const DragContext=createContext({});const DraggableContext=()=>{const context=useContext(DragContext);if(context===void 0){throw new Error("DraggableContext must be used within a DraggableProvider")}return context};const DraggableProvider=({children:children,initialItems:initialItems,onReorder:onReorder,onDragStart:onDragStart,onDragEnter:onDragEnter,onDragEnd:onDragEnd,onDrop:onDrop,onDragOver:onDragOver,dropZone:dropZone={type:"ghost",color:"neutral",direction:"vertical"}})=>{const[state,dispatch]=useReducer(reducer,initialState);const initialItemsRef=useRef(initialItems);const[isDragging,setIsDragging]=useState(false);let dropZoneType="ghost";let dropZoneColor="neutral";let dropZoneDirection="vertical";if(typeof dropZone==="string"){dropZoneType=dropZone}else{dropZoneType=dropZone.type||"ghost";dropZoneColor=dropZone.type==="line"?dropZone.color||"primary":dropZone.color||"neutral";if(dropZoneType==="line"){dropZoneDirection=dropZone.direction||"vertical"}}useEffect((()=>{dispatch({type:"SET_ITEMS",payload:initialItems});initialItemsRef.current=initialItems}),[initialItems]);useEffect((()=>{if(onReorder){onReorder(state.items)}}),[state.items,onReorder]);const handleDragStart=(id,container)=>{setIsDragging(true);dispatch({type:"SET_DRAG_DATA",payload:{id:id,initialGroup:container}});dispatch({type:"SET_IS_DRAGGING",payload:id});dispatch({type:"SET_ACTIVE_CONTAINER",payload:container});if(onDragStart)onDragStart(id,container)};const handleDragEnter=(id,container)=>{if(!isDragging||container!==state.activeContainer)return;if(state.dragData.id===id)return;const draggedItem=state.items.find((item=>item.id===state.dragData.id));const targetItem=state.items.find((item=>item.id===id));if(!draggedItem||!targetItem||draggedItem.container!==targetItem.container){return}dispatch({type:"REORDER_ITEMS",payload:{dragId:state.dragData.id,targetId:id}});if(onDragEnter)onDragEnter(id,container)};const handleDragEnd=()=>{setIsDragging(false);dispatch({type:"SET_IS_DRAGGING",payload:""});dispatch({type:"SET_ACTIVE_CONTAINER",payload:""});if(onDragEnd)onDragEnd()};const handleDrop=container=>{const draggedItem=state.items.find((item=>item.id===state.dragData.id));if(draggedItem&&draggedItem.container!==container){dispatch({type:"CHANGE_CATEGORY",payload:{itemId:state.dragData.id,container:container}})}dispatch({type:"SET_IS_DRAGGING",payload:""});dispatch({type:"SET_ACTIVE_CONTAINER",payload:""});setIsDragging(false);if(onDrop)onDrop(container)};const handleDragOver=(e,container)=>{e.preventDefault();e.stopPropagation();dispatch({type:"SET_ACTIVE_CONTAINER",payload:container});if(onDragOver)onDragOver(e,container)};const contextValue=useMemo((()=>({items:state.items,dragData:state.dragData,isDragging:state.isDragging,activeContainer:state.activeContainer,dropZone:dropZoneType,dropZoneColor:dropZoneColor,...dropZoneType==="line"?{direction:dropZoneDirection}:{},handleDragStart:handleDragStart,handleDragEnter:handleDragEnter,handleDragEnd:handleDragEnd,handleDrop:handleDrop,handleDragOver:handleDragOver})),[state,dropZoneType,dropZoneColor,dropZoneDirection,handleDragStart,handleDragEnter,handleDragEnd,handleDrop,handleDragOver]);return jsx$1(DragContext.Provider,{value:contextValue,children:children})};var classnames$1={exports:{}};
|
2
2
|
/*!
|
3
3
|
Copyright (c) 2018 Jed Watson.
|
4
4
|
Licensed under the MIT License (MIT), see
|