playbook_ui 14.15.0.pre.alpha.play1917lodashremoval2of36615 → 14.15.0.pre.rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +3 -143
  3. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +99 -45
  4. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +7 -123
  5. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +299 -153
  6. data/app/pb_kits/playbook/pb_bar_graph/_bar_graph.tsx +1 -1
  7. data/app/pb_kits/playbook/pb_card/_card.tsx +1 -2
  8. data/app/pb_kits/playbook/pb_circle_chart/_circle_chart.tsx +1 -1
  9. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +1 -4
  10. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +0 -2
  11. data/app/pb_kits/playbook/pb_dialog/dialog.html.erb +6 -5
  12. data/app/pb_kits/playbook/pb_dialog/dialogHelper.js +0 -2
  13. data/app/pb_kits/playbook/pb_drawer/_drawer.scss +3 -43
  14. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.jsx +3 -3
  15. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.jsx +37 -20
  16. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_default.html.erb +1 -20
  17. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +6 -6
  18. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.jsx +0 -1
  19. data/app/pb_kits/playbook/pb_drawer/docs/example.yml +0 -6
  20. data/app/pb_kits/playbook/pb_drawer/drawer.html.erb +12 -20
  21. data/app/pb_kits/playbook/pb_drawer/drawer.rb +1 -49
  22. data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.tsx +4 -5
  23. data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.tsx +2 -2
  24. data/app/pb_kits/playbook/pb_filter/Filter/SortMenu.tsx +1 -2
  25. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +2 -2
  26. data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +2 -9
  27. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +0 -4
  28. data/app/pb_kits/playbook/pb_form_pill/docs/example.yml +0 -2
  29. data/app/pb_kits/playbook/pb_form_pill/docs/index.js +0 -1
  30. data/app/pb_kits/playbook/pb_form_pill/form_pill.rb +1 -7
  31. data/app/pb_kits/playbook/pb_gauge/_gauge.tsx +1 -1
  32. data/app/pb_kits/playbook/pb_lightbox/Carousel/Slide.tsx +1 -1
  33. data/app/pb_kits/playbook/pb_lightbox/Carousel/Slides.tsx +1 -1
  34. data/app/pb_kits/playbook/pb_lightbox/Carousel/Thumbnails.tsx +1 -1
  35. data/app/pb_kits/playbook/pb_line_graph/_line_graph.tsx +1 -1
  36. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +0 -7
  37. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +3 -13
  38. data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +1 -2
  39. data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +0 -1
  40. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.rb +0 -6
  41. data/app/pb_kits/playbook/pb_overlay/_overlay.scss +0 -13
  42. data/app/pb_kits/playbook/pb_overlay/_overlay.tsx +1 -7
  43. data/app/pb_kits/playbook/pb_overlay/docs/example.yml +0 -3
  44. data/app/pb_kits/playbook/pb_overlay/docs/index.js +0 -1
  45. data/app/pb_kits/playbook/pb_overlay/overlay.html.erb +3 -5
  46. data/app/pb_kits/playbook/pb_overlay/overlay.rb +1 -16
  47. data/app/pb_kits/playbook/pb_overlay/overlay.test.jsx +0 -12
  48. data/app/pb_kits/playbook/pb_popover/_popover.tsx +2 -2
  49. data/app/pb_kits/playbook/pb_popover/popover.test.js +1 -1
  50. data/app/pb_kits/playbook/pb_radio/_radio.tsx +74 -85
  51. data/app/pb_kits/playbook/pb_radio/docs/example.yml +1 -2
  52. data/app/pb_kits/playbook/pb_radio/docs/index.js +0 -1
  53. data/app/pb_kits/playbook/pb_radio/radio.test.js +0 -16
  54. data/app/pb_kits/playbook/pb_select/docs/example.yml +0 -1
  55. data/app/pb_kits/playbook/pb_select/docs/index.js +0 -1
  56. data/app/pb_kits/playbook/pb_select/select.html.erb +5 -3
  57. data/app/pb_kits/playbook/pb_select/select.rb +0 -8
  58. data/app/pb_kits/playbook/pb_selectable_card/selectable_card.html.erb +5 -1
  59. data/app/pb_kits/playbook/pb_selectable_card_icon/selectable_card_icon.html.erb +4 -1
  60. data/app/pb_kits/playbook/pb_selectable_icon/selectable_icon.html.erb +5 -1
  61. data/app/pb_kits/playbook/pb_text_input/inputMask.ts +3 -2
  62. data/app/pb_kits/playbook/pb_timeline/_timeline.scss +2 -2
  63. data/app/pb_kits/playbook/pb_title/_title.scss +0 -32
  64. data/app/pb_kits/playbook/pb_title/_title.tsx +1 -10
  65. data/app/pb_kits/playbook/pb_title/docs/_title_default.html.erb +2 -1
  66. data/app/pb_kits/playbook/pb_title/docs/_title_default.jsx +1 -1
  67. data/app/pb_kits/playbook/pb_title/docs/example.yml +0 -2
  68. data/app/pb_kits/playbook/pb_title/docs/index.js +0 -1
  69. data/app/pb_kits/playbook/pb_title/title.rb +1 -10
  70. data/app/pb_kits/playbook/pb_tooltip/_tooltip.scss +3 -0
  71. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +0 -25
  72. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_icon.erb +10 -0
  73. data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +1 -4
  74. data/app/pb_kits/playbook/pb_tooltip/docs/index.js +0 -1
  75. data/app/pb_kits/playbook/pb_tooltip/index.js +1 -1
  76. data/app/pb_kits/playbook/pb_tooltip/tooltip.rb +2 -10
  77. data/app/pb_kits/playbook/pb_treemap_chart/_treemap_chart.tsx +1 -1
  78. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +5 -51
  79. data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +1 -5
  80. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_pills_async_custom_options.jsx +1 -1
  81. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_pills_async_users.jsx +1 -1
  82. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +0 -3
  83. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +0 -1
  84. data/app/pb_kits/playbook/pb_typeahead/index.ts +8 -61
  85. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +2 -17
  86. data/app/pb_kits/playbook/utilities/object.ts +1 -103
  87. data/app/pb_kits/playbook/utilities/text.ts +1 -1
  88. data/dist/chunks/_typeahead-PqkcDf1H.js +36 -0
  89. data/dist/chunks/_weekday_stacked-BrSrpj7J.js +45 -0
  90. data/dist/chunks/{lib-e7oBFFDo.js → lib-D3us1bGD.js} +2 -2
  91. data/dist/chunks/{pb_form_validation-CMXevI1t.js → pb_form_validation-BpihMSOQ.js} +1 -1
  92. data/dist/chunks/vendor.js +1 -1
  93. data/dist/menu.yml +2 -2
  94. data/dist/playbook-doc.js +1 -1
  95. data/dist/playbook-rails-react-bindings.js +1 -1
  96. data/dist/playbook-rails.js +1 -1
  97. data/dist/playbook.css +1 -1
  98. data/lib/playbook/version.rb +2 -2
  99. metadata +7 -61
  100. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +0 -127
  101. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +0 -55
  102. data/app/pb_kits/playbook/pb_advanced_table/Components/TablePagination.tsx +0 -33
  103. data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +0 -275
  104. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +0 -66
  105. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +0 -195
  106. data/app/pb_kits/playbook/pb_advanced_table/Utilities/CellRendererUtils.tsx +0 -73
  107. data/app/pb_kits/playbook/pb_advanced_table/Utilities/RowUtils.ts +0 -52
  108. data/app/pb_kits/playbook/pb_advanced_table/Utilities/TableContainerStyles.ts +0 -80
  109. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_infinite_scroll.jsx +0 -50
  110. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_infinite_scroll.json +0 -152002
  111. data/app/pb_kits/playbook/pb_date_picker/index.ts +0 -38
  112. data/app/pb_kits/playbook/pb_dialog/index.js +0 -75
  113. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_behavior.html.erb +0 -8
  114. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.html.erb +0 -33
  115. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.html.erb +0 -0
  116. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.html.erb +0 -24
  117. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.html.erb +0 -21
  118. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.md +0 -1
  119. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_sizes.html.erb +0 -49
  120. data/app/pb_kits/playbook/pb_drawer/index.js +0 -257
  121. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.html.erb +0 -40
  122. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.jsx +0 -50
  123. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.md +0 -3
  124. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.html.erb +0 -72
  125. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.jsx +0 -91
  126. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar.html.erb +0 -11
  127. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar.jsx +0 -37
  128. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar_rails.md +0 -1
  129. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar_react.md +0 -1
  130. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.html.erb +0 -11
  131. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.md +0 -1
  132. data/app/pb_kits/playbook/pb_overlay/index.js +0 -61
  133. data/app/pb_kits/playbook/pb_radio/docs/_radio_react_hook.jsx +0 -60
  134. data/app/pb_kits/playbook/pb_radio/docs/_radio_react_hook.md +0 -1
  135. data/app/pb_kits/playbook/pb_select/docs/_select_react_hook.jsx +0 -58
  136. data/app/pb_kits/playbook/pb_select/docs/_select_react_hook.md +0 -1
  137. data/app/pb_kits/playbook/pb_select/index.js +0 -38
  138. data/app/pb_kits/playbook/pb_title/docs/_title_display_size.html.erb +0 -7
  139. data/app/pb_kits/playbook/pb_title/docs/_title_display_size.jsx +0 -54
  140. data/app/pb_kits/playbook/pb_title/docs/_title_display_size.md +0 -1
  141. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_delay_rails.html.erb +0 -39
  142. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_delay_rails.md +0 -3
  143. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_icon_rails.html.erb +0 -22
  144. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_interaction.html.erb +0 -26
  145. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_sizing.jsx +0 -69
  146. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_sizing.md +0 -3
  147. data/app/pb_kits/playbook/pb_tooltip/floating_ui.js +0 -282
  148. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options.html.erb +0 -45
  149. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options.md +0 -5
  150. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options_pure_rails.html.erb +0 -33
  151. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options_pure_rails.md +0 -3
  152. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_react_hook.jsx +0 -66
  153. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_react_hook.md +0 -1
  154. data/app/pb_kits/playbook/utilities/object.test.js +0 -237
  155. data/dist/chunks/_typeahead-CdVbIURO.js +0 -36
  156. data/dist/chunks/_weekday_stacked-BSTKfYPJ.js +0 -45
@@ -1,282 +0,0 @@
1
- import PbEnhancedElement from '../pb_enhanced_element'
2
- import { computePosition, offset, flip, shift, arrow, autoUpdate } from '@floating-ui/dom'
3
-
4
- const TOOLTIP_OFFSET = 20
5
- const TOOLTIP_TIMEOUT = 250
6
- const SAFE_ZONE_MARGIN = 1
7
-
8
- export default class PbTooltipFloatingUi extends PbEnhancedElement {
9
- static get selector() {
10
- return '[data-pb-tooltip-kit="true"][data-pb-tooltip-delay-open], [data-pb-tooltip-kit="true"][data-pb-tooltip-delay-close], [data-pb-tooltip-kit="true"][data-pb-tooltip-interaction="true"]'
11
- }
12
-
13
- connect() {
14
- if (this.tooltipInteraction) {
15
- document.addEventListener('mousemove', (e) => {
16
- this.lastMouseX = e.clientX
17
- this.lastMouseY = e.clientY
18
- })
19
- }
20
-
21
- this.triggerElements.forEach((trigger) => {
22
- const method = this.triggerMethod
23
- const interactionEnabled = this.tooltipInteraction
24
-
25
- if (method === 'click') {
26
- trigger.addEventListener('click', () => {
27
- this.showTooltip(trigger)
28
- })
29
- } else {
30
- trigger.addEventListener('mouseenter', () => {
31
- clearSafeZoneListener(this)
32
- clearTimeout(this.mouseleaveTimeout)
33
- this.currentTrigger = trigger
34
- const delayOpen = this.delayOpen ? parseInt(this.delayOpen) : TOOLTIP_TIMEOUT
35
- this.mouseenterTimeout = setTimeout(() => {
36
- this.showTooltip(trigger)
37
- if (interactionEnabled) {
38
- this.checkCloseTooltip(trigger)
39
- }
40
- }, delayOpen)
41
- })
42
-
43
- trigger.addEventListener('mouseleave', () => {
44
- clearTimeout(this.mouseenterTimeout)
45
- if (this.delayClose) {
46
- const delayClose = parseInt(this.delayClose)
47
- this.mouseleaveTimeout = setTimeout(() => {
48
- if (interactionEnabled) {
49
- this.attachSafeZoneListener()
50
- } else {
51
- this.hideTooltip()
52
- }
53
- }, delayClose)
54
- } else {
55
- if (interactionEnabled) {
56
- this.attachSafeZoneListener()
57
- } else {
58
- this.hideTooltip()
59
- }
60
- }
61
- })
62
-
63
- if (interactionEnabled) {
64
- this.tooltip.addEventListener('mouseenter', () => {
65
- clearSafeZoneListener(this)
66
- })
67
-
68
- this.tooltip.addEventListener('mouseleave', () => {
69
- this.attachSafeZoneListener()
70
- })
71
- }
72
- }
73
- })
74
- }
75
-
76
- attachSafeZoneListener() {
77
- clearSafeZoneListener(this)
78
- this.safeZoneHandler = (e) => {
79
- if (!this.currentTrigger) return
80
- const triggerRect = this.currentTrigger.getBoundingClientRect()
81
- const tooltipRect = this.tooltip.getBoundingClientRect()
82
- const safeRect = getSafeZone(triggerRect, tooltipRect, this.position, SAFE_ZONE_MARGIN)
83
- if (!isPointInsideRect(e.clientX, e.clientY, safeRect)) {
84
- this.hideTooltip()
85
- clearSafeZoneListener(this)
86
- }
87
- }
88
- document.addEventListener('mousemove', this.safeZoneHandler)
89
- }
90
-
91
- checkCloseTooltip(trigger) {
92
- document.querySelector('body').addEventListener('click', ({ target }) => {
93
- const isTooltip = target.closest(`#${this.tooltipId}`) === this.tooltip
94
- const isTrigger = target.closest(this.triggerElementSelector) === trigger
95
- if (isTrigger || isTooltip) {
96
- this.checkCloseTooltip(trigger)
97
- } else {
98
- this.hideTooltip()
99
- }
100
- }, { once: true })
101
- }
102
-
103
- showTooltip(trigger) {
104
- if (this.shouldShowTooltip === 'false') return
105
-
106
- clearSafeZoneListener(this)
107
-
108
- this.tooltip.style.opacity = '1'
109
- this.tooltip.style.visibility = 'visible'
110
- this.tooltip.style.pointerEvents = 'auto'
111
-
112
- if (this.cleanup) {
113
- this.cleanup()
114
- }
115
-
116
- const arrowElement = document.querySelector(`#${this.tooltipId}-arrow`)
117
-
118
- this.cleanup = autoUpdate(trigger, this.tooltip, () => {
119
- computePosition(trigger, this.tooltip, {
120
- placement: this.position,
121
- strategy: 'fixed',
122
- middleware: [
123
- offset({ mainAxis: TOOLTIP_OFFSET, crossAxis: 0 }),
124
- flip(),
125
- shift(),
126
- arrow({ element: arrowElement })
127
- ],
128
- }).then(({ x, y, placement, middlewareData }) => {
129
- Object.assign(this.tooltip.style, {
130
- left: `${x}px`,
131
- top: `${y}px`,
132
- position: 'fixed'
133
- })
134
- this.tooltip.setAttribute('data-popper-placement', placement)
135
- if (arrowElement && middlewareData.arrow) {
136
- const { x: arrowX, y: arrowY } = middlewareData.arrow
137
- Object.assign(arrowElement.style, {
138
- left: arrowX != null ? `${arrowX}px` : '',
139
- top: arrowY != null ? `${arrowY}px` : '',
140
- position: 'absolute'
141
- })
142
- }
143
- })
144
- })
145
-
146
- this.tooltip.classList.add('show')
147
-
148
- if (this.triggerMethod === 'click') {
149
- clearTimeout(this.autoHideTimeout)
150
- this.autoHideTimeout = setTimeout(() => {
151
- this.hideTooltip()
152
- }, 1000)
153
- }
154
- }
155
-
156
- hideTooltip() {
157
- if (!this.tooltip) return
158
-
159
- this.tooltip.classList.add('fade_out')
160
- setTimeout(() => {
161
- if (this.cleanup) {
162
- this.cleanup()
163
- this.cleanup = null
164
- }
165
- this.tooltip.classList.remove('show')
166
- this.tooltip.classList.remove('fade_out')
167
- this.tooltip.style.opacity = '0'
168
- this.tooltip.style.visibility = 'hidden'
169
- this.tooltip.style.pointerEvents = 'none'
170
- this.tooltip.style.position = ''
171
- this.tooltip.style.top = ''
172
- this.tooltip.style.left = ''
173
- this.tooltip.style.transform = ''
174
- }, TOOLTIP_TIMEOUT)
175
- }
176
-
177
- get triggerElements() {
178
- let triggerEl
179
- if (this.triggerElementId) {
180
- triggerEl = document.querySelector(`#${this.triggerElementId}`)
181
- } else if (this.triggerElementSelector) {
182
- const selectorIsId = this.triggerElementSelector.indexOf('#') > -1
183
- triggerEl = selectorIsId
184
- ? document.querySelector(this.triggerElementSelector)
185
- : document.querySelectorAll(this.triggerElementSelector)
186
- } else {
187
- triggerEl = this.element
188
- }
189
- if (!triggerEl) {
190
- console.error('Tooltip Kit: No valid trigger element found!')
191
- return []
192
- }
193
- if (triggerEl.length === undefined) {
194
- triggerEl = [triggerEl]
195
- }
196
- return triggerEl
197
- }
198
-
199
- get tooltip() {
200
- return (this._tooltip = this._tooltip || this.element.querySelector(`#${this.tooltipId}`))
201
- }
202
-
203
- get position() {
204
- return this.element.dataset.pbTooltipPosition
205
- }
206
-
207
- get triggerElementId() {
208
- return this.element.dataset.pbTooltipTriggerElementId
209
- }
210
-
211
- get tooltipId() {
212
- return this.element.dataset.pbTooltipTooltipId
213
- }
214
-
215
- get triggerElementSelector() {
216
- return this.element.dataset.pbTooltipTriggerElementSelector
217
- }
218
-
219
- get shouldShowTooltip() {
220
- return this.element.dataset.pbTooltipShowTooltip
221
- }
222
-
223
- get triggerMethod() {
224
- return this.element.dataset.pbTooltipTriggerMethod || 'hover'
225
- }
226
-
227
- get tooltipInteraction() {
228
- return this.element.dataset.pbTooltipInteraction === 'true'
229
- }
230
-
231
- get delayOpen() {
232
- return this.element.dataset.pbTooltipDelayOpen
233
- }
234
-
235
- get delayClose() {
236
- return this.element.dataset.pbTooltipDelayClose
237
- }
238
- }
239
-
240
- function clearSafeZoneListener(context) {
241
- if (context.safeZoneHandler) {
242
- document.removeEventListener('mousemove', context.safeZoneHandler)
243
- context.safeZoneHandler = null
244
- }
245
- }
246
-
247
- function getSafeZone(triggerRect, tooltipRect, placement, margin) {
248
- let safeRect = {}
249
- if (placement.startsWith('top')) {
250
- safeRect.left = triggerRect.left - margin
251
- safeRect.right = triggerRect.right + margin
252
- safeRect.top = tooltipRect.bottom - margin
253
- safeRect.bottom = triggerRect.top + margin
254
- } else if (placement.startsWith('bottom')) {
255
- safeRect.left = triggerRect.left - margin
256
- safeRect.right = triggerRect.right + margin
257
- safeRect.top = triggerRect.bottom - margin
258
- safeRect.bottom = tooltipRect.top + margin
259
- } else if (placement.startsWith('left')) {
260
- safeRect.top = triggerRect.top - margin
261
- safeRect.bottom = triggerRect.bottom + margin
262
- safeRect.left = tooltipRect.right - margin
263
- safeRect.right = triggerRect.left + margin
264
- } else if (placement.startsWith('right')) {
265
- safeRect.top = triggerRect.top - margin
266
- safeRect.bottom = triggerRect.bottom + margin
267
- safeRect.left = triggerRect.right - margin
268
- safeRect.right = tooltipRect.left + margin
269
- } else {
270
- safeRect = {
271
- left: triggerRect.left - margin,
272
- right: triggerRect.right + margin,
273
- top: triggerRect.top - margin,
274
- bottom: triggerRect.bottom + margin,
275
- }
276
- }
277
- return safeRect
278
- }
279
-
280
- function isPointInsideRect(x, y, rect) {
281
- return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
282
- }
@@ -1,45 +0,0 @@
1
- <%= pb_rails("select", props: {
2
- id:"color_context_2",
3
- label: "Choose a Color",
4
- name: "color_name",
5
- options: [
6
- { value: "red", value_text: "Red" },
7
- { value: "blue", value_text: "Blue" },
8
- { value: "green", value_text: "Green" }
9
- ],
10
- }) %>
11
-
12
- <%= pb_rails("typeahead", props: {
13
- label: "Pick a Shade",
14
- is_multi: false,
15
- search_context_selector: "color_context_2",
16
- options_by_context: {
17
- "red": [
18
- { label: "Scarlet", value: "scarlet" },
19
- { label: "Mahogany", value: "mahogany" },
20
- { label: "Crimson", value: "crimson" }
21
- ],
22
- "blue": [
23
- { label: "Sky Blue", value: "sky" },
24
- { label: "Cerulean", value: "cerulean" },
25
- { label: "Navy", value: "navy" }
26
- ],
27
- "green": [
28
- { label: "Emerald", value: "emerald" },
29
- { label: "Mint", value: "mint" },
30
- { label: "Olive", value: "olive" }
31
- ]
32
- },
33
- id: "typeahead-dynamic-options",
34
- }) %>
35
-
36
-
37
- <%= javascript_tag defer: "defer" do %>
38
- document.addEventListener("pb-typeahead-kit-typeahead-dynamic-options-result-option-select", function(event) {
39
- console.log('Single Option selected')
40
- console.dir(event.detail)
41
- })
42
- document.addEventListener("pb-typeahead-kit-typeahead-dynamic-options-result-clear", function() {
43
- console.log('All options cleared')
44
- })
45
- <% end %>
@@ -1,5 +0,0 @@
1
- You can also set up a typeahead to render options dynamically based on input from a select. To achieve this:
2
- - The typeahead must have a unique `id`
3
- - Use the `search_context_selector` prop on the typeahead. The value here must match the id of the select so the Typeahead knows where to read the current "context" from.
4
- - Use `options_by_context` to pass in a hash whose keys match the possible values of your “context” select. Each key maps to an array of { label, value } objects. The typeahead automatically displays only the subset of options matching the current context.
5
- - Additionally, the optional `clear_on_context_change` prop controls whether the typeahead clears or not when a change happens in the linked select. This prop is set to true by default so that whenever a selection is made in the select, the Typeahead automatically clears its current input/selection.
@@ -1,33 +0,0 @@
1
- <%= pb_rails("select", props: {
2
- id:"color_context",
3
- label: "Choose a Color",
4
- name: "color_name_2",
5
- options: [
6
- { value: "red", value_text: "Red" },
7
- { value: "blue", value_text: "Blue" },
8
- { value: "green", value_text: "Green" }
9
- ],
10
- }) %>
11
-
12
- <%= pb_rails("typeahead", props: {
13
- label: "Pick a Shade",
14
- search_context_selector: "color_context",
15
- options_by_context: {
16
- "red": [
17
- { label: "Scarlet", value: "scarlet" },
18
- { label: "Mahogany", value: "mahogany" },
19
- { label: "Crimson", value: "crimson" }
20
- ],
21
- "blue": [
22
- { label: "Sky Blue", value: "sky" },
23
- { label: "Cerulean", value: "cerulean" },
24
- { label: "Navy", value: "navy" }
25
- ],
26
- "green": [
27
- { label: "Emerald", value: "emerald" },
28
- { label: "Mint", value: "mint" },
29
- { label: "Olive", value: "olive" }
30
- ]
31
- },
32
- search_term_minimum_length: 0,
33
- }) %>
@@ -1,3 +0,0 @@
1
- The dynamic rendering of options for the typeahead can also be achieved with a pure Rails implementation (not react rendered). For this implementation, use all the props as above with the following additions:
2
-
3
- - `search_term_minimum_length`: this sets the minimum input in the typeahead needed to display the dropdown. This is set to 3 by default. Set it to 0 for the dropdown to always display when the typeahead is interacted with.
@@ -1,66 +0,0 @@
1
- import React from 'react'
2
-
3
- import { Typeahead, Title } from 'playbook-ui'
4
- import { useForm } from 'react-hook-form'
5
-
6
- const languages = [
7
- { label: 'JavaScript', value: '1995', category: 'Web Development' },
8
- { label: 'Python', value: '1991', category: 'General Purpose' },
9
- { label: 'Java', value: '1995', category: 'Enterprise' },
10
- { label: 'C++', value: '1985', category: 'Systems Programming' },
11
- { label: 'Go', value: '2009', category: 'Systems Programming' },
12
- { label: 'Rust', value: '2010', category: 'Systems Programming' },
13
- { label: 'Swift', value: '2014', category: 'Mobile Development' },
14
- { label: 'Kotlin', value: '2011', category: 'Mobile Development' },
15
- { label: 'Ruby', value: '1995', category: 'General Purpose' },
16
- { label: 'PHP', value: '1995', category: 'Web Development' },
17
- ]
18
-
19
- const colors = [
20
- { label: 'Orange', value: '#FFA500' },
21
- { label: 'Red', value: '#FF0000' },
22
- { label: 'Green', value: '#00FF00' },
23
- { label: 'Blue', value: '#0000FF' },
24
- ]
25
-
26
- const TypeaheadReactHook = (props) => {
27
- const { register, watch } = useForm()
28
-
29
- const selectedLanguages = watch('languages')
30
- const selectedColor = watch('color')
31
-
32
- return (
33
- <>
34
- <Typeahead
35
- isMulti
36
- label="Multi Select Languages"
37
- multiKit="language"
38
- options={languages}
39
- {...props}
40
- {...register('languages')}
41
- />
42
- <Title
43
- size={4}
44
- text='Selected Languages'
45
- />
46
- {selectedLanguages && selectedLanguages.map(language => (
47
- <p key={language.label}>{`${language.label} - ${language.value} - ${language.category}`}</p>
48
- ))}
49
-
50
- <Typeahead
51
- label="Colors"
52
- marginTop="lg"
53
- options={colors}
54
- {...props}
55
- {...register('color')}
56
- />
57
- <Title
58
- size={4}
59
- text='Selected Color'
60
- />
61
- <p>{ selectedColor && `${selectedColor.label} - ${selectedColor.value}`}</p>
62
- </>
63
- )
64
- }
65
-
66
- export default TypeaheadReactHook
@@ -1 +0,0 @@
1
- You can pass `react-hook-form` props to the Typeahead kit.
@@ -1,237 +0,0 @@
1
- import { isEmpty, get, isString, uniqueId, omitBy, noop, merge, filter, find, partial } from './object';
2
-
3
- describe('Lodash functions', () => {
4
- describe('isEmpty', () => {
5
- test('returns true for empty objects', () => {
6
- expect(isEmpty({})).toBe(true);
7
- });
8
- test('returns true for empty arrays', () => {
9
- expect(isEmpty([])).toBe(true);
10
- });
11
- test('returns false for non-empty objects', () => {
12
- expect(isEmpty({ a: 1 })).toBe(false);
13
- });
14
- test('returns false for non-empty arrays', () => {
15
- expect(isEmpty([1])).toBe(false);
16
- });
17
- test('returns true for null and undefined', () => {
18
- expect(isEmpty(null)).toBe(true);
19
- expect(isEmpty(undefined)).toBe(true);
20
- });
21
- test('returns false for non-object, non-array values', () => {
22
- expect(isEmpty("hello")).toBe(false);
23
- expect(isEmpty(123)).toBe(false);
24
- });
25
- });
26
-
27
- describe('get', () => {
28
- const obj = { a: { b: { c: 42 } }, arr: [{ x: 1 }, { y: 2 }] };
29
-
30
- test('retrieves nested properties by dot path', () => {
31
- expect(get(obj, 'a.b.c')).toBe(42);
32
- });
33
- test('returns default value if path does not exist', () => {
34
- expect(get(obj, 'a.b.d', 'default')).toBe('default');
35
- });
36
- test('retrieves array values using bracket notation', () => {
37
- expect(get(obj, 'arr[1].y')).toBe(2);
38
- });
39
- test('returns default for non-existent paths', () => {
40
- expect(get(obj, 'non.existent.path', null)).toBe(null);
41
- });
42
- });
43
-
44
- describe('isString', () => {
45
- test('returns true for string literal', () => {
46
- expect(isString('test')).toBe(true);
47
- });
48
- test('returns true for String object', () => {
49
- expect(isString(new String('test'))).toBe(true);
50
- });
51
- test('returns false for non-string values', () => {
52
- expect(isString(123)).toBe(false);
53
- expect(isString(null)).toBe(false);
54
- expect(isString({ a: 1 })).toBe(false);
55
- expect(isString([ 'a','b','c' ])).toBe(false);
56
- });
57
- });
58
-
59
- describe('uniqueId', () => {
60
- test('generates unique ids without prefix', () => {
61
- const id1 = uniqueId();
62
- const id2 = uniqueId();
63
- expect(id1).not.toBe(id2);
64
- expect(Number(id1)).toBeLessThan(Number(id2));
65
- });
66
- test('generates unique ids with prefix', () => {
67
- const id1 = uniqueId('id_');
68
- const id2 = uniqueId('id_');
69
- const id3 = uniqueId('id_');
70
- expect(id1).not.toBe(id2);
71
- expect(id1).not.toBe(id3);
72
- expect(id2).not.toBe(id3);
73
- expect(id1.startsWith('id_')).toBe(true);
74
- expect(id2.startsWith('id_')).toBe(true);
75
- expect(id3.startsWith('id_')).toBe(true);
76
- });
77
- });
78
-
79
- describe('omitBy', () => {
80
- test('omits keys for which predicate returns true', () => {
81
- const obj = { a: 1, b: 2, c: 3 };
82
- const isEven = value => value % 2 === 0;
83
- const noEvenValues = omitBy(obj, isEven);
84
- expect(noEvenValues).toEqual({ a: 1, c: 3 });
85
- });
86
- test('returns empty object for null input', () => {
87
- expect(omitBy(null, () => true)).toEqual({});
88
- });
89
- test('returns empty object for non-object input', () => {
90
- expect(omitBy("string", () => true)).toEqual({});
91
- });
92
- test('returns original object if predicate returns false for all keys', () => {
93
- const obj = { a: 1, b: 2 };
94
- const isBiggerThanFive = value => value >= 4;
95
- const objWithSmallValues = omitBy(obj, isBiggerThanFive);
96
- expect(objWithSmallValues).toEqual(obj);
97
- });
98
- });
99
-
100
- describe('noop', () => {
101
- test('should do nothing and return undefined', () => {
102
- expect(noop()).toBeUndefined();
103
- });
104
- });
105
-
106
- describe('merge', () => {
107
- test('merges two objects correctly', () => {
108
- const obj1 = { a: 1, b: { x: 10 } };
109
- const obj2 = { b: { y: 20 }, c: 3 };
110
- expect(merge(obj1, obj2)).toEqual({ a: 1, b: { x: 10, y: 20 }, c: 3 });
111
- });
112
-
113
- test('when keys repeat use last occurrence value', () => {
114
- const obj1 = { a: 1 };
115
- const obj2 = { b: 2 };
116
- const obj3 = { a: 3, c: 4 };
117
- expect(merge(obj1, obj2, obj3)).toEqual({ a: 3, b: 2, c: 4 });
118
- });
119
-
120
- test('ignores non-object arguments', () => {
121
- expect(merge(null, { a: 1 })).toEqual({ a: 1 });
122
- expect(merge(undefined, { a: 1 })).toEqual({ a: 1 });
123
- });
124
- });
125
-
126
- describe('filter', () => {
127
- test('filters an array using a function predicate', () => {
128
- const arr = [1, 2, 3, 4, 5];
129
- const isEven = (n) => n % 2 === 0;
130
- expect(filter(arr, isEven)).toEqual([2, 4]);
131
- });
132
-
133
- test('filters an array using a string predicate', () => {
134
- const arr = [
135
- { active: true, name: 'John' },
136
- { active: false, name: 'Jane' },
137
- { active: true, name: 'Doe' }
138
- ];
139
- expect(filter(arr, 'active')).toEqual([
140
- { active: true, name: 'John' },
141
- { active: true, name: 'Doe' }
142
- ]);
143
- });
144
-
145
- test('filters an array using an array predicate', () => {
146
- const arr = [
147
- { type: 'fruit', name: 'apple' },
148
- { type: 'vegetable', name: 'carrot' },
149
- { type: 'fruit', name: 'banana' }
150
- ];
151
- expect(filter(arr, ['type', 'fruit'])).toEqual([
152
- { type: 'fruit', name: 'apple' },
153
- { type: 'fruit', name: 'banana' }
154
- ]);
155
- });
156
-
157
- test('filters an array using an object predicate', () => {
158
- const arr = [
159
- { type: 'fruit', name: 'apple', color: 'red' },
160
- { type: 'fruit', name: 'banana', color: 'yellow' },
161
- { type: 'vegetable', name: 'carrot', color: 'orange' }
162
- ];
163
- expect(filter(arr, { type: 'fruit', color: 'red' })).toEqual([
164
- { type: 'fruit', name: 'apple', color: 'red' }
165
- ]);
166
- });
167
- });
168
-
169
- describe('find', () => {
170
- test('finds an element using a function predicate', () => {
171
- const arr = [1, 2, 3, 4, 5];
172
- const greaterThanThree = (n) => n > 3;
173
- expect(find(arr, greaterThanThree)).toBe(4);
174
- });
175
-
176
- test('finds an element using a string predicate', () => {
177
- const arr = [
178
- { active: false, name: 'John' },
179
- { active: true, name: 'Jane' },
180
- { active: true, name: 'Doe' }
181
- ];
182
- expect(find(arr, 'active')).toEqual({ active: true, name: 'Jane' });
183
- });
184
-
185
- test('finds an element using an array predicate', () => {
186
- const arr = [
187
- { type: 'fruit', name: 'apple' },
188
- { type: 'vegetable', name: 'carrot' },
189
- { type: 'fruit', name: 'banana' }
190
- ];
191
- expect(find(arr, ['type', 'vegetable'])).toEqual({ type: 'vegetable', name: 'carrot' });
192
- });
193
-
194
- test('finds an element using an object predicate', () => {
195
- const arr = [
196
- { type: 'fruit', name: 'apple', color: 'red' },
197
- { type: 'fruit', name: 'banana', color: 'yellow' },
198
- { type: 'vegetable', name: 'carrot', color: 'orange' }
199
- ];
200
- expect(find(arr, { name: 'banana', color: 'yellow' })).toEqual({ type: 'fruit', name: 'banana', color: 'yellow' });
201
- });
202
-
203
- test('returns undefined if no element matches', () => {
204
- const arr = [{ id: 1 }, { id: 2 }];
205
- expect(find(arr, { id: 3 })).toBeUndefined();
206
- });
207
- });
208
-
209
- describe('partial', () => {
210
- function add(a, b, c) {
211
- return a + b + c;
212
- }
213
-
214
- test('partials arguments without placeholders', () => {
215
- const add5 = partial(add, 2, 3);
216
- expect(add5(4)).toBe(9);
217
- });
218
-
219
- test('partials arguments with placeholders', () => {
220
- const addWithPlaceholder = partial(add, partial.placeholder, 3, partial.placeholder);
221
- expect(addWithPlaceholder(2, 4)).toBe(9);
222
- });
223
-
224
- test('returns correct result when all arguments are pre-filled', () => {
225
- const addAll = partial(add, 1, 2, 3);
226
- expect(addAll()).toBe(6);
227
- });
228
-
229
- test('appends extra arguments when provided', () => {
230
- function join(...args) {
231
- return args.join('_');
232
- }
233
- const joinPartial = partial(join, 'a');
234
- expect(joinPartial('b', 'c')).toBe('a_b_c');
235
- });
236
- });
237
- });