From 9c37875ea08a9cadf348fb42f78f576b1b3848d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Sun, 22 Sep 2019 23:12:33 +0200 Subject: [PATCH 01/38] fix(dropdown): focus-out handling when new focus comes from another `dropdown-toggle` (closes #4113) (#4139) * fix(dropdown): focus-out handling when new focus somes from another `dropdown-toggle` * Try delaying the show handler * Update dropdown.js * Update dropdown.js * Trying with clickout handler disabled * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * lint * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.spec.js * Update dropdown.spec.js * Update dom.js * Update dom.spec.js * Update dom.js * Update dom.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Update dropdown.js * Correct typos --- src/components/dropdown/dropdown.spec.js | 14 +++-- src/mixins/dropdown.js | 79 ++++++++++++++---------- src/utils/dom.js | 9 ++- src/utils/dom.spec.js | 2 + 4 files changed, 63 insertions(+), 41 deletions(-) diff --git a/src/components/dropdown/dropdown.spec.js b/src/components/dropdown/dropdown.spec.js index 45af4776cbc..dab55bf7c98 100644 --- a/src/components/dropdown/dropdown.spec.js +++ b/src/components/dropdown/dropdown.spec.js @@ -479,8 +479,10 @@ describe('dropdown', () => { expect(document.activeElement).toBe($menu.element) // Close menu by moving focus away from menu - const focusInEvt = new FocusEvent('focusin') - document.dispatchEvent(focusInEvt) + // which triggers a focusout event on menu + $menu.trigger('focusout', { + relatedTarget: document.body + }) await waitNT(wrapper.vm) await waitRAF() expect($dropdown.classes()).not.toContain('show') @@ -494,9 +496,11 @@ describe('dropdown', () => { expect($toggle.attributes('aria-expanded')).toEqual('true') expect(document.activeElement).toBe($menu.element) - // Close menu by clicking outside of menu - const clickEvt = new MouseEvent('click') - document.dispatchEvent(clickEvt) + // Close menu by moving focus away from menu + // which triggers a focusout event on menu + $menu.trigger('focusout', { + relatedTarget: document.body + }) await waitNT(wrapper.vm) await waitRAF() expect($dropdown.classes()).not.toContain('show') diff --git a/src/mixins/dropdown.js b/src/mixins/dropdown.js index 2ec4e216ca4..c950298e7f4 100644 --- a/src/mixins/dropdown.js +++ b/src/mixins/dropdown.js @@ -1,15 +1,22 @@ import Popper from 'popper.js' -import { BvEvent } from '../utils/bv-event.class' import KeyCodes from '../utils/key-codes' import warn from '../utils/warn' -import { closest, contains, isVisible, requestAF, selectAll } from '../utils/dom' +import { BvEvent } from '../utils/bv-event.class' +import { closest, contains, isVisible, requestAF, selectAll, eventOn, eventOff } from '../utils/dom' import { isNull } from '../utils/inspect' -import clickOutMixin from './click-out' -import focusInMixin from './focus-in' +import idMixin from './id' // Return an array of visible items const filterVisibles = els => (els || []).filter(isVisible) +// Root dropdown event names +const ROOT_DROPDOWN_PREFIX = 'bv::dropdown::' +const ROOT_DROPDOWN_SHOWN = `${ROOT_DROPDOWN_PREFIX}shown` +const ROOT_DROPDOWN_HIDDEN = `${ROOT_DROPDOWN_PREFIX}hidden` + +// Delay when loosing focus before closing menu (in ms) +const FOCUSOUT_DELAY = 100 + // Dropdown item CSS selectors const Selector = { FORM_CHILD: '.dropdown form', @@ -40,7 +47,7 @@ const AttachmentMap = { // @vue/component export default { - mixins: [clickOutMixin, focusInMixin], + mixins: [idMixin], provide() { return { bvDropdown: this @@ -136,7 +143,8 @@ export default { cancelable: true, vueTarget: this, target: this.$refs.menu, - relatedTarget: null + relatedTarget: null, + componentId: this.safeId ? this.safeId() : this.id || null }) this.emitEvent(bvEvt) if (bvEvt.defaultPrevented) { @@ -181,16 +189,13 @@ export default { emitEvent(bvEvt) { const type = bvEvt.type this.$emit(type, bvEvt) - this.$root.$emit(`bv::dropdown::${type}`, bvEvt) + this.$root.$emit(`${ROOT_DROPDOWN_PREFIX}${type}`, bvEvt) }, showMenu() { if (this.disabled) { /* istanbul ignore next */ return } - // Ensure other menus are closed - this.$root.$emit('bv::dropdown::shown', this) - // Are we in a navbar ? if (isNull(this.inNavbar) && this.isNav) { // We should use an injection for this @@ -213,6 +218,9 @@ export default { } } + // Ensure other menus are closed + this.$root.$emit(ROOT_DROPDOWN_SHOWN, this) + this.whileOpenListen(true) // Wrap in nextTick to ensure menu is fully rendered/shown @@ -225,7 +233,7 @@ export default { }, hideMenu() { this.whileOpenListen(false) - this.$root.$emit('bv::dropdown::hidden', this) + this.$root.$emit(ROOT_DROPDOWN_HIDDEN, this) this.$emit('hidden') this.removePopper() }, @@ -263,19 +271,16 @@ export default { } return { ...popperConfig, ...(this.popperOpts || {}) } }, - whileOpenListen(open) { + whileOpenListen(isOpen) { // turn listeners on/off while open - if (open) { + if (isOpen) { // If another dropdown is opened - this.$root.$on('bv::dropdown::shown', this.rootCloseListener) - // Hide the dropdown when clicked outside - this.listenForClickOut = true - // Hide the dropdown when it loses focus - this.listenForFocusIn = true + this.$root.$on(ROOT_DROPDOWN_SHOWN, this.rootCloseListener) + // Hide the menu when focus moves out + eventOn(this.$el, 'focusout', this.onFocusOut, { passive: true }) } else { - this.$root.$off('bv::dropdown::shown', this.rootCloseListener) - this.listenForClickOut = false - this.listenForFocusIn = false + this.$root.$off(ROOT_DROPDOWN_SHOWN, this.rootCloseListener) + eventOff(this.$el, 'focusout', this.onFocusOut, { passive: true }) } }, rootCloseListener(vm) { @@ -360,6 +365,7 @@ export default { this.focusNext(evt, true) } }, + // If uses presses ESC to close menu onEsc(evt) { if (this.visible) { this.visible = false @@ -369,18 +375,25 @@ export default { this.$once('hidden', this.focusToggler) } }, - // Document click out listener - clickOutHandler() { - if (this.visible) { - this.visible = false - } - }, - // Document focusin listener - focusInHandler(evt) { - const target = evt.target - // If focus leaves dropdown, hide it - if (this.visible && !contains(this.$refs.menu, target) && !contains(this.toggler, target)) { - this.visible = false + // Dropdown wrapper focusOut handler + onFocusOut(evt) { + // `relatedTarget` is the element gaining focus + const relatedTarget = evt.relatedTarget + // If focus moves outside the menu or toggler, then close menu + if ( + this.visible && + !contains(this.$refs.menu, relatedTarget) && + !contains(this.toggler, relatedTarget) + ) { + const doHide = () => { + this.visible = false + } + // When we are in a navbar (which has been responsively stacked), we + // delay the dropdown's closing so that the next element has a chance + // to have it's click handler fired (in case it's position moves on + // the screen do to a navbar menu above it collapsing) + // https://github.com/bootstrap-vue/bootstrap-vue/issues/4113 + this.inNavbar ? setTimeout(doHide, FOCUSOUT_DELAY) : doHide() } }, // Keyboard nav diff --git a/src/utils/dom.js b/src/utils/dom.js index 33e6c505955..5802bf8a12c 100644 --- a/src/utils/dom.js +++ b/src/utils/dom.js @@ -122,13 +122,16 @@ export const matches = (el, selector) => { } // Finds closest element matching selector. Returns `null` if not found -export const closest = (selector, root) => { +export const closest = (selector, root, includeRoot = false) => { if (!isElement(root)) { return null } const el = closestEl.call(root, selector) - // Emulate jQuery closest and return `null` if match is the passed in element (root) - return el === root ? null : el + + // Native closest behaviour when `includeRoot` is truthy, + // else emulate jQuery closest and return `null` if match is + // the passed in root element when `includeRoot` is falsey + return includeRoot ? el : el === root ? null : el } // Returns true if the parent element contains the child element diff --git a/src/utils/dom.spec.js b/src/utils/dom.spec.js index 74fbacbc172..c697a527215 100644 --- a/src/utils/dom.spec.js +++ b/src/utils/dom.spec.js @@ -120,6 +120,8 @@ describe('utils/dom', () => { expect(closest('div.baz', $btns.at(0).element)).toBeDefined() expect(closest('div.baz', $btns.at(0).element)).toBe($baz.element) expect(closest('div.nothere', $btns.at(0).element)).toBe(null) + expect(closest('div.baz', $baz.element)).toBe(null) + expect(closest('div.baz', $baz.element, true)).toBe($baz.element) wrapper.destroy() }) From 6848bb376d396996b7ab398237732a68eeac7996 Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Mon, 23 Sep 2019 03:58:13 -0300 Subject: [PATCH 02/38] docs: clarify the autofocus prop (#4144) * docs: clarify the autofocus prop * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --- src/components/form-checkbox/README.md | 5 +++-- src/components/form-file/README.md | 5 +++-- src/components/form-input/README.md | 7 ++++--- src/components/form-radio/README.md | 5 +++-- src/components/form-select/README.md | 5 +++-- src/components/form-textarea/README.md | 7 ++++--- 6 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/components/form-checkbox/README.md b/src/components/form-checkbox/README.md index 4a7e39d08a5..66b896b3021 100644 --- a/src/components/form-checkbox/README.md +++ b/src/components/form-checkbox/README.md @@ -550,8 +550,9 @@ the group. ## Autofocus When the `autofocus` prop is set on ``, the input will be auto-focused when it is -inserted into the document, or re-activated when inside a Vue `` component. Note that -this prop **does not** set the `autofocus` attribute on the input. +inserted (i.e. **mounted**) into the document, or re-activated when inside a Vue `` +component. Note that this prop **does not** set the `autofocus` attribute on the input, nor can it +tell when the input becomes visible. ## Indeterminate (tri-state) support diff --git a/src/components/form-file/README.md b/src/components/form-file/README.md index b83b1ea100e..b3898e6e049 100644 --- a/src/components/form-file/README.md +++ b/src/components/form-file/README.md @@ -238,8 +238,9 @@ invalid), `true` (for valid), or `null` (no validation state). ## Autofocus When the `autofocus` prop is set on ``, the input will be auto-focused when it is -inserted into the document or re-activated when inside a Vue `` component. Note that -this prop **does not** set the `autofocus` attribute on the input. +inserted (i.e. **mounted**) into the document, or re-activated when inside a Vue `` +component. Note that this prop **does not** set the `autofocus` attribute on the input, nor can it +tell when the input becomes visible. ## Accessibility diff --git a/src/components/form-input/README.md b/src/components/form-input/README.md index 5ee983121e2..a9b9fee7d19 100644 --- a/src/components/form-input/README.md +++ b/src/components/form-input/README.md @@ -479,9 +479,10 @@ Emulation of the `.lazy` modifier is _not_ supported (listen for `change` or `bl ## Autofocus -When the `autofocus` prop is set, the input will be auto-focused when it is inserted into the -document, or re-activated when inside a Vue `` component. Note that this prop **does -not** set the `autofocus` attribute on the input. +When the `autofocus` prop is set, the input will be auto-focused when it is inserted (i.e. +**mounted**) into the document, or re-activated when inside a Vue `` component. Note +that this prop **does not** set the `autofocus` attribute on the input, nor can it tell when the +input becomes visible. ## Native and custom events diff --git a/src/components/form-radio/README.md b/src/components/form-radio/README.md index c2d3808176f..4467e5d9d12 100644 --- a/src/components/form-radio/README.md +++ b/src/components/form-radio/README.md @@ -349,8 +349,9 @@ group. ## Autofocus When the `autofocus` prop is set on ``, the input will be auto-focused when it is -inserted into the document or re-activated when inside a Vue `` component. Note that -this prop **does not** set the `autofocus` attribute on the input. +inserted (i.e. **mounted**) into the document or re-activated when inside a Vue `` +component. Note that this prop **does not** set the `autofocus` attribute on the input, nor can it +tell when the input becomes visible. ## Contextual states diff --git a/src/components/form-select/README.md b/src/components/form-select/README.md index 2b8b5d7c7c4..df8a5775e54 100644 --- a/src/components/form-select/README.md +++ b/src/components/form-select/README.md @@ -410,8 +410,9 @@ control the select width, place the input inside standard Bootstrap grid column. ## Autofocus When the `autofocus` prop is set on ``, the select will be auto-focused when it is -inserted into the document or re-activated when inside a Vue `` component. Note that -this prop **does not** set the `autofocus` attribute on the select. +inserted (i.e. **mounted**) into the document or re-activated when inside a Vue `` +component. Note that this prop **does not** set the `autofocus` attribute on the select, nor can it +tell when the select becomes visible. ## Contextual states diff --git a/src/components/form-textarea/README.md b/src/components/form-textarea/README.md index 6c09a84e5a8..fd0f955814f 100644 --- a/src/components/form-textarea/README.md +++ b/src/components/form-textarea/README.md @@ -295,9 +295,10 @@ Emulation of the `.lazy` modifier is _not_ supported (listen for `change` or `bl ## Autofocus -When the `autofocus` prop is set, the textarea will be auto-focused when it is inserted into the -document, or re-activated when inside a Vue `` component. Note that this prop **does -not** set the `autofocus` attribute on the textarea. +When the `autofocus` prop is set on ``, the tetarea will be auto-focused when it is +inserted (i.e. **mounted**) into the document or re-activated when inside a Vue `` +component. Note that this prop **does not** set the `autofocus` attribute on the tetarea, nor can it +tell when the textarea becomes visible. ## Native and custom events From 51c3999b017ca1c95737dd1e2f8ba8ef60fb18c4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2019 02:06:37 -0300 Subject: [PATCH 03/38] chore(deps): update all non-major dependencies to ^7.6.2 (#4152) --- package.json | 10 +-- yarn.lock | 177 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 120 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index 578ef13eda5..16d2224b78f 100644 --- a/package.json +++ b/package.json @@ -78,12 +78,12 @@ "vue-functional-data-merge": "^3.1.0" }, "devDependencies": { - "@babel/cli": "^7.6.0", - "@babel/core": "^7.6.0", + "@babel/cli": "^7.6.2", + "@babel/core": "^7.6.2", "@babel/plugin-transform-modules-commonjs": "^7.6.0", - "@babel/plugin-transform-runtime": "^7.6.0", - "@babel/preset-env": "^7.6.0", - "@babel/standalone": "^7.6.0", + "@babel/plugin-transform-runtime": "^7.6.2", + "@babel/preset-env": "^7.6.2", + "@babel/standalone": "^7.6.2", "@nuxtjs/google-analytics": "^2.2.0", "@nuxtjs/pwa": "^3.0.0-beta.19", "@vue/test-utils": "^1.0.0-beta.29", diff --git a/yarn.lock b/yarn.lock index 83282426797..7a38f958eae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@babel/cli@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.6.0.tgz#1470a04394eaf37862989ea4912adf440fa6ff8d" - integrity sha512-1CTDyGUjQqW3Mz4gfKZ04KGOckyyaNmKneAMlABPS+ZyuxWv3FrVEVz7Ag08kNIztVx8VaJ8YgvYLSNlMKAT5Q== +"@babel/cli@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.6.2.tgz#4ce8b5b4b2e4b4c1b7bd841cec62085e2dfc4465" + integrity sha512-JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ== dependencies: commander "^2.8.1" convert-source-map "^1.1.0" @@ -73,17 +73,17 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.0.tgz#9b00f73554edd67bebc86df8303ef678be3d7b48" - integrity sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw== +"@babel/core@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.2.tgz#069a776e8d5e9eefff76236bc8845566bd31dd91" + integrity sha512-l8zto/fuoZIbncm+01p8zPSDZu/VuuJhAfA7d/AbzM09WR7iVhavvfNDYCNpo1VvLk6E6xgAoP9P+/EMJHuRkQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.0" - "@babel/helpers" "^7.6.0" - "@babel/parser" "^7.6.0" + "@babel/generator" "^7.6.2" + "@babel/helpers" "^7.6.2" + "@babel/parser" "^7.6.2" "@babel/template" "^7.6.0" - "@babel/traverse" "^7.6.0" + "@babel/traverse" "^7.6.2" "@babel/types" "^7.6.0" convert-source-map "^1.1.0" debug "^4.1.0" @@ -115,16 +115,15 @@ source-map "^0.5.0" trim-right "^1.0.1" -"@babel/generator@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.0.tgz#e2c21efbfd3293ad819a2359b448f002bfdfda56" - integrity sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA== +"@babel/generator@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.2.tgz#dac8a3c2df118334c2a29ff3446da1636a8f8c03" + integrity sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ== dependencies: "@babel/types" "^7.6.0" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" - trim-right "^1.0.1" "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" @@ -340,13 +339,13 @@ "@babel/traverse" "^7.5.5" "@babel/types" "^7.5.5" -"@babel/helpers@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.0.tgz#21961d16c6a3c3ab597325c34c465c0887d31c6e" - integrity sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ== +"@babel/helpers@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.2.tgz#681ffe489ea4dcc55f23ce469e58e59c1c045153" + integrity sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA== dependencies: "@babel/template" "^7.6.0" - "@babel/traverse" "^7.6.0" + "@babel/traverse" "^7.6.2" "@babel/types" "^7.6.0" "@babel/highlight@^7.0.0": @@ -373,6 +372,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b" integrity sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ== +"@babel/parser@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" + integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== + "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" @@ -423,6 +427,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" +"@babel/plugin-proposal-object-rest-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096" + integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-proposal-optional-catch-binding@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" @@ -440,6 +452,15 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" +"@babel/plugin-proposal-unicode-property-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz#05413762894f41bfe42b9a5e80919bd575dcc802" + integrity sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + "@babel/plugin-syntax-async-generators@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" @@ -520,10 +541,10 @@ "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.13" -"@babel/plugin-transform-block-scoping@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.0.tgz#c49e21228c4bbd4068a35667e6d951c75439b1dc" - integrity sha512-tIt4E23+kw6TgL/edACZwP1OUKrjOTyMrFMLoT5IOFrfMRabCgekjqFd5o6PaAMildBu46oFkekIdMuGkkPEpA== +"@babel/plugin-transform-block-scoping@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.2.tgz#96c33ab97a9ae500cc6f5b19e04a7e6553360a79" + integrity sha512-zZT8ivau9LOQQaOGC7bQLQOT4XPkPXgN2ERfUgk1X8ql+mVkLc4E8eKk+FO3o0154kxzqenWCorfmEXpEZcrSQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.13" @@ -572,6 +593,15 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" +"@babel/plugin-transform-dotall-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz#44abb948b88f0199a627024e1508acaf8dc9b2f9" + integrity sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + "@babel/plugin-transform-duplicate-keys@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" @@ -669,12 +699,12 @@ dependencies: regexp-tree "^0.1.6" -"@babel/plugin-transform-named-capturing-groups-regex@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.0.tgz#1e6e663097813bb4f53d42df0750cf28ad3bb3f1" - integrity sha512-jem7uytlmrRl3iCAuQyw8BpB4c4LWvSpvIeXKpMb+7j84lkx4m4mYr5ErAcmN5KM7B6BqrAvRGjBIbbzqCczew== +"@babel/plugin-transform-named-capturing-groups-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.2.tgz#c1ca0bb84b94f385ca302c3932e870b0fb0e522b" + integrity sha512-xBdB+XOs+lgbZc2/4F5BVDVcDNS4tcSKQc96KmlqLEAwz6tpYPEvPdmDfvVG0Ssn8lAhronaRs6Z6KSexIpK5g== dependencies: - regexp-tree "^0.1.13" + regexpu-core "^4.6.0" "@babel/plugin-transform-new-target@^7.4.4": version "7.4.4" @@ -731,10 +761,10 @@ resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-runtime@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.0.tgz#85a3cce402b28586138e368fce20ab3019b9713e" - integrity sha512-Da8tMf7uClzwUm/pnJ1S93m/aRXmoYNDD7TkHua8xBDdaAs54uZpTWvEt6NGwmoVMb9mZbntfTqmG2oSzN/7Vg== +"@babel/plugin-transform-runtime@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.2.tgz#2669f67c1fae0ae8d8bf696e4263ad52cb98b6f8" + integrity sha512-cqULw/QB4yl73cS5Y0TZlQSjDvNkzDbu0FurTZyHlJpWE5T3PCMdnyV+xXoH1opr1ldyHODe3QAX3OMAii5NxA== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -755,6 +785,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd" + integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-sticky-regex@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" @@ -787,6 +824,15 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" +"@babel/plugin-transform-unicode-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz#b692aad888a7e8d8b1b214be6b9dc03d5031f698" + integrity sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + "@babel/preset-env@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.5.5.tgz#bc470b53acaa48df4b8db24a570d6da1fef53c9a" @@ -843,19 +889,19 @@ js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/preset-env@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.0.tgz#aae4141c506100bb2bfaa4ac2a5c12b395619e50" - integrity sha512-1efzxFv/TcPsNXlRhMzRnkBFMeIqBBgzwmZwlFDw5Ubj0AGLeufxugirwZmkkX/ayi3owsSqoQ4fw8LkfK9SYg== +"@babel/preset-env@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.2.tgz#abbb3ed785c7fe4220d4c82a53621d71fc0c75d3" + integrity sha512-Ru7+mfzy9M1/YTEtlDS8CD45jd22ngb9tXnn64DvQK3ooyqSw9K4K9DUWmYknTTVk4TqygL9dqCrZgm1HMea/Q== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-async-generator-functions" "^7.2.0" "@babel/plugin-proposal-dynamic-import" "^7.5.0" "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.5.5" + "@babel/plugin-proposal-object-rest-spread" "^7.6.2" "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.6.2" "@babel/plugin-syntax-async-generators" "^7.2.0" "@babel/plugin-syntax-dynamic-import" "^7.2.0" "@babel/plugin-syntax-json-strings" "^7.2.0" @@ -864,11 +910,11 @@ "@babel/plugin-transform-arrow-functions" "^7.2.0" "@babel/plugin-transform-async-to-generator" "^7.5.0" "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.6.0" + "@babel/plugin-transform-block-scoping" "^7.6.2" "@babel/plugin-transform-classes" "^7.5.5" "@babel/plugin-transform-computed-properties" "^7.2.0" "@babel/plugin-transform-destructuring" "^7.6.0" - "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.6.2" "@babel/plugin-transform-duplicate-keys" "^7.5.0" "@babel/plugin-transform-exponentiation-operator" "^7.2.0" "@babel/plugin-transform-for-of" "^7.4.4" @@ -879,7 +925,7 @@ "@babel/plugin-transform-modules-commonjs" "^7.6.0" "@babel/plugin-transform-modules-systemjs" "^7.5.0" "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.2" "@babel/plugin-transform-new-target" "^7.4.4" "@babel/plugin-transform-object-super" "^7.5.5" "@babel/plugin-transform-parameters" "^7.4.4" @@ -887,11 +933,11 @@ "@babel/plugin-transform-regenerator" "^7.4.5" "@babel/plugin-transform-reserved-words" "^7.2.0" "@babel/plugin-transform-shorthand-properties" "^7.2.0" - "@babel/plugin-transform-spread" "^7.2.0" + "@babel/plugin-transform-spread" "^7.6.2" "@babel/plugin-transform-sticky-regex" "^7.2.0" "@babel/plugin-transform-template-literals" "^7.4.4" "@babel/plugin-transform-typeof-symbol" "^7.2.0" - "@babel/plugin-transform-unicode-regex" "^7.4.4" + "@babel/plugin-transform-unicode-regex" "^7.6.2" "@babel/types" "^7.6.0" browserslist "^4.6.0" core-js-compat "^3.1.1" @@ -906,10 +952,10 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/standalone@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.6.0.tgz#bcc226c38b9769e2a59cd88a6a7318181a173091" - integrity sha512-bOZnW6amPLr2296mPl+cHCAG4GNo1NTmoi7cURzLtb08Er1nM9QpT6RecYR/UNlYOOvzUWUYlUTKrKJs9tpbcw== +"@babel/standalone@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.6.2.tgz#484fb4fc7b9cec3dfbb6c012f0c81340596adb09" + integrity sha512-bfrGoJA6bHD3zJdTM8DANDKM2MjuhH7SLTeHuQMyfCn4VQgJlwe9MByqiTTKWZ1dAD0HrC7WDaL60WV+9HUXnQ== "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4": version "7.4.4" @@ -959,16 +1005,16 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.0.tgz#389391d510f79be7ce2ddd6717be66d3fed4b516" - integrity sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ== +"@babel/traverse@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" + integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.0" + "@babel/generator" "^7.6.2" "@babel/helper-function-name" "^7.1.0" "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.6.0" + "@babel/parser" "^7.6.2" "@babel/types" "^7.6.0" debug "^4.1.0" globals "^11.1.0" @@ -10263,7 +10309,7 @@ redent@^2.0.0: indent-string "^3.0.0" strip-indent "^2.0.0" -regenerate-unicode-properties@^8.0.2: +regenerate-unicode-properties@^8.0.2, regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== @@ -10300,11 +10346,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp-tree@^0.1.13: - version "0.1.13" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.13.tgz#5b19ab9377edc68bc3679256840bb29afc158d7f" - integrity sha512-hwdV/GQY5F8ReLZWO+W1SRoN5YfpOKY6852+tBFcma72DKBIcHjPRIlIvQN35bCOljuAfP2G2iB0FC/w236mUw== - regexp-tree@^0.1.6: version "0.1.11" resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.11.tgz#c9c7f00fcf722e0a56c7390983a7a63dd6c272f3" @@ -10332,6 +10373,18 @@ regexpu-core@^4.5.4: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.1.0" +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.1.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + registry-auth-token@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e" From 24c62c5b5624b68b16b3729144b16c3e5ea052c1 Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Tue, 24 Sep 2019 03:15:59 -0300 Subject: [PATCH 04/38] fix(table): disable sticky header max-height on printers (#4147) * fix(table): disable sticky header max-height on printers * Update _table.scss --- src/components/table/_table.scss | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/components/table/_table.scss b/src/components/table/_table.scss index 9058fa553cc..34c905cbe25 100644 --- a/src/components/table/_table.scss +++ b/src/components/table/_table.scss @@ -112,6 +112,15 @@ max-height: $b-table-sticky-header-max-height; } + @media print { + // Overide any styles (including inline styles) + // when printing + .b-table-sticky-header { + overflow-y: visible !important; + max-height: none !important; + } + } + @supports (position: sticky) { // Positioning of sticky headers .b-table-sticky-header > .table.b-table > thead > tr > th { From 28427ea1dd32992a2a600486aa36f89a4a50fe4c Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Tue, 24 Sep 2019 03:20:06 -0300 Subject: [PATCH 05/38] chore(docs): update meta for getting started page (#4148) * Update meta.json * Update index.js * Update index.js * Update index.js --- docs/markdown/intro/meta.json | 4 +++- docs/pages/docs/index.js | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/markdown/intro/meta.json b/docs/markdown/intro/meta.json index 3463942b215..9baa0543f7d 100644 --- a/docs/markdown/intro/meta.json +++ b/docs/markdown/intro/meta.json @@ -1,3 +1,5 @@ { - "name": "Intro" + "name": "Intro", + "title": "Getting Started", + "description": "Get started with BootstrapVue, based on the world's most popular framework - Bootstrap v4, for building responsive, mobile-first sites using Vue.js" } diff --git a/docs/pages/docs/index.js b/docs/pages/docs/index.js index 1919a81e885..92f5797a4bc 100644 --- a/docs/pages/docs/index.js +++ b/docs/pages/docs/index.js @@ -44,5 +44,15 @@ export default { vueVersionMinor: vueVersion.replace(minorRE, '$1'), vueVersionMajor: vueVersion.replace(majorRE, '$1') } + }, + computed: { + // TODO: pull this from the meta.json file + meta() { + return { + title: 'Getting started', + description: + "Get started with BootstrapVue, based on the world's most popular framework - Bootstrap v4, for building responsive, mobile-first sites using Vue.js" + } + } } } From 3f3a46ca93a917a6862650582ca083230ebdbfd5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2019 14:29:29 +0200 Subject: [PATCH 06/38] chore(deps): update devdependency terser to ^4.3.2 (#4153) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 16d2224b78f..0d49c08929e 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,7 @@ "rollup-plugin-node-resolve": "^5.2.0", "sass-loader": "^8.0.0", "standard-version": "^7.0.0", - "terser": "^4.3.1", + "terser": "^4.3.2", "vue": "^2.6.10", "vue-jest": "^3.0.5", "vue-router": "^3.1.3", diff --git a/yarn.lock b/yarn.lock index 7a38f958eae..bf8a86c5e6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11650,10 +11650,10 @@ terser@^4.1.2: source-map "~0.6.1" source-map-support "~0.5.12" -terser@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.1.tgz#09820bcb3398299c4b48d9a86aefc65127d0ed65" - integrity sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg== +terser@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.2.tgz#ed830de484b0103652799063e605618e80f97f93" + integrity sha512-obxk4x19Zlzj9zY4QeXj9iPCb5W8YGn4v3pn4/fHj0Nw8+R7N02Kvwvz9VpOItCZZD8RC+vnYCDL0gP6FAJ7Xg== dependencies: commander "^2.20.0" source-map "~0.6.1" From c9715a89b1d693974dff8db7e24f97cdf908ff99 Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Wed, 25 Sep 2019 11:39:51 -0300 Subject: [PATCH 07/38] perf(tables): make `b-th` extend `b-td` instead of using functional wrappers (#4156) --- src/components/table/helpers/table-cell.js | 185 -------------------- src/components/table/td.js | 186 ++++++++++++++++++++- src/components/table/th.js | 16 +- 3 files changed, 183 insertions(+), 204 deletions(-) delete mode 100644 src/components/table/helpers/table-cell.js diff --git a/src/components/table/helpers/table-cell.js b/src/components/table/helpers/table-cell.js deleted file mode 100644 index de2b3eadacd..00000000000 --- a/src/components/table/helpers/table-cell.js +++ /dev/null @@ -1,185 +0,0 @@ -import Vue from '../../../utils/vue' -import toString from '../../../utils/to-string' -import { isUndefinedOrNull } from '../../../utils/inspect' -import normalizeSlotMixin from '../../../mixins/normalize-slot' - -const digitsRx = /^\d+$/ - -// Parse a rowspan or colspan into a digit (or null if < 1 or NaN) -const parseSpan = val => { - val = parseInt(val, 10) - return digitsRx.test(String(val)) && val > 0 ? val : null -} - -/* istanbul ignore next */ -const spanValidator = val => isUndefinedOrNull(val) || parseSpan(val) > 0 - -export const props = { - header: { - type: Boolean, - default: false - }, - variant: { - type: String, - default: null - }, - colspan: { - type: [Number, String], - default: null, - validator: spanValidator - }, - rowspan: { - type: [Number, String], - default: null, - validator: spanValidator - }, - stackedHeading: { - type: String, - default: null - }, - stickyColumn: { - type: Boolean, - default: false - } -} - -// @vue/component -export const BTableCell = /*#__PURE__*/ Vue.extend({ - name: 'BTableCell', - mixins: [normalizeSlotMixin], - inheritAttrs: false, - inject: { - // Injections for feature / attribute detection - bvTable: { - default: null - }, - bvTableTbody: { - default: null - }, - bvTableThead: { - default: null - }, - bvTableTfoot: { - default: null - }, - bvTableTr: { - default: null - } - }, - props, - computed: { - isDark() { - return this.bvTable && this.bvTable.dark - }, - isStacked() { - return this.bvTable && this.bvTable.isStacked - }, - isStackedCell() { - // We only support stacked-heading in tbody in stacked mode - return this.isStacked && this.bvTableTbody - }, - isResponsive() { - return this.bvTable && this.bvTable.isResponsive && !this.isStacked - }, - isStickyHeader() { - // Needed to handle header background classes, due to lack of - // bg color inheritance with Bootstrap v4 tabl css - // Sticky headers only apply to cells in table `thead` - return ( - !this.isStacked && - this.bvTable && - this.bvTableThead && - this.bvTableTr && - this.bvTable.stickyHeader - ) - }, - isStickyColumn() { - // Needed to handle header background classes, due to lack of - // background color inheritance with Bootstrap v4 table css. - // Sticky column cells are only available in responsive - // mode (horzontal scrolling) or when sticky header mode. - // Applies to cells in `thead`, `tbody` and `tfoot` - return ( - (this.isResponsive || this.isStickyHeader) && - this.stickyColumn && - !this.isStacked && - this.bvTable && - this.bvTableTr - ) - }, - cellClasses() { - // We use computed props here for improved performance by caching - // the results of the string interpolation - let variant = this.variant - if ( - (!variant && this.isStickyHeader && !this.bvTableThead.headVariant) || - (!variant && this.isStickyColumn) - ) { - // Needed for stickyheader mode as Bootstrap v4 table cells do - // not inherit parent's background-color. Boo! - variant = this.bvTableTr.variant || this.bvTable.tableVariant || 'b-table-default' - } - return [ - variant ? `${this.isDark ? 'bg' : 'table'}-${variant}` : null, - this.isStickyColumn ? 'b-table-sticky-column' : null - ] - }, - computedColspan() { - return parseSpan(this.colspan) - }, - computedRowspan() { - return parseSpan(this.rowspan) - }, - cellAttrs() { - // We use computed props here for improved performance by caching - // the results of the object spread (Object.assign) - const headOrFoot = this.bvTableThead || this.bvTableTfoot - // Make sure col/rowspan's are > 0 or null - const colspan = this.computedColspan - const rowspan = this.computedRowspan - // Default role and scope - let role = 'cell' - let scope = null - - // Compute role and scope - // We only add scopes with an explicit span of 1 or greater - if (headOrFoot) { - // Header or footer cells - role = 'columnheader' - scope = colspan > 0 ? 'colspan' : 'col' - } else if (this.header) { - // th's in tbody - role = 'rowheader' - scope = rowspan > 0 ? 'rowgroup' : 'row' - } - - return { - colspan: colspan, - rowspan: rowspan, - role: role, - scope: scope, - // Allow users to override role/scope plus add other attributes - ...this.$attrs, - // Add in the stacked cell label data-attribute if in - // stacked mode (if a stacked heading label is provided) - 'data-label': - this.isStackedCell && !isUndefinedOrNull(this.stackedHeading) - ? toString(this.stackedHeading) - : null - } - } - }, - render(h) { - const content = [this.normalizeSlot('default')] - return h( - this.header ? 'th' : 'td', - { - class: this.cellClasses, - attrs: this.cellAttrs, - // Transfer any native listeners - on: this.$listeners - }, - [this.isStackedCell ? h('div', {}, [content]) : content] - ) - } -}) diff --git a/src/components/table/td.js b/src/components/table/td.js index 8173d438e04..d889ebcf768 100644 --- a/src/components/table/td.js +++ b/src/components/table/td.js @@ -1,17 +1,185 @@ import Vue from '../../utils/vue' -import { omit } from '../../utils/object' -import { props as cellProps, BTableCell } from './helpers/table-cell' +import toString from '../../utils/to-string' +import { isUndefinedOrNull } from '../../utils/inspect' +import normalizeSlotMixin from '../../mixins/normalize-slot' -export const props = omit(cellProps, ['header']) +const digitsRx = /^\d+$/ + +// Parse a rowspan or colspan into a digit (or null if < 1 or NaN) +const parseSpan = val => { + val = parseInt(val, 10) + return digitsRx.test(String(val)) && val > 0 ? val : null +} + +/* istanbul ignore next */ +const spanValidator = val => isUndefinedOrNull(val) || parseSpan(val) > 0 + +export const props = { + variant: { + type: String, + default: null + }, + colspan: { + type: [Number, String], + default: null, + validator: spanValidator + }, + rowspan: { + type: [Number, String], + default: null, + validator: spanValidator + }, + stackedHeading: { + type: String, + default: null + }, + stickyColumn: { + type: Boolean, + default: false + } +} // @vue/component export const BTd = /*#__PURE__*/ Vue.extend({ - name: 'BTd', - functional: true, + name: 'BTableCell', + mixins: [normalizeSlotMixin], + inheritAttrs: false, + inject: { + // Injections for feature / attribute detection + bvTable: { + default: null + }, + bvTableTbody: { + default: null + }, + bvTableThead: { + default: null + }, + bvTableTfoot: { + default: null + }, + bvTableTr: { + default: null + } + }, props, - render(h, { props, data, children }) { - // `data` already includes any listeners - data.props = { ...props, header: false } - return h(BTableCell, data, children) + computed: { + tag() { + // Overridden by + return 'td' + }, + isDark() { + return this.bvTable && this.bvTable.dark + }, + isStacked() { + return this.bvTable && this.bvTable.isStacked + }, + isStackedCell() { + // We only support stacked-heading in tbody in stacked mode + return this.bvTableTbody && this.isStacked + }, + isResponsive() { + return this.bvTable && this.bvTable.isResponsive && !this.isStacked + }, + isStickyHeader() { + // Needed to handle header background classes, due to lack of + // background color inheritance with Bootstrap v4 table CSS + // Sticky headers only apply to cells in table `thead` + return ( + !this.isStacked && + this.bvTable && + this.bvTableThead && + this.bvTableTr && + this.bvTable.stickyHeader + ) + }, + isStickyColumn() { + // Needed to handle header background classes, due to lack of + // background color inheritance with Bootstrap v4 table CSS + // Sticky column cells are only available in responsive + // mode (horizontal scrolling) or when sticky header mode + // Applies to cells in `thead`, `tbody` and `tfoot` + return ( + (this.isResponsive || this.isStickyHeader) && + this.stickyColumn && + !this.isStacked && + this.bvTable && + this.bvTableTr + ) + }, + cellClasses() { + // We use computed props here for improved performance by caching + // the results of the string interpolation + let variant = this.variant + if ( + (!variant && this.isStickyHeader && !this.bvTableThead.headVariant) || + (!variant && this.isStickyColumn) + ) { + // Needed for sticky-header mode as Bootstrap v4 table cells do + // not inherit parent's background-color. Boo! + variant = this.bvTableTr.variant || this.bvTable.tableVariant || 'b-table-default' + } + return [ + variant ? `${this.isDark ? 'bg' : 'table'}-${variant}` : null, + this.isStickyColumn ? 'b-table-sticky-column' : null + ] + }, + computedColspan() { + return parseSpan(this.colspan) + }, + computedRowspan() { + return parseSpan(this.rowspan) + }, + cellAttrs() { + // We use computed props here for improved performance by caching + // the results of the object spread (Object.assign) + const headOrFoot = this.bvTableThead || this.bvTableTfoot + // Make sure col/rowspan's are > 0 or null + const colspan = this.computedColspan + const rowspan = this.computedRowspan + // Default role and scope + let role = 'cell' + let scope = null + + // Compute role and scope + // We only add scopes with an explicit span of 1 or greater + if (headOrFoot) { + // Header or footer cells + role = 'columnheader' + scope = colspan > 0 ? 'colspan' : 'col' + } else if (this.tag === 'th') { + // th's in tbody + role = 'rowheader' + scope = rowspan > 0 ? 'rowgroup' : 'row' + } + + return { + colspan: colspan, + rowspan: rowspan, + role: role, + scope: scope, + // Allow users to override role/scope plus add other attributes + ...this.$attrs, + // Add in the stacked cell label data-attribute if in + // stacked mode (if a stacked heading label is provided) + 'data-label': + this.isStackedCell && !isUndefinedOrNull(this.stackedHeading) + ? toString(this.stackedHeading) + : null + } + } + }, + render(h) { + const content = [this.normalizeSlot('default')] + return h( + this.tag, + { + class: this.cellClasses, + attrs: this.cellAttrs, + // Transfer any native listeners + on: this.$listeners + }, + [this.isStackedCell ? h('div', [content]) : content] + ) } }) diff --git a/src/components/table/th.js b/src/components/table/th.js index ef52ffaa262..a7bd353e562 100644 --- a/src/components/table/th.js +++ b/src/components/table/th.js @@ -1,17 +1,13 @@ import Vue from '../../utils/vue' -import { omit } from '../../utils/object' -import { props as cellProps, BTableCell } from './helpers/table-cell' - -export const props = omit(cellProps, ['header']) +import { BTd } from './td' // @vue/component export const BTh = /*#__PURE__*/ Vue.extend({ name: 'BTh', - functional: true, - props, - render(h, { props, data, children }) { - // `data` already includes any listeners - data.props = { ...props, header: true } - return h(BTableCell, data, children) + extends: BTd, + computed: { + tag() { + return 'th' + } } }) From d6d00ca7548d4e933e619ee0af205f4c396c25cb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2019 21:53:48 +0200 Subject: [PATCH 08/38] chore(deps): update devdependency terser to ^4.3.3 (#4159) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0d49c08929e..95ebae9a618 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,7 @@ "rollup-plugin-node-resolve": "^5.2.0", "sass-loader": "^8.0.0", "standard-version": "^7.0.0", - "terser": "^4.3.2", + "terser": "^4.3.3", "vue": "^2.6.10", "vue-jest": "^3.0.5", "vue-router": "^3.1.3", diff --git a/yarn.lock b/yarn.lock index bf8a86c5e6d..cff93ccfd3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11650,10 +11650,10 @@ terser@^4.1.2: source-map "~0.6.1" source-map-support "~0.5.12" -terser@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.2.tgz#ed830de484b0103652799063e605618e80f97f93" - integrity sha512-obxk4x19Zlzj9zY4QeXj9iPCb5W8YGn4v3pn4/fHj0Nw8+R7N02Kvwvz9VpOItCZZD8RC+vnYCDL0gP6FAJ7Xg== +terser@^4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.3.tgz#f626c6779cadd60a3018e072fedeceabe4769db1" + integrity sha512-Nzr7dpRjSzMEUS+z2UYQBtzE0LDm5k0Yy8RgLRPy85QUo1TjU5lIOBwzS5/FVAMaVyHZ3WTTU2BuQcMn8KXnNQ== dependencies: commander "^2.20.0" source-map "~0.6.1" From 22268aa9d78addac19a5fd292915a836b90271c1 Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Thu, 26 Sep 2019 19:24:39 -0300 Subject: [PATCH 09/38] docs: add quick links to docs pages for small screens and add section table of contents indexes (#4145) --- docs/components/doc-breadcrumbs.vue | 49 +++++++ docs/components/feedback.js | 8 ++ docs/components/quick-links.vue | 127 ++++++++++++++++++ docs/components/search.vue | 24 ---- docs/components/section-toc.vue | 75 +++++++++++ docs/components/section.js | 2 +- docs/components/sidebar.vue | 10 +- docs/components/toc.vue | 17 +-- docs/content/index.js | 12 +- docs/layouts/docs.js | 27 +++- docs/markdown/intro/README.md | 26 +++- .../reference/spacing-classes/meta.json | 2 +- docs/pages/docs/components/index.js | 9 +- docs/pages/docs/directives/index.js | 9 +- docs/pages/docs/misc/index.js | 9 +- docs/pages/docs/reference/index.js | 9 +- docs/plugins/docs-mixin.js | 29 ++-- src/components/link/package.json | 2 +- src/components/pagination/package.json | 2 +- 19 files changed, 366 insertions(+), 82 deletions(-) create mode 100644 docs/components/doc-breadcrumbs.vue create mode 100644 docs/components/quick-links.vue create mode 100644 docs/components/section-toc.vue diff --git a/docs/components/doc-breadcrumbs.vue b/docs/components/doc-breadcrumbs.vue new file mode 100644 index 00000000000..1a75457936b --- /dev/null +++ b/docs/components/doc-breadcrumbs.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/docs/components/feedback.js b/docs/components/feedback.js index d83d4d2e3d2..0b997a86683 100644 --- a/docs/components/feedback.js +++ b/docs/components/feedback.js @@ -6,6 +6,11 @@ export default { } }, computed: { + show() { + const name = this.$route.name + const slug = this.$route.params.slug + return slug || name === 'docs' + }, reportIssueUrl() { // Add appreciate query params for proper issue title return `${this.baseUrl}/issues/new?title=Docs` @@ -35,6 +40,9 @@ export default { } }, render(h) { + if (!this.show) { + return h() + } const $reportIssueButton = h( 'b-button', { diff --git a/docs/components/quick-links.vue b/docs/components/quick-links.vue new file mode 100644 index 00000000000..3db70c2f991 --- /dev/null +++ b/docs/components/quick-links.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/docs/components/search.vue b/docs/components/search.vue index f1642c73087..e1d468e78e9 100644 --- a/docs/components/search.vue +++ b/docs/components/search.vue @@ -11,30 +11,6 @@ placeholder="Search..." aria-label="Search docs" > - diff --git a/docs/components/section-toc.vue b/docs/components/section-toc.vue new file mode 100644 index 00000000000..e66cc17f58b --- /dev/null +++ b/docs/components/section-toc.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/docs/components/section.js b/docs/components/section.js index 747dc5f25a3..cc60689cdfb 100644 --- a/docs/components/section.js +++ b/docs/components/section.js @@ -9,7 +9,7 @@ const scrollIntoView = (evt, href) => { evt.preventDefault() evt.stopPropagation() // We use an attribute `querySelector()` rather than `getElementByID()`, - // as some auto-generated ID's are invalid or may not be unique + // as some auto-generated ID's are invalid or not unique const id = (href || '').replace(/#/g, '') const $el = document.body.querySelector(`[id="${id}"]`) if ($el) { diff --git a/docs/components/sidebar.vue b/docs/components/sidebar.vue index 471b34a0673..e0502c9de8d 100644 --- a/docs/components/sidebar.vue +++ b/docs/components/sidebar.vue @@ -1,11 +1,5 @@