playbook_ui 14.14.0.pre.alpha.play1868dependencyremovallodash6286 → 14.14.0.pre.alpha.play1868dependencyremovallodash6413
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_currency/_currency.tsx +46 -31
- data/app/pb_kits/playbook/pb_currency/currency.html.erb +15 -8
- data/app/pb_kits/playbook/pb_currency/currency.rb +17 -2
- data/app/pb_kits/playbook/pb_currency/docs/_currency_null_display.html.erb +22 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_null_display.jsx +34 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_null_display_rails.md +1 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_null_display_react.md +1 -0
- data/app/pb_kits/playbook/pb_currency/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_currency/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_drawer/_drawer.scss +32 -8
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_behavior.html.erb +8 -0
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.html.erb +33 -0
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.html.erb +0 -0
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_default.html.erb +20 -1
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.html.erb +24 -0
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.html.erb +21 -0
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.md +1 -0
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_sizes.html.erb +49 -0
- data/app/pb_kits/playbook/pb_drawer/docs/example.yml +5 -0
- data/app/pb_kits/playbook/pb_drawer/drawer.html.erb +20 -12
- data/app/pb_kits/playbook/pb_drawer/drawer.rb +49 -1
- data/app/pb_kits/playbook/pb_drawer/index.js +257 -0
- data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.tsx +2 -1
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -1
- data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.html.erb +11 -0
- data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.md +1 -0
- data/app/pb_kits/playbook/pb_overlay/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_overlay/index.js +61 -0
- data/app/pb_kits/playbook/pb_overlay/overlay.html.erb +5 -3
- data/app/pb_kits/playbook/pb_overlay/overlay.rb +9 -0
- data/app/pb_kits/playbook/pb_popover/_popover.tsx +1 -1
- data/app/pb_kits/playbook/pb_select/index.js +38 -0
- data/app/pb_kits/playbook/pb_select/select.rb +8 -0
- data/app/pb_kits/playbook/pb_tooltip/_tooltip.scss +0 -3
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_delay_rails.html.erb +39 -0
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_delay_rails.md +3 -0
- data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_interaction.html.erb +26 -0
- data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_tooltip/floating_ui.js +282 -0
- data/app/pb_kits/playbook/pb_tooltip/index.js +1 -1
- data/app/pb_kits/playbook/pb_tooltip/tooltip.rb +10 -2
- data/app/pb_kits/playbook/pb_treemap_chart/_treemap_chart.tsx +4 -5
- data/app/pb_kits/playbook/utilities/object.test.js +99 -0
- data/app/pb_kits/playbook/utilities/object.ts +8 -61
- data/dist/chunks/_typeahead-Dd8gkRY2.js +36 -0
- data/dist/chunks/{_weekday_stacked-D2tZHCNS.js → _weekday_stacked-bhqmtN2l.js} +2 -2
- data/dist/chunks/{lib-CrrD678a.js → lib-Dzh-65PP.js} +2 -2
- data/dist/chunks/{pb_form_validation-BbWhQeoO.js → pb_form_validation-1T09rwCG.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +2 -2
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +27 -6
- data/dist/chunks/_typeahead-CHxdYnAw.js +0 -36
@@ -0,0 +1,257 @@
|
|
1
|
+
import PbEnhancedElement from "../pb_enhanced_element"
|
2
|
+
|
3
|
+
export default class PbDrawer extends PbEnhancedElement {
|
4
|
+
static get selector() {
|
5
|
+
return ".pb_drawer_wrapper"
|
6
|
+
}
|
7
|
+
|
8
|
+
connect() {
|
9
|
+
this.handleToggleClick = this.handleToggleClick.bind(this)
|
10
|
+
this.handleOutsideClick = this.handleOutsideClick.bind(this)
|
11
|
+
this.handleResize = this.handleResize.bind(this)
|
12
|
+
|
13
|
+
this._toggleTriggers = Array.from(document.querySelectorAll("[data-open-drawer]"))
|
14
|
+
this._toggleTriggers.forEach(el => {
|
15
|
+
el.addEventListener("click", this.handleToggleClick)
|
16
|
+
})
|
17
|
+
|
18
|
+
this._wrappers = Array.from(document.querySelectorAll(".pb_drawer_wrapper"))
|
19
|
+
this._wrappers.forEach(el => {
|
20
|
+
el.addEventListener("mousedown", this.handleOutsideClick)
|
21
|
+
})
|
22
|
+
|
23
|
+
this._withinElementDrawers = Array.from(
|
24
|
+
document.querySelectorAll(".pb_drawer_within_element_rails[data-breakpoint]")
|
25
|
+
)
|
26
|
+
|
27
|
+
window.addEventListener("resize", this.handleResize)
|
28
|
+
this.handleResize()
|
29
|
+
}
|
30
|
+
|
31
|
+
disconnect() {
|
32
|
+
this._toggleTriggers.forEach(el => {
|
33
|
+
el.removeEventListener("click", this.handleToggleClick)
|
34
|
+
})
|
35
|
+
this._wrappers.forEach(el => {
|
36
|
+
el.removeEventListener("mousedown", this.handleOutsideClick)
|
37
|
+
})
|
38
|
+
window.removeEventListener("resize", this.handleResize)
|
39
|
+
}
|
40
|
+
|
41
|
+
getOverlay(wrapper) {
|
42
|
+
if (wrapper.id && wrapper.id.startsWith("drawer-wrapper-")) {
|
43
|
+
const overlayId = wrapper.id.replace("drawer-wrapper-", "drawer-overlay-")
|
44
|
+
return document.getElementById(overlayId)
|
45
|
+
}
|
46
|
+
return wrapper.querySelector(".pb_drawer_overlay") || wrapper.querySelector(".pb_drawer_no_overlay")
|
47
|
+
}
|
48
|
+
|
49
|
+
handleToggleClick(event) {
|
50
|
+
const trigger = event.currentTarget
|
51
|
+
const drawerId = trigger.dataset.openDrawer
|
52
|
+
const dialog = document.getElementById(drawerId)
|
53
|
+
if (!dialog) return
|
54
|
+
|
55
|
+
if (dialog.classList.contains("pb_drawer_within_element_rails")) {
|
56
|
+
if (dialog.classList.contains("open")) {
|
57
|
+
this.closeWithinElementDrawer(dialog)
|
58
|
+
dialog.dataset.manualOpen = "false"
|
59
|
+
} else {
|
60
|
+
this.openWithinElementDrawer(dialog)
|
61
|
+
dialog.dataset.manualOpen = "true"
|
62
|
+
}
|
63
|
+
return
|
64
|
+
}
|
65
|
+
|
66
|
+
const wrapperId = `drawer-wrapper-${drawerId}`
|
67
|
+
const wrapper = document.getElementById(wrapperId)
|
68
|
+
if (!wrapper) return
|
69
|
+
|
70
|
+
if (wrapper !== this.element) return
|
71
|
+
|
72
|
+
if (wrapper.classList.contains("open")) {
|
73
|
+
this.closeDrawer(wrapper, dialog)
|
74
|
+
wrapper.dataset.manualOpen = "false"
|
75
|
+
} else {
|
76
|
+
this.openDrawer(wrapper, dialog)
|
77
|
+
wrapper.dataset.manualOpen = "true"
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
openWithinElementDrawer(dialog) {
|
82
|
+
if (dialog.classList.contains("open")) return
|
83
|
+
dialog.style.maxHeight = "0px"
|
84
|
+
dialog.offsetHeight
|
85
|
+
dialog.classList.add("open")
|
86
|
+
// Get trigger's height and add it to the final height
|
87
|
+
const trigger = document.querySelector(`[data-open-drawer="${dialog.id}"]`)
|
88
|
+
const triggerHeight = trigger ? trigger.offsetHeight : 0
|
89
|
+
const finalHeight = (dialog.scrollHeight + triggerHeight) + "px"
|
90
|
+
dialog.style.maxHeight = finalHeight
|
91
|
+
dialog.addEventListener("transitionend", function handleOpenEnd(e) {
|
92
|
+
if (e.propertyName === "max-height") {
|
93
|
+
dialog.style.maxHeight = "none"
|
94
|
+
dialog.removeEventListener("transitionend", handleOpenEnd)
|
95
|
+
}
|
96
|
+
})
|
97
|
+
}
|
98
|
+
|
99
|
+
closeWithinElementDrawer(dialog) {
|
100
|
+
if (!dialog.classList.contains("open")) return
|
101
|
+
const currentHeight = dialog.scrollHeight
|
102
|
+
dialog.style.maxHeight = currentHeight + "px"
|
103
|
+
dialog.offsetHeight
|
104
|
+
dialog.classList.remove("open")
|
105
|
+
dialog.style.maxHeight = "0px"
|
106
|
+
dialog.addEventListener("transitionend", function handleCloseEnd(e) {
|
107
|
+
if (e.propertyName === "max-height") {
|
108
|
+
dialog.removeEventListener("transitionend", handleCloseEnd)
|
109
|
+
dialog.style.maxHeight = "0px"
|
110
|
+
}
|
111
|
+
})
|
112
|
+
}
|
113
|
+
|
114
|
+
openDrawer(wrapper, dialog) {
|
115
|
+
const behavior = wrapper.dataset.behavior
|
116
|
+
const size = wrapper.dataset.size
|
117
|
+
const placement = wrapper.dataset.placement
|
118
|
+
this.handlePushOpen(behavior, size, placement)
|
119
|
+
|
120
|
+
wrapper.style.display = ""
|
121
|
+
const overlay = this.getOverlay(wrapper)
|
122
|
+
if (overlay) overlay.style.display = ""
|
123
|
+
|
124
|
+
wrapper.classList.add("open")
|
125
|
+
dialog.classList.add("open")
|
126
|
+
}
|
127
|
+
|
128
|
+
closeDrawer(wrapper, dialog) {
|
129
|
+
const behavior = wrapper.dataset.behavior
|
130
|
+
this.handlePushClose(behavior)
|
131
|
+
|
132
|
+
if (wrapper.className.includes("open")) wrapper.style.display = "none"
|
133
|
+
const overlay = this.getOverlay(wrapper)
|
134
|
+
if (overlay && wrapper.className.includes("open")) overlay.style.display = "none"
|
135
|
+
|
136
|
+
wrapper.classList.remove("open")
|
137
|
+
dialog.classList.remove("open")
|
138
|
+
}
|
139
|
+
|
140
|
+
handleOutsideClick(event) {
|
141
|
+
const wrapper = event.currentTarget
|
142
|
+
const dialog = wrapper.querySelector(".pb_drawer")
|
143
|
+
const overlay = this.getOverlay(wrapper)
|
144
|
+
|
145
|
+
if (dialog && dialog.classList.contains("pb_drawer_within_element_rails")) {
|
146
|
+
return
|
147
|
+
}
|
148
|
+
|
149
|
+
if (wrapper.dataset.overlayClick === "overlay_close" && event.target === overlay) {
|
150
|
+
this.closeDrawer(wrapper, dialog)
|
151
|
+
event.stopPropagation()
|
152
|
+
return
|
153
|
+
}
|
154
|
+
|
155
|
+
const dialogRect = dialog.getBoundingClientRect()
|
156
|
+
const clickedOutside =
|
157
|
+
event.clientX < dialogRect.left ||
|
158
|
+
event.clientX > dialogRect.right ||
|
159
|
+
event.clientY < dialogRect.top ||
|
160
|
+
event.clientY > dialogRect.bottom
|
161
|
+
|
162
|
+
if (clickedOutside) {
|
163
|
+
this.closeDrawer(wrapper, dialog)
|
164
|
+
event.stopPropagation()
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
handleResize() {
|
169
|
+
const breakpointValues = {
|
170
|
+
none: 0,
|
171
|
+
xs: 575,
|
172
|
+
sm: 768,
|
173
|
+
md: 992,
|
174
|
+
lg: 1200,
|
175
|
+
xl: 1400,
|
176
|
+
}
|
177
|
+
|
178
|
+
// Process wrappers
|
179
|
+
this._wrappers.forEach(wrapper => {
|
180
|
+
const bp = wrapper.dataset.breakpoint || "none"
|
181
|
+
if (bp === "none") return
|
182
|
+
|
183
|
+
const threshold = breakpointValues[bp] || 0
|
184
|
+
const dialog = wrapper.querySelector(".pb_drawer")
|
185
|
+
const trigger = dialog ? document.querySelector(`[data-open-drawer="${dialog.id}"]`) : null
|
186
|
+
|
187
|
+
if (window.innerWidth >= threshold) {
|
188
|
+
if (!wrapper.classList.contains("open")) {
|
189
|
+
this.openDrawer(wrapper, dialog)
|
190
|
+
}
|
191
|
+
if (trigger) trigger.style.display = "none"
|
192
|
+
} else {
|
193
|
+
if (trigger) trigger.style.display = ""
|
194
|
+
if (wrapper.classList.contains("open") && wrapper.dataset.manualOpen !== "true") {
|
195
|
+
this.closeDrawer(wrapper, dialog)
|
196
|
+
}
|
197
|
+
}
|
198
|
+
})
|
199
|
+
|
200
|
+
// Process within element drawers
|
201
|
+
this._withinElementDrawers.forEach(drawer => {
|
202
|
+
const bp = drawer.dataset.breakpoint || "none"
|
203
|
+
if (bp === "none") return
|
204
|
+
|
205
|
+
const threshold = breakpointValues[bp] || 0
|
206
|
+
const trigger = document.querySelector(`[data-open-drawer="${drawer.id}"]`)
|
207
|
+
|
208
|
+
if (window.innerWidth >= threshold) {
|
209
|
+
if (!drawer.classList.contains("open")) {
|
210
|
+
this.openWithinElementDrawer(drawer)
|
211
|
+
}
|
212
|
+
if (trigger) trigger.style.display = "none"
|
213
|
+
} else {
|
214
|
+
if (trigger) trigger.style.display = ""
|
215
|
+
if (drawer.classList.contains("open") && drawer.dataset.manualOpen !== "true") {
|
216
|
+
this.closeWithinElementDrawer(drawer)
|
217
|
+
}
|
218
|
+
}
|
219
|
+
})
|
220
|
+
}
|
221
|
+
|
222
|
+
handlePushOpen(behavior, size, placement) {
|
223
|
+
if (behavior !== "push") return
|
224
|
+
|
225
|
+
const sizeMap = {
|
226
|
+
xl: "365px",
|
227
|
+
lg: "300px",
|
228
|
+
md: "250px",
|
229
|
+
sm: "200px",
|
230
|
+
xs: "64px",
|
231
|
+
full: "100%",
|
232
|
+
}
|
233
|
+
|
234
|
+
const body = document.querySelector("body")
|
235
|
+
if (!body) return
|
236
|
+
|
237
|
+
if (placement === "left") {
|
238
|
+
body.style.cssText = `margin-left: ${sizeMap[size]} !important; margin-right: '' !important;`
|
239
|
+
} else if (placement === "right") {
|
240
|
+
body.style.cssText = `margin-right: ${sizeMap[size]} !important; margin-left: '' !important;`
|
241
|
+
}
|
242
|
+
body.classList.add("PBDrawer__Body--open")
|
243
|
+
}
|
244
|
+
|
245
|
+
handlePushClose(behavior) {
|
246
|
+
if (behavior !== "push") return
|
247
|
+
|
248
|
+
const body = document.querySelector("body")
|
249
|
+
if (!body) return
|
250
|
+
|
251
|
+
if (body.classList.contains("PBDrawer__Body--open")) {
|
252
|
+
body.classList.add("PBDrawer__Body--close")
|
253
|
+
}
|
254
|
+
body.style.cssText = ""
|
255
|
+
body.classList.remove("PBDrawer__Body--open")
|
256
|
+
}
|
257
|
+
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import React from 'react'
|
2
|
-
import {
|
2
|
+
import { map } from 'lodash'
|
3
|
+
import { isEmpty, omitBy } from '../../utilities/object'
|
3
4
|
|
4
5
|
import Body from '../../pb_body/_body'
|
5
6
|
import Caption from '../../pb_caption/_caption'
|
@@ -32,7 +32,7 @@
|
|
32
32
|
<%= form.url_field :example_url_field_validation, props: { label: true, required: true } %>
|
33
33
|
<%= form.text_area :example_text_area_validation, props: { label: true, required: true } %>
|
34
34
|
<%= form.dropdown_field :example_dropdown_validation, props: { label: true, options: example_dropdown_options, required: true } %>
|
35
|
-
<%= form.select :example_select_validation, [ ["Yes", 1], ["No", 2] ], props: { label: true, blank_selection: "Select One...", required: true } %>
|
35
|
+
<%= form.select :example_select_validation, [ ["Yes", 1], ["No", 2] ], props: { label: true, blank_selection: "Select One...", required: true, validation_message: "Please, select an option." } %>
|
36
36
|
<%= form.collection_select :example_collection_select_validation, example_collection, :value, :name, props: { label: true, blank_selection: "Select One...", required: true } %>
|
37
37
|
<%= form.check_box :example_checkbox, props: { text: "Example Checkbox", label: true, required: true } %>
|
38
38
|
<%= form.date_picker :example_date_picker_2, props: { label: true, required: true } %>
|
data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.html.erb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
<%= pb_rails("overlay", props: { layout: { "x": "xl" }, color: "card_light", dynamic: true }) do %>
|
2
|
+
<%= pb_rails("flex", props: { column_gap: "lg", orientation: "row", overflow_x: "auto" }) do %>
|
3
|
+
<% 15.times do %>
|
4
|
+
<%= pb_rails("flex/flex_item") do %>
|
5
|
+
<%= pb_rails("card") do %>
|
6
|
+
Card content
|
7
|
+
<% end %>
|
8
|
+
<% end %>
|
9
|
+
<% end %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
Pass the `dynamic` prop to make the overlay render while the scrollbar isn't at either end on the scrollbar.
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import PbEnhancedElement from '../pb_enhanced_element'
|
2
|
+
|
3
|
+
const OVERLAY_SELECTOR = '[data-pb-overlay]'
|
4
|
+
const OVERLAY_SCROLL_ELEMENT = '[data-overlay-scroll-element]'
|
5
|
+
const PREVIOUS_OVERLAY_CLASSNAME = '[data-previous-overlay-classname]'
|
6
|
+
const SUBSEQUENT_OVERLAY_CLASSNAME = '[data-subsequent-overlay-classname]'
|
7
|
+
|
8
|
+
export default class PbOverlay extends PbEnhancedElement {
|
9
|
+
static get selector() {
|
10
|
+
return OVERLAY_SELECTOR
|
11
|
+
}
|
12
|
+
|
13
|
+
get target() {
|
14
|
+
return this.element.querySelector(OVERLAY_SCROLL_ELEMENT).children[0]
|
15
|
+
}
|
16
|
+
|
17
|
+
connect() {
|
18
|
+
this.handleOverlayDynamic()
|
19
|
+
}
|
20
|
+
|
21
|
+
handleOverlayDynamic() {
|
22
|
+
const isOverlayDynamic = this.element.dataset?.overlayDynamic
|
23
|
+
|
24
|
+
if (isOverlayDynamic) {
|
25
|
+
const previousOverlayElement = this.element.querySelector(PREVIOUS_OVERLAY_CLASSNAME)
|
26
|
+
const previousOverlayClassname = previousOverlayElement?.dataset?.previousOverlayClassname
|
27
|
+
const subsequentOverlayElement = this.element.querySelector(SUBSEQUENT_OVERLAY_CLASSNAME)
|
28
|
+
const subsequentOverlayClassname = subsequentOverlayElement?.dataset?.subsequentOverlayClassname
|
29
|
+
|
30
|
+
const handleScrollChange = (target) => {
|
31
|
+
const { scrollLeft, scrollWidth, clientWidth } = target
|
32
|
+
const isScrollAtStart = scrollLeft === 0
|
33
|
+
const isScrollAtEnd = scrollLeft + clientWidth >= scrollWidth - 1
|
34
|
+
|
35
|
+
if (isScrollAtStart) {
|
36
|
+
previousOverlayElement.classList.remove(previousOverlayClassname)
|
37
|
+
} else {
|
38
|
+
previousOverlayElement.classList.add(previousOverlayClassname)
|
39
|
+
}
|
40
|
+
|
41
|
+
if (isScrollAtEnd) {
|
42
|
+
subsequentOverlayElement.classList.remove(subsequentOverlayClassname)
|
43
|
+
} else {
|
44
|
+
subsequentOverlayElement.classList.add(subsequentOverlayClassname)
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
this.target.addEventListener('scroll', (event) => {
|
49
|
+
handleScrollChange(event.target)
|
50
|
+
})
|
51
|
+
|
52
|
+
handleScrollChange(this.target)
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
disconnect() {
|
57
|
+
if (this.element.dataset?.overlayDynamic) {
|
58
|
+
this.target.removeEventListener('scroll')
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
@@ -16,12 +16,14 @@ id: object.id,
|
|
16
16
|
<% end %>
|
17
17
|
|
18
18
|
<% else %>
|
19
|
-
<div class="<%= previous_overlay_class_name %>"></div>
|
19
|
+
<div class="<%= previous_overlay_class_name %>" data-previous-overlay-classname="<%= previous_overlay_class_name %>"></div>
|
20
20
|
|
21
|
-
|
21
|
+
<div data-overlay-scroll-element="true">
|
22
|
+
<%= content.presence %>
|
23
|
+
</div>
|
22
24
|
|
23
25
|
<% if has_subsequent_overlay %>
|
24
|
-
<div class="<%= subsequent_overlay_class_name %>"></div>
|
26
|
+
<div class="<%= subsequent_overlay_class_name %>" data-subsequent-overlay-classname="<%= subsequent_overlay_class_name %>"></div>
|
25
27
|
<% end %>
|
26
28
|
<% end %>
|
27
29
|
<% end %>
|
@@ -8,6 +8,8 @@ module Playbook
|
|
8
8
|
default: "card_light"
|
9
9
|
prop :layout, type: Playbook::Props::HashProp,
|
10
10
|
default: { "bottom": "full" }
|
11
|
+
prop :dynamic, type: Playbook::Props::Boolean,
|
12
|
+
default: false
|
11
13
|
|
12
14
|
def classname
|
13
15
|
generate_classname("pb_overlay")
|
@@ -105,6 +107,13 @@ module Playbook
|
|
105
107
|
"bg_dark": "#0a0527",
|
106
108
|
}
|
107
109
|
end
|
110
|
+
|
111
|
+
def data_attributes
|
112
|
+
data ||= {}
|
113
|
+
data.merge!("data-pb-overlay" => true)
|
114
|
+
data.merge!("data-overlay-dynamic" => true) if dynamic
|
115
|
+
data
|
116
|
+
end
|
108
117
|
end
|
109
118
|
end
|
110
119
|
end
|
@@ -19,7 +19,7 @@ import {
|
|
19
19
|
|
20
20
|
import classnames from "classnames";
|
21
21
|
import { globalProps, GlobalProps } from "../utilities/globalProps";
|
22
|
-
import { uniqueId } from '
|
22
|
+
import { uniqueId } from '../utilities/object';
|
23
23
|
|
24
24
|
type ModifiedGlobalProps = Omit<GlobalProps, 'minWidth' | 'maxHeight' | 'minHeight'>
|
25
25
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import PbEnhancedElement from "../pb_enhanced_element";
|
2
|
+
|
3
|
+
const SELECT_WRAPPER_SELECTOR = "[data-pb-select]";
|
4
|
+
const SELECT_VALIDATION_MESSAGE_CLASS = ".pb_body_kit_negative";
|
5
|
+
|
6
|
+
export default class PbSelect extends PbEnhancedElement {
|
7
|
+
static get selector() {
|
8
|
+
return SELECT_WRAPPER_SELECTOR;
|
9
|
+
}
|
10
|
+
|
11
|
+
connect() {
|
12
|
+
this.setValidationMessage();
|
13
|
+
}
|
14
|
+
|
15
|
+
setValidationMessage() {
|
16
|
+
const validationMessage = this.element.dataset?.validationMessage;
|
17
|
+
|
18
|
+
if (validationMessage) {
|
19
|
+
const selectElement = this.element.querySelector("select");
|
20
|
+
const setErrorTextContent = (text, timeout) => {
|
21
|
+
setTimeout(() => {
|
22
|
+
const errorMessageElement = this.element.querySelector(SELECT_VALIDATION_MESSAGE_CLASS);
|
23
|
+
if (errorMessageElement) {
|
24
|
+
errorMessageElement.textContent = text;
|
25
|
+
} else {
|
26
|
+
setErrorTextContent(text, 100);
|
27
|
+
}
|
28
|
+
}, timeout);
|
29
|
+
};
|
30
|
+
|
31
|
+
selectElement.addEventListener("change", (e) => {
|
32
|
+
if (!e.target.checkValidity()) {
|
33
|
+
setErrorTextContent(validationMessage, 300);
|
34
|
+
}
|
35
|
+
});
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
@@ -21,6 +21,7 @@ module Playbook
|
|
21
21
|
prop :options, type: Playbook::Props::HashArray, required: false, default: []
|
22
22
|
prop :show_arrow, type: Playbook::Props::Boolean, default: false
|
23
23
|
prop :required, type: Playbook::Props::Boolean, default: false
|
24
|
+
prop :validation_message, type: Playbook::Props::String, default: ""
|
24
25
|
|
25
26
|
def classnames
|
26
27
|
classname + inline_class + compact_class + show_arrow_class
|
@@ -88,6 +89,13 @@ module Playbook
|
|
88
89
|
"app/pb_kits/playbook/utilities/icons/angle-down.svg"
|
89
90
|
end
|
90
91
|
|
92
|
+
def data_attributes
|
93
|
+
data = attributes[:data] || {}
|
94
|
+
data.merge!("data-pb-select" => true)
|
95
|
+
data.merge!("data-validation-message" => validation_message) if validation_message.present?
|
96
|
+
data
|
97
|
+
end
|
98
|
+
|
91
99
|
private
|
92
100
|
|
93
101
|
def error_class
|
@@ -141,7 +141,6 @@ $tooltip_shadow: rgba(60, 106, 172, 0.18);
|
|
141
141
|
|
142
142
|
&[data-popper-placement="right"] {
|
143
143
|
box-shadow: -8px 0 28px 0 $tooltip_shadow;
|
144
|
-
margin: 0 0 0 $space_sm;
|
145
144
|
.arrow {
|
146
145
|
left: -18px;
|
147
146
|
right: auto;
|
@@ -156,7 +155,6 @@ $tooltip_shadow: rgba(60, 106, 172, 0.18);
|
|
156
155
|
|
157
156
|
&[data-popper-placement="bottom"] {
|
158
157
|
box-shadow: 0 -12px 28px 0 $tooltip_shadow;
|
159
|
-
margin: $space_sm 0 0 0;
|
160
158
|
.arrow {
|
161
159
|
top: -18px;
|
162
160
|
margin-bottom: 0;
|
@@ -169,7 +167,6 @@ $tooltip_shadow: rgba(60, 106, 172, 0.18);
|
|
169
167
|
|
170
168
|
&[data-popper-placement="left"] {
|
171
169
|
box-shadow: 8px 0 28px 0 $tooltip_shadow;
|
172
|
-
margin: 0 $space_sm 0 0;
|
173
170
|
.arrow {
|
174
171
|
margin-bottom: 0;
|
175
172
|
right: -18px;
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<%= pb_rails("flex", props: { orientation: "row", gap: "md" }) do %>
|
2
|
+
<%= pb_rails("flex/flex_item", props: {margin_top: "md"}) do %>
|
3
|
+
<%= pb_rails("button", props: {classname: "tooltip-delay", text: "1s delay"}) %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<%= pb_rails("flex/flex_item", props: {margin_top: "md"}) do %>
|
7
|
+
<%= pb_rails("button", props: {classname: "tooltip-open-delay", text: "Open only"}) %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<%= pb_rails("flex/flex_item", props: {margin_top: "md"}) do %>
|
11
|
+
<%= pb_rails("button", props: {classname: "tooltip-close-delay", text: "Close only"}) %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<%= pb_rails("tooltip", props: {
|
15
|
+
trigger_element_selector: ".tooltip-delay",
|
16
|
+
tooltip_id: "delay-tooltip",
|
17
|
+
position: 'top',
|
18
|
+
delay_open: 1000,
|
19
|
+
delay_close: 1000
|
20
|
+
}) do %>
|
21
|
+
1s open/close delay
|
22
|
+
<% end %>
|
23
|
+
<%= pb_rails("tooltip", props: {
|
24
|
+
trigger_element_selector: ".tooltip-open-delay",
|
25
|
+
tooltip_id: "open-tooltip",
|
26
|
+
position: 'top',
|
27
|
+
delay_open: 1000
|
28
|
+
}) do %>
|
29
|
+
1s open delay
|
30
|
+
<% end %>
|
31
|
+
<%= pb_rails("tooltip", props: {
|
32
|
+
trigger_element_selector: ".tooltip-close-delay",
|
33
|
+
tooltip_id: "close-tooltip",
|
34
|
+
position: 'top',
|
35
|
+
delay_close: 1000
|
36
|
+
}) do %>
|
37
|
+
1s close delay
|
38
|
+
<% end %>
|
39
|
+
<% end %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= pb_rails("flex", props: { gap: "md", wrap: true }) do %>
|
2
|
+
<%= pb_rails("flex/flex_item") do %>
|
3
|
+
<%= pb_rails("button", props: { text: "With Interaction", id: "tooltip-interaction"}) %>
|
4
|
+
|
5
|
+
<%= pb_rails("tooltip", props: {
|
6
|
+
trigger_element_selector: "#tooltip-interaction",
|
7
|
+
tooltip_id: "tooltip-with-interaction",
|
8
|
+
position: 'top',
|
9
|
+
interaction: true
|
10
|
+
}) do %>
|
11
|
+
You can copy me
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<%= pb_rails("flex/flex_item") do %>
|
16
|
+
<%= pb_rails("button", props: { text: "No Interaction", id: "tooltip-no-interaction"}) %>
|
17
|
+
|
18
|
+
<%= pb_rails("tooltip", props: {
|
19
|
+
trigger_element_selector: "#tooltip-no-interaction",
|
20
|
+
tooltip_id: "tooltip-without-interaction",
|
21
|
+
position: 'top',
|
22
|
+
}) do %>
|
23
|
+
I'm just a regular tooltip
|
24
|
+
<% end %>
|
25
|
+
<% end %>
|
26
|
+
<% end %>
|
@@ -2,8 +2,10 @@ examples:
|
|
2
2
|
|
3
3
|
rails:
|
4
4
|
- tooltip_default: Default
|
5
|
+
- tooltip_interaction: Content Interaction
|
5
6
|
- tooltip_selectors: Using Common Selectors
|
6
7
|
- tooltip_with_icon_circle: Icon Circle Tooltip
|
8
|
+
- tooltip_delay_rails: Delay
|
7
9
|
- tooltip_show_tooltip: Show Tooltip
|
8
10
|
|
9
11
|
react:
|