@gitlab/ui 126.3.3 → 126.4.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 (100) hide show
  1. package/dist/components/base/alert/alert.js +9 -0
  2. package/dist/components/base/breadcrumb/breadcrumb.js +3 -0
  3. package/dist/components/base/breadcrumb/breadcrumb_item.js +15 -0
  4. package/dist/components/base/datepicker/datepicker.js +54 -0
  5. package/dist/components/base/daterange_picker/daterange_picker.js +70 -1
  6. package/dist/components/base/filtered_search/filtered_search.js +1 -1
  7. package/dist/components/base/form/form_input_group/form_input_group.js +9 -1
  8. package/dist/components/base/path/data.js +1 -1
  9. package/dist/components/base/search_box_by_click/search_box_by_click.js +9 -1
  10. package/dist/components/charts/shared/tooltip/tooltip.js +2 -2
  11. package/dist/components/charts/stacked_column/stacked_column.js +16 -5
  12. package/dist/components/dashboards/dashboard_panel/dashboard_panel.js +10 -2
  13. package/dist/directives/resize_observer/resize_observer.js +10 -3
  14. package/dist/index.css +1 -1
  15. package/dist/index.css.map +1 -1
  16. package/dist/tailwind.css +1 -1
  17. package/dist/tailwind.css.map +1 -1
  18. package/dist/utils/charts/config.js +36 -1
  19. package/dist/utils/charts/mock_data.js +18 -1
  20. package/dist/vendor/bootstrap-vue/src/components/modal/modal.js +7 -2
  21. package/dist/vendor/bootstrap-vue/src/components/table/helpers/mixin-filtering.js +8 -0
  22. package/dist/vendor/bootstrap-vue/src/components/table/helpers/mixin-items.js +4 -0
  23. package/dist/vendor/bootstrap-vue/src/components/table/helpers/mixin-provider.js +8 -4
  24. package/dist/vendor/bootstrap-vue/src/components/table/helpers/mixin-selectable.js +3 -19
  25. package/dist/vendor/bootstrap-vue/src/components/table/helpers/mixin-sorting.js +1 -16
  26. package/dist/vendor/bootstrap-vue/src/components/table/helpers/mixin-tbody.js +8 -2
  27. package/dist/vendor/bootstrap-vue/src/components/table/helpers/mixin-thead.js +4 -0
  28. package/dist/vendor/bootstrap-vue/src/components/toast/helpers/bv-toast.js +15 -7
  29. package/dist/vendor/bootstrap-vue/src/components/tooltip/helpers/bv-popper.js +15 -13
  30. package/dist/vendor/bootstrap-vue/src/components/tooltip/helpers/bv-tooltip.js +24 -21
  31. package/dist/vendor/bootstrap-vue/src/components/tooltip/tooltip.js +10 -9
  32. package/dist/vendor/bootstrap-vue/src/components/transition/bv-transition.js +3 -0
  33. package/dist/vendor/bootstrap-vue/src/components/transporter/transporter.js +29 -21
  34. package/dist/vendor/bootstrap-vue/src/constants/events.js +1 -5
  35. package/dist/vendor/bootstrap-vue/src/directives/tooltip/tooltip.js +15 -13
  36. package/dist/vendor/bootstrap-vue/src/directives/visible/visible.js +15 -16
  37. package/dist/vendor/bootstrap-vue/src/mixins/attrs.js +1 -18
  38. package/dist/vendor/bootstrap-vue/src/mixins/dropdown.js +8 -3
  39. package/dist/vendor/bootstrap-vue/src/mixins/has-listener.js +1 -1
  40. package/dist/vendor/bootstrap-vue/src/mixins/listeners.js +13 -12
  41. package/dist/vendor/bootstrap-vue/src/utils/cache.js +35 -13
  42. package/dist/vendor/bootstrap-vue/src/utils/config-set.js +16 -11
  43. package/dist/vendor/bootstrap-vue/src/utils/config.js +4 -10
  44. package/dist/vendor/bootstrap-vue/src/utils/create-new-child-component.js +102 -3
  45. package/dist/vendor/bootstrap-vue/src/utils/element-to-vue-instance-registry.js +3 -9
  46. package/dist/vendor/bootstrap-vue/src/utils/get-instance-from-directive.js +1 -3
  47. package/dist/vendor/bootstrap-vue/src/utils/on-instance-destroy.js +22 -0
  48. package/dist/vendor/bootstrap-vue/src/utils/plugins.js +2 -21
  49. package/dist/vendor/bootstrap-vue/src/utils/router.js +15 -1
  50. package/dist/vendor/bootstrap-vue/src/utils/safe-vue-instance.js +1 -1
  51. package/dist/vendor/bootstrap-vue/src/vue.js +16 -81
  52. package/package.json +6 -6
  53. package/src/components/base/alert/alert.vue +9 -0
  54. package/src/components/base/breadcrumb/breadcrumb.vue +3 -0
  55. package/src/components/base/breadcrumb/breadcrumb_item.vue +15 -0
  56. package/src/components/base/datepicker/datepicker.vue +54 -0
  57. package/src/components/base/daterange_picker/daterange_picker.vue +70 -1
  58. package/src/components/base/filtered_search/filtered_search.vue +1 -1
  59. package/src/components/base/form/form_input_group/form_input_group.vue +9 -1
  60. package/src/components/base/new_dropdowns/dropdown_item.scss +1 -1
  61. package/src/components/base/path/data.js +1 -1
  62. package/src/components/base/search_box_by_click/search_box_by_click.vue +9 -0
  63. package/src/components/charts/shared/tooltip/tooltip.vue +2 -1
  64. package/src/components/charts/stacked_column/stacked_column.vue +16 -5
  65. package/src/components/dashboards/dashboard_panel/dashboard_panel.vue +27 -9
  66. package/src/directives/resize_observer/resize_observer.js +6 -0
  67. package/src/utils/charts/config.js +28 -0
  68. package/src/utils/charts/mock_data.js +7 -0
  69. package/src/vendor/bootstrap-vue/src/components/modal/modal.js +6 -1
  70. package/src/vendor/bootstrap-vue/src/components/table/helpers/mixin-filtering.js +8 -0
  71. package/src/vendor/bootstrap-vue/src/components/table/helpers/mixin-items.js +4 -0
  72. package/src/vendor/bootstrap-vue/src/components/table/helpers/mixin-provider.js +9 -4
  73. package/src/vendor/bootstrap-vue/src/components/table/helpers/mixin-selectable.js +3 -24
  74. package/src/vendor/bootstrap-vue/src/components/table/helpers/mixin-sorting.js +1 -20
  75. package/src/vendor/bootstrap-vue/src/components/table/helpers/mixin-tbody.js +8 -2
  76. package/src/vendor/bootstrap-vue/src/components/table/helpers/mixin-thead.js +4 -0
  77. package/src/vendor/bootstrap-vue/src/components/toast/helpers/bv-toast.js +15 -13
  78. package/src/vendor/bootstrap-vue/src/components/tooltip/helpers/bv-popper.js +14 -13
  79. package/src/vendor/bootstrap-vue/src/components/tooltip/helpers/bv-tooltip.js +16 -23
  80. package/src/vendor/bootstrap-vue/src/components/tooltip/tooltip.js +10 -9
  81. package/src/vendor/bootstrap-vue/src/components/transition/bv-transition.js +4 -0
  82. package/src/vendor/bootstrap-vue/src/components/transporter/transporter.js +36 -26
  83. package/src/vendor/bootstrap-vue/src/constants/events.js +0 -5
  84. package/src/vendor/bootstrap-vue/src/directives/tooltip/tooltip.js +17 -13
  85. package/src/vendor/bootstrap-vue/src/directives/visible/visible.js +13 -9
  86. package/src/vendor/bootstrap-vue/src/mixins/attrs.js +1 -17
  87. package/src/vendor/bootstrap-vue/src/mixins/dropdown.js +8 -3
  88. package/src/vendor/bootstrap-vue/src/mixins/has-listener.js +1 -1
  89. package/src/vendor/bootstrap-vue/src/mixins/listeners.js +14 -14
  90. package/src/vendor/bootstrap-vue/src/utils/cache.js +27 -7
  91. package/src/vendor/bootstrap-vue/src/utils/config-set.js +16 -11
  92. package/src/vendor/bootstrap-vue/src/utils/config.js +4 -10
  93. package/src/vendor/bootstrap-vue/src/utils/create-new-child-component.js +85 -2
  94. package/src/vendor/bootstrap-vue/src/utils/element-to-vue-instance-registry.js +3 -10
  95. package/src/vendor/bootstrap-vue/src/utils/get-instance-from-directive.js +1 -4
  96. package/src/vendor/bootstrap-vue/src/utils/on-instance-destroy.js +21 -0
  97. package/src/vendor/bootstrap-vue/src/utils/plugins.js +1 -26
  98. package/src/vendor/bootstrap-vue/src/utils/router.js +13 -1
  99. package/src/vendor/bootstrap-vue/src/utils/safe-vue-instance.js +1 -1
  100. package/src/vendor/bootstrap-vue/src/vue.js +11 -98
@@ -3,13 +3,8 @@
3
3
  */
4
4
 
5
5
  import { NAME_TOAST, NAME_TOASTER, NAME_TOAST_POP } from '../../../constants/components'
6
- import {
7
- EVENT_NAME_DESTROYED,
8
- EVENT_NAME_HIDDEN,
9
- EVENT_NAME_HIDE,
10
- EVENT_NAME_SHOW,
11
- HOOK_EVENT_NAME_DESTROYED
12
- } from '../../../constants/events'
6
+ import { EVENT_NAME_DESTROYED, EVENT_NAME_HIDE, EVENT_NAME_SHOW } from '../../../constants/events'
7
+ import { onInstanceDestroy } from '../../../utils/on-instance-destroy'
13
8
  import { useParentMixin } from '../../../mixins/use-parent'
14
9
  import { concat } from '../../../utils/array'
15
10
  import { getComponentConfig } from '../../../utils/config'
@@ -77,8 +72,8 @@ const plugin = Vue => {
77
72
  }
78
73
  },
79
74
  mounted() {
80
- // Self destruct handler
81
- const handleDestroy = () => {
75
+ // Self destruct handler (stored as instance property for use in onAfterLeave)
76
+ this.$_handleDestroy = () => {
82
77
  // Ensure the toast has been force hidden
83
78
  this.localShow = false
84
79
  this.doRender = false
@@ -93,16 +88,23 @@ const plugin = Vue => {
93
88
  })
94
89
  }
95
90
  // Self destruct if parent destroyed
96
- this.bvParent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy)
97
- // Self destruct after hidden
98
- this.$once(EVENT_NAME_HIDDEN, handleDestroy)
91
+ onInstanceDestroy(this.bvParent, this.$_handleDestroy)
99
92
  // Self destruct when toaster is destroyed
100
93
  this.listenOnRoot(getRootEventName(NAME_TOASTER, EVENT_NAME_DESTROYED), toaster => {
101
94
  /* istanbul ignore next: hard to test */
102
95
  if (toaster === this.toaster) {
103
- handleDestroy()
96
+ this.$_handleDestroy()
104
97
  }
105
98
  })
99
+ },
100
+ methods: {
101
+ // Override parent's onAfterLeave to self-destruct after hidden
102
+ onAfterLeave() {
103
+ // Call parent's implementation
104
+ BToast.options.methods.onAfterLeave.call(this)
105
+ // Self destruct after hidden
106
+ this.$_handleDestroy()
107
+ }
106
108
  }
107
109
  })
108
110
 
@@ -12,9 +12,9 @@ import {
12
12
  EVENT_NAME_HIDDEN,
13
13
  EVENT_NAME_HIDE,
14
14
  EVENT_NAME_SHOW,
15
- EVENT_NAME_SHOWN,
16
- HOOK_EVENT_NAME_DESTROYED
15
+ EVENT_NAME_SHOWN
17
16
  } from '../../../constants/events'
17
+ import { onInstanceDestroy } from '../../../utils/on-instance-destroy'
18
18
  import {
19
19
  PROP_TYPE_ARRAY_STRING,
20
20
  PROP_TYPE_NUMBER_STRING,
@@ -136,12 +136,8 @@ export const BVPopper = /*#__PURE__*/ extend({
136
136
  this.$_popper = null
137
137
  // Ensure we show as we mount
138
138
  this.localShow = true
139
- // Create popper instance before shown
140
- this.$on(EVENT_NAME_SHOW, el => {
141
- this.popperCreate(el)
142
- })
143
- // Self destruct handler
144
- const handleDestroy = () => {
139
+ // Self destruct handler (stored as instance property for use in afterLeave)
140
+ this.$_handleDestroy = () => {
145
141
  this.$nextTick(() => {
146
142
  // In a `requestAF()` to release control back to application
147
143
  requestAF(() => {
@@ -150,9 +146,7 @@ export const BVPopper = /*#__PURE__*/ extend({
150
146
  })
151
147
  }
152
148
  // Self destruct if parent destroyed
153
- this.bvParent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy)
154
- // Self destruct after hidden
155
- this.$once(EVENT_NAME_HIDDEN, handleDestroy)
149
+ onInstanceDestroy(this.bvParent, this.$_handleDestroy)
156
150
  },
157
151
  beforeMount() {
158
152
  // Ensure that the attachment position is correct before mounting
@@ -236,10 +230,17 @@ export const BVPopper = /*#__PURE__*/ extend({
236
230
  props: { appear: true, noFade },
237
231
  on: {
238
232
  // Events used by parent component/instance
239
- beforeEnter: el => this.$emit(EVENT_NAME_SHOW, el),
233
+ beforeEnter: el => {
234
+ this.popperCreate(el)
235
+ this.$emit(EVENT_NAME_SHOW, el)
236
+ },
240
237
  afterEnter: el => this.$emit(EVENT_NAME_SHOWN, el),
241
238
  beforeLeave: el => this.$emit(EVENT_NAME_HIDE, el),
242
- afterLeave: el => this.$emit(EVENT_NAME_HIDDEN, el)
239
+ afterLeave: el => {
240
+ this.$emit(EVENT_NAME_HIDDEN, el)
241
+ // Self destruct after hidden
242
+ this.$_handleDestroy()
243
+ }
243
244
  }
244
245
  },
245
246
  [this.localShow ? this.renderTemplate(h) : h()]
@@ -18,10 +18,9 @@ import {
18
18
  EVENT_NAME_MOUSELEAVE,
19
19
  EVENT_NAME_SHOW,
20
20
  EVENT_NAME_SHOWN,
21
- EVENT_OPTIONS_NO_CAPTURE,
22
- HOOK_EVENT_NAME_BEFORE_DESTROY,
23
- HOOK_EVENT_NAME_DESTROYED
21
+ EVENT_OPTIONS_NO_CAPTURE
24
22
  } from '../../../constants/events'
23
+ import { onInstanceDestroy } from '../../../utils/on-instance-destroy'
25
24
  import { useParentMixin } from '../../../mixins/use-parent'
26
25
  import { arrayIncludes, concat, from as arrayFrom } from '../../../utils/array'
27
26
  import { getInstanceFromElement } from '../../../utils/element-to-vue-instance-registry'
@@ -65,7 +64,7 @@ import { toInteger } from '../../../utils/number'
65
64
  import { keys } from '../../../utils/object'
66
65
  import { warn } from '../../../utils/warn'
67
66
  import { BvEvent } from '../../../utils/bv-event.class'
68
- import { createNewChildComponent } from '../../../utils/create-new-child-component'
67
+ import { createNewChildComponent, eventProp } from '../../../utils/create-new-child-component'
69
68
  import { listenOnRootMixin } from '../../../mixins/listen-on-root'
70
69
  import { BVTooltipTemplate } from './bv-tooltip-template'
71
70
 
@@ -250,7 +249,7 @@ export const BVTooltip = /*#__PURE__*/ extend({
250
249
 
251
250
  // Destroy ourselves when the parent is destroyed
252
251
  if (this.bvParent) {
253
- this.bvParent.$once(HOOK_EVENT_NAME_BEFORE_DESTROY, () => {
252
+ onInstanceDestroy(this.bvParent, () => {
254
253
  this.$nextTick(() => {
255
254
  // In a `requestAF()` to release control back to application
256
255
  requestAF(() => {
@@ -343,29 +342,23 @@ export const BVTooltip = /*#__PURE__*/ extend({
343
342
  // Ensure the following are integers
344
343
  offset: toInteger(this.offset, 0),
345
344
  arrowPadding: toInteger(this.arrowPadding, 0),
346
- boundaryPadding: toInteger(this.boundaryPadding, 0)
345
+ boundaryPadding: toInteger(this.boundaryPadding, 0),
346
+ // Template transition phase events (handled once only)
347
+ [eventProp(EVENT_NAME_SHOW, { once: true })]: this.onTemplateShow,
348
+ [eventProp(EVENT_NAME_SHOWN, { once: true })]: this.onTemplateShown,
349
+ [eventProp(EVENT_NAME_HIDE, { once: true })]: this.onTemplateHide,
350
+ [eventProp(EVENT_NAME_HIDDEN, { once: true })]: this.onTemplateHidden,
351
+ // Convenience events from template
352
+ [eventProp(EVENT_NAME_FOCUSIN)]: this.handleEvent,
353
+ [eventProp(EVENT_NAME_FOCUSOUT)]: this.handleEvent,
354
+ [eventProp(EVENT_NAME_MOUSEENTER)]: this.handleEvent,
355
+ [eventProp(EVENT_NAME_MOUSELEAVE)]: this.handleEvent
347
356
  }
348
357
  }))
349
358
  // We set the initial reactive data (values that can be changed while open)
350
359
  this.handleTemplateUpdate()
351
- // Template transition phase events (handled once only)
352
- // When the template has mounted, but not visibly shown yet
353
- $tip.$once(EVENT_NAME_SHOW, this.onTemplateShow)
354
- // When the template has completed showing
355
- $tip.$once(EVENT_NAME_SHOWN, this.onTemplateShown)
356
- // When the template has started to hide
357
- $tip.$once(EVENT_NAME_HIDE, this.onTemplateHide)
358
- // When the template has completed hiding
359
- $tip.$once(EVENT_NAME_HIDDEN, this.onTemplateHidden)
360
360
  // When the template gets destroyed for any reason
361
- $tip.$once(HOOK_EVENT_NAME_DESTROYED, this.destroyTemplate)
362
- // Convenience events from template
363
- // To save us from manually adding/removing DOM
364
- // listeners to tip element when it is open
365
- $tip.$on(EVENT_NAME_FOCUSIN, this.handleEvent)
366
- $tip.$on(EVENT_NAME_FOCUSOUT, this.handleEvent)
367
- $tip.$on(EVENT_NAME_MOUSEENTER, this.handleEvent)
368
- $tip.$on(EVENT_NAME_MOUSELEAVE, this.handleEvent)
361
+ onInstanceDestroy($tip, this.destroyTemplate)
369
362
  // Mount (which triggers the `show`)
370
363
  $tip.$mount(container.appendChild(document.createElement('div')))
371
364
  // Template will automatically remove its markup from DOM when hidden
@@ -28,7 +28,7 @@ import { getScopeId } from '../../utils/get-scope-id'
28
28
  import { isUndefinedOrNull } from '../../utils/inspect'
29
29
  import { pick } from '../../utils/object'
30
30
  import { makeProp, makePropsConfigurable } from '../../utils/props'
31
- import { createNewChildComponent } from '../../utils/create-new-child-component'
31
+ import { createNewChildComponent, eventProp } from '../../utils/create-new-child-component'
32
32
  import { normalizeSlotMixin } from '../../mixins/normalize-slot'
33
33
  import { BVTooltip } from './helpers/bv-tooltip'
34
34
 
@@ -197,17 +197,18 @@ export const BTooltip = /*#__PURE__*/ extend({
197
197
  // Create the instance
198
198
  const $toolpop = (this.$_toolpop = createNewChildComponent(this, Component, {
199
199
  // Pass down the scoped style ID
200
- _scopeId: scopeId || undefined
200
+ _scopeId: scopeId || undefined,
201
+ propsData: {
202
+ [eventProp(EVENT_NAME_SHOW)]: this.onShow,
203
+ [eventProp(EVENT_NAME_SHOWN)]: this.onShown,
204
+ [eventProp(EVENT_NAME_HIDE)]: this.onHide,
205
+ [eventProp(EVENT_NAME_HIDDEN)]: this.onHidden,
206
+ [eventProp(EVENT_NAME_DISABLED)]: this.onDisabled,
207
+ [eventProp(EVENT_NAME_ENABLED)]: this.onEnabled
208
+ }
201
209
  }))
202
210
  // Set the initial data
203
211
  $toolpop.updateData(this.templateData)
204
- // Set listeners
205
- $toolpop.$on(EVENT_NAME_SHOW, this.onShow)
206
- $toolpop.$on(EVENT_NAME_SHOWN, this.onShown)
207
- $toolpop.$on(EVENT_NAME_HIDE, this.onHide)
208
- $toolpop.$on(EVENT_NAME_HIDDEN, this.onHidden)
209
- $toolpop.$on(EVENT_NAME_DISABLED, this.onDisabled)
210
- $toolpop.$on(EVENT_NAME_ENABLED, this.onEnabled)
211
212
  // Initially disabled?
212
213
  if (this[MODEL_PROP_NAME_ENABLED]) {
213
214
  // Initially disabled
@@ -86,6 +86,10 @@ export const BVTransition = /*#__PURE__*/ extend({
86
86
 
87
87
  const dataCopy = { ...data }
88
88
  delete dataCopy.props
89
+ Object.keys(props).forEach(key => {
90
+ delete dataCopy[key]
91
+ })
92
+
89
93
  return h(
90
94
  'transition',
91
95
  // Any transition event listeners will get merged here
@@ -1,4 +1,4 @@
1
- import { Vue, extend, isVue3 } from '../../vue'
1
+ import { isVue3, extend } from '../../vue'
2
2
  import { NAME_TRANSPORTER, NAME_TRANSPORTER_TARGET } from '../../constants/components'
3
3
  import { IS_BROWSER } from '../../constants/env'
4
4
  import {
@@ -79,7 +79,7 @@ export const props = {
79
79
  // --- Main component ---
80
80
 
81
81
  // @vue/component
82
- const BVTransporterVue2 = /*#__PURE__*/ extend({
82
+ export const BVTransporter = /*#__PURE__*/ extend({
83
83
  name: NAME_TRANSPORTER,
84
84
  mixins: [normalizeSlotMixin],
85
85
  props,
@@ -87,28 +87,41 @@ const BVTransporterVue2 = /*#__PURE__*/ extend({
87
87
  disabled: {
88
88
  immediate: true,
89
89
  handler(disabled) {
90
+ // Vue 2 only: manage manual portaling
91
+ if (isVue3(this)) return
92
+
90
93
  disabled ? this.unmountTarget() : this.$nextTick(this.mountTarget)
91
94
  }
92
95
  }
93
96
  },
94
97
  created() {
95
- // Create private non-reactive props
98
+ // Vue 2 only: create private non-reactive props
99
+ if (isVue3(this)) return
100
+
96
101
  this.$_defaultFn = null
97
102
  this.$_target = null
98
103
  },
99
104
  beforeMount() {
105
+ // Vue 2 only
106
+ if (isVue3(this)) return
107
+
100
108
  this.mountTarget()
101
109
  },
102
110
  updated() {
111
+ // Vue 2 only
103
112
  // We need to make sure that all children have completed updating
104
113
  // before rendering in the target
105
114
  // `vue-simple-portal` has the this in a `$nextTick()`,
106
115
  // while `portal-vue` doesn't
107
116
  // Just trying to see if the `$nextTick()` delay is required or not
108
117
  // Since all slots in Vue 2.6.x are always functions
118
+ if (isVue3(this)) return
109
119
  this.updateTarget()
110
120
  },
111
121
  beforeDestroy() {
122
+ // Vue 2 only
123
+ if (isVue3(this)) return
124
+
112
125
  this.unmountTarget()
113
126
  this.$_defaultFn = null
114
127
  },
@@ -167,36 +180,33 @@ const BVTransporterVue2 = /*#__PURE__*/ extend({
167
180
  }
168
181
  },
169
182
  render(h) {
170
- // This component has no root element, so only a single VNode is allowed
171
- if (this.disabled) {
172
- const $nodes = concat(this.normalizeSlot()).filter(identity)
173
- if ($nodes.length > 0 && !$nodes[0].text) {
174
- return $nodes[0]
183
+ if (isVue3(this)) {
184
+ // Vue 3: use native Teleport
185
+ if (this.disabled) {
186
+ const $nodes = concat(this.normalizeSlot()).filter(identity)
187
+ if ($nodes.length > 0) {
188
+ return $nodes[0]
189
+ }
175
190
  }
191
+
192
+ const { Teleport } = this.$.appContext.config.globalProperties.constructor
193
+
194
+ return h(
195
+ Teleport,
196
+ {
197
+ to: this.container
198
+ },
199
+ this.normalizeSlot()
200
+ )
176
201
  }
177
- return h()
178
- }
179
- })
180
202
 
181
- const BVTransporterVue3 = /*#__PURE__*/ extend({
182
- name: NAME_TRANSPORTER,
183
- mixins: [normalizeSlotMixin],
184
- props,
185
- render(h) {
203
+ // Vue 2: this component has no root element, so only a single VNode is allowed
186
204
  if (this.disabled) {
187
205
  const $nodes = concat(this.normalizeSlot()).filter(identity)
188
- if ($nodes.length > 0) {
206
+ if ($nodes.length > 0 && !$nodes[0].text) {
189
207
  return $nodes[0]
190
208
  }
191
209
  }
192
- return h(
193
- Vue.Teleport,
194
- {
195
- to: this.container
196
- },
197
- this.normalizeSlot()
198
- )
210
+ return h()
199
211
  }
200
212
  })
201
-
202
- export const BVTransporter = isVue3 ? BVTransporterVue3 : BVTransporterVue2
@@ -1,5 +1,3 @@
1
- import { isVue3 } from '../vue'
2
-
3
1
  export const EVENT_NAME_ACTIVATE_TAB = 'activate-tab'
4
2
  export const EVENT_NAME_BLUR = 'blur'
5
3
  export const EVENT_NAME_CANCEL = 'cancel'
@@ -45,9 +43,6 @@ export const EVENT_NAME_SORT_CHANGED = 'sort-changed'
45
43
  export const EVENT_NAME_TOGGLE = 'toggle'
46
44
  export const EVENT_NAME_UPDATE = 'update'
47
45
 
48
- export const HOOK_EVENT_NAME_BEFORE_DESTROY = isVue3 ? 'vnodeBeforeUnmount' : 'hook:beforeDestroy'
49
- export const HOOK_EVENT_NAME_DESTROYED = isVue3 ? 'vNodeUnmounted' : 'hook:destroyed'
50
-
51
46
  export const MODEL_EVENT_NAME_PREFIX = 'update:'
52
47
 
53
48
  export const ROOT_EVENT_NAME_PREFIX = 'bv'
@@ -2,7 +2,7 @@ import { NAME_TOOLTIP } from '../../constants/components'
2
2
  import { IS_BROWSER } from '../../constants/env'
3
3
  import { EVENT_NAME_SHOW } from '../../constants/events'
4
4
  import { concat } from '../../utils/array'
5
- import { isVue3, nextTick } from '../../vue'
5
+ import { isVue3 } from '../../vue'
6
6
  import { getComponentConfig } from '../../utils/config'
7
7
  import { getScopeId } from '../../utils/get-scope-id'
8
8
  import { identity } from '../../utils/identity'
@@ -18,7 +18,7 @@ import {
18
18
  import { looseEqual } from '../../utils/loose-equal'
19
19
  import { toInteger } from '../../utils/number'
20
20
  import { keys } from '../../utils/object'
21
- import { createNewChildComponent } from '../../utils/create-new-child-component'
21
+ import { createNewChildComponent, eventProp } from '../../utils/create-new-child-component'
22
22
  import { BVTooltip } from '../../components/tooltip/helpers/bv-tooltip'
23
23
 
24
24
  // Key which we use to store tooltip object on element
@@ -86,7 +86,9 @@ const parseBindings = (bindings, vnode) => /* istanbul ignore next: not easy to
86
86
  // If title is not provided, try title attribute
87
87
  if (isUndefined(config.title)) {
88
88
  // Try attribute
89
- const attrs = isVue3 ? vnode.props : (vnode.data || {}).attrs
89
+ const attrs = isVue3(getInstanceFromDirective(vnode, bindings))
90
+ ? vnode.props
91
+ : (vnode.data || {}).attrs
90
92
  config.title = attrs && !isUndefinedOrNull(attrs.title) ? attrs.title : undefined
91
93
  }
92
94
 
@@ -195,17 +197,19 @@ const applyTooltip = (el, bindings, vnode) => {
195
197
  const parent = getInstanceFromDirective(vnode, bindings)
196
198
  el[BV_TOOLTIP] = createNewChildComponent(parent, BVTooltip, {
197
199
  // Add the parent's scoped style attribute data
198
- _scopeId: getScopeId(parent, undefined)
199
- })
200
- el[BV_TOOLTIP].__bv_prev_data__ = {}
201
- el[BV_TOOLTIP].$on(EVENT_NAME_SHOW, () => /* istanbul ignore next: for now */ {
202
- // Before showing the tooltip, we update the title if it is a function
203
- if (isFunction(config.title)) {
204
- el[BV_TOOLTIP].updateData({
205
- title: config.title(el)
206
- })
200
+ _scopeId: getScopeId(parent, undefined),
201
+ propsData: {
202
+ [eventProp(EVENT_NAME_SHOW)]: () => /* istanbul ignore next: for now */ {
203
+ // Before showing the tooltip, we update the title if it is a function
204
+ if (isFunction(config.title)) {
205
+ el[BV_TOOLTIP].updateData({
206
+ title: config.title(el)
207
+ })
208
+ }
209
+ }
207
210
  }
208
211
  })
212
+ el[BV_TOOLTIP].__bv_prev_data__ = {}
209
213
  }
210
214
  const data = {
211
215
  title: config.title,
@@ -260,7 +264,7 @@ export const VBTooltip = {
260
264
  // waits until the containing component and children have finished updating
261
265
  componentUpdated(el, bindings, vnode) {
262
266
  // Performed in a `$nextTick()` to prevent render update loops
263
- nextTick(() => {
267
+ getInstanceFromDirective(vnode, bindings).$nextTick(() => {
264
268
  applyTooltip(el, bindings, vnode)
265
269
  })
266
270
  },
@@ -36,12 +36,12 @@ import { requestAF } from '../../utils/dom'
36
36
  import { isFunction } from '../../utils/inspect'
37
37
  import { looseEqual } from '../../utils/loose-equal'
38
38
  import { clone, keys } from '../../utils/object'
39
- import { nextTick } from '../../vue'
39
+ import { getInstanceFromDirective } from '../../utils/get-instance-from-directive'
40
40
 
41
41
  const OBSERVER_PROP_NAME = '__bv__visibility_observer'
42
42
 
43
43
  class VisibilityObserver {
44
- constructor(el, options) {
44
+ constructor(el, options, instance) {
45
45
  this.el = el
46
46
  this.callback = options.callback
47
47
  this.margin = options.margin || 0
@@ -49,6 +49,7 @@ class VisibilityObserver {
49
49
  this.observer = null
50
50
  this.visible = undefined
51
51
  this.doneOnce = false
52
+ this.instance = instance
52
53
  // Create the observer instance (if possible)
53
54
  this.createObserver()
54
55
  }
@@ -88,7 +89,7 @@ class VisibilityObserver {
88
89
 
89
90
  // Start observing in a `$nextTick()` (to allow DOM to complete rendering)
90
91
  /* istanbul ignore next: IntersectionObserver not supported in JSDOM */
91
- nextTick(() => {
92
+ this.instance.$nextTick(() => {
92
93
  requestAF(() => {
93
94
  // Placed in an `if` just in case we were destroyed before
94
95
  // this `requestAnimationFrame` runs
@@ -128,7 +129,8 @@ const destroy = el => {
128
129
  delete el[OBSERVER_PROP_NAME]
129
130
  }
130
131
 
131
- const bind = (el, { value, modifiers }) => {
132
+ const bind = (el, bindings, vnode) => {
133
+ const { value, modifiers } = bindings
132
134
  // `value` is the callback function
133
135
  const options = {
134
136
  margin: '0px',
@@ -147,26 +149,28 @@ const bind = (el, { value, modifiers }) => {
147
149
  // Destroy any previous observer
148
150
  destroy(el)
149
151
  // Create new observer
150
- el[OBSERVER_PROP_NAME] = new VisibilityObserver(el, options)
152
+ const instance = getInstanceFromDirective(vnode, bindings)
153
+ el[OBSERVER_PROP_NAME] = new VisibilityObserver(el, options, instance)
151
154
  // Store the current modifiers on the object (cloned)
152
155
  el[OBSERVER_PROP_NAME]._prevModifiers = clone(modifiers)
153
156
  }
154
157
 
155
158
  // When the directive options may have been updated (or element)
156
- const componentUpdated = (el, { value, oldValue, modifiers }, vnode) => {
159
+ const componentUpdated = (el, bindings, vnode) => {
160
+ const { value, oldValue, modifiers } = bindings
157
161
  // Compare value/oldValue and modifiers to see if anything has changed
158
162
  // and if so, destroy old observer and create new observer
159
163
  /* istanbul ignore next */
160
- modifiers = clone(modifiers)
164
+ const clonedModifiers = clone(modifiers)
161
165
  /* istanbul ignore next */
162
166
  if (
163
167
  el &&
164
168
  (value !== oldValue ||
165
169
  !el[OBSERVER_PROP_NAME] ||
166
- !looseEqual(modifiers, el[OBSERVER_PROP_NAME]._prevModifiers))
170
+ !looseEqual(clonedModifiers, el[OBSERVER_PROP_NAME]._prevModifiers))
167
171
  ) {
168
172
  // Re-bind on element
169
- bind(el, { value, modifiers }, vnode)
173
+ bind(el, bindings, vnode)
170
174
  }
171
175
  }
172
176
 
@@ -1,19 +1,3 @@
1
1
  import { makePropCacheMixin } from '../utils/cache'
2
- import { extend, isVue3 } from '../vue'
3
2
 
4
- const attrsMixinVue2 = makePropCacheMixin('$attrs', 'bvAttrs')
5
- const attrsMixinVue3 = extend({
6
- computed: {
7
- bvAttrs() {
8
- const bvAttrs = { ...this.$attrs }
9
- Object.keys(bvAttrs).forEach(key => {
10
- if (bvAttrs[key] === undefined) {
11
- delete bvAttrs[key]
12
- }
13
- })
14
- return bvAttrs
15
- }
16
- }
17
- })
18
-
19
- export const attrsMixin = isVue3 ? attrsMixinVue3 : attrsMixinVue2
3
+ export const attrsMixin = makePropCacheMixin('$attrs', 'bvAttrs')
@@ -142,7 +142,7 @@ export const dropdownMixin = extend({
142
142
  this.visibleChangePrevented = true
143
143
  this.visible = oldValue
144
144
  // Just in case a child element triggered `this.hide(true)`
145
- this.$off(EVENT_NAME_HIDDEN, this.focusToggler)
145
+ this.$_focusOnHidden = false
146
146
  return
147
147
  }
148
148
  if (newValue) {
@@ -223,6 +223,11 @@ export const dropdownMixin = extend({
223
223
  this.emitOnRoot(ROOT_EVENT_NAME_HIDDEN, this)
224
224
  this.$emit(EVENT_NAME_HIDDEN)
225
225
  this.destroyPopper()
226
+ // Handle pending focus request
227
+ if (this.$_focusOnHidden) {
228
+ this.$_focusOnHidden = false
229
+ this.focusToggler()
230
+ }
226
231
  },
227
232
  createPopper(element) {
228
233
  this.destroyPopper()
@@ -299,7 +304,7 @@ export const dropdownMixin = extend({
299
304
  this.visible = false
300
305
  if (refocus) {
301
306
  // Child element is closing the dropdown on click
302
- this.$once(EVENT_NAME_HIDDEN, this.focusToggler)
307
+ this.$_focusOnHidden = true
303
308
  }
304
309
  },
305
310
  // Called only by a button that toggles the menu
@@ -361,7 +366,7 @@ export const dropdownMixin = extend({
361
366
  this.visible = false
362
367
  stopEvent(event)
363
368
  // Return focus to original trigger button
364
- this.$once(EVENT_NAME_HIDDEN, this.focusToggler)
369
+ this.$_focusOnHidden = true
365
370
  }
366
371
  },
367
372
  // Called only in split button mode, for the split button
@@ -9,7 +9,7 @@ import { isArray, isUndefined } from '../utils/inspect'
9
9
  export const hasListenerMixin = extend({
10
10
  methods: {
11
11
  hasListener(name) {
12
- if (isVue3) {
12
+ if (isVue3(this)) {
13
13
  return true
14
14
  }
15
15
  // Only includes listeners registered via `v-on:name`
@@ -1,24 +1,24 @@
1
- import { makePropCacheMixin } from '../utils/cache'
2
- import { extend, isVue3 } from '../vue'
1
+ import { isVue3 } from '../vue'
2
+ import { makePropCacheMixin, getInternalPropName } from '../utils/cache'
3
3
 
4
- const listenersMixinVue2 = makePropCacheMixin('$listeners', 'bvListeners')
5
-
6
- const listenersMixinVue3 = extend({
7
- data() {
8
- return {
9
- bvListeners: {}
10
- }
11
- },
4
+ const internalPropName = getInternalPropName('bvListeners')
5
+ export const listenersMixin = makePropCacheMixin('$listeners', 'bvListeners').extend({
12
6
  created() {
13
- this.bvListeners = {
7
+ if (!isVue3(this)) {
8
+ return
9
+ }
10
+
11
+ this[internalPropName] = {
12
+ // bug: this.$listeners is non-reactive in Vue.js 3 compat
14
13
  ...this.$listeners
15
14
  }
16
15
  },
17
16
  beforeUpdate() {
18
- this.bvListeners = {
17
+ if (!isVue3(this)) {
18
+ return
19
+ }
20
+ this[internalPropName] = {
19
21
  ...this.$listeners
20
22
  }
21
23
  }
22
24
  })
23
-
24
- export const listenersMixin = isVue3 ? listenersMixinVue3 : listenersMixinVue2
@@ -1,4 +1,4 @@
1
- import { extend } from '../vue'
1
+ import { extend, isVue3 } from '../vue'
2
2
  import { cloneDeep } from './clone-deep'
3
3
  import { looseEqual } from './loose-equal'
4
4
  import { hasOwnProperty, keys } from './object'
@@ -25,13 +25,33 @@ export const makePropWatcher = propName => ({
25
25
  }
26
26
  })
27
27
 
28
- export const makePropCacheMixin = (propName, proxyPropName) =>
29
- extend({
28
+ export const getInternalPropName = proxyPropName => `bv_internal__${proxyPropName}`
29
+
30
+ export const makePropCacheMixin = (propName, proxyPropName) => {
31
+ const internalPropName = getInternalPropName(proxyPropName)
32
+ return extend({
30
33
  data() {
31
- return { [proxyPropName]: cloneDeep(this[propName]) }
34
+ return { [internalPropName]: isVue3(this) ? null : cloneDeep(this[propName] || {}) }
35
+ },
36
+ computed: {
37
+ [proxyPropName]() {
38
+ if (internalPropName in this && this[internalPropName]) {
39
+ return this[internalPropName]
40
+ }
41
+ const result = { ...this[propName] }
42
+ Object.keys(result).forEach(key => {
43
+ if (result[key] === undefined) {
44
+ delete result[key]
45
+ }
46
+ })
47
+ return result
48
+ }
32
49
  },
33
- watch: {
34
- // Work around unwanted re-renders: https://github.com/vuejs/vue/issues/10115
35
- [propName]: makePropWatcher(proxyPropName)
50
+ created() {
51
+ if (!isVue3(this)) {
52
+ // Work around unwanted re-renders: https://github.com/vuejs/vue/issues/10115
53
+ this.$watch(propName, makePropWatcher(internalPropName).handler)
54
+ }
36
55
  }
37
56
  })
57
+ }