diff --git a/.versionrc b/.versionrc
new file mode 100644
index 00000000000..da7d73a2476
--- /dev/null
+++ b/.versionrc
@@ -0,0 +1,43 @@
+{
+ "scripts": {
+ "postchangelog": "./node_modules/.bin/prettier --write CHANGELOG.md"
+ },
+ "skip": {
+ "commit": true,
+ "tag": true
+ },
+ "types": [
+ {
+ "type": "fix",
+ "section": "Bug Fixes"
+ },
+ {
+ "type": "feat",
+ "section": "Features"
+ },
+ {
+ "type": "perf",
+ "section": "Performance"
+ },
+ {
+ "type": "docs",
+ "hidden": true
+ },
+ {
+ "type": "style",
+ "hidden": true
+ },
+ {
+ "type": "refactor",
+ "hidden": true
+ },
+ {
+ "type": "chore",
+ "hidden": true
+ },
+ {
+ "type": "test",
+ "hidden": true
+ }
+ ]
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dea60b74bcf..497255d7a3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file. See
[standard-version](https://github.com/conventional-changelog/standard-version) for commit
guidelines.
+
+
+### [v2.17.2](https://github.com/bootstrap-vue/bootstrap-vue/compare/v2.17.1...v2.17.2)
+
+Released: 2020-09-18
+
+### Bug Fixes v2.17.2
+
+- **b-nav-item-dropdown:** `boundary` handling in `` (closes
+ [#5789](https://github.com/bootstrap-vue/bootstrap-vue/issues/5789))
+ ([#5794](https://github.com/bootstrap-vue/bootstrap-vue/issues/5794))
+ ([73383bf](https://github.com/bootstrap-vue/bootstrap-vue/commit/73383bfd935c097604bf5ad39a9cc2d18961ba87))
+- **b-skeleton:** add missing component exports
+ ([#5806](https://github.com/bootstrap-vue/bootstrap-vue/issues/5806))
+ ([871ce22](https://github.com/bootstrap-vue/bootstrap-vue/commit/871ce22504c4e64348b844c0e4306161317abf60))
+- **b-tooltip, b-popover:** fix `title` not being reset on hide
+ ([#5793](https://github.com/bootstrap-vue/bootstrap-vue/issues/5793))
+ ([31eeb0a](https://github.com/bootstrap-vue/bootstrap-vue/commit/31eeb0ab5ef262c33579f43969c7d6ee6c802e3d))
+
### [v2.17.1](https://github.com/bootstrap-vue/bootstrap-vue/compare/v2.17.0...v2.17.1)
diff --git a/docs/common-props.json b/docs/common-props.json
index 6267ab2c657..2be2f4b6370 100644
--- a/docs/common-props.json
+++ b/docs/common-props.json
@@ -126,7 +126,7 @@
"description": "Sets the `placeholder` attribute value on the form control"
},
"disabled": {
- "description": "When set to 'true', disables the component's functionality and places it in a disabled state"
+ "description": "When set to `true`, disables the component's functionality and places it in a disabled state"
},
"readonly": {
"description": "Sets the `readonly` attribute on the form control"
diff --git a/package.json b/package.json
index df3b35147a7..217e9576daf 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "bootstrap-vue",
- "version": "2.17.1",
+ "version": "2.17.2",
"description": "With more than 85 components, over 45 available plugins, several directives, and 1000+ icons, BootstrapVue provides one of the most comprehensive implementations of the Bootstrap v4 component and grid system available for Vue.js v2.6, complete with extensive and automated WAI-ARIA accessibility markup.",
"main": "dist/bootstrap-vue.common.js",
"web": "dist/bootstrap-vue.js",
@@ -149,125 +149,83 @@
"marked": "^1.1.1",
"node-sass": "^4.14.1",
"nuxt": "^2.14.5",
- "postcss": "^7.0.32",
+ "postcss": "^7.0.34",
"postcss-cli": "^7.1.2",
"prettier": "1.14.3",
"require-context": "^1.1.0",
- "rollup": "^2.27.0",
+ "rollup": "^2.27.1",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"sass-loader": "^10.0.2",
"standard-version": "^9.0.0",
- "terser": "^5.3.1",
+ "terser": "^5.3.2",
"vue": "^2.6.12",
"vue-jest": "^3.0.7",
"vue-router": "^3.4.3",
"vue-server-renderer": "^2.6.12",
"vue-template-compiler": "^2.6.12"
},
- "standard-version": {
- "scripts": {
- "postchangelog": "./node_modules/.bin/prettier --write CHANGELOG.md"
- },
- "types": [
- {
- "type": "fix",
- "section": "Bug Fixes"
- },
- {
- "type": "feat",
- "section": "Features"
- },
- {
- "type": "perf",
- "section": "Performance"
- },
- {
- "type": "docs",
- "hidden": true
- },
- {
- "type": "style",
- "hidden": true
- },
- {
- "type": "refactor",
- "hidden": true
- },
- {
- "type": "chore",
- "hidden": true
- },
- {
- "type": "test",
- "hidden": true
- }
- ]
- },
"keywords": [
"Bootstrap",
"Bootstrap v4",
"Bootstrap for Vue",
+ "Vue",
+ "Vue.js",
+ "Vue v2",
"SSR",
"Web",
"Components",
"Directives",
+ "Icons",
+ "Bootstrap Icons",
"ARIA",
"Accessibility",
"a11y",
- "Polymer",
- "Vue",
- "VueJS",
- "Vue2",
- "WebComponents",
- "jquery",
"Popper.js",
- "Popper",
"CSS",
"SCSS",
- "Icons",
- "Bootstrap Icons",
- "Flexbox",
"Alert",
+ "Avatar",
+ "Badge",
"Breadcrumb",
"Button",
- "Checkbox",
- "Radio",
+ "Calendar",
"Card",
"Carousel",
- "Slider",
- "Calendar",
+ "Checkbox",
+ "Collapse",
+ "Collapse",
"Date picker",
"Datepicker",
- "Collapse",
"Dropdown",
+ "Dropzone",
"Form",
- "Select",
- "Option",
"Input",
"Jumbotron",
"List",
- "Nav",
"Modal",
- "MessageBox",
- "Upload",
- "Dropzone",
+ "Nav",
"Navbar",
+ "Option",
+ "Overlay",
"Pagination",
"Popover",
"Progress",
+ "Radio",
+ "Select",
+ "Sidebar",
+ "Skeleton",
+ "Slider",
"Spinner",
"Tab",
"Table",
"Tag",
"Tags",
+ "Time picker",
+ "Timepicker",
"Toast",
- "Tooltip",
- "vue-bootstrap",
- "vue-strap",
- "vuestrap",
- "uiv"
+ "Tooltip"
],
"collective": {
"type": "opencollective",
diff --git a/src/components/form-rating/README.md b/src/components/form-rating/README.md
index e381da62de0..8fb7c0c60e9 100644
--- a/src/components/form-rating/README.md
+++ b/src/components/form-rating/README.md
@@ -295,7 +295,7 @@ may prefer the custom input to occupy on the space required for it's contents. S
### Borderless
-By default, `` has standard Bootstrap form-control styling. To disable the default
+By default, `` has standard Bootstrap form-control styling. To disable the default
form-control border, simply set the `no-border` prop to `true`.
```html
diff --git a/src/components/form-tags/README.md b/src/components/form-tags/README.md
index e8434eb82d1..87d934a0d7b 100644
--- a/src/components/form-tags/README.md
+++ b/src/components/form-tags/README.md
@@ -833,7 +833,7 @@ You can easily create a custom wrapper component with your preferred rendering s
import { BFormTags } from 'bootstrap-vue'
export default {
- name: 'MyCustomTags",
+ name: 'MyCustomTags',
components: { BFormTags },
model: {
prop: 'value',
diff --git a/src/components/nav/nav-item-dropdown.js b/src/components/nav/nav-item-dropdown.js
index 176203e0cdb..fc783dc5253 100644
--- a/src/components/nav/nav-item-dropdown.js
+++ b/src/components/nav/nav-item-dropdown.js
@@ -29,10 +29,6 @@ export const BNavItemDropdown = /*#__PURE__*/ Vue.extend({
toggleId() {
return this.safeId('_BV_toggle_')
},
- isNav() {
- // Signal to dropdown mixin that we are in a navbar
- return true
- },
dropdownClasses() {
return [this.directionClass, this.boundaryClass, { show: this.visible }]
},
diff --git a/src/components/nav/nav-item-dropdown.spec.js b/src/components/nav/nav-item-dropdown.spec.js
index df15c5e5b5a..f9a115cd1ad 100644
--- a/src/components/nav/nav-item-dropdown.spec.js
+++ b/src/components/nav/nav-item-dropdown.spec.js
@@ -34,15 +34,6 @@ describe('nav-item-dropdown', () => {
wrapper.destroy()
})
- it('should have a flag that we are in a nav', async () => {
- const wrapper = mount(BNavItemDropdown)
-
- expect(wrapper.vm).toBeDefined()
- expect(wrapper.vm.isNav).toBe(true)
-
- wrapper.destroy()
- })
-
it('should have custom toggle class when "toggle-class" prop set', async () => {
const wrapper = mount(BNavItemDropdown, {
propsData: {
diff --git a/src/components/nav/package.json b/src/components/nav/package.json
index 192dcfbed5c..805bb3f8739 100644
--- a/src/components/nav/package.json
+++ b/src/components/nav/package.json
@@ -98,11 +98,11 @@
"props": [
{
"prop": "text",
- "description": "Text to place in the toggle button, or in the split button is split mode"
+ "description": "Text to place in the toggle element (link)"
},
{
"prop": "html",
- "description": "HTML string to place in the toggle button, or in the split button is split mode. Use with caution"
+ "description": "HTML string to place in the toggle element (link). Use with caution"
},
{
"prop": "dropup",
@@ -138,16 +138,16 @@
},
{
"prop": "toggleClass",
- "description": "CSS class (or classes) to add to the toggle button"
+ "description": "CSS class (or classes) to add to the toggle element (link)"
},
{
"prop": "noCaret",
- "description": "Hide the caret indicator on the toggle button"
+ "description": "Hide the caret indicator on the toggle element (link)"
},
{
"prop": "boundary",
"version": "2.4.0",
- "description": "The boundary constraint of the menu: 'scrollParent', 'window', 'viewport', or a reference to an HTMLElement. Has no effect when dropdown is inside a b-navbar"
+ "description": "The boundary constraint of the menu: 'scrollParent', 'window', 'viewport', or a reference to an HTMLElement. Has no effect when dropdown is inside a ``"
}
],
"slots": [
diff --git a/src/components/popover/package.json b/src/components/popover/package.json
index be889f05bd0..50e9dc9f4df 100644
--- a/src/components/popover/package.json
+++ b/src/components/popover/package.json
@@ -29,7 +29,7 @@
},
{
"prop": "placement",
- "description": "Placement of the popover: One of 'top', 'bottom', 'right', 'left', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'left-top', 'left-bottom', 'right-top', 'right-bottom'"
+ "description": "Placement of the popover: One of 'top', 'bottom', 'right', 'left', 'topleft', 'topright', 'bottomleft', 'bottomright', 'lefttop', 'leftbottom', 'righttop', 'rightbottom'"
},
{
"prop": "fallbackPlacement",
diff --git a/src/components/skeleton/index.js b/src/components/skeleton/index.js
index 108ecde0a09..9b656621098 100644
--- a/src/components/skeleton/index.js
+++ b/src/components/skeleton/index.js
@@ -8,11 +8,11 @@ import { BSkeletonWrapper } from './skeleton-wrapper'
const SkeletonPlugin = /*#__PURE__*/ pluginFactory({
components: {
BSkeleton,
- BSkeletonWrapper,
- BSkeletonTable,
+ BSkeletonIcon,
BSkeletonImg,
- BSkeletonIcon
+ BSkeletonTable,
+ BSkeletonWrapper
}
})
-export { SkeletonPlugin, BSkeleton, BSkeletonWrapper, BSkeletonTable, BSkeletonImg, BSkeletonIcon }
+export { SkeletonPlugin, BSkeleton, BSkeletonIcon, BSkeletonImg, BSkeletonTable, BSkeletonWrapper }
diff --git a/src/components/tooltip/helpers/bv-tooltip.js b/src/components/tooltip/helpers/bv-tooltip.js
index 63f33824aad..28893c2e71b 100644
--- a/src/components/tooltip/helpers/bv-tooltip.js
+++ b/src/components/tooltip/helpers/bv-tooltip.js
@@ -621,19 +621,31 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
}
},
fixTitle() {
- // If the target has a `title` attribute, remove it and store it on a data attribute
+ // If the target has a `title` attribute,
+ // remove it and store it on a data attribute
const target = this.getTarget()
- if (target && hasAttr(target, 'title')) {
- setAttr(target, DATA_TITLE_ATTR, getAttr(target, 'title') || '')
+ if (hasAttr(target, 'title')) {
+ // Get `title` attribute value and remove it from target
+ const title = getAttr(target, 'title')
setAttr(target, 'title', '')
+ // Only set the data attribute when the value is truthy
+ if (title) {
+ setAttr(target, DATA_TITLE_ATTR, title)
+ }
}
},
restoreTitle() {
- // If the target had a title, restore it and remove the data attribute
+ // If the target had a `title` attribute,
+ // restore it and remove the data attribute
const target = this.getTarget()
- if (target && hasAttr(target, DATA_TITLE_ATTR)) {
- setAttr(target, 'title', getAttr(target, DATA_TITLE_ATTR) || '')
+ if (hasAttr(target, DATA_TITLE_ATTR)) {
+ // Get data attribute value and remove it from target
+ const title = getAttr(target, DATA_TITLE_ATTR)
removeAttr(target, DATA_TITLE_ATTR)
+ // Only restore the `title` attribute when the value is truthy
+ if (title) {
+ setAttr(target, 'title', title)
+ }
}
},
// --- BvEvent helpers ---
diff --git a/src/components/tooltip/package.json b/src/components/tooltip/package.json
index 39e6a214e2c..f03f1674ebe 100644
--- a/src/components/tooltip/package.json
+++ b/src/components/tooltip/package.json
@@ -25,7 +25,7 @@
},
{
"prop": "placement",
- "description": "Placement of the tooltip: One of 'top', 'bottom', 'right', 'left', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'left-top', 'left-bottom', 'right-top', 'right-bottom'"
+ "description": "Placement of the tooltip: One of 'top', 'bottom', 'right', 'left', 'topleft', 'topright', 'bottomleft', 'bottomright', 'lefttop', 'leftbottom', 'righttop', 'rightbottom'"
},
{
"prop": "fallbackPlacement",
diff --git a/src/components/tooltip/tooltip.spec.js b/src/components/tooltip/tooltip.spec.js
index 8818767987f..3235462bd01 100644
--- a/src/components/tooltip/tooltip.spec.js
+++ b/src/components/tooltip/tooltip.spec.js
@@ -1445,4 +1445,85 @@ describe('b-tooltip', () => {
wrapper.destroy()
})
+
+ it('saves title in data attribute on open and adds to back on hide', async () => {
+ jest.useFakeTimers()
+ const wrapper = mount(App, {
+ attachTo: createContainer(),
+ propsData: {
+ triggers: 'click',
+ show: false,
+ titleAttr: 'bar'
+ },
+ slots: {
+ default: 'title'
+ }
+ })
+
+ expect(wrapper.vm).toBeDefined()
+ await waitNT(wrapper.vm)
+ await waitRAF()
+ await waitNT(wrapper.vm)
+ await waitRAF()
+ jest.runOnlyPendingTimers()
+
+ expect(wrapper.element.tagName).toBe('ARTICLE')
+ expect(wrapper.attributes('id')).toBeDefined()
+ expect(wrapper.attributes('id')).toEqual('wrapper')
+
+ // The trigger button
+ const $button = wrapper.find('button')
+ expect($button.exists()).toBe(true)
+ expect($button.attributes('id')).toBeDefined()
+ expect($button.attributes('id')).toEqual('foo')
+ expect($button.attributes('title')).toBeDefined()
+ expect($button.attributes('title')).toEqual('bar')
+ expect($button.attributes('data-original-title')).not.toBeDefined()
+ expect($button.attributes('aria-describedby')).not.toBeDefined()
+
+ // Show tooltip
+ await wrapper.setProps({ show: true })
+
+ expect($button.attributes('title')).toBeDefined()
+ expect($button.attributes('title')).toEqual('')
+ expect($button.attributes('data-original-title')).toBeDefined()
+ expect($button.attributes('data-original-title')).toEqual('bar')
+ expect($button.attributes('aria-describedby')).toBeDefined()
+ // ID of the tooltip that will be in the body
+ const adb = $button.attributes('aria-describedby')
+
+ // wrapper
+ const $tipHolder = wrapper.findComponent(BTooltip)
+ expect($tipHolder.exists()).toBe(true)
+ expect($tipHolder.element.nodeType).toEqual(Node.COMMENT_NODE)
+
+ // Find the tooltip element in the document
+ const tip = document.getElementById(adb)
+ expect(tip).not.toBe(null)
+ expect(tip).toBeInstanceOf(HTMLElement)
+ expect(tip.tagName).toEqual('DIV')
+ expect(tip.classList.contains('tooltip')).toBe(true)
+ expect(tip.classList.contains('b-tooltip')).toBe(true)
+ expect(tip.classList.contains('interactive')).toBe(false)
+ expect(tip.textContent).toEqual('title')
+
+ // Hide the tooltip
+ await wrapper.setProps({ show: false })
+ await waitRAF()
+ await waitRAF()
+ jest.runOnlyPendingTimers()
+ await waitNT(wrapper.vm)
+ await waitRAF()
+
+ expect($button.attributes('title')).toBeDefined()
+ expect($button.attributes('title')).toEqual('bar')
+ expect($button.attributes('data-original-title')).not.toBeDefined()
+ expect($button.attributes('aria-describedby')).not.toBeDefined()
+
+ // Tooltip element should not be in the document
+ expect(document.body.contains(tip)).toBe(false)
+ expect(document.querySelector(adb)).toBe(null)
+
+ wrapper.destroy()
+ })
})
diff --git a/src/index.js b/src/index.js
index 5ab58738dba..c5382db644c 100644
--- a/src/index.js
+++ b/src/index.js
@@ -285,7 +285,11 @@ export { BSidebar } from './components/sidebar/sidebar'
// export * from './components/skeleton'
export { SkeletonPlugin } from './components/skeleton'
-export { BSkeleton } from './components/skeleton'
+export { BSkeleton } from './components/skeleton/skeleton'
+export { BSkeletonIcon } from './components/skeleton/skeleton-icon'
+export { BSkeletonImg } from './components/skeleton/skeleton-img'
+export { BSkeletonTable } from './components/skeleton/skeleton-table'
+export { BSkeletonWrapper } from './components/skeleton/skeleton-wrapper'
// export * from './components/spinner'
export { SpinnerPlugin } from './components/spinner'
diff --git a/src/mixins/dropdown.js b/src/mixins/dropdown.js
index a23ff245f24..c9fced295c1 100644
--- a/src/mixins/dropdown.js
+++ b/src/mixins/dropdown.js
@@ -127,8 +127,7 @@ export default {
// Position `static` is needed to allow menu to "breakout" of the `scrollParent`
// boundaries when boundary is anything other than `scrollParent`
// See: https://github.com/twbs/bootstrap/issues/24251#issuecomment-341413786
- const { boundary } = this
- return boundary !== 'scrollParent' || !boundary ? 'position-static' : ''
+ return this.boundary !== 'scrollParent' && !this.inNavbar ? 'position-static' : ''
}
},
watch: {
diff --git a/yarn.lock b/yarn.lock
index 5103a375e17..957a2436165 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11146,6 +11146,15 @@ postcss@7.x.x, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17,
source-map "^0.6.1"
supports-color "^6.1.0"
+postcss@^7.0.34:
+ version "7.0.34"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.34.tgz#f2baf57c36010df7de4009940f21532c16d65c20"
+ integrity sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==
+ dependencies:
+ chalk "^2.4.2"
+ source-map "^0.6.1"
+ supports-color "^6.1.0"
+
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -12106,10 +12115,10 @@ rollup-pluginutils@^2.8.1:
dependencies:
estree-walker "^0.6.1"
-rollup@^2.27.0:
- version "2.27.0"
- resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.27.0.tgz#f2b70a8dd583bc3675b36686289aa9a51e27af4f"
- integrity sha512-1WlbhNdzhLjdhh2wsf6CDxmuBAYG+5O53fYqCcGv8aJOoX/ymCfCY6oZnvllXZzaC/Ng+lPPwq9EMbHOKc5ozA==
+rollup@^2.27.1:
+ version "2.27.1"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.27.1.tgz#372744e1d36eba0fd942d997600c2fc2ca266305"
+ integrity sha512-GiWHQvnmMgBktSpY/1+nrGpwPsTw4b9P28og2uedfeq4JZ16rzAmnQ5Pm/E0/BEmDNia1ZbY7+qu3nBgNa19Hg==
optionalDependencies:
fsevents "~2.1.2"
@@ -13253,10 +13262,10 @@ terser@^4.1.2, terser@^4.3.9, terser@^4.6.12, terser@^4.6.3:
source-map "~0.6.1"
source-map-support "~0.5.12"
-terser@^5.3.1:
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.1.tgz#f50fe20ab48b15234fe9bdd86b10148ad5fca787"
- integrity sha512-yD80f4hdwCWTH5mojzxe1q8bN1oJbsK/vfJGLcPZM/fl+/jItIVNKhFIHqqR71OipFWMLgj3Kc+GIp6CeIqfnA==
+terser@^5.3.2:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.2.tgz#f4bea90eb92945b2a028ceef79181b9bb586e7af"
+ integrity sha512-H67sydwBz5jCUA32ZRL319ULu+Su1cAoZnnc+lXnenGRYWyLE3Scgkt8mNoAsMx0h5kdo758zdoS0LG9rYZXDQ==
dependencies:
commander "^2.20.0"
source-map "~0.6.1"