From 2ce667248a558f93efbab36465e5d415ef364e96 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 17 Nov 2021 17:18:27 +0200 Subject: [PATCH 01/34] chore(compat): introduce Vue3 testing infrastructure Add basic setup for running tests with vue3 compat --- jest.config.js | 14 +- package.json | 7 +- tests/setup.js | 18 +- yarn.lock | 691 ++++++++++++++++++++++++++++++++----------------- 4 files changed, 484 insertions(+), 246 deletions(-) diff --git a/jest.config.js b/jest.config.js index 044993b8baf..c39accbb5e3 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,10 +1,20 @@ +const useVue2 = 'USE_VUE2' in process.env + +const moduleNameMapper = useVue2 + ? {} + : { + '^vue$': '@vue/compat', + '^@vue/test-utils$': '@vue/test-utils-vue3' + } + module.exports = { testRegex: 'spec.js$', moduleFileExtensions: ['js', 'vue'], + moduleNameMapper, transform: { - '^.+\\.js$': 'babel-jest', - '.*\\.(vue)$': 'vue-jest' + '^.+\\.js$': 'babel-jest' }, + transformIgnorePatterns: ['/node_modules(?![\\\\/]vue-test-utils-compat[\\\\/])'], coverageDirectory: './coverage/', testEnvironmentOptions: { pretendToBeVisual: true diff --git a/package.json b/package.json index b566ad1cc71..1beaf77d806 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,10 @@ "@nuxtjs/robots": "^2.5.0", "@nuxtjs/sitemap": "^2.4.0", "@testing-library/jest-dom": "^5.12.0", + "@vue/compat": "^3.2.24", + "@vue/compiler-dom": "^3.2.24", "@vue/test-utils": "^1.3.0", + "@vue/test-utils-vue3": "npm:@vue/test-utils@2.0.0-rc.18", "autoprefixer": "^10.4.0", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "^10.1.0", @@ -148,10 +151,10 @@ "standard-version": "^9.3.0", "terser": "^5.15.0", "vue": "^2.6.12", - "vue-jest": "^3.0.7", "vue-router": "^3.5.1", "vue-server-renderer": "^2.6.12", - "vue-template-compiler": "^2.6.12" + "vue-template-compiler": "^2.6.12", + "vue-test-utils-compat": "0.0.3" }, "keywords": [ "Bootstrap", diff --git a/tests/setup.js b/tests/setup.js index f7810e142c4..d2947b2cb6d 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -1,6 +1,18 @@ import '@testing-library/jest-dom' -import { config as vtuConfig } from '@vue/test-utils' +import Vue from 'vue' +import * as VTU from '@vue/test-utils' +import { installCompat as installVTUCompat, fullCompatConfig } from 'vue-test-utils-compat' + +const useVue2 = 'USE_VUE2' in process.env +if (!useVue2) { + Vue.configureCompat({ + MODE: 2 + }) + + const compatH = new Vue({}).$createElement + installVTUCompat(VTU, fullCompatConfig, compatH) +} // Don't stub `` and `` components -vtuConfig.stubs.transition = false -vtuConfig.stubs['transition-group'] = false +VTU.config.stubs.transition = false +VTU.config.stubs['transition-group'] = false diff --git a/yarn.lock b/yarn.lock index e3cc8c25a30..80202c98cdc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,13 +25,20 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11", "@babel/code-frame@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== dependencies: "@babel/highlight" "^7.16.0" +"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + "@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.0": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.0.tgz#a901128bce2ad02565df95e6ecbf195cf9465919" @@ -42,7 +49,49 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.4.tgz#081d6bbc336ec5c2435c6346b2ae1fb98b5ac68e" integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q== -"@babel/core@^7.1.0", "@babel/core@^7.14.0", "@babel/core@^7.16.5", "@babel/core@^7.7.5": +"@babel/core@^7.1.0", "@babel/core@^7.7.5": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.10" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.10" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.0.tgz#47299ff3ec8d111b493f1a9d04bf88c04e728d88" + integrity sha512-8YqpRig5NmIHlMLw09zMlPTvUVMILjqCOtVgu+TVNWEBvy9b5I3RRyhqnrV4hjgEK7n8P9OqvkWJAFmEL6Wwfw== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.14.0" + "@babel/helper-compilation-targets" "^7.13.16" + "@babel/helper-module-transforms" "^7.14.0" + "@babel/helpers" "^7.14.0" + "@babel/parser" "^7.14.0" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.14.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/core@^7.16.5": version "7.16.5" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.5.tgz#924aa9e1ae56e1e55f7184c8bf073a50d8677f5c" integrity sha512-wUcenlLzuWMZ9Zt8S0KmFwGlH6QKRh3vsm/dhDA3CHkiTA45YuG1XkHRcNRl73EFPXDp/d5kVOU0/y7x2w6OaQ== @@ -63,6 +112,24 @@ semver "^6.3.0" source-map "^0.5.0" +"@babel/generator@^7.12.10", "@babel/generator@^7.12.11", "@babel/generator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.0.tgz#d40f3d1d5075e62d3500bccb67f3daa8a95265b2" + integrity sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew== + dependencies: + "@babel/types" "^7.16.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.14.0", "@babel/generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" + integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== + dependencies: + "@babel/types" "^7.16.8" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/generator@^7.16.5": version "7.16.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.5.tgz#26e1192eb8f78e0a3acaf3eede3c6fc96d22bedf" @@ -152,6 +219,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-explode-assignable-expression@^7.12.13": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz#17b5c59ff473d9f956f40ef570cf3a76ca12657f" @@ -159,6 +233,15 @@ dependencies: "@babel/types" "^7.13.0" +"@babel/helper-function-name@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== + dependencies: + "@babel/helper-get-function-arity" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/types" "^7.12.11" + "@babel/helper-function-name@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" @@ -186,6 +269,22 @@ "@babel/template" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-get-function-arity@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== + dependencies: + "@babel/types" "^7.12.10" + "@babel/helper-get-function-arity@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" @@ -200,6 +299,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-hoist-variables@^7.13.0": version "7.13.16" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.16.tgz#1b1651249e94b51f8f0d33439843e33e39775b30" @@ -215,6 +321,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-member-expression-to-functions@^7.13.12": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz#dfe368f26d426a07299d8d6513821768216e6d72" @@ -222,14 +335,64 @@ dependencies: "@babel/types" "^7.13.12" -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.13.12", "@babel/helper-module-imports@^7.16.0": +"@babel/helper-member-expression-to-functions@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz#29287040efd197c77636ef75188e81da8bccd5a4" + integrity sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" + integrity sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA== + dependencies: + "@babel/types" "^7.13.12" + +"@babel/helper-module-imports@^7.12.1": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" + integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== + dependencies: + "@babel/types" "^7.12.5" + +"@babel/helper-module-imports@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" integrity sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg== dependencies: "@babel/types" "^7.16.0" -"@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.14.0", "@babel/helper-module-transforms@^7.14.2", "@babel/helper-module-transforms@^7.16.5": +"@babel/helper-module-transforms@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== + dependencies: + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-simple-access" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/helper-validator-identifier" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + lodash "^4.17.19" + +"@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.14.0.tgz#8fcf78be220156f22633ee204ea81f73f826a8ad" + integrity sha512-L40t9bxIuGOfpIGA3HNkJhU9qYrf4y5A5LUSw7rGMSn+pcG8dfJ0g6Zval6YJGd2nEjI7oP00fRdnhLKndx6bw== + dependencies: + "@babel/helper-module-imports" "^7.13.12" + "@babel/helper-replace-supers" "^7.13.12" + "@babel/helper-simple-access" "^7.13.12" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/helper-validator-identifier" "^7.14.0" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.14.0" + +"@babel/helper-module-transforms@^7.14.2", "@babel/helper-module-transforms@^7.16.5": version "7.16.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.5.tgz#530ebf6ea87b500f60840578515adda2af470a29" integrity sha512-CkvMxgV4ZyyioElFwcuWnDCcNIeyqTkCm9BxXZi73RR1ozqlpboqsbGUNvRTflgZtFbbJ1v5Emvm+lkjMYY/LQ== @@ -250,7 +413,19 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.16.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-optimise-call-expression@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338" + integrity sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af" + integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ== + +"@babel/helper-plugin-utils@^7.16.5": version "7.16.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.5.tgz#afe37a45f39fce44a3d50a7958129ea5b1a5c074" integrity sha512-59KHWHXxVA9K4HNF4sbHCf+eJeFe0Te/ZFGqBT4OjXhrwvA04sGfaEGsVTdsjoszq0YTP49RC9UKe5g8uN2RwQ== @@ -264,6 +439,16 @@ "@babel/helper-wrap-function" "^7.13.0" "@babel/types" "^7.13.0" +"@babel/helper-replace-supers@^7.12.1": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz#73055e8d3cf9bcba8ddb55cad93fedc860f68f17" + integrity sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.16.0" + "@babel/helper-optimise-call-expression" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" + "@babel/helper-replace-supers@^7.12.13", "@babel/helper-replace-supers@^7.13.12": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz#6442f4c1ad912502481a564a7386de0c77ff3804" @@ -274,6 +459,13 @@ "@babel/traverse" "^7.13.0" "@babel/types" "^7.13.12" +"@babel/helper-simple-access@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== + dependencies: + "@babel/types" "^7.12.1" + "@babel/helper-simple-access@^7.13.12": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz#dd6c538afb61819d205a012c31792a39c7a5eaf6" @@ -295,6 +487,13 @@ dependencies: "@babel/types" "^7.12.1" +"@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11", "@babel/helper-split-export-declaration@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz#29672f43663e936df370aaeb22beddb3baec7438" + integrity sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw== + dependencies: + "@babel/types" "^7.16.0" + "@babel/helper-split-export-declaration@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" @@ -302,14 +501,19 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-split-export-declaration@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz#29672f43663e936df370aaeb22beddb3baec7438" - integrity sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw== +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.16.7" + +"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== -"@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.14.0": +"@babel/helper-validator-identifier@^7.14.0": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288" integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== @@ -319,6 +523,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + "@babel/helper-validator-option@^7.12.17": version "7.12.17" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" @@ -339,6 +548,24 @@ "@babel/traverse" "^7.13.0" "@babel/types" "^7.13.0" +"@babel/helpers@^7.12.5": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.0.tgz#875519c979c232f41adfbd43a3b0398c2e388183" + integrity sha512-dVRM0StFMdKlkt7cVcGgwD8UMaBfWJHl3A83Yfs8GQ3MO0LHIIIMvK7Fa0RGOGUQ10qikLaX6D7o5htcQWgTMQ== + dependencies: + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" + +"@babel/helpers@^7.14.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.7.tgz#7e3504d708d50344112767c3542fc5e357fffefc" + integrity sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helpers@^7.16.5": version "7.16.5" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.5.tgz#29a052d4b827846dd76ece16f565b9634c554ebd" @@ -366,11 +593,35 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.16.0", "@babel/parser@^7.16.5", "@babel/parser@^7.7.0": +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.16.5", "@babel/parser@^7.7.0": version "7.16.6" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.6.tgz#8f194828193e8fa79166f34a4b4e52f3e769a314" integrity sha512-Gr86ujcNuPDnNOY8mi383Hvi8IYrJVJYuf3XcuBM/Dgd+bINn/7tHqsj+tKkoreMbmGsFLsltI/JJd8fOFWGDQ== +"@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== + +"@babel/parser@^7.12.13", "@babel/parser@^7.14.0", "@babel/parser@^7.16.10", "@babel/parser@^7.16.7": + version "7.16.12" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.12.tgz#9474794f9a650cf5e2f892444227f98e28cdf8b6" + integrity sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A== + +"@babel/parser@^7.15.0", "@babel/parser@^7.16.0": + version "7.16.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.2.tgz#3723cd5c8d8773eef96ce57ea1d9b7faaccd12ac" + integrity sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw== + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.13.12": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.13.12.tgz#a3484d84d0b549f3fc916b99ee4783f26fabad2a" @@ -1012,7 +1263,25 @@ resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.16.6.tgz#2999d50df80207f747095118c19ed63a596a268b" integrity sha512-wjildVe951w1IPEPN4G76j+y5JFZfJN9gdyP8o9zd61qbiVEecAgORKskK1D/7VrJZrZS+nxDbhj2akEFU2RJw== -"@babel/template@^7.12.13", "@babel/template@^7.16.0", "@babel/template@^7.3.3": +"@babel/template@^7.10.4", "@babel/template@^7.12.7", "@babel/template@^7.3.3": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" + +"@babel/template@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" + integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/parser" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/template@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" integrity sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A== @@ -1021,7 +1290,76 @@ "@babel/parser" "^7.16.0" "@babel/types" "^7.16.0" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.15", "@babel/traverse@^7.16.5", "@babel/traverse@^7.7.0": +"@babel/template@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.7.0": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" + integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== + dependencies: + "@babel/code-frame" "^7.12.11" + "@babel/generator" "^7.12.11" + "@babel/helper-function-name" "^7.12.11" + "@babel/helper-split-export-declaration" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/types" "^7.12.12" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + +"@babel/traverse@^7.13.0", "@babel/traverse@^7.13.15": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.0.tgz#cea0dc8ae7e2b1dec65f512f39f3483e8cc95aef" + integrity sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.14.0" + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/parser" "^7.14.0" + "@babel/types" "^7.14.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.14.0", "@babel/traverse@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.10.tgz#448f940defbe95b5a8029975b051f75993e8239f" + integrity sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.16.10" + "@babel/types" "^7.16.8" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.0.tgz#965df6c6bfc0a958c1e739284d3c9fa4a6e3c45b" + integrity sha512-qQ84jIs1aRQxaGaxSysII9TuDaguZ5yVrEuC0BN2vcPlalwfLovVmCjbFDPECPXcYM/wLvNFfp8uDOliLxIoUQ== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/generator" "^7.16.0" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-hoist-variables" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" + "@babel/parser" "^7.16.0" + "@babel/types" "^7.16.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.16.5": version "7.16.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.5.tgz#d7d400a8229c714a59b87624fc67b0f1fbd4b2b3" integrity sha512-FOCODAzqUMROikDYLYxl4nmwiLlu85rNqBML/A5hKRVXG2LV8d0iMqgPzdYTcIpjZEBB7D6UDU9vxRZiriASdQ== @@ -1037,7 +1375,32 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.16", "@babel/types@^7.14.2", "@babel/types@^7.16.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": +"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + +"@babel/types@^7.12.13", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.16", "@babel/types@^7.14.2": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.2.tgz#4208ae003107ef8a057ea8333e56eb64d2f6a2c3" + integrity sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw== + dependencies: + "@babel/helper-validator-identifier" "^7.14.0" + to-fast-properties "^2.0.0" + +"@babel/types@^7.14.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" + integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + +"@babel/types@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== @@ -2169,16 +2532,6 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== -"@types/strip-bom@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" - integrity sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I= - -"@types/strip-json-comments@0.0.30": - version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" - integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== - "@types/tapable@^1", "@types/tapable@^1.0.5": version "1.0.7" resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.7.tgz#545158342f949e8fd3bfd813224971ecddc3fac4" @@ -2401,6 +2754,29 @@ "@vue/babel-plugin-transform-vue-jsx" "^1.2.1" camelcase "^5.0.0" +"@vue/compat@^3.2.24": + version "3.2.24" + resolved "https://registry.yarnpkg.com/@vue/compat/-/compat-3.2.24.tgz#6b10efb2773ccc8a59e625b4082bdc7cf2012549" + integrity sha512-fhnNc+SJ/hbhKZexVHVK+vZ0VstHm32VXgFEoiV1WWYNGRFJB5X7jbO/1a09IQgURiHwP0Km9jQQzN7/7sSbag== + +"@vue/compiler-core@3.2.24": + version "3.2.24" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.24.tgz#cadcda0e026e7f1cd453ce87160be51a5f313fe0" + integrity sha512-A0SxB2HAggKzP57LDin5gfgWOTwFyGCtQ5MTMNBADnfQYALWnYuC8kMI0DhRSplGTWRvn9Z2DAnG8f35BnojuA== + dependencies: + "@babel/parser" "^7.15.0" + "@vue/shared" "3.2.24" + estree-walker "^2.0.2" + source-map "^0.6.1" + +"@vue/compiler-dom@^3.2.24": + version "3.2.24" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.24.tgz#32235cb444660245be5cc58f4beb76747400505c" + integrity sha512-KQEm8r0JFsrNNIfbD28pcwMvHpcJcwjVR1XWFcD0yyQ8eREd7IXhT7J6j7iNCSE/TIo78NOvkwbyX+lnIm836w== + dependencies: + "@vue/compiler-core" "3.2.24" + "@vue/shared" "3.2.24" + "@vue/component-compiler-utils@^3.1.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz#8f85182ceed28e9b3c75313de669f83166d11e5d" @@ -2417,6 +2793,16 @@ optionalDependencies: prettier "^1.18.2" +"@vue/shared@3.2.24": + version "3.2.24" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.24.tgz#d74615e856013b17fb60b19b09d712729ad5e090" + integrity sha512-BUgRiZCkCrqDps5aQ9av05xcge3rn092ztKIh17tHkeEFgP4zfXMQWBA2zfdoCdCEdBL26xtOv+FZYiOp9RUDA== + +"@vue/test-utils-vue3@npm:@vue/test-utils@2.0.0-rc.18": + version "2.0.0-rc.18" + resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.0.0-rc.18.tgz#ff22b252424fe72e5462cbb3a8e7405cef11ffb6" + integrity sha512-aifolXjVdsogjaLmDoZ0FU8vN+R67aWmg9OuVeED4w5Ij5GFQLrlhM19uhWe/r5xXUL4fXMk3pX5wW6FJP1NcQ== + "@vue/test-utils@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.3.0.tgz#d563decdcd9c68a7bca151d4179a2bfd6d5c3e15" @@ -3131,15 +3517,6 @@ axios@^0.21.1: dependencies: follow-redirects "^1.10.0" -babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - babel-core@^7.0.0-bridge.0: version "7.0.0-bridge.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" @@ -3181,13 +3558,6 @@ babel-loader@^8.2.2: make-dir "^3.1.0" schema-utils "^2.6.5" -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= - dependencies: - babel-runtime "^6.22.0" - babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" @@ -3264,24 +3634,6 @@ babel-plugin-polyfill-regenerator@^0.3.0: dependencies: "@babel/helper-define-polyfill-provider" "^0.3.0" -babel-plugin-transform-es2015-modules-commonjs@^6.26.0: - version "6.26.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -3308,55 +3660,6 @@ babel-preset-jest@^26.6.2: babel-plugin-jest-hoist "^26.6.2" babel-preset-current-node-syntax "^1.0.0" -babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - bail@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" @@ -4201,11 +4504,6 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" -clone@2.x: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= - co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -4724,7 +5022,7 @@ core-js-pure@^3.0.0: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.12.1.tgz#934da8b9b7221e2a2443dc71dfa5bd77a7ea00b8" integrity sha512-1cch+qads4JnDSWsvc7d6nzlKAippwjUlf6vykkTLW53VSV+NkE6muGBToAjEA8pG90cSfcud3JgVmW2ds5TaQ== -core-js@^2.4.0, core-js@^2.6.5: +core-js@^2.6.5: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== @@ -4978,16 +5276,6 @@ css.escape@^1.5.1: resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= -css@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" - integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== - dependencies: - inherits "^2.0.3" - source-map "^0.6.1" - source-map-resolve "^0.5.2" - urix "^0.1.0" - css@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" @@ -5176,15 +5464,7 @@ de-indent@^1.0.2: resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= -deasync@^0.1.15: - version "0.1.21" - resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.21.tgz#bb11eabd4466c0d8776f0d82deb8a6126460d30f" - integrity sha512-kUmM8Y+PZpMpQ+B4AuOW9k2Pfx/mSupJtxOsLzmnHY2WqZUYRFccFn2RhzPAqt3Xb+sorK/badW2D4zNzqZz5w== - dependencies: - bindings "^1.5.0" - node-addon-api "^1.7.1" - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -6048,6 +6328,11 @@ estree-walker@^0.6.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -6232,13 +6517,6 @@ extract-css-chunks-webpack-plugin@^4.9.0: schema-utils "^1.0.0" webpack-sources "^1.1.0" -extract-from-css@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/extract-from-css/-/extract-from-css-0.4.4.tgz#1ea7df2e7c7c6eb9922fa08e8adaea486f6f8f92" - integrity sha1-HqffLnx8brmSL6COitrqSG9vj5I= - dependencies: - css "^2.1.0" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -6379,14 +6657,6 @@ finalhandler@1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-babel-config@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.2.0.tgz#a9b7b317eb5b9860cda9d54740a8c8337a2283a2" - integrity sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA== - dependencies: - json5 "^0.5.1" - path-exists "^3.0.0" - find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -6660,7 +6930,7 @@ genfun@^4.0.1: resolved "https://registry.yarnpkg.com/genfun/-/genfun-4.0.1.tgz#ed10041f2e4a7f1b0a38466d17a5c3e27df1dfc1" integrity sha1-7RAEHy5KfxsKOEZtF6XD4n3x38E= -gensync@^1.0.0-beta.2: +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== @@ -6929,12 +7199,19 @@ globals@^13.6.0: dependencies: type-fest "^0.20.2" -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globby@^11.0.0, globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" -globby@^11.0.0, globby@^11.0.1, globby@^11.0.3: +globby@^11.0.3: version "11.0.3" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb" integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg== @@ -7704,13 +7981,6 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - ip@^1.1.4, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" @@ -8666,7 +8936,7 @@ jiti@^1.9.2: resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.9.2.tgz#2ee44830883dbb1b2e222adc053c3052d0bf3b61" integrity sha512-wymUBR/YGGVNVRAxX52yvFoZdUAYKEGjk0sYrz6gXLCvMblnRvJAmDUnMvQiH4tUHDBtbKHnZ4GT3R+m3Hc39A== -js-beautify@^1.6.12, js-beautify@^1.6.14: +js-beautify@^1.6.12: version "1.13.13" resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.13.13.tgz#756907d1728f329f2b84c42efd56ad17514620bf" integrity sha512-oH+nc0U5mOAqX8M5JO1J0Pw/7Q35sAdOsM5W3i87pir9Ntx6P/5Gx1xLNoK+MGyvHk4rqqRCE4Oq58H6xl2W7A== @@ -8677,16 +8947,11 @@ js-beautify@^1.6.12, js-beautify@^1.6.14: mkdirp "^1.0.4" nopt "^5.0.0" -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: +js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - js-yaml@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f" @@ -8784,11 +9049,6 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -9146,7 +9406,12 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.15.0, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.7.0: +lodash@^4.15.0, lodash@^4.17.12, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.3, lodash@^4.17.5: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +lodash@^4.17.15, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -9181,13 +9446,6 @@ longest-streak@^2.0.0: resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" @@ -9972,19 +10230,6 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" -node-addon-api@^1.7.1: - version "1.7.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d" - integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== - -node-cache@^4.1.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.1.tgz#efd8474dee4edec4138cdded580f5516500f7334" - integrity sha512-BOb67bWg2dTyax5kdef5WfU3X8xu4wPg+zHzkvls0Q/QpYycIFRLEEIdAx9Wma43DxG6Qzn4illdZoYseKWa4A== - dependencies: - clone "2.x" - lodash "^4.17.15" - node-dir@^0.1.17: version "0.1.17" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" @@ -12097,11 +12342,6 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: version "0.13.7" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" @@ -12712,7 +12952,7 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -13057,7 +13297,7 @@ source-list-map@^2.0.0, source-list-map@^2.0.1: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf" integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA== -source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: +source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== @@ -13491,16 +13731,16 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + style-resources-loader@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/style-resources-loader/-/style-resources-loader-1.4.1.tgz#87f520e6c8120a71e756726c1c53a78c544ca7db" @@ -13831,11 +14071,6 @@ to-buffer@^1.1.1: resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -13957,16 +14192,6 @@ tsconfig-paths@^3.11.0: minimist "^1.2.0" strip-bom "^3.0.0" -tsconfig@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" - integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== - dependencies: - "@types/strip-bom" "^3.0.0" - "@types/strip-json-comments" "0.0.30" - strip-bom "^3.0.0" - strip-json-comments "^2.0.0" - tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -14579,23 +14804,6 @@ vue-hot-reload-api@^2.3.0: resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog== -vue-jest@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/vue-jest/-/vue-jest-3.0.7.tgz#a6d29758a5cb4d750f5d1242212be39be4296a33" - integrity sha512-PIOxFM+wsBMry26ZpfBvUQ/DGH2hvp5khDQ1n51g3bN0TwFwTy4J85XVfxTRMukqHji/GnAoGUnlZ5Ao73K62w== - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.26.0" - chalk "^2.1.0" - deasync "^0.1.15" - extract-from-css "^0.4.4" - find-babel-config "^1.1.0" - js-beautify "^1.6.14" - node-cache "^4.1.1" - object-assign "^4.1.1" - source-map "^0.5.6" - tsconfig "^7.0.0" - vue-template-es2015-compiler "^1.6.0" - vue-loader@^15.9.7: version "15.9.7" resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.7.tgz#15b05775c3e0c38407679393c2ce6df673b01044" @@ -14654,11 +14862,16 @@ vue-template-compiler@^2.6.12: de-indent "^1.0.2" he "^1.1.0" -vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0: +vue-template-es2015-compiler@^1.9.0: version "1.9.1" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== +vue-test-utils-compat@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/vue-test-utils-compat/-/vue-test-utils-compat-0.0.3.tgz#d3efb08b049e97fc4577bdb1a93e417f546c2651" + integrity sha512-2zFkkcoirkp2FTrO7y2y4fZ9ZJ3WaoPoxwAZ7MmptlUhLchxbcay1KJ8t9qdJS1PHnu6aF98mD0Dn0jMQGoDGQ== + vue@^2.6.12: version "2.6.12" resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123" From 7b02d336b55cd75422a40a1af522aec490b56934 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Sat, 6 Nov 2021 19:43:12 +0200 Subject: [PATCH 02/34] chore(compat): replace providing components with getter functions Vue3 compat build fails so hard when you have a Vue component inside provide. To avoid this replace direct provides with combination of getter functions and computed --- src/components/avatar/avatar-group.js | 2 +- src/components/avatar/avatar.js | 5 +++- src/components/avatar/avatar.spec.js | 12 +++++----- src/components/carousel/carousel-slide.js | 7 ++++-- .../carousel/carousel-slide.spec.js | 8 +++---- src/components/carousel/carousel.js | 2 +- .../dropdown/dropdown-item-button.js | 6 ++++- .../dropdown/dropdown-item-button.spec.js | 8 +++---- src/components/dropdown/dropdown-item.js | 5 +++- src/components/dropdown/dropdown-item.spec.js | 8 +++---- .../form-checkbox/form-checkbox-group.js | 2 +- src/components/form-checkbox/form-checkbox.js | 9 ++++--- src/components/form-radio/form-radio-group.js | 2 +- src/components/form-radio/form-radio.js | 11 ++++++--- src/components/navbar/navbar.js | 2 +- src/components/progress/progress-bar.js | 7 ++++-- src/components/progress/progress-bar.spec.js | 20 ++++++++-------- src/components/progress/progress.js | 2 +- .../table/helpers/mixin-table-renderer.js | 2 +- src/components/table/tbody.js | 9 ++++--- src/components/table/td.js | 7 ++++-- src/components/table/tfoot.js | 9 ++++--- src/components/table/thead.js | 9 ++++--- src/components/table/tr.js | 9 ++++--- src/components/tabs/tab.js | 7 ++++-- src/components/tabs/tab.spec.js | 24 +++++++++---------- src/components/tabs/tabs.js | 11 ++++++--- src/mixins/dropdown.js | 7 ++++-- 28 files changed, 131 insertions(+), 81 deletions(-) diff --git a/src/components/avatar/avatar-group.js b/src/components/avatar/avatar-group.js index e80bc3b2190..89772dd5339 100644 --- a/src/components/avatar/avatar-group.js +++ b/src/components/avatar/avatar-group.js @@ -37,7 +37,7 @@ export const BAvatarGroup = /*#__PURE__*/ Vue.extend({ name: NAME_AVATAR_GROUP, mixins: [normalizeSlotMixin], provide() { - return { bvAvatarGroup: this } + return { getBvAvatarGroup: () => this } }, props, computed: { diff --git a/src/components/avatar/avatar.js b/src/components/avatar/avatar.js index c510f198c1d..ec7a966c791 100644 --- a/src/components/avatar/avatar.js +++ b/src/components/avatar/avatar.js @@ -71,7 +71,7 @@ export const BAvatar = /*#__PURE__*/ Vue.extend({ name: NAME_AVATAR, mixins: [normalizeSlotMixin], inject: { - bvAvatarGroup: { default: null } + getBvAvatarGroup: { default: () => () => null } }, props, data() { @@ -80,6 +80,9 @@ export const BAvatar = /*#__PURE__*/ Vue.extend({ } }, computed: { + bvAvatarGroup() { + return this.getBvAvatarGroup() + }, computedSize() { // Always use the avatar group size const { bvAvatarGroup } = this diff --git a/src/components/avatar/avatar.spec.js b/src/components/avatar/avatar.spec.js index 304766a4d84..013698ff412 100644 --- a/src/components/avatar/avatar.spec.js +++ b/src/components/avatar/avatar.spec.js @@ -250,7 +250,7 @@ describe('avatar', () => { const wrapper1 = mount(BAvatar, { provide: { // Emulate `undefined`/`null` props - bvAvatarGroup: {} + getBvAvatarGroup: () => ({}) } }) @@ -265,9 +265,9 @@ describe('avatar', () => { const wrapper2 = mount(BAvatar, { provide: { - bvAvatarGroup: { + getBvAvatarGroup: () => ({ variant: 'danger' - } + }) } }) @@ -289,7 +289,7 @@ describe('avatar', () => { }, provide: { // Emulate `undefined`/`null` props - bvAvatarGroup: {} + getBvAvatarGroup: () => ({}) } }) @@ -307,9 +307,9 @@ describe('avatar', () => { size: '2em' }, provide: { - bvAvatarGroup: { + getBvAvatarGroup: () => ({ size: '5em' - } + }) } }) diff --git a/src/components/carousel/carousel-slide.js b/src/components/carousel/carousel-slide.js index 95a0396185a..b958fe5af40 100644 --- a/src/components/carousel/carousel-slide.js +++ b/src/components/carousel/carousel-slide.js @@ -47,13 +47,16 @@ export const BCarouselSlide = /*#__PURE__*/ Vue.extend({ name: NAME_CAROUSEL_SLIDE, mixins: [idMixin, normalizeSlotMixin], inject: { - bvCarousel: { + getBvCarousel: { // Explicitly disable touch if not a child of carousel - default: () => ({ noTouch: true }) + default: () => () => ({ noTouch: true }) } }, props, computed: { + bvCarousel() { + return this.getBvCarousel() + }, contentClasses() { return [ this.contentVisibleUp ? 'd-none' : '', diff --git a/src/components/carousel/carousel-slide.spec.js b/src/components/carousel/carousel-slide.spec.js index 5e26b93084b..832f8966740 100644 --- a/src/components/carousel/carousel-slide.spec.js +++ b/src/components/carousel/carousel-slide.spec.js @@ -144,9 +144,9 @@ describe('carousel-slide', () => { it('has style background inherited from carousel parent', async () => { const wrapper = mount(BCarouselSlide, { provide: { - bvCarousel: { + getBvCarousel: () => ({ background: 'rgb(1, 2, 3)' - } + }) } }) @@ -254,10 +254,10 @@ describe('carousel-slide', () => { const wrapper = mount(BCarouselSlide, { provide: { // Mock carousel injection - bvCarousel: { + getBvCarousel: () => ({ imgWidth: '1024', imgHeight: '480' - } + }) }, propsData: { imgSrc: 'https://picsum.photos/1024/480/?image=52' diff --git a/src/components/carousel/carousel.js b/src/components/carousel/carousel.js index 287b311e716..83970ca4d95 100644 --- a/src/components/carousel/carousel.js +++ b/src/components/carousel/carousel.js @@ -136,7 +136,7 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ name: NAME_CAROUSEL, mixins: [idMixin, modelMixin, normalizeSlotMixin], provide() { - return { bvCarousel: this } + return { getBvCarousel: () => this } }, props, data() { diff --git a/src/components/dropdown/dropdown-item-button.js b/src/components/dropdown/dropdown-item-button.js index 6e3b1057a85..53599fc3296 100644 --- a/src/components/dropdown/dropdown-item-button.js +++ b/src/components/dropdown/dropdown-item-button.js @@ -30,11 +30,15 @@ export const BDropdownItemButton = /*#__PURE__*/ Vue.extend({ name: NAME_DROPDOWN_ITEM_BUTTON, mixins: [attrsMixin, normalizeSlotMixin], inject: { - bvDropdown: { default: null } + getBvDropdown: { default: () => () => null } }, inheritAttrs: false, props, computed: { + bvDropdown() { + return this.getBvDropdown() + }, + computedAttrs() { return { ...this.bvAttrs, diff --git a/src/components/dropdown/dropdown-item-button.spec.js b/src/components/dropdown/dropdown-item-button.spec.js index 0c01b8c1301..66e5183537d 100644 --- a/src/components/dropdown/dropdown-item-button.spec.js +++ b/src/components/dropdown/dropdown-item-button.spec.js @@ -54,12 +54,12 @@ describe('dropdown-item-button', () => { let refocus = null const wrapper = mount(BDropdownItemButton, { provide: { - bvDropdown: { + getBvDropdown: () => ({ hide(arg) { called = true refocus = arg } - } + }) } }) expect(wrapper.element.tagName).toBe('LI') @@ -81,12 +81,12 @@ describe('dropdown-item-button', () => { disabled: true }, provide: { - bvDropdown: { + getBvDropdown: () => ({ hide(arg) { called = true refocus = arg } - } + }) } }) expect(wrapper.element.tagName).toBe('LI') diff --git a/src/components/dropdown/dropdown-item.js b/src/components/dropdown/dropdown-item.js index d2bb1da1d58..e741b0fe35e 100644 --- a/src/components/dropdown/dropdown-item.js +++ b/src/components/dropdown/dropdown-item.js @@ -29,11 +29,14 @@ export const BDropdownItem = /*#__PURE__*/ Vue.extend({ name: NAME_DROPDOWN_ITEM, mixins: [attrsMixin, normalizeSlotMixin], inject: { - bvDropdown: { default: null } + getBvDropdown: { default: () => () => null } }, inheritAttrs: false, props, computed: { + bvDropdown() { + return this.getBvDropdown() + }, computedAttrs() { return { ...this.bvAttrs, diff --git a/src/components/dropdown/dropdown-item.spec.js b/src/components/dropdown/dropdown-item.spec.js index 5533e58df67..f5b6dcd8af3 100644 --- a/src/components/dropdown/dropdown-item.spec.js +++ b/src/components/dropdown/dropdown-item.spec.js @@ -34,12 +34,12 @@ describe('dropdown-item', () => { let refocus = null const wrapper = mount(BDropdownItem, { provide: { - bvDropdown: { + getBvDropdown: () => ({ hide(arg) { called = true refocus = arg } - } + }) } }) expect(wrapper.element.tagName).toBe('LI') @@ -60,12 +60,12 @@ describe('dropdown-item', () => { const wrapper = mount(BDropdownItem, { propsData: { disabled: true }, provide: { - bvDropdown: { + getBvDropdown: () => ({ hide(arg) { called = true refocus = arg } - } + }) } }) expect(wrapper.element.tagName).toBe('LI') diff --git a/src/components/form-checkbox/form-checkbox-group.js b/src/components/form-checkbox/form-checkbox-group.js index 10b6dc24a32..4d607797bab 100644 --- a/src/components/form-checkbox/form-checkbox-group.js +++ b/src/components/form-checkbox/form-checkbox-group.js @@ -30,7 +30,7 @@ export const BFormCheckboxGroup = /*#__PURE__*/ Vue.extend({ mixins: [formRadioCheckGroupMixin], provide() { return { - bvCheckGroup: this + getBvCheckGroup: () => this } }, props, diff --git a/src/components/form-checkbox/form-checkbox.js b/src/components/form-checkbox/form-checkbox.js index a9dc68f7ef4..ac86517fd3e 100644 --- a/src/components/form-checkbox/form-checkbox.js +++ b/src/components/form-checkbox/form-checkbox.js @@ -41,13 +41,16 @@ export const BFormCheckbox = /*#__PURE__*/ Vue.extend({ name: NAME_FORM_CHECKBOX, mixins: [formRadioCheckMixin], inject: { - bvGroup: { - from: 'bvCheckGroup', - default: null + getBvGroup: { + from: 'getBvCheckGroup', + default: () => () => null } }, props, computed: { + bvGroup() { + return this.getBvGroup() + }, isChecked() { const { value, computedLocalChecked: checked } = this return isArray(checked) ? looseIndexOf(checked, value) > -1 : looseEqual(checked, value) diff --git a/src/components/form-radio/form-radio-group.js b/src/components/form-radio/form-radio-group.js index 2c8d434c0cc..5fef309ae5b 100644 --- a/src/components/form-radio/form-radio-group.js +++ b/src/components/form-radio/form-radio-group.js @@ -18,7 +18,7 @@ export const BFormRadioGroup = /*#__PURE__*/ Vue.extend({ mixins: [formRadioCheckGroupMixin], provide() { return { - bvRadioGroup: this + getBvRadioGroup: () => this } }, props, diff --git a/src/components/form-radio/form-radio.js b/src/components/form-radio/form-radio.js index 27577d12b09..c4ac840668c 100644 --- a/src/components/form-radio/form-radio.js +++ b/src/components/form-radio/form-radio.js @@ -19,12 +19,17 @@ export const BFormRadio = /*#__PURE__*/ Vue.extend({ name: NAME_FORM_RADIO, mixins: [formRadioCheckMixin], inject: { - bvGroup: { - from: 'bvRadioGroup', - default: false + getBvGroup: { + from: 'getBvRadioGroup', + default: () => () => null } }, props, + computed: { + bvGroup() { + return this.getBvGroup() + } + }, watch: { computedLocalChecked(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { diff --git a/src/components/navbar/navbar.js b/src/components/navbar/navbar.js index 79b64917e0e..0c6d7e1afc3 100644 --- a/src/components/navbar/navbar.js +++ b/src/components/navbar/navbar.js @@ -33,7 +33,7 @@ export const BNavbar = /*#__PURE__*/ Vue.extend({ name: NAME_NAVBAR, mixins: [normalizeSlotMixin], provide() { - return { bvNavbar: this } + return { getBvNavbar: () => this } }, props, computed: { diff --git a/src/components/progress/progress-bar.js b/src/components/progress/progress-bar.js index 8fe23e70832..ae8ced02ec2 100644 --- a/src/components/progress/progress-bar.js +++ b/src/components/progress/progress-bar.js @@ -34,12 +34,15 @@ export const BProgressBar = /*#__PURE__*/ Vue.extend({ name: NAME_PROGRESS_BAR, mixins: [normalizeSlotMixin], inject: { - bvProgress: { - default: /* istanbul ignore next */ () => ({}) + getBvProgress: { + default: /* istanbul ignore next */ () => () => ({}) } }, props, computed: { + bvProgress() { + return this.getBvProgress() + }, progressBarClasses() { const { computedAnimated, computedVariant } = this return [ diff --git a/src/components/progress/progress-bar.spec.js b/src/components/progress/progress-bar.spec.js index 3fb64e8c293..730db5ceb60 100644 --- a/src/components/progress/progress-bar.spec.js +++ b/src/components/progress/progress-bar.spec.js @@ -38,9 +38,9 @@ describe('progress-bar', () => { it('has class bg-info when parent variant=info', async () => { const wrapper = mount(BProgressBar, { provide: { - bvProgress: { + getBvProgress: () => ({ variant: 'info' - } + }) } }) @@ -53,9 +53,9 @@ describe('progress-bar', () => { it('has class bg-primary when prop variant=primary and parent variant=info', async () => { const wrapper = mount(BProgressBar, { provide: { - bvProgress: { + getBvProgress: () => ({ variant: 'info' - } + }) }, propsData: { variant: 'primary' @@ -83,9 +83,9 @@ describe('progress-bar', () => { it('has class progress-bar-striped when parent prop striped set', async () => { const wrapper = mount(BProgressBar, { provide: { - bvProgress: { + getBvProgress: () => ({ striped: true - } + }) } }) @@ -112,9 +112,9 @@ describe('progress-bar', () => { it('has class progress-bar-animated and progress-bar-striped when parent prop animated set', async () => { const wrapper = mount(BProgressBar, { provide: { - bvProgress: { + getBvProgress: () => ({ animated: true - } + }) } }) @@ -159,9 +159,9 @@ describe('progress-bar', () => { it('has max set when parent max set', async () => { const wrapper = mount(BProgressBar, { provide: { - bvProgress: { + getBvProgress: () => ({ max: 50 - } + }) }, propsData: { value: 25 diff --git a/src/components/progress/progress.js b/src/components/progress/progress.js index 17180502477..341b3d6669f 100644 --- a/src/components/progress/progress.js +++ b/src/components/progress/progress.js @@ -31,7 +31,7 @@ export const BProgress = /*#__PURE__*/ Vue.extend({ name: NAME_PROGRESS, mixins: [normalizeSlotMixin], provide() { - return { bvProgress: this } + return { getBvProgress: () => this } }, props, computed: { diff --git a/src/components/table/helpers/mixin-table-renderer.js b/src/components/table/helpers/mixin-table-renderer.js index 545da7af61c..8075968bc6f 100644 --- a/src/components/table/helpers/mixin-table-renderer.js +++ b/src/components/table/helpers/mixin-table-renderer.js @@ -41,7 +41,7 @@ export const tableRendererMixin = Vue.extend({ mixins: [attrsMixin], provide() { return { - bvTable: this + getBvTable: () => this } }, // Don't place attributes on root element automatically, diff --git a/src/components/table/tbody.js b/src/components/table/tbody.js index 5f6bd6c6615..f42fc613064 100644 --- a/src/components/table/tbody.js +++ b/src/components/table/tbody.js @@ -27,18 +27,21 @@ export const BTbody = /*#__PURE__*/ Vue.extend({ mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide() { return { - bvTableRowGroup: this + getBvTableRowGroup: () => this } }, inject: { // Sniffed by `` / `` / `` - bvTable: { - default: /* istanbul ignore next */ () => ({}) + getBvTable: { + default: /* istanbul ignore next */ () => () => ({}) } }, inheritAttrs: false, props, computed: { + bvTable() { + return this.getBvTable() + }, // Sniffed by `` / `` / `` isTbody() { return true diff --git a/src/components/table/td.js b/src/components/table/td.js index 4ac26d343ee..26c8047b5f2 100644 --- a/src/components/table/td.js +++ b/src/components/table/td.js @@ -45,13 +45,16 @@ export const BTd = /*#__PURE__*/ Vue.extend({ // Mixin order is important! mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], inject: { - bvTableTr: { - default: /* istanbul ignore next */ () => ({}) + getBvTableTr: { + default: /* istanbul ignore next */ () => () => ({}) } }, inheritAttrs: false, props, computed: { + bvTableTr() { + return this.getBvTableTr() + }, // Overridden by `` tag() { return 'td' diff --git a/src/components/table/tfoot.js b/src/components/table/tfoot.js index 40ec68c7aa9..669f2474a6f 100644 --- a/src/components/table/tfoot.js +++ b/src/components/table/tfoot.js @@ -27,18 +27,21 @@ export const BTfoot = /*#__PURE__*/ Vue.extend({ mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide() { return { - bvTableRowGroup: this + getBvTableRowGroup: () => this } }, inject: { // Sniffed by `` / `` / `` - bvTable: { - default: /* istanbul ignore next */ () => ({}) + getBvTable: { + default: /* istanbul ignore next */ () => () => ({}) } }, inheritAttrs: false, props, computed: { + bvTable() { + return this.getBvTable() + }, // Sniffed by `` / `` / `` isTfoot() { return true diff --git a/src/components/table/thead.js b/src/components/table/thead.js index ec8fea6cfc3..3ffd55fa308 100644 --- a/src/components/table/thead.js +++ b/src/components/table/thead.js @@ -28,18 +28,21 @@ export const BThead = /*#__PURE__*/ Vue.extend({ mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide() { return { - bvTableRowGroup: this + getBvTableRowGroup: () => this } }, inject: { // Sniffed by `` / `` / `` - bvTable: { - default: /* istanbul ignore next */ () => ({}) + getBvTable: { + default: /* istanbul ignore next */ () => () => ({}) } }, inheritAttrs: false, props, computed: { + bvTable() { + return this.getBvTable() + }, // Sniffed by `` / `` / `` isThead() { return true diff --git a/src/components/table/tr.js b/src/components/table/tr.js index 320cc4ad5e1..e9f0c61f7da 100644 --- a/src/components/table/tr.js +++ b/src/components/table/tr.js @@ -31,17 +31,20 @@ export const BTr = /*#__PURE__*/ Vue.extend({ mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide() { return { - bvTableTr: this + getBvTableTr: () => this } }, inject: { - bvTableRowGroup: { - default: /* istanbul ignore next */ () => ({}) + getBvTableRowGroup: { + default: /* istanbul ignore next */ () => () => ({}) } }, inheritAttrs: false, props, computed: { + bvTableRowGroup() { + return this.getBvTableRowGroup() + }, // Sniffed by `` / `` inTbody() { return this.bvTableRowGroup.isTbody diff --git a/src/components/tabs/tab.js b/src/components/tabs/tab.js index 1a527432004..f75f813af59 100644 --- a/src/components/tabs/tab.js +++ b/src/components/tabs/tab.js @@ -47,8 +47,8 @@ export const BTab = /*#__PURE__*/ Vue.extend({ name: NAME_TAB, mixins: [idMixin, normalizeSlotMixin], inject: { - bvTabs: { - default: () => ({}) + getBvTabs: { + default: () => () => ({}) } }, props, @@ -58,6 +58,9 @@ export const BTab = /*#__PURE__*/ Vue.extend({ } }, computed: { + bvTabs() { + return this.getBvTabs() + }, // For parent sniffing of child _isTab() { return true diff --git a/src/components/tabs/tab.spec.js b/src/components/tabs/tab.spec.js index c47a9fbe16d..5592a193f19 100644 --- a/src/components/tabs/tab.spec.js +++ b/src/components/tabs/tab.spec.js @@ -125,12 +125,12 @@ describe('tab', () => { const wrapper = mount(BTab, { provide() { return { - bvTabs: { + getBvTabs: () => ({ fade: false, lazy: false, card: true, noKeyNav: true - } + }) } } }) @@ -147,12 +147,12 @@ describe('tab', () => { const wrapper = mount(BTab, { provide() { return { - bvTabs: { + getBvTabs: () => ({ fade: false, lazy: false, card: true, noKeyNav: true - } + }) } }, propsData: { @@ -174,7 +174,7 @@ describe('tab', () => { const wrapper = mount(BTab, { provide() { return { - bvTabs: { + getBvTabs: () => ({ fade: false, lazy: false, card: false, @@ -184,7 +184,7 @@ describe('tab', () => { vm = tab return true } - } + }) } }, slots: { @@ -209,7 +209,7 @@ describe('tab', () => { const wrapper = mount(BTab, { provide() { return { - bvTabs: { + getBvTabs: () => ({ fade: false, lazy: false, card: false, @@ -226,7 +226,7 @@ describe('tab', () => { tab.localActive = false return true } - } + }) } } }) @@ -265,7 +265,7 @@ describe('tab', () => { const wrapper = mount(BTab, { provide() { return { - bvTabs: { + getBvTabs: () => ({ fade: false, lazy: false, card: false, @@ -276,7 +276,7 @@ describe('tab', () => { tab.localActive = true return true } - } + }) } }, propsData: { disabled: true } @@ -300,7 +300,7 @@ describe('tab', () => { const wrapper = mount(BTab, { provide() { return { - bvTabs: { + getBvTabs: () => ({ fade: false, lazy: false, card: false, @@ -311,7 +311,7 @@ describe('tab', () => { tab.localActive = false return true } - } + }) } } }) diff --git a/src/components/tabs/tabs.js b/src/components/tabs/tabs.js index 3e5f9a47e19..bc89b9e1da1 100644 --- a/src/components/tabs/tabs.js +++ b/src/components/tabs/tabs.js @@ -70,8 +70,8 @@ const notDisabled = tab => !tab.disabled const BVTabButton = /*#__PURE__*/ Vue.extend({ name: NAME_TAB_BUTTON_HELPER, inject: { - bvTabs: { - default: /* istanbul ignore next */ () => ({}) + getBvTabs: { + default: /* istanbul ignore next */ () => () => ({}) } }, props: { @@ -84,6 +84,11 @@ const BVTabButton = /*#__PURE__*/ Vue.extend({ tab: makeProp(), tabIndex: makeProp(PROP_TYPE_NUMBER) }, + computed: { + bvTabs() { + return this.getBvTabs() + } + }, methods: { focus() { attemptFocus(this.$refs.link) @@ -218,7 +223,7 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ mixins: [idMixin, modelMixin, normalizeSlotMixin], provide() { return { - bvTabs: this + getBvTabs: () => this } }, props, diff --git a/src/mixins/dropdown.js b/src/mixins/dropdown.js index fdae8028acb..532001f3a83 100644 --- a/src/mixins/dropdown.js +++ b/src/mixins/dropdown.js @@ -87,10 +87,10 @@ export const props = makePropsConfigurable( export const dropdownMixin = Vue.extend({ mixins: [idMixin, listenOnRootMixin, clickOutMixin, focusInMixin], provide() { - return { bvDropdown: this } + return { getBvDropdown: () => this } }, inject: { - bvNavbar: { default: null } + getBvNavbar: { default: () => () => null } }, props, data() { @@ -100,6 +100,9 @@ export const dropdownMixin = Vue.extend({ } }, computed: { + bvNavbar() { + return this.getBvNavbar() + }, inNavbar() { return !isNull(this.bvNavbar) }, From c096e2d8af0302aa4f508ea93834d3087ee5eaa6 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Sat, 6 Nov 2021 20:58:05 +0200 Subject: [PATCH 03/34] chore(compat): replace parent/root access with wrappers Vue 3 compat does not allow to pass parent as parameter to new Vue instance, so we need to introduce a mixin to handle that. In future root mixin might be replaced with some tiny emitter like mitt --- src/components/modal/helpers/bv-modal.js | 23 +++++++------ src/components/table/helpers/mixin-items.js | 10 +++--- .../table/helpers/mixin-tbody-row.js | 14 ++++---- src/components/toast/helpers/bv-toast.js | 15 +++++---- src/components/toast/toast.js | 4 +-- src/components/tooltip/helpers/bv-popper.js | 4 ++- .../tooltip/helpers/bv-tooltip-template.js | 2 +- src/components/tooltip/helpers/bv-tooltip.js | 32 +++++++++---------- src/components/tooltip/tooltip.js | 9 +++--- src/components/transporter/transporter.js | 4 +-- src/directives/modal/modal.js | 3 +- src/directives/popover/popover.js | 8 ++--- src/directives/scrollspy/scrollspy.js | 5 +-- src/directives/toggle/toggle.js | 9 +++--- src/directives/tooltip/tooltip.js | 8 ++--- src/mixins/dropdown.js | 4 +-- src/mixins/listen-on-root.js | 23 +++++++------ src/mixins/scoped-style.js | 4 ++- src/mixins/use-parent.js | 12 +++++++ src/utils/create-new-child-component.js | 9 ++++++ src/utils/get-event-root.js | 3 ++ 21 files changed, 125 insertions(+), 80 deletions(-) create mode 100644 src/mixins/use-parent.js create mode 100644 src/utils/create-new-child-component.js create mode 100644 src/utils/get-event-root.js diff --git a/src/components/modal/helpers/bv-modal.js b/src/components/modal/helpers/bv-modal.js index 31d052b339a..898a9b5c9a1 100644 --- a/src/components/modal/helpers/bv-modal.js +++ b/src/components/modal/helpers/bv-modal.js @@ -6,6 +6,7 @@ import { HOOK_EVENT_NAME_BEFORE_DESTROY, HOOK_EVENT_NAME_DESTROYED } from '../../../constants/events' +import { useParentMixin } from '../../../mixins/use-parent' import { concat } from '../../../utils/array' import { getComponentConfig } from '../../../utils/config' import { requestAF } from '../../../utils/dom' @@ -22,6 +23,8 @@ import { } from '../../../utils/object' import { pluginFactory } from '../../../utils/plugins' import { warn, warnNotClient, warnNoPromiseSupport } from '../../../utils/warn' +import { createNewChildComponent } from '../../../utils/create-new-child-component' +import { getEventRoot } from '../../../utils/get-event-root' import { BModal, props as modalProps } from '../modal' // --- Constants --- @@ -69,6 +72,7 @@ const plugin = Vue => { const BMsgBox = Vue.extend({ name: NAME_MSG_BOX, extends: BModal, + mixins: [useParentMixin], destroyed() { // Make sure we not in document any more if (this.$el && this.$el.parentNode) { @@ -86,7 +90,7 @@ const plugin = Vue => { }) } // Self destruct if parent destroyed - this.$parent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy) + this.bvParent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy) // Self destruct after hidden this.$once(EVENT_NAME_HIDDEN, handleDestroy) // Self destruct on route change @@ -103,17 +107,16 @@ const plugin = Vue => { // Method to generate the on-demand modal message box // Returns a promise that resolves to a value returned by the resolve - const asyncMsgBox = ($parent, props, resolver = defaultResolver) => { + const asyncMsgBox = (parent, props, resolver = defaultResolver) => { if (warnNotClient(PROP_NAME) || warnNoPromiseSupport(PROP_NAME)) { /* istanbul ignore next */ return } // Create an instance of `BMsgBox` component - const msgBox = new BMsgBox({ - // We set parent as the local VM so these modals can emit events on - // the app `$root`, as needed by things like tooltips and popovers - // And it helps to ensure `BMsgBox` is destroyed when parent is destroyed - parent: $parent, + // We set parent as the local VM so these modals can emit events on + // the app `$root`, as needed by things like tooltips and popovers + // And it helps to ensure `BMsgBox` is destroyed when parent is destroyed + const msgBox = createNewChildComponent(parent, BMsgBox, { // Preset the prop values propsData: { ...filterOptions(getComponentConfig(NAME_MODAL)), @@ -166,7 +169,7 @@ const plugin = Vue => { // Private utility method to open a user defined message box and returns a promise. // Not to be used directly by consumers, as this method may change calling syntax - const makeMsgBox = ($parent, content, options = {}, resolver = null) => { + const makeMsgBox = (parent, content, options = {}, resolver = null) => { if ( !content || warnNoPromiseSupport(PROP_NAME) || @@ -176,14 +179,14 @@ const plugin = Vue => { /* istanbul ignore next */ return } - return asyncMsgBox($parent, { ...filterOptions(options), msgBoxContent: content }, resolver) + return asyncMsgBox(parent, { ...filterOptions(options), msgBoxContent: content }, resolver) } // BvModal instance class class BvModal { constructor(vm) { // Assign the new properties to this instance - assign(this, { _vm: vm, _root: vm.$root }) + assign(this, { _vm: vm, _root: getEventRoot(vm) }) // Set these properties as read-only and non-enumerable defineProperties(this, { _vm: readonlyDescriptor(), diff --git a/src/components/table/helpers/mixin-items.js b/src/components/table/helpers/mixin-items.js index 9d334ecf0e9..c870d904811 100644 --- a/src/components/table/helpers/mixin-items.js +++ b/src/components/table/helpers/mixin-items.js @@ -1,10 +1,12 @@ import { Vue } from '../../../vue' import { EVENT_NAME_CONTEXT_CHANGED } from '../../../constants/events' import { PROP_TYPE_ARRAY, PROP_TYPE_STRING } from '../../../constants/props' +import { useParentMixin } from '../../../mixins/use-parent' import { isArray, isFunction, isString } from '../../../utils/inspect' import { looseEqual } from '../../../utils/loose-equal' import { mathMax } from '../../../utils/math' import { makeModelMixin } from '../../../utils/model' + import { toInteger } from '../../../utils/number' import { clone, sortKeys } from '../../../utils/object' import { makeProp } from '../../../utils/props' @@ -42,7 +44,7 @@ export const props = sortKeys({ // @vue/component export const itemsMixin = Vue.extend({ - mixins: [modelMixin], + mixins: [modelMixin, useParentMixin], props, data() { const { items } = this @@ -64,15 +66,15 @@ export const itemsMixin = Vue.extend({ // Mainly for formatter lookup and use in `scopedSlots` for convenience // If the field has a formatter, it normalizes formatter to a // function ref or `undefined` if no formatter - const { $parent } = this + const { bvParent } = this return this.computedFields.reduce((obj, f) => { // We use object spread here so we don't mutate the original field object obj[f.key] = clone(f) if (f.formatter) { // Normalize formatter to a function ref or `undefined` let formatter = f.formatter - if (isString(formatter) && isFunction($parent[formatter])) { - formatter = $parent[formatter] + if (isString(formatter) && isFunction(bvParent[formatter])) { + formatter = bvParent[formatter] } else if (!isFunction(formatter)) { /* istanbul ignore next */ formatter = undefined diff --git a/src/components/table/helpers/mixin-tbody-row.js b/src/components/table/helpers/mixin-tbody-row.js index e796e8e8b2d..ffa0b73b189 100644 --- a/src/components/table/helpers/mixin-tbody-row.js +++ b/src/components/table/helpers/mixin-tbody-row.js @@ -10,6 +10,7 @@ import { PROP_TYPE_OBJECT_FUNCTION } from '../../../constants/props' import { SLOT_NAME_ROW_DETAILS } from '../../../constants/slots' +import { useParentMixin } from '../../../mixins/use-parent' import { get } from '../../../utils/get' import { isFunction, isString, isUndefinedOrNull } from '../../../utils/inspect' import { makeProp } from '../../../utils/props' @@ -31,30 +32,31 @@ export const props = { // @vue/component export const tbodyRowMixin = Vue.extend({ + mixins: [useParentMixin], props, methods: { // Methods for computing classes, attributes and styles for table cells getTdValues(item, key, tdValue, defaultValue) { - const { $parent } = this + const { bvParent } = this if (tdValue) { const value = get(item, key, '') if (isFunction(tdValue)) { return tdValue(value, key, item) - } else if (isString(tdValue) && isFunction($parent[tdValue])) { - return $parent[tdValue](value, key, item) + } else if (isString(tdValue) && isFunction(bvParent[tdValue])) { + return bvParent[tdValue](value, key, item) } return tdValue } return defaultValue }, getThValues(item, key, thValue, type, defaultValue) { - const { $parent } = this + const { bvParent } = this if (thValue) { const value = get(item, key, '') if (isFunction(thValue)) { return thValue(value, key, item, type) - } else if (isString(thValue) && isFunction($parent[thValue])) { - return $parent[thValue](value, key, item, type) + } else if (isString(thValue) && isFunction(bvParent[thValue])) { + return bvParent[thValue](value, key, item, type) } return thValue } diff --git a/src/components/toast/helpers/bv-toast.js b/src/components/toast/helpers/bv-toast.js index 6de91803ae0..f02b0ac40a4 100644 --- a/src/components/toast/helpers/bv-toast.js +++ b/src/components/toast/helpers/bv-toast.js @@ -10,6 +10,7 @@ import { EVENT_NAME_SHOW, HOOK_EVENT_NAME_DESTROYED } from '../../../constants/events' +import { useParentMixin } from '../../../mixins/use-parent' import { concat } from '../../../utils/array' import { getComponentConfig } from '../../../utils/config' import { requestAF } from '../../../utils/dom' @@ -26,6 +27,8 @@ import { } from '../../../utils/object' import { pluginFactory } from '../../../utils/plugins' import { warn, warnNotClient } from '../../../utils/warn' +import { createNewChildComponent } from '../../../utils/create-new-child-component' +import { getEventRoot } from '../../../utils/get-event-root' import { BToast, props as toastProps } from '../toast' // --- Constants --- @@ -65,6 +68,7 @@ const plugin = Vue => { const BVToastPop = Vue.extend({ name: NAME_TOAST_POP, extends: BToast, + mixins: [useParentMixin], destroyed() { // Make sure we not in document any more const { $el } = this @@ -89,7 +93,7 @@ const plugin = Vue => { }) } // Self destruct if parent destroyed - this.$parent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy) + this.bvParent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy) // Self destruct after hidden this.$once(EVENT_NAME_HIDDEN, handleDestroy) // Self destruct when toaster is destroyed @@ -103,16 +107,15 @@ const plugin = Vue => { }) // Private method to generate the on-demand toast - const makeToast = (props, $parent) => { + const makeToast = (props, parent) => { if (warnNotClient(PROP_NAME)) { /* istanbul ignore next */ return } // Create an instance of `BVToastPop` component - const toast = new BVToastPop({ + const toast = createNewChildComponent(parent, BVToastPop, { // We set parent as the local VM so these toasts can emit events on the // app `$root`, and it ensures `BToast` is destroyed when parent is destroyed - parent: $parent, propsData: { ...filterOptions(getComponentConfig(NAME_TOAST)), // Add in (filtered) user supplied props @@ -129,7 +132,7 @@ const plugin = Vue => { // Can be a string, or array of VNodes if (prop === 'title' && isString(value)) { // Special case for title if it is a string, we wrap in a - value = [$parent.$createElement('strong', { class: 'mr-2' }, value)] + value = [parent.$createElement('strong', { class: 'mr-2' }, value)] } toast.$slots[propsToSlots[prop]] = concat(value) } @@ -144,7 +147,7 @@ const plugin = Vue => { class BvToast { constructor(vm) { // Assign the new properties to this instance - assign(this, { _vm: vm, _root: vm.$root }) + assign(this, { _vm: vm, _root: getEventRoot(vm) }) // Set these properties as read-only and non-enumerable defineProperties(this, { _vm: readonlyDescriptor(), diff --git a/src/components/toast/toast.js b/src/components/toast/toast.js index 42294e29542..73ad6325bc3 100644 --- a/src/components/toast/toast.js +++ b/src/components/toast/toast.js @@ -26,6 +26,7 @@ import { toInteger } from '../../utils/number' import { pick, sortKeys } from '../../utils/object' import { makeProp, makePropsConfigurable, pluckProps } from '../../utils/props' import { isLink } from '../../utils/router' +import { createNewChildComponent } from '../../utils/create-new-child-component' import { attrsMixin } from '../../mixins/attrs' import { idMixin, props as idProps } from '../../mixins/id' import { listenOnRootMixin } from '../../mixins/listen-on-root' @@ -264,8 +265,7 @@ export const BToast = /*#__PURE__*/ Vue.extend({ const div = document.createElement('div') document.body.appendChild(div) - const toaster = new BToaster({ - parent: this.$root, + const toaster = createNewChildComponent(this.bvEventRoot, BToaster, { propsData: { name: computedToaster } }) diff --git a/src/components/tooltip/helpers/bv-popper.js b/src/components/tooltip/helpers/bv-popper.js index 34e35813593..0d00bc2d409 100644 --- a/src/components/tooltip/helpers/bv-popper.js +++ b/src/components/tooltip/helpers/bv-popper.js @@ -21,6 +21,7 @@ import { PROP_TYPE_STRING } from '../../../constants/props' import { HTMLElement, SVGElement } from '../../../constants/safe-types' +import { useParentMixin } from '../../../mixins/use-parent' import { getCS, requestAF, select } from '../../../utils/dom' import { toFloat } from '../../../utils/number' import { makeProp } from '../../../utils/props' @@ -83,6 +84,7 @@ export const props = { // @vue/component export const BVPopper = /*#__PURE__*/ Vue.extend({ name: NAME_POPPER, + mixins: [useParentMixin], props, data() { return { @@ -148,7 +150,7 @@ export const BVPopper = /*#__PURE__*/ Vue.extend({ }) } // Self destruct if parent destroyed - this.$parent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy) + this.bvParent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy) // Self destruct after hidden this.$once(EVENT_NAME_HIDDEN, handleDestroy) }, diff --git a/src/components/tooltip/helpers/bv-tooltip-template.js b/src/components/tooltip/helpers/bv-tooltip-template.js index 0d2ed190165..22813b7e3d2 100644 --- a/src/components/tooltip/helpers/bv-tooltip-template.js +++ b/src/components/tooltip/helpers/bv-tooltip-template.js @@ -64,7 +64,7 @@ export const BVTooltipTemplate = /*#__PURE__*/ Vue.extend({ return { // Apply attributes from root tooltip component - ...this.$parent.$parent.$attrs, + ...this.bvParent.bvParent.$attrs, id, role: 'tooltip', diff --git a/src/components/tooltip/helpers/bv-tooltip.js b/src/components/tooltip/helpers/bv-tooltip.js index 1f0d114ac82..b7cbb5e7f7b 100644 --- a/src/components/tooltip/helpers/bv-tooltip.js +++ b/src/components/tooltip/helpers/bv-tooltip.js @@ -22,6 +22,7 @@ import { HOOK_EVENT_NAME_BEFORE_DESTROY, HOOK_EVENT_NAME_DESTROYED } from '../../../constants/events' +import { useParentMixin } from '../../../mixins/use-parent' import { arrayIncludes, concat, from as arrayFrom } from '../../../utils/array' import { attemptFocus, @@ -63,6 +64,7 @@ import { toInteger } from '../../../utils/number' import { keys } from '../../../utils/object' import { warn } from '../../../utils/warn' import { BvEvent } from '../../../utils/bv-event.class' +import { createNewChildComponent } from '../../../utils/create-new-child-component' import { listenOnRootMixin } from '../../../mixins/listen-on-root' import { BVTooltipTemplate } from './bv-tooltip-template' @@ -139,7 +141,7 @@ const templateData = { // @vue/component export const BVTooltip = /*#__PURE__*/ Vue.extend({ name: NAME_TOOLTIP_HELPER, - mixins: [listenOnRootMixin], + mixins: [listenOnRootMixin, useParentMixin], data() { return { // BTooltip/BPopover/VBTooltip/VBPopover will update this data @@ -249,8 +251,8 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ this.$_noop = noop.bind(this) // Destroy ourselves when the parent is destroyed - if (this.$parent) { - this.$parent.$once(HOOK_EVENT_NAME_BEFORE_DESTROY, () => { + if (this.bvParent) { + this.bvParent.$once(HOOK_EVENT_NAME_BEFORE_DESTROY, () => { this.$nextTick(() => { // In a `requestAF()` to release control back to application requestAF(() => { @@ -264,7 +266,7 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ const target = this.getTarget() if (target && contains(document.body, target)) { // Copy the parent's scoped style attribute - this.scopeId = getScopeId(this.$parent) + this.scopeId = getScopeId(this.bvParent) // Set up all trigger handlers and listeners this.listen() } else { @@ -330,8 +332,7 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ // Creates the template instance and show it const container = this.getContainer() const Template = this.getTemplate() - const $tip = (this.$_tip = new Template({ - parent: this, + const $tip = (this.$_tip = createNewChildComponent(this, Template, { // The following is not reactive to changes in the props data propsData: { // These values cannot be changed while template is showing @@ -730,15 +731,12 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ }, setRootListener(on) { // Listen for global `bv::{hide|show}::{tooltip|popover}` hide request event - const $root = this.$root - if ($root) { - const method = on ? '$on' : '$off' - const type = this.templateType - $root[method](getRootActionEventName(type, EVENT_NAME_HIDE), this.doHide) - $root[method](getRootActionEventName(type, EVENT_NAME_SHOW), this.doShow) - $root[method](getRootActionEventName(type, EVENT_NAME_DISABLE), this.doDisable) - $root[method](getRootActionEventName(type, EVENT_NAME_ENABLE), this.doEnable) - } + const method = on ? 'listenOnRoot' : 'listenOffRoot' + const type = this.templateType + this[method](getRootActionEventName(type, EVENT_NAME_HIDE), this.doHide) + this[method](getRootActionEventName(type, EVENT_NAME_SHOW), this.doShow) + this[method](getRootActionEventName(type, EVENT_NAME_DISABLE), this.doDisable) + this[method](getRootActionEventName(type, EVENT_NAME_ENABLE), this.doEnable) }, setWhileOpenListeners(on) { // Events that are only registered when the template is showing @@ -770,7 +768,7 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ // Handle case where tooltip/target is in a modal if (this.isInModal()) { // We can listen for modal hidden events on `$root` - this.$root[on ? '$on' : '$off'](ROOT_EVENT_NAME_MODAL_HIDDEN, this.forceHide) + this[on ? 'listenOnRoot' : 'listenOffRoot'](ROOT_EVENT_NAME_MODAL_HIDDEN, this.forceHide) } }, /* istanbul ignore next: JSDOM doesn't support `ontouchstart` */ @@ -787,7 +785,7 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ }, setDropdownListener(on) { const target = this.getTarget() - if (!target || !this.$root || !this.isDropdown) { + if (!target || !this.bvEventRoot || !this.isDropdown) { return } // We can listen for dropdown shown events on its instance diff --git a/src/components/tooltip/tooltip.js b/src/components/tooltip/tooltip.js index b27a060846d..7ea687edfdd 100644 --- a/src/components/tooltip/tooltip.js +++ b/src/components/tooltip/tooltip.js @@ -23,10 +23,12 @@ import { PROP_TYPE_STRING } from '../../constants/props' import { HTMLElement, SVGElement } from '../../constants/safe-types' +import { useParentMixin } from '../../mixins/use-parent' import { getScopeId } from '../../utils/get-scope-id' import { isUndefinedOrNull } from '../../utils/inspect' import { pick } from '../../utils/object' import { makeProp, makePropsConfigurable } from '../../utils/props' +import { createNewChildComponent } from '../../utils/create-new-child-component' import { normalizeSlotMixin } from '../../mixins/normalize-slot' import { BVTooltip } from './helpers/bv-tooltip' @@ -83,7 +85,7 @@ export const props = makePropsConfigurable( // @vue/component export const BTooltip = /*#__PURE__*/ Vue.extend({ name: NAME_TOOLTIP, - mixins: [normalizeSlotMixin], + mixins: [normalizeSlotMixin, useParentMixin], inheritAttrs: false, props, data() { @@ -191,10 +193,9 @@ export const BTooltip = /*#__PURE__*/ Vue.extend({ // Ensure we have initial content this.updateContent() // Pass down the scoped style attribute if available - const scopeId = getScopeId(this) || getScopeId(this.$parent) + const scopeId = getScopeId(this) || getScopeId(this.bvParent) // Create the instance - const $toolpop = (this.$_toolpop = new Component({ - parent: this, + const $toolpop = (this.$_toolpop = createNewChildComponent(this, Component, { // Pass down the scoped style ID _scopeId: scopeId || undefined })) diff --git a/src/components/transporter/transporter.js b/src/components/transporter/transporter.js index 130edc7671c..68fa0bc02a6 100644 --- a/src/components/transporter/transporter.js +++ b/src/components/transporter/transporter.js @@ -13,6 +13,7 @@ import { identity } from '../../utils/identity' import { isFunction, isString } from '../../utils/inspect' import { normalizeSlotMixin } from '../../mixins/normalize-slot' import { makeProp } from '../../utils/props' +import { createNewChildComponent } from '../../utils/create-new-child-component' // --- Helper components --- @@ -129,9 +130,8 @@ export const BVTransporter = /*#__PURE__*/ Vue.extend({ if ($container) { const $el = document.createElement('div') $container.appendChild($el) - this.$_target = new BVTransporterTarget({ + this.$_target = createNewChildComponent(this, BVTransporterTarget, { el: $el, - parent: this, propsData: { // Initial nodes to be rendered nodes: concat(this.normalizeSlot()) diff --git a/src/directives/modal/modal.js b/src/directives/modal/modal.js index 661023e7584..0cc8d1e9156 100644 --- a/src/directives/modal/modal.js +++ b/src/directives/modal/modal.js @@ -5,6 +5,7 @@ import { getAttr, hasAttr, isDisabled, matches, select, setAttr } from '../../ut import { getRootActionEventName, eventOn, eventOff } from '../../utils/events' import { isString } from '../../utils/inspect' import { keys } from '../../utils/object' +import { getEventRoot } from '../../utils/get-event-root' // Emitted show event for modal const ROOT_ACTION_EVENT_NAME_SHOW = getRootActionEventName(NAME_MODAL, EVENT_NAME_SHOW) @@ -52,7 +53,7 @@ const bind = (el, binding, vnode) => { type === 'click' || (type === 'keydown' && (key === CODE_ENTER || key === CODE_SPACE)) ) { - vnode.context.$root.$emit(ROOT_ACTION_EVENT_NAME_SHOW, target, currentTarget) + getEventRoot(vnode.context).$emit(ROOT_ACTION_EVENT_NAME_SHOW, target, currentTarget) } } } diff --git a/src/directives/popover/popover.js b/src/directives/popover/popover.js index e3687f4dc69..fdccd13d5ff 100644 --- a/src/directives/popover/popover.js +++ b/src/directives/popover/popover.js @@ -16,6 +16,7 @@ import { import { looseEqual } from '../../utils/loose-equal' import { toInteger } from '../../utils/number' import { keys } from '../../utils/object' +import { createNewChildComponent } from '../../utils/create-new-child-component' import { BVPopover } from '../../components/popover/helpers/bv-popover' // Key which we use to store tooltip object on element @@ -185,11 +186,10 @@ const applyPopover = (el, bindings, vnode) => { } const config = parseBindings(bindings, vnode) if (!el[BV_POPOVER]) { - const $parent = vnode.context - el[BV_POPOVER] = new BVPopover({ - parent: $parent, + const parent = vnode.context + el[BV_POPOVER] = createNewChildComponent(parent, BVPopover, { // Add the parent's scoped style attribute data - _scopeId: getScopeId($parent, undefined) + _scopeId: getScopeId(parent, undefined) }) el[BV_POPOVER].__bv_prev_data__ = {} el[BV_POPOVER].$on(EVENT_NAME_SHOW, () => /* istanbul ignore next: for now */ { diff --git a/src/directives/scrollspy/scrollspy.js b/src/directives/scrollspy/scrollspy.js index ed10495a419..bf7bdb7668f 100644 --- a/src/directives/scrollspy/scrollspy.js +++ b/src/directives/scrollspy/scrollspy.js @@ -3,6 +3,7 @@ import { isNumber, isObject, isString } from '../../utils/inspect' import { mathRound } from '../../utils/math' import { toInteger } from '../../utils/number' import { keys } from '../../utils/object' +import { getEventRoot } from '../../utils/get-event-root' import { BVScrollspy } from './helpers/bv-scrollspy.class' // Key we use to store our instance @@ -64,9 +65,9 @@ const applyScrollspy = (el, bindings, vnode) => /* istanbul ignore next: not eas } const config = parseBindings(bindings) if (el[BV_SCROLLSPY]) { - el[BV_SCROLLSPY].updateConfig(config, vnode.context.$root) + el[BV_SCROLLSPY].updateConfig(config, getEventRoot(vnode.context)) } else { - el[BV_SCROLLSPY] = new BVScrollspy(el, config, vnode.context.$root) + el[BV_SCROLLSPY] = new BVScrollspy(el, config, getEventRoot(vnode.context)) } } diff --git a/src/directives/toggle/toggle.js b/src/directives/toggle/toggle.js index 0e03de2fa74..bc2267d2c54 100644 --- a/src/directives/toggle/toggle.js +++ b/src/directives/toggle/toggle.js @@ -21,6 +21,7 @@ import { getRootActionEventName, getRootEventName, eventOn, eventOff } from '../ import { isString } from '../../utils/inspect' import { looseEqual } from '../../utils/loose-equal' import { keys } from '../../utils/object' +import { getEventRoot } from '../../utils/get-event-root' // --- Constants --- @@ -115,7 +116,7 @@ const addClickListener = (el, vnode) => { ) { const targets = el[BV_TOGGLE_TARGETS] || [] targets.forEach(target => { - vnode.context.$root.$emit(ROOT_ACTION_EVENT_NAME_TOGGLE, target) + getEventRoot(vnode.context).$emit(ROOT_ACTION_EVENT_NAME_TOGGLE, target) }) } } @@ -129,7 +130,7 @@ const addClickListener = (el, vnode) => { const removeRootListeners = (el, vnode) => { if (el[BV_TOGGLE_ROOT_HANDLER] && vnode.context) { - vnode.context.$root.$off( + getEventRoot(vnode.context).$off( [ROOT_EVENT_NAME_STATE, ROOT_EVENT_NAME_SYNC_STATE], el[BV_TOGGLE_ROOT_HANDLER] ) @@ -151,7 +152,7 @@ const addRootListeners = (el, vnode) => { } el[BV_TOGGLE_ROOT_HANDLER] = handler // Listen for toggle state changes (public) and sync (private) - vnode.context.$root.$on([ROOT_EVENT_NAME_STATE, ROOT_EVENT_NAME_SYNC_STATE], handler) + getEventRoot(vnode.context).$on([ROOT_EVENT_NAME_STATE, ROOT_EVENT_NAME_SYNC_STATE], handler) } } @@ -228,7 +229,7 @@ const handleUpdate = (el, binding, vnode) => { // Request a state update from targets so that we can // ensure expanded state is correct (in most cases) targets.forEach(target => { - vnode.context.$root.$emit(ROOT_ACTION_EVENT_NAME_REQUEST_STATE, target) + getEventRoot(vnode.context).$emit(ROOT_ACTION_EVENT_NAME_REQUEST_STATE, target) }) } } diff --git a/src/directives/tooltip/tooltip.js b/src/directives/tooltip/tooltip.js index af0a21cb0ae..e5b354976da 100644 --- a/src/directives/tooltip/tooltip.js +++ b/src/directives/tooltip/tooltip.js @@ -16,6 +16,7 @@ import { import { looseEqual } from '../../utils/loose-equal' import { toInteger } from '../../utils/number' import { keys } from '../../utils/object' +import { createNewChildComponent } from '../../utils/create-new-child-component' import { BVTooltip } from '../../components/tooltip/helpers/bv-tooltip' // Key which we use to store tooltip object on element @@ -190,11 +191,10 @@ const applyTooltip = (el, bindings, vnode) => { } const config = parseBindings(bindings, vnode) if (!el[BV_TOOLTIP]) { - const $parent = vnode.context - el[BV_TOOLTIP] = new BVTooltip({ - parent: $parent, + const parent = vnode.context + el[BV_TOOLTIP] = createNewChildComponent(parent, BVTooltip, { // Add the parent's scoped style attribute data - _scopeId: getScopeId($parent, undefined) + _scopeId: getScopeId(parent, undefined) }) el[BV_TOOLTIP].__bv_prev_data__ = {} el[BV_TOOLTIP].$on(EVENT_NAME_SHOW, () => /* istanbul ignore next: for now */ { diff --git a/src/mixins/dropdown.js b/src/mixins/dropdown.js index 532001f3a83..e533e790eb2 100644 --- a/src/mixins/dropdown.js +++ b/src/mixins/dropdown.js @@ -286,8 +286,8 @@ export const dropdownMixin = Vue.extend({ // Hide the dropdown when it loses focus this.listenForFocusIn = isOpen // Hide the dropdown when another dropdown is opened - const method = isOpen ? '$on' : '$off' - this.$root[method](ROOT_EVENT_NAME_SHOWN, this.rootCloseListener) + const method = isOpen ? 'listenOnRoot' : 'listenOffRoot' + this[method](ROOT_EVENT_NAME_SHOWN, this.rootCloseListener) }, rootCloseListener(vm) { if (vm !== this) { diff --git a/src/mixins/listen-on-root.js b/src/mixins/listen-on-root.js index 8002d2daf08..5d8fb95f764 100644 --- a/src/mixins/listen-on-root.js +++ b/src/mixins/listen-on-root.js @@ -1,7 +1,7 @@ import { Vue } from '../vue' import { arrayIncludes } from '../utils/array' import { keys } from '../utils/object' - +import { getEventRoot } from '../utils/get-event-root' // --- Constants --- const PROP = '$_rootListeners' @@ -10,6 +10,11 @@ const PROP = '$_rootListeners' // @vue/component export const listenOnRootMixin = Vue.extend({ + computed: { + bvEventRoot() { + return getEventRoot(this) + } + }, created() { // Define non-reactive property // Object of arrays, keyed by event name, @@ -55,8 +60,8 @@ export const listenOnRootMixin = Vue.extend({ * @param {function} callback */ listenOnRoot(event, callback) { - if (this.$root) { - this.$root.$on(event, callback) + if (this.bvEventRoot) { + this.bvEventRoot.$on(event, callback) this.registerRootListener(event, callback) } }, @@ -75,14 +80,14 @@ export const listenOnRootMixin = Vue.extend({ * @param {function} callback */ listenOnRootOnce(event, callback) { - if (this.$root) { + if (this.bvEventRoot) { const _callback = (...args) => { this.unregisterRootListener(_callback) // eslint-disable-next-line node/no-callback-literal callback(...args) } - this.$root.$once(event, _callback) + this.bvEventRoot.$once(event, _callback) this.registerRootListener(event, _callback) } }, @@ -96,8 +101,8 @@ export const listenOnRootMixin = Vue.extend({ listenOffRoot(event, callback) { this.unregisterRootListener(event, callback) - if (this.$root) { - this.$root.$off(event, callback) + if (this.bvEventRoot) { + this.bvEventRoot.$off(event, callback) } }, @@ -108,8 +113,8 @@ export const listenOnRootMixin = Vue.extend({ * @param {*} args */ emitOnRoot(event, ...args) { - if (this.$root) { - this.$root.$emit(event, ...args) + if (this.bvEventRoot) { + this.bvEventRoot.$emit(event, ...args) } } } diff --git a/src/mixins/scoped-style.js b/src/mixins/scoped-style.js index af9e11f4df8..f99f5e58b2d 100644 --- a/src/mixins/scoped-style.js +++ b/src/mixins/scoped-style.js @@ -1,11 +1,13 @@ import { Vue } from '../vue' +import { useParentMixin } from '../mixins/use-parent' import { getScopeId } from '../utils/get-scope-id' // @vue/component export const scopedStyleMixin = Vue.extend({ + mixins: [useParentMixin], computed: { scopedStyleAttrs() { - const scopeId = getScopeId(this.$parent) + const scopeId = getScopeId(this.bvParent) return scopeId ? { [scopeId]: '' } : {} } } diff --git a/src/mixins/use-parent.js b/src/mixins/use-parent.js new file mode 100644 index 00000000000..aeb3808a85f --- /dev/null +++ b/src/mixins/use-parent.js @@ -0,0 +1,12 @@ +import { Vue } from '../vue' + +// --- Mixin --- + +// @vue/component +export const useParentMixin = Vue.extend({ + computed: { + bvParent() { + return this.$parent || (this.$root === this && this.$options.bvParent) + } + } +}) diff --git a/src/utils/create-new-child-component.js b/src/utils/create-new-child-component.js new file mode 100644 index 00000000000..64b97e26191 --- /dev/null +++ b/src/utils/create-new-child-component.js @@ -0,0 +1,9 @@ +export const createNewChildComponent = (parent, Component, config = {}) => { + const bvEventRoot = parent.$root ? parent.$root.$options.bvEventRoot || parent.$root : null + + return new Component({ + ...config, + bvParent: parent, + bvEventRoot + }) +} diff --git a/src/utils/get-event-root.js b/src/utils/get-event-root.js new file mode 100644 index 00000000000..91ee66e2a80 --- /dev/null +++ b/src/utils/get-event-root.js @@ -0,0 +1,3 @@ +export const getEventRoot = vm => { + return vm.$root.$options.bvEventRoot || vm.$root +} From 71b37ff7cb67d0c190979de5a76b860dd6704317 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 17 Nov 2021 18:23:00 +0200 Subject: [PATCH 04/34] chore(compat): introduce vue3 compatibility wrapper * fixes vModel issues * fixes rendering problems for functional components * expose new helpers: isVue3, nextTick --- src/vue.js | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 2 deletions(-) diff --git a/src/vue.js b/src/vue.js index de1247dfb29..6a2728fb486 100644 --- a/src/vue.js +++ b/src/vue.js @@ -2,7 +2,116 @@ import Vue from 'vue' import { mergeData } from 'vue-functional-data-merge' // --- Constants --- - const COMPONENT_UID_KEY = '_uid' -export { COMPONENT_UID_KEY, Vue, mergeData } +const isVue3 = Vue.version.startsWith('3') + +const ALLOWED_FIELDS_IN_DATA = [ + 'class', + 'staticClass', + 'style', + 'attrs', + 'props', + 'domProps', + 'on', + 'nativeOn', + 'directives', + 'scopedSlots', + 'slot', + 'key', + 'ref', + 'refInFor' +] + +if (isVue3) { + const { extend: originalExtend } = Vue + const KNOWN_COMPONENTS = ['router-link', 'transition'] + const originalVModelDynamicCreated = Vue.vModelDynamic.created + const originalVModelDynamicBeforeUpdate = Vue.vModelDynamic.beforeUpdate + + // See https://github.com/vuejs/vue-next/pull/4121 for details + Vue.vModelDynamic.created = function(el, binding, vnode) { + originalVModelDynamicCreated.call(this, el, binding, vnode) + if (!el._assign) { + el._assign = () => {} + } + } + Vue.vModelDynamic.beforeUpdate = function(el, binding, vnode) { + originalVModelDynamicBeforeUpdate.call(this, el, binding, vnode) + if (!el._assign) { + el._assign = () => {} + } + } + Vue.extend = function(definition) { + if (typeof definition === 'object' && definition.render && !definition.__alreadyPatched) { + const originalRender = definition.render + definition.__alreadyPatched = true + definition.render = function(h) { + const patchedH = function(tag, dataObjOrChildren, ...rest) { + const isTag = typeof tag === 'string' && !KNOWN_COMPONENTS.includes(tag) + const isSecondArgumentDataObject = + dataObjOrChildren && + typeof dataObjOrChildren === 'object' && + !Array.isArray(dataObjOrChildren) + + if (!isSecondArgumentDataObject) { + return h(tag, dataObjOrChildren, ...rest) + } + + const { attrs, props, ...restData } = dataObjOrChildren + const normalizedData = { + ...restData, + attrs, + props: isTag ? {} : props + } + if (tag === 'router-link' && !normalizedData.slots && !normalizedData.scopedSlots) { + // terrible workaround to fix router-link rendering with compat vue-router + normalizedData.scopedSlots = { $hasNormal: () => {} } + } + return h(tag, normalizedData, ...rest) + } + + if (definition.functional) { + const ctx = arguments[1] + const patchedCtx = { ...ctx } + patchedCtx.data = { + attrs: { ...(ctx.data.attrs || {}) }, + props: { ...(ctx.data.props || {}) } + } + Object.keys(ctx.data || {}).forEach(key => { + if (ALLOWED_FIELDS_IN_DATA.includes(key)) { + patchedCtx.data[key] = ctx.data[key] + } else if (key in ctx.props) { + patchedCtx.data.props[key] = ctx.data[key] + } else if (!key.startsWith('on')) { + patchedCtx.data.attrs[key] = ctx.data[key] + } + }) + + const IGNORED_CHILDREN_KEYS = ['_ctx'] + const children = ctx.children?.default?.() || ctx.children + + if ( + children && + Object.keys(patchedCtx.children).filter(k => !IGNORED_CHILDREN_KEYS.includes(k)) + .length === 0 + ) { + delete patchedCtx.children + } else { + patchedCtx.children = children + } + + patchedCtx.data.on = ctx.listeners + return originalRender.call(this, patchedH, patchedCtx) + } + + return originalRender.call(this, patchedH) + } + } + return originalExtend.call(this, definition) + } +} + +const nextTick = Vue.nextTick + +export { COMPONENT_UID_KEY, Vue, mergeData, isVue3, nextTick } From f8731213d15378a818f3814d747909d018a0eb14 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 17 Nov 2021 18:29:59 +0200 Subject: [PATCH 05/34] chore(compat): update attrs mixin for vue3 --- src/mixins/attrs.js | 18 +++++++++++++++++- src/mixins/attrs.spec.js | 13 +++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/mixins/attrs.js b/src/mixins/attrs.js index 581f9cc36e1..80eb3818b6f 100644 --- a/src/mixins/attrs.js +++ b/src/mixins/attrs.js @@ -1,3 +1,19 @@ import { makePropCacheMixin } from '../utils/cache' +import { Vue, isVue3 } from '../vue' -export const attrsMixin = makePropCacheMixin('$attrs', 'bvAttrs') +const attrsMixinVue2 = makePropCacheMixin('$attrs', 'bvAttrs') +const attrsMixinVue3 = Vue.extend({ + computed: { + bvAttrs() { + const bvAttrs = { ...this.$attrs } + Object.keys(bvAttrs).forEach(key => { + if (bvAttrs[key] === undefined) { + delete bvAttrs[key] + } + }) + return bvAttrs + } + } +}) + +export const attrsMixin = isVue3 ? attrsMixinVue3 : attrsMixinVue2 diff --git a/src/mixins/attrs.spec.js b/src/mixins/attrs.spec.js index e08d260834e..232d6d7cc6a 100644 --- a/src/mixins/attrs.spec.js +++ b/src/mixins/attrs.spec.js @@ -1,3 +1,4 @@ +import { isVue3 } from '../vue' import { mount } from '@vue/test-utils' import { attrsMixin } from './attrs' @@ -159,15 +160,19 @@ describe('mixins > attrs', () => { await wrapper1.setProps({ value1: 'foo' }) expect($inputs1.at(0).vm.value).toBe('foo') expect($inputs1.at(1).vm.value).toBe(undefined) - // Both `Input1`'s are re-rendered (See: https://github.com/vuejs/vue/issues/7257) - expect(input1RenderCount).toBe(4) + if (!isVue3) { + // Both `Input1`'s are re-rendered (See: https://github.com/vuejs/vue/issues/7257) + expect(input1RenderCount).toBe(4) + } // Update the value for the second `Input1` await wrapper1.setProps({ value2: 'bar' }) expect($inputs1.at(0).vm.value).toBe('foo') expect($inputs1.at(1).vm.value).toBe('bar') - // Both `Input1`'s are re-rendered (See: https://github.com/vuejs/vue/issues/7257) - expect(input1RenderCount).toBe(6) + if (!isVue3) { + // Both `Input1`'s are re-rendered (See: https://github.com/vuejs/vue/issues/7257) + expect(input1RenderCount).toBe(6) + } // Update the value for the first `Input2` await wrapper2.setProps({ value1: 'foo' }) From 92db60b395a30aa5e531ebac5620152b952dc773 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 10 Nov 2021 00:12:58 +0200 Subject: [PATCH 06/34] chore(compat): implement component access from vnode for vue3 Replace __vue__ with platform dependent access --- src/components/link/link.js | 5 +++-- src/components/modal/modal.spec.js | 5 +++-- src/components/tooltip/helpers/bv-tooltip.js | 5 +++-- src/components/transporter/transporter.spec.js | 5 +++-- src/utils/get-instance-from-vnode.js | 4 ++++ 5 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 src/utils/get-instance-from-vnode.js diff --git a/src/components/link/link.js b/src/components/link/link.js index 4c026f5fed4..5f2d16e8b8a 100644 --- a/src/components/link/link.js +++ b/src/components/link/link.js @@ -14,6 +14,7 @@ import { isBoolean, isEvent, isFunction, isUndefined } from '../../utils/inspect import { omit, sortKeys } from '../../utils/object' import { makeProp, makePropsConfigurable, pluckProps } from '../../utils/props' import { computeHref, computeRel, computeTag, isRouterLink } from '../../utils/router' +import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode' import { attrsMixin } from '../../mixins/attrs' import { listenOnRootMixin } from '../../mixins/listen-on-root' import { listenersMixin } from '../../mixins/listeners' @@ -162,8 +163,8 @@ export const BLink = /*#__PURE__*/ Vue.extend({ // Router links do not emit instance `click` events, so we // add in an `$emit('click', event)` on its Vue instance /* istanbul ignore next: difficult to test, but we know it works */ - if (isRouterLink && event.currentTarget.__vue__) { - event.currentTarget.__vue__.$emit(EVENT_NAME_CLICK, event) + if (isRouterLink && getInstanceFromVNode(event.currentTarget)) { + getInstanceFromVNode(event.currentTarget).$emit(EVENT_NAME_CLICK, event) } // Call the suppliedHandler(s), if any provided concat(suppliedHandler) diff --git a/src/components/modal/modal.spec.js b/src/components/modal/modal.spec.js index ee7d62985a6..1e63c3a5808 100644 --- a/src/components/modal/modal.spec.js +++ b/src/components/modal/modal.spec.js @@ -1,5 +1,6 @@ import { createWrapper, mount } from '@vue/test-utils' import { waitNT, waitRAF } from '../../../tests/utils' +import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode' import { BModal } from './modal' import { BvModalEvent } from './helpers/bv-modal-event.class' @@ -175,8 +176,8 @@ describe('modal', () => { expect(outer).toBeDefined() expect(outer).not.toBe(null) - expect(outer.__vue__).toBeDefined() // Target - expect(outer.__vue__.$options.name).toBe('BVTransporterTarget') + expect(getInstanceFromVNode(outer)).toBeDefined() // Target + expect(getInstanceFromVNode(outer).$options.name).toBe('BVTransporterTarget') expect(outer.parentElement).toBeDefined() expect(outer.parentElement).toBe(document.body) diff --git a/src/components/tooltip/helpers/bv-tooltip.js b/src/components/tooltip/helpers/bv-tooltip.js index b7cbb5e7f7b..686ad4a1507 100644 --- a/src/components/tooltip/helpers/bv-tooltip.js +++ b/src/components/tooltip/helpers/bv-tooltip.js @@ -24,6 +24,7 @@ import { } from '../../../constants/events' import { useParentMixin } from '../../../mixins/use-parent' import { arrayIncludes, concat, from as arrayFrom } from '../../../utils/array' +import { getInstanceFromVNode } from '../../../utils/get-instance-from-vnode' import { attemptFocus, closest, @@ -795,8 +796,8 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ // Dropdown shown and hidden events will need to emit // Note: Dropdown auto-ID happens in a `$nextTick()` after mount // So the ID lookup would need to be done in a `$nextTick()` - if (target.__vue__) { - target.__vue__[on ? '$on' : '$off'](EVENT_NAME_SHOWN, this.forceHide) + if (getInstanceFromVNode(target)) { + getInstanceFromVNode(target)[on ? '$on' : '$off'](EVENT_NAME_SHOWN, this.forceHide) } }, // --- Event handlers --- diff --git a/src/components/transporter/transporter.spec.js b/src/components/transporter/transporter.spec.js index f6b7eb97879..d2817baa598 100644 --- a/src/components/transporter/transporter.spec.js +++ b/src/components/transporter/transporter.spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils' import { waitNT } from '../../../tests/utils' +import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode' import { BVTransporter } from './transporter' describe('utils/transporter component', () => { @@ -43,8 +44,8 @@ describe('utils/transporter component', () => { const target = document.getElementById('foobar') expect(target).toBeDefined() expect(target).not.toBe(null) - expect(target.__vue__).toBeDefined() // Target - expect(target.__vue__.$options.name).toBe('BVTransporterTarget') + expect(getInstanceFromVNode(target)).toBeDefined() // Target + expect(getInstanceFromVNode(target).$options.name).toBe('BVTransporterTarget') expect(target.tagName).toEqual('DIV') expect(target.parentElement).toBeDefined() expect(target.parentElement).toBe(document.body) diff --git a/src/utils/get-instance-from-vnode.js b/src/utils/get-instance-from-vnode.js new file mode 100644 index 00000000000..efcfb122bea --- /dev/null +++ b/src/utils/get-instance-from-vnode.js @@ -0,0 +1,4 @@ +import { isVue3 } from '../vue' + +export const getInstanceFromVNode = vnode => + isVue3 ? vnode.__vueParentComponent.ctx : vnode.__vue__ From 9726a64f3f9a22e1c684b8f9779ae0edc441337b Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 17 Nov 2021 22:47:43 +0200 Subject: [PATCH 07/34] chore(compat): update listeners mixin for vue3 --- src/mixins/listeners.js | 23 +++++++++++++++++++++- src/mixins/listeners.spec.js | 37 ++++++++++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/mixins/listeners.js b/src/mixins/listeners.js index 082672e69a4..dbe828f898c 100644 --- a/src/mixins/listeners.js +++ b/src/mixins/listeners.js @@ -1,3 +1,24 @@ import { makePropCacheMixin } from '../utils/cache' +import { Vue, isVue3 } from '../vue' -export const listenersMixin = makePropCacheMixin('$listeners', 'bvListeners') +const listenersMixinVue2 = makePropCacheMixin('$listeners', 'bvListeners') + +const listenersMixinVue3 = Vue.extend({ + data() { + return { + bvListeners: {} + } + }, + created() { + this.bvListeners = { + ...this.$listeners + } + }, + beforeUpdate() { + this.bvListeners = { + ...this.$listeners + } + } +}) + +export const listenersMixin = isVue3 ? listenersMixinVue3 : listenersMixinVue2 diff --git a/src/mixins/listeners.spec.js b/src/mixins/listeners.spec.js index fe4c0bd2c59..ad634121daf 100644 --- a/src/mixins/listeners.spec.js +++ b/src/mixins/listeners.spec.js @@ -1,3 +1,4 @@ +import { isVue3 } from '../vue' import { mount } from '@vue/test-utils' import { listenersMixin } from './listeners' @@ -133,17 +134,41 @@ describe('mixins > listeners', () => { const App1 = { components: { Input1 }, props: ['listenFocus1', 'listenFocus2'], + methods: { + emit1($event) { + if (this.listenFocus1) { + this.$emit('focus1', $event) + } + }, + emit2($event) { + if (this.listenFocus2) { + this.$emit('focus2', $event) + } + } + }, template: `
- - + +
` } const App2 = { components: { Input2 }, props: ['listenFocus1', 'listenFocus2'], + methods: { + emit1($event) { + if (this.listenFocus1) { + this.$emit('focus1', $event) + } + }, + emit2($event) { + if (this.listenFocus2) { + this.$emit('focus2', $event) + } + } + }, template: `
- - + +
` } @@ -172,7 +197,7 @@ describe('mixins > listeners', () => { expect(wrapper1.emitted().focus1).toBeTruthy() expect(wrapper1.emitted().focus2).not.toBeTruthy() // Both `Input1`'s are re-rendered (See: https://github.com/vuejs/vue/issues/7257) - expect(input1RenderCount).toBe(4) + expect(input1RenderCount).toBe(isVue3 ? 2 : 4) // Enable focus events for the second input and trigger it await wrapper1.setProps({ listenFocus2: true }) @@ -180,7 +205,7 @@ describe('mixins > listeners', () => { expect(wrapper1.emitted().focus1).toBeTruthy() expect(wrapper1.emitted().focus2).toBeTruthy() // Both `Input1`'s are re-rendered (See: https://github.com/vuejs/vue/issues/7257) - expect(input1RenderCount).toBe(6) + expect(input1RenderCount).toBe(isVue3 ? 2 : 6) // --- `Input2` tests --- From 358ee9b7f3b37f45622eafc23a3241743b5f1baf Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 17 Nov 2021 22:48:26 +0200 Subject: [PATCH 08/34] chore(compat): delay first attempt to show image for nextTick It seems Vue 2 and Vue 3 are not consistent about when lifecycle hooks are called. Unify this behavior --- src/components/image/img-lazy.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/image/img-lazy.js b/src/components/image/img-lazy.js index 6aace5dd50d..bf1c3b505b8 100644 --- a/src/components/image/img-lazy.js +++ b/src/components/image/img-lazy.js @@ -104,7 +104,9 @@ export const BImgLazy = /*#__PURE__*/ Vue.extend({ }, mounted() { // If `IntersectionObserver` is not available, image is always shown - this.isShown = HAS_INTERACTION_OBSERVER_SUPPORT ? this[MODEL_PROP_NAME_SHOW] : true + this.$nextTick(() => { + this.isShown = HAS_INTERACTION_OBSERVER_SUPPORT ? this[MODEL_PROP_NAME_SHOW] : true + }) }, methods: { updateShowProp() { From e65f80266f22d19ec323f0e45b6239c995e347b2 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 17 Nov 2021 22:55:10 +0200 Subject: [PATCH 09/34] feature(vue3): replace transporter implementation with teleport * Use built-in teleport in Vue3 --- src/components/modal/modal.spec.js | 5 +++- src/components/toast/toaster.spec.js | 9 +++++-- src/components/transporter/transporter.js | 27 +++++++++++++++++-- .../transporter/transporter.spec.js | 5 +++- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/components/modal/modal.spec.js b/src/components/modal/modal.spec.js index 1e63c3a5808..7275a16d474 100644 --- a/src/components/modal/modal.spec.js +++ b/src/components/modal/modal.spec.js @@ -1,4 +1,5 @@ import { createWrapper, mount } from '@vue/test-utils' +import { isVue3 } from '../../vue' import { waitNT, waitRAF } from '../../../tests/utils' import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode' import { BModal } from './modal' @@ -177,7 +178,9 @@ describe('modal', () => { expect(outer).not.toBe(null) expect(getInstanceFromVNode(outer)).toBeDefined() // Target - expect(getInstanceFromVNode(outer).$options.name).toBe('BVTransporterTarget') + if (!isVue3) { + expect(getInstanceFromVNode(outer).$options.name).toBe('BVTransporterTarget') + } expect(outer.parentElement).toBeDefined() expect(outer.parentElement).toBe(document.body) diff --git a/src/components/toast/toaster.spec.js b/src/components/toast/toaster.spec.js index 9016c436b70..6df924dc8a9 100644 --- a/src/components/toast/toaster.spec.js +++ b/src/components/toast/toaster.spec.js @@ -1,5 +1,6 @@ import { PortalTarget } from 'portal-vue' import { mount } from '@vue/test-utils' +import { isVue3 } from '../../vue' import { waitNT, waitRAF } from '../../../tests/utils' import { BToaster } from './toaster' @@ -27,7 +28,9 @@ describe('b-toaster', () => { expect(wrapper.find('.b-toaster-slot').exists()).toBe(true) const $slot = wrapper.find('.b-toaster-slot') - expect($slot.findComponent(PortalTarget).exists()).toBe(true) + if (!isVue3) { + expect($slot.findComponent(PortalTarget).exists()).toBe(true) + } expect($slot.element.tagName).toBe('DIV') expect($slot.classes()).toContain('b-toaster-slot') expect($slot.classes()).toContain('vue-portal-target') @@ -60,7 +63,9 @@ describe('b-toaster', () => { expect(wrapper.find('.b-toaster-slot').exists()).toBe(true) const $slot = wrapper.find('.b-toaster-slot') - expect($slot.findComponent(PortalTarget).exists()).toBe(true) + if (!isVue3) { + expect($slot.findComponent(PortalTarget).exists()).toBe(true) + } expect($slot.element.tagName).toBe('DIV') expect($slot.classes()).toContain('b-toaster-slot') expect($slot.classes()).toContain('vue-portal-target') diff --git a/src/components/transporter/transporter.js b/src/components/transporter/transporter.js index 68fa0bc02a6..b3fd778b481 100644 --- a/src/components/transporter/transporter.js +++ b/src/components/transporter/transporter.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { Vue, isVue3 } from '../../vue' import { NAME_TRANSPORTER, NAME_TRANSPORTER_TARGET } from '../../constants/components' import { IS_BROWSER } from '../../constants/env' import { @@ -79,7 +79,7 @@ export const props = { // --- Main component --- // @vue/component -export const BVTransporter = /*#__PURE__*/ Vue.extend({ +const BVTransporterVue2 = /*#__PURE__*/ Vue.extend({ name: NAME_TRANSPORTER, mixins: [normalizeSlotMixin], props, @@ -177,3 +177,26 @@ export const BVTransporter = /*#__PURE__*/ Vue.extend({ return h() } }) + +const BVTransporterVue3 = /*#__PURE__*/ Vue.extend({ + name: NAME_TRANSPORTER, + mixins: [normalizeSlotMixin], + props, + render(h) { + if (this.disabled) { + const $nodes = concat(this.normalizeSlot()).filter(identity) + if ($nodes.length > 0) { + return $nodes[0] + } + } + return h( + Vue.Teleport, + { + to: this.container + }, + this.normalizeSlot() + ) + } +}) + +export const BVTransporter = isVue3 ? BVTransporterVue3 : BVTransporterVue2 diff --git a/src/components/transporter/transporter.spec.js b/src/components/transporter/transporter.spec.js index d2817baa598..f4bc72816a5 100644 --- a/src/components/transporter/transporter.spec.js +++ b/src/components/transporter/transporter.spec.js @@ -1,3 +1,4 @@ +import { isVue3 } from '../../vue' import { mount } from '@vue/test-utils' import { waitNT } from '../../../tests/utils' import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode' @@ -45,7 +46,9 @@ describe('utils/transporter component', () => { expect(target).toBeDefined() expect(target).not.toBe(null) expect(getInstanceFromVNode(target)).toBeDefined() // Target - expect(getInstanceFromVNode(target).$options.name).toBe('BVTransporterTarget') + if (!isVue3) { + expect(getInstanceFromVNode(target).$options.name).toBe('BVTransporterTarget') + } expect(target.tagName).toEqual('DIV') expect(target.parentElement).toBeDefined() expect(target.parentElement).toBe(document.body) From 35c888e91a23ce287fc9822fa0dd3cb11d835128 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 17 Nov 2021 23:01:09 +0200 Subject: [PATCH 10/34] chore(compat): disable tests related to has-listener in Vue 3 There is no way to answer, if we have listeners for even when using Vue3 compat build with $on available. Disable these tests for now, these could be enabled later, when INSTANCE_EVENT_EMITTER flag will be disabled --- src/components/table/table-tbody-row-events.spec.js | 11 +++++++++++ src/components/table/table-tbody-transition.spec.js | 9 +++++++++ src/components/table/table-thead-events.spec.js | 5 +++++ src/mixins/has-listener.js | 5 ++++- 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/components/table/table-tbody-row-events.spec.js b/src/components/table/table-tbody-row-events.spec.js index e6c56ed7569..bc42c8afe22 100644 --- a/src/components/table/table-tbody-row-events.spec.js +++ b/src/components/table/table-tbody-row-events.spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils' +import { isVue3 } from '../../vue' import { waitNT } from '../../../tests/utils' import { BTable } from './table' @@ -245,6 +246,11 @@ describe('table > tbody row events', () => { }) it('should not emit row-hovered event when a row is hovered and no listener', async () => { + if (isVue3) { + // We can't track if we have an event listener in vue3 so we skip this test for vue 3 + return + } + const wrapper = mount(BTable, { propsData: { fields: testFields, @@ -309,6 +315,11 @@ describe('table > tbody row events', () => { }) it('should not emit row-unhovered event when a row is hovered and no listener', async () => { + if (isVue3) { + // We can't track if we have an event listener in vue3 so we skip this test for vue 3 + return + } + const wrapper = mount(BTable, { propsData: { fields: testFields, diff --git a/src/components/table/table-tbody-transition.spec.js b/src/components/table/table-tbody-transition.spec.js index 85f36d87799..2eebe5adbce 100644 --- a/src/components/table/table-tbody-transition.spec.js +++ b/src/components/table/table-tbody-transition.spec.js @@ -1,5 +1,6 @@ import { config as vtuConfig, mount } from '@vue/test-utils' import { TransitionGroupStub } from '../../../tests/components' +import { isVue3 } from '../../vue' import { BTable } from './table' // Stub `` component @@ -9,6 +10,14 @@ const testItems = [{ a: 1, b: 2, c: 3 }, { a: 5, b: 5, c: 6 }, { a: 7, b: 8, c: const testFields = ['a', 'b', 'c'] describe('table > tbody transition', () => { + if (isVue3) { + // @vue/test-utils does not support stubbing transition, so impossible to test ATM + + // adding dummy test to keep jest happy + it('skipped due to vue3', () => {}) + return + } + it('tbody should not be a transition-group component by default', async () => { const wrapper = mount(BTable, { attachTo: document.body, diff --git a/src/components/table/table-thead-events.spec.js b/src/components/table/table-thead-events.spec.js index 1e4d96be889..ec4889f97fe 100644 --- a/src/components/table/table-thead-events.spec.js +++ b/src/components/table/table-thead-events.spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils' +import { isVue3 } from '../../vue' import { BTable } from './table' const testItems = [{ a: 1, b: 2, c: 3 }] @@ -6,6 +7,10 @@ const testFields = [{ key: 'a', label: 'A' }, { key: 'b', label: 'B' }, { key: ' describe('table > thead events', () => { it('should not emit head-clicked event when a head cell is clicked and no head-clicked listener', async () => { + if (isVue3) { + // We can't track if we have an event listener in vue3 so we skip this test for vue 3 + return + } const wrapper = mount(BTable, { propsData: { fields: testFields, diff --git a/src/mixins/has-listener.js b/src/mixins/has-listener.js index 562288d4fbb..62184fc686f 100644 --- a/src/mixins/has-listener.js +++ b/src/mixins/has-listener.js @@ -2,13 +2,16 @@ // either via `v-on:name` (in the parent) or programmatically // via `vm.$on('name', ...)` // See: https://github.com/vuejs/vue/issues/10825 -import { Vue } from '../vue' +import { isVue3, Vue } from '../vue' import { isArray, isUndefined } from '../utils/inspect' // @vue/component export const hasListenerMixin = Vue.extend({ methods: { hasListener(name) { + if (isVue3) { + return true + } // Only includes listeners registered via `v-on:name` const $listeners = this.$listeners || {} // Includes `v-on:name` and `this.$on('name')` registered listeners From 3f0a141dd28ddf16ca278792b1db39eebb1f172e Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 17 Nov 2021 23:14:21 +0200 Subject: [PATCH 11/34] chore(compat): skip tbody-transition tests in Vue 3 * @vue/test-utils v2 does not allow stub transitions ATM --- src/components/table/table-tbody-transition.spec.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/table/table-tbody-transition.spec.js b/src/components/table/table-tbody-transition.spec.js index 2eebe5adbce..8e699a32aab 100644 --- a/src/components/table/table-tbody-transition.spec.js +++ b/src/components/table/table-tbody-transition.spec.js @@ -4,7 +4,9 @@ import { isVue3 } from '../../vue' import { BTable } from './table' // Stub `` component -vtuConfig.stubs['transition-group'] = TransitionGroupStub +if (!isVue3) { + vtuConfig.stubs['transition-group'] = TransitionGroupStub +} const testItems = [{ a: 1, b: 2, c: 3 }, { a: 5, b: 5, c: 6 }, { a: 7, b: 8, c: 9 }] const testFields = ['a', 'b', 'c'] From 50afc563da684add1cf8aff2886f19eb2d23f5e7 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 17 Nov 2021 23:16:57 +0200 Subject: [PATCH 12/34] chore(compat): disable subset of config specs due to localVue localVue implementation provided by vue-test-utils-compat is limited and does not allow us to cover all use cases --- src/utils/config.spec.js | 76 +++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/src/utils/config.spec.js b/src/utils/config.spec.js index 3d92e82aa54..c76a20af98b 100644 --- a/src/utils/config.spec.js +++ b/src/utils/config.spec.js @@ -1,4 +1,5 @@ import { createLocalVue } from '@vue/test-utils' +import { isVue3 } from '../../src/vue' import { BootstrapVue } from '../../src' import { AlertPlugin } from '../../src/components/alert' import { BVConfigPlugin } from '../../src/bv-config' @@ -53,53 +54,56 @@ describe('utils/config', () => { expect(getConfig()).toEqual({}) }) - it('config via Vue.use(BootstrapVue) works', async () => { - const localVue = createLocalVue() - const config = { - BAlert: { variant: 'foobar' } - } + if (!isVue3) { + // We do not have complete localVue support, so resetting config does not work in proper way + it('config via Vue.use(BootstrapVue) works', async () => { + const localVue = createLocalVue() + const config = { + BAlert: { variant: 'foobar' } + } - expect(getConfig()).toEqual({}) + expect(getConfig()).toEqual({}) - localVue.use(BootstrapVue, config) - expect(getConfig()).toEqual(config) + localVue.use(BootstrapVue, config) + expect(getConfig()).toEqual(config) - // Reset the configuration - resetConfig() - expect(getConfig()).toEqual({}) - }) + // Reset the configuration + resetConfig() + expect(getConfig()).toEqual({}) + }) - it('config via Vue.use(ComponentPlugin) works', async () => { - const localVue = createLocalVue() - const config = { - BAlert: { variant: 'foobar' } - } + it('config via Vue.use(ComponentPlugin) works', async () => { + const localVue = createLocalVue() + const config = { + BAlert: { variant: 'foobar' } + } - expect(getConfig()).toEqual({}) + expect(getConfig()).toEqual({}) - localVue.use(AlertPlugin, config) - expect(getConfig()).toEqual(config) + localVue.use(AlertPlugin, config) + expect(getConfig()).toEqual(config) - // Reset the configuration - resetConfig() - expect(getConfig()).toEqual({}) - }) + // Reset the configuration + resetConfig() + expect(getConfig()).toEqual({}) + }) - it('config via Vue.use(BVConfig) works', async () => { - const localVue = createLocalVue() - const config = { - BAlert: { variant: 'foobar' } - } + it('config via Vue.use(BVConfig) works', async () => { + const localVue = createLocalVue() + const config = { + BAlert: { variant: 'foobar' } + } - expect(getConfig()).toEqual({}) + expect(getConfig()).toEqual({}) - localVue.use(BVConfigPlugin, config) - expect(getConfig()).toEqual(config) + localVue.use(BVConfigPlugin, config) + expect(getConfig()).toEqual(config) - // Reset the configuration - resetConfig() - expect(getConfig()).toEqual({}) - }) + // Reset the configuration + resetConfig() + expect(getConfig()).toEqual({}) + }) + } it('getConfigValue() works', async () => { const config = { From 543b9f51e0a7d4f5f63f78e6ccd8d37d94bee1d7 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 17 Nov 2021 23:48:15 +0200 Subject: [PATCH 13/34] chore(compat): unify access to component instance from directive Getting component instance from directive is different in Vue 2 and Vue 3. Introduce new util to solve this --- src/directives/modal/modal.js | 7 ++++- src/directives/popover/popover.js | 6 +++-- src/directives/scrollspy/scrollspy.js | 9 +++++-- src/directives/toggle/toggle.js | 34 +++++++++++++----------- src/directives/tooltip/tooltip.js | 11 ++++---- src/directives/visible/visible.js | 13 ++++----- src/utils/get-instance-from-directive.js | 4 +++ 7 files changed, 53 insertions(+), 31 deletions(-) create mode 100644 src/utils/get-instance-from-directive.js diff --git a/src/directives/modal/modal.js b/src/directives/modal/modal.js index 0cc8d1e9156..5d603e5bc90 100644 --- a/src/directives/modal/modal.js +++ b/src/directives/modal/modal.js @@ -6,6 +6,7 @@ import { getRootActionEventName, eventOn, eventOff } from '../../utils/events' import { isString } from '../../utils/inspect' import { keys } from '../../utils/object' import { getEventRoot } from '../../utils/get-event-root' +import { getInstanceFromDirective } from '../../utils/get-instance-from-directive' // Emitted show event for modal const ROOT_ACTION_EVENT_NAME_SHOW = getRootActionEventName(NAME_MODAL, EVENT_NAME_SHOW) @@ -53,7 +54,11 @@ const bind = (el, binding, vnode) => { type === 'click' || (type === 'keydown' && (key === CODE_ENTER || key === CODE_SPACE)) ) { - getEventRoot(vnode.context).$emit(ROOT_ACTION_EVENT_NAME_SHOW, target, currentTarget) + getEventRoot(getInstanceFromDirective(vnode, binding)).$emit( + ROOT_ACTION_EVENT_NAME_SHOW, + target, + currentTarget + ) } } } diff --git a/src/directives/popover/popover.js b/src/directives/popover/popover.js index fdccd13d5ff..4e6510eb0ad 100644 --- a/src/directives/popover/popover.js +++ b/src/directives/popover/popover.js @@ -5,6 +5,7 @@ import { concat } from '../../utils/array' import { getComponentConfig } from '../../utils/config' import { getScopeId } from '../../utils/get-scope-id' import { identity } from '../../utils/identity' +import { getInstanceFromDirective } from '../../utils/get-instance-from-directive' import { isFunction, isNumber, @@ -18,6 +19,7 @@ import { toInteger } from '../../utils/number' import { keys } from '../../utils/object' import { createNewChildComponent } from '../../utils/create-new-child-component' import { BVPopover } from '../../components/popover/helpers/bv-popover' +import { nextTick } from '../../vue' // Key which we use to store tooltip object on element const BV_POPOVER = '__BV_Popover__' @@ -186,7 +188,7 @@ const applyPopover = (el, bindings, vnode) => { } const config = parseBindings(bindings, vnode) if (!el[BV_POPOVER]) { - const parent = vnode.context + const parent = getInstanceFromDirective(vnode, bindings) el[BV_POPOVER] = createNewChildComponent(parent, BVPopover, { // Add the parent's scoped style attribute data _scopeId: getScopeId(parent, undefined) @@ -263,7 +265,7 @@ export const VBPopover = { // waits until the containing component and children have finished updating componentUpdated(el, bindings, vnode) { // Performed in a `$nextTick()` to prevent endless render/update loops - vnode.context.$nextTick(() => { + nextTick(() => { applyPopover(el, bindings, vnode) }) }, diff --git a/src/directives/scrollspy/scrollspy.js b/src/directives/scrollspy/scrollspy.js index bf7bdb7668f..745b7c3e0e4 100644 --- a/src/directives/scrollspy/scrollspy.js +++ b/src/directives/scrollspy/scrollspy.js @@ -4,6 +4,7 @@ import { mathRound } from '../../utils/math' import { toInteger } from '../../utils/number' import { keys } from '../../utils/object' import { getEventRoot } from '../../utils/get-event-root' +import { getInstanceFromDirective } from '../../utils/get-instance-from-directive' import { BVScrollspy } from './helpers/bv-scrollspy.class' // Key we use to store our instance @@ -65,9 +66,13 @@ const applyScrollspy = (el, bindings, vnode) => /* istanbul ignore next: not eas } const config = parseBindings(bindings) if (el[BV_SCROLLSPY]) { - el[BV_SCROLLSPY].updateConfig(config, getEventRoot(vnode.context)) + el[BV_SCROLLSPY].updateConfig(config, getEventRoot(getInstanceFromDirective(vnode, bindings))) } else { - el[BV_SCROLLSPY] = new BVScrollspy(el, config, getEventRoot(vnode.context)) + el[BV_SCROLLSPY] = new BVScrollspy( + el, + config, + getEventRoot(getInstanceFromDirective(vnode, bindings)) + ) } } diff --git a/src/directives/toggle/toggle.js b/src/directives/toggle/toggle.js index bc2267d2c54..aceb3c89761 100644 --- a/src/directives/toggle/toggle.js +++ b/src/directives/toggle/toggle.js @@ -4,6 +4,7 @@ import { EVENT_OPTIONS_PASSIVE } from '../../constants/events' import { CODE_ENTER, CODE_SPACE } from '../../constants/key-codes' import { RX_HASH, RX_HASH_ID, RX_SPACE_SPLIT } from '../../constants/regex' import { arrayIncludes, concat } from '../../utils/array' +import { getInstanceFromDirective } from '../../utils/get-instance-from-directive' import { addClass, getAttr, @@ -106,9 +107,9 @@ const removeClickListener = el => { el[BV_TOGGLE_CLICK_HANDLER] = null } -const addClickListener = (el, vnode) => { +const addClickListener = (el, instance) => { removeClickListener(el) - if (vnode.context) { + if (instance) { const handler = event => { if ( !(event.type === 'keydown' && !arrayIncludes(KEYDOWN_KEY_CODES, event.keyCode)) && @@ -116,7 +117,7 @@ const addClickListener = (el, vnode) => { ) { const targets = el[BV_TOGGLE_TARGETS] || [] targets.forEach(target => { - getEventRoot(vnode.context).$emit(ROOT_ACTION_EVENT_NAME_TOGGLE, target) + getEventRoot(instance).$emit(ROOT_ACTION_EVENT_NAME_TOGGLE, target) }) } } @@ -128,9 +129,9 @@ const addClickListener = (el, vnode) => { } } -const removeRootListeners = (el, vnode) => { - if (el[BV_TOGGLE_ROOT_HANDLER] && vnode.context) { - getEventRoot(vnode.context).$off( +const removeRootListeners = (el, instance) => { + if (el[BV_TOGGLE_ROOT_HANDLER] && instance) { + getEventRoot(instance).$off( [ROOT_EVENT_NAME_STATE, ROOT_EVENT_NAME_SYNC_STATE], el[BV_TOGGLE_ROOT_HANDLER] ) @@ -138,9 +139,9 @@ const removeRootListeners = (el, vnode) => { el[BV_TOGGLE_ROOT_HANDLER] = null } -const addRootListeners = (el, vnode) => { - removeRootListeners(el, vnode) - if (vnode.context) { +const addRootListeners = (el, instance) => { + removeRootListeners(el, instance) + if (instance) { const handler = (id, state) => { // `state` will be `true` if target is expanded if (arrayIncludes(el[BV_TOGGLE_TARGETS] || [], id)) { @@ -152,7 +153,7 @@ const addRootListeners = (el, vnode) => { } el[BV_TOGGLE_ROOT_HANDLER] = handler // Listen for toggle state changes (public) and sync (private) - getEventRoot(vnode.context).$on([ROOT_EVENT_NAME_STATE, ROOT_EVENT_NAME_SYNC_STATE], handler) + getEventRoot(instance).$on([ROOT_EVENT_NAME_STATE, ROOT_EVENT_NAME_SYNC_STATE], handler) } } @@ -178,7 +179,7 @@ const resetProp = (el, prop) => { // Handle directive updates const handleUpdate = (el, binding, vnode) => { /* istanbul ignore next: should never happen */ - if (!IS_BROWSER || !vnode.context) { + if (!IS_BROWSER || !getInstanceFromDirective(vnode, binding)) { return } @@ -218,7 +219,7 @@ const handleUpdate = (el, binding, vnode) => { // Wrap in a `requestAF()` to allow any previous // click handling to occur first requestAF(() => { - addClickListener(el, vnode) + addClickListener(el, getInstanceFromDirective(vnode, binding)) }) // If targets array has changed, update @@ -229,7 +230,10 @@ const handleUpdate = (el, binding, vnode) => { // Request a state update from targets so that we can // ensure expanded state is correct (in most cases) targets.forEach(target => { - getEventRoot(vnode.context).$emit(ROOT_ACTION_EVENT_NAME_REQUEST_STATE, target) + getEventRoot(getInstanceFromDirective(vnode, binding)).$emit( + ROOT_ACTION_EVENT_NAME_REQUEST_STATE, + target + ) }) } } @@ -244,7 +248,7 @@ export const VBToggle = { // Assume no targets initially el[BV_TOGGLE_TARGETS] = [] // Add our root listeners - addRootListeners(el, vnode) + addRootListeners(el, getInstanceFromDirective(vnode, binding)) // Initial update of trigger handleUpdate(el, binding, vnode) }, @@ -253,7 +257,7 @@ export const VBToggle = { unbind(el, binding, vnode) { removeClickListener(el) // Remove our $root listener - removeRootListeners(el, vnode) + removeRootListeners(el, getInstanceFromDirective(vnode, binding)) // Reset custom props resetProp(el, BV_TOGGLE_ROOT_HANDLER) resetProp(el, BV_TOGGLE_CLICK_HANDLER) diff --git a/src/directives/tooltip/tooltip.js b/src/directives/tooltip/tooltip.js index e5b354976da..05f81c14984 100644 --- a/src/directives/tooltip/tooltip.js +++ b/src/directives/tooltip/tooltip.js @@ -2,9 +2,11 @@ import { NAME_TOOLTIP } from '../../constants/components' import { IS_BROWSER } from '../../constants/env' import { EVENT_NAME_SHOW } from '../../constants/events' import { concat } from '../../utils/array' +import { isVue3, nextTick } from '../../vue' import { getComponentConfig } from '../../utils/config' import { getScopeId } from '../../utils/get-scope-id' import { identity } from '../../utils/identity' +import { getInstanceFromDirective } from '../../utils/get-instance-from-directive' import { isFunction, isNumber, @@ -69,7 +71,6 @@ const parseBindings = (bindings, vnode) => /* istanbul ignore next: not easy to variant: getComponentConfig(NAME_TOOLTIP, 'variant'), customClass: getComponentConfig(NAME_TOOLTIP, 'customClass') } - // Process `bindings.value` if (isString(bindings.value) || isNumber(bindings.value)) { // Value is tooltip content (HTML optionally supported) @@ -85,8 +86,8 @@ const parseBindings = (bindings, vnode) => /* istanbul ignore next: not easy to // If title is not provided, try title attribute if (isUndefined(config.title)) { // Try attribute - const data = vnode.data || {} - config.title = data.attrs && !isUndefinedOrNull(data.attrs.title) ? data.attrs.title : undefined + const attrs = isVue3 ? vnode.props : (vnode.data || {}).attrs + config.title = attrs && !isUndefinedOrNull(attrs.title) ? attrs.title : undefined } // Normalize delay @@ -191,7 +192,7 @@ const applyTooltip = (el, bindings, vnode) => { } const config = parseBindings(bindings, vnode) if (!el[BV_TOOLTIP]) { - const parent = vnode.context + const parent = getInstanceFromDirective(vnode, bindings) el[BV_TOOLTIP] = createNewChildComponent(parent, BVTooltip, { // Add the parent's scoped style attribute data _scopeId: getScopeId(parent, undefined) @@ -259,7 +260,7 @@ export const VBTooltip = { // waits until the containing component and children have finished updating componentUpdated(el, bindings, vnode) { // Performed in a `$nextTick()` to prevent render update loops - vnode.context.$nextTick(() => { + nextTick(() => { applyTooltip(el, bindings, vnode) }) }, diff --git a/src/directives/visible/visible.js b/src/directives/visible/visible.js index 276465b016a..694db6b9fa3 100644 --- a/src/directives/visible/visible.js +++ b/src/directives/visible/visible.js @@ -36,11 +36,12 @@ import { requestAF } from '../../utils/dom' import { isFunction } from '../../utils/inspect' import { looseEqual } from '../../utils/loose-equal' import { clone, keys } from '../../utils/object' +import { nextTick } from '../../vue' const OBSERVER_PROP_NAME = '__bv__visibility_observer' class VisibilityObserver { - constructor(el, options, vnode) { + constructor(el, options) { this.el = el this.callback = options.callback this.margin = options.margin || 0 @@ -49,10 +50,10 @@ class VisibilityObserver { this.visible = undefined this.doneOnce = false // Create the observer instance (if possible) - this.createObserver(vnode) + this.createObserver() } - createObserver(vnode) { + createObserver() { // Remove any previous observer if (this.observer) { /* istanbul ignore next */ @@ -87,7 +88,7 @@ class VisibilityObserver { // Start observing in a `$nextTick()` (to allow DOM to complete rendering) /* istanbul ignore next: IntersectionObserver not supported in JSDOM */ - vnode.context.$nextTick(() => { + nextTick(() => { requestAF(() => { // Placed in an `if` just in case we were destroyed before // this `requestAnimationFrame` runs @@ -127,7 +128,7 @@ const destroy = el => { delete el[OBSERVER_PROP_NAME] } -const bind = (el, { value, modifiers }, vnode) => { +const bind = (el, { value, modifiers }) => { // `value` is the callback function const options = { margin: '0px', @@ -146,7 +147,7 @@ const bind = (el, { value, modifiers }, vnode) => { // Destroy any previous observer destroy(el) // Create new observer - el[OBSERVER_PROP_NAME] = new VisibilityObserver(el, options, vnode) + el[OBSERVER_PROP_NAME] = new VisibilityObserver(el, options) // Store the current modifiers on the object (cloned) el[OBSERVER_PROP_NAME]._prevModifiers = clone(modifiers) } diff --git a/src/utils/get-instance-from-directive.js b/src/utils/get-instance-from-directive.js new file mode 100644 index 00000000000..f4c5aaa6b65 --- /dev/null +++ b/src/utils/get-instance-from-directive.js @@ -0,0 +1,4 @@ +import { isVue3 } from '../vue' + +export const getInstanceFromDirective = (vnode, bindings) => + isVue3 ? bindings.instance : vnode.context From ea1269f045965afbb89b87947fcdc4ae2cc6e9fe Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Thu, 18 Nov 2021 00:02:21 +0200 Subject: [PATCH 14/34] chore(compat): make tabs properly filter in Vue 3 * correctly handle `null` inside children * fix test --- src/components/tabs/tabs.js | 2 +- src/components/tabs/tabs.spec.js | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/components/tabs/tabs.js b/src/components/tabs/tabs.js index bc89b9e1da1..e745662b69e 100644 --- a/src/components/tabs/tabs.js +++ b/src/components/tabs/tabs.js @@ -357,7 +357,7 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ }, getTabs() { const $tabs = this.registeredTabs.filter( - $tab => $tab.$children.filter($t => $t._isTab).length === 0 + $tab => $tab.$children.filter($t => $t && $t._isTab).length === 0 ) // DOM Order of Tabs diff --git a/src/components/tabs/tabs.spec.js b/src/components/tabs/tabs.spec.js index 74a0ad3776c..338c998ea21 100644 --- a/src/components/tabs/tabs.spec.js +++ b/src/components/tabs/tabs.spec.js @@ -35,7 +35,12 @@ describe('tabs', () => { it('has correct card classes when prop card is true', async () => { const wrapper = mount(BTabs, { propsData: { card: true }, - slots: { default: [BTab, BTab, BTab] } + slots: { + default: { + components: { BTab }, + template: '
' + } + } }) await waitNT(wrapper.vm) @@ -55,7 +60,12 @@ describe('tabs', () => { it('has correct card classes when props card and vertical are true', async () => { const wrapper = mount(BTabs, { propsData: { card: true, vertical: true }, - slots: { default: [BTab, BTab, BTab] } + slots: { + default: { + components: { BTab }, + template: '
' + } + } }) await waitNT(wrapper.vm) @@ -84,7 +94,12 @@ describe('tabs', () => { const tabIndex = 1 const wrapper = mount(BTabs, { propsData: { value: tabIndex }, - slots: { default: [BTab, BTab, BTab] } + slots: { + default: { + components: { BTab }, + template: '
' + } + } }) await waitNT(wrapper.vm) From 2d6660f7c12ca82480402c49edde833842e1cd2b Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Thu, 18 Nov 2021 00:55:58 +0200 Subject: [PATCH 15/34] chore(compat): silence most warning from Vue 3 compat build --- tests/setup.js | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/tests/setup.js b/tests/setup.js index d2947b2cb6d..36b35934858 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -6,10 +6,46 @@ import { installCompat as installVTUCompat, fullCompatConfig } from 'vue-test-ut const useVue2 = 'USE_VUE2' in process.env if (!useVue2) { Vue.configureCompat({ - MODE: 2 + MODE: 2, + ATTR_FALSE_VALUE: 'suppress-warning', + COMPONENT_FUNCTIONAL: 'suppress-warning', + COMPONENT_V_MODEL: 'suppress-warning', + CONFIG_OPTION_MERGE_STRATS: 'suppress-warning', + CONFIG_WHITESPACE: 'suppress-warning', + CUSTOM_DIR: 'suppress-warning', + GLOBAL_EXTEND: 'suppress-warning', + GLOBAL_MOUNT: 'suppress-warning', + GLOBAL_PRIVATE_UTIL: 'suppress-warning', + GLOBAL_PROTOTYPE: 'suppress-warning', + GLOBAL_SET: 'suppress-warning', + INSTANCE_ATTRS_CLASS_STYLE: 'suppress-warning', + INSTANCE_CHILDREN: 'suppress-warning', + INSTANCE_DELETE: 'suppress-warning', + INSTANCE_DESTROY: 'suppress-warning', + INSTANCE_EVENT_EMITTER: 'suppress-warning', + INSTANCE_EVENT_HOOKS: 'suppress-warning', + INSTANCE_LISTENERS: 'suppress-warning', + INSTANCE_SCOPED_SLOTS: 'suppress-warning', + INSTANCE_SET: 'suppress-warning', + OPTIONS_BEFORE_DESTROY: 'suppress-warning', + OPTIONS_DATA_MERGE: 'suppress-warning', + OPTIONS_DESTROYED: 'suppress-warning', + RENDER_FUNCTION: 'suppress-warning', + V_FOR_REF: 'suppress-warning', + WATCH_ARRAY: 'suppress-warning' }) - const compatH = new Vue({}).$createElement + let compatH + Vue.config.compilerOptions.whitespace = 'condense' + Vue.createApp({ + compatConfig: { + MODE: 3, + RENDER_FUNCTION: 'suppress-warning' + }, + render(h) { + compatH = h + } + }).mount(document.createElement('div')) installVTUCompat(VTU, fullCompatConfig, compatH) } From b7e764ac6b37993f5c0e1993807fc8a22f985ccb Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Thu, 18 Nov 2021 00:56:46 +0200 Subject: [PATCH 16/34] chore: fix warnings about accessing undefined fields in render * introduce "safe-vue-instance" helper --- src/components/calendar/calendar.js | 2 +- .../form-spinbutton/form-spinbutton.js | 3 ++ src/components/form-textarea/form-textarea.js | 3 ++ src/components/table/helpers/mixin-empty.js | 5 +-- src/components/table/helpers/mixin-items.js | 15 +++++---- .../table/helpers/mixin-pagination.js | 4 ++- .../table/helpers/mixin-provider.js | 7 ++-- src/components/table/helpers/mixin-sorting.js | 9 ++++-- .../table/helpers/mixin-table-renderer.js | 32 ++++++++++++------- .../table/helpers/mixin-tbody-row.js | 21 +++++++----- src/components/table/helpers/mixin-tbody.js | 13 ++++++-- src/components/table/helpers/mixin-thead.js | 3 +- src/components/table/table-lite.js | 1 + src/mixins/form-state.js | 3 +- src/mixins/pagination.js | 7 ++-- src/utils/router.js | 6 ++-- src/utils/safe-vue-instance.js | 13 ++++++++ 17 files changed, 102 insertions(+), 45 deletions(-) create mode 100644 src/utils/safe-vue-instance.js diff --git a/src/components/calendar/calendar.js b/src/components/calendar/calendar.js index b68013a1910..83eb336e246 100644 --- a/src/components/calendar/calendar.js +++ b/src/components/calendar/calendar.js @@ -811,7 +811,7 @@ export const BCalendar = Vue.extend({ { staticClass: 'b-calendar-header', class: { 'sr-only': this.hideHeader }, - attrs: { title: this.selectedDate ? this.labelSelectedDate || null : null } + attrs: { title: this.selectedDate ? this.labelSelected || null : null } }, [$header] ) diff --git a/src/components/form-spinbutton/form-spinbutton.js b/src/components/form-spinbutton/form-spinbutton.js index 50318e36b8b..aa8617e7f23 100644 --- a/src/components/form-spinbutton/form-spinbutton.js +++ b/src/components/form-spinbutton/form-spinbutton.js @@ -113,6 +113,9 @@ export const BFormSpinbutton = /*#__PURE__*/ Vue.extend({ } }, computed: { + required() { + return false + }, spinId() { return this.safeId() }, diff --git a/src/components/form-textarea/form-textarea.js b/src/components/form-textarea/form-textarea.js index 7117ec273a9..54699051fa9 100644 --- a/src/components/form-textarea/form-textarea.js +++ b/src/components/form-textarea/form-textarea.js @@ -67,6 +67,9 @@ export const BFormTextarea = /*#__PURE__*/ Vue.extend({ } }, computed: { + type() { + return null + }, computedStyle() { const styles = { // Setting `noResize` to true will disable the ability for the user to diff --git a/src/components/table/helpers/mixin-empty.js b/src/components/table/helpers/mixin-empty.js index f4c22ca21f6..de4fad4ad66 100644 --- a/src/components/table/helpers/mixin-empty.js +++ b/src/components/table/helpers/mixin-empty.js @@ -8,6 +8,7 @@ import { import { htmlOrText } from '../../../utils/html' import { isFunction } from '../../../utils/inspect' import { makeProp } from '../../../utils/props' +import { safeVueInstance } from '../../../utils/safe-vue-instance' import { BTr } from '../tr' import { BTd } from '../td' @@ -28,14 +29,14 @@ export const emptyMixin = Vue.extend({ props, methods: { renderEmpty() { - const { computedItems: items } = this + const { computedItems: items, computedBusy } = safeVueInstance(this) const h = this.$createElement let $empty = h() if ( this.showEmpty && (!items || items.length === 0) && - !(this.computedBusy && this.hasNormalizedSlot(SLOT_NAME_TABLE_BUSY)) + !(computedBusy && this.hasNormalizedSlot(SLOT_NAME_TABLE_BUSY)) ) { const { computedFields: fields, diff --git a/src/components/table/helpers/mixin-items.js b/src/components/table/helpers/mixin-items.js index c870d904811..f1f1045b810 100644 --- a/src/components/table/helpers/mixin-items.js +++ b/src/components/table/helpers/mixin-items.js @@ -10,6 +10,7 @@ import { makeModelMixin } from '../../../utils/model' import { toInteger } from '../../../utils/number' import { clone, sortKeys } from '../../../utils/object' import { makeProp } from '../../../utils/props' +import { safeVueInstance } from '../../../utils/safe-vue-instance' import { normalizeFields } from './normalize-fields' // --- Constants --- @@ -86,24 +87,26 @@ export const itemsMixin = Vue.extend({ }, {}) }, computedItems() { + const { paginatedItems, sortedItems, filteredItems, localItems } = safeVueInstance(this) // Fallback if various mixins not provided return ( - this.paginatedItems || - this.sortedItems || - this.filteredItems || - this.localItems || + paginatedItems || + sortedItems || + filteredItems || + localItems || /* istanbul ignore next */ [] ).slice() }, context() { + const { perPage, currentPage } = safeVueInstance(this) // Current state of sorting, filtering and pagination props/values return { filter: this.localFilter, sortBy: this.localSortBy, sortDesc: this.localSortDesc, - perPage: mathMax(toInteger(this.perPage, 0), 0), - currentPage: mathMax(toInteger(this.currentPage, 0), 1), + perPage: mathMax(toInteger(perPage, 0), 0), + currentPage: mathMax(toInteger(currentPage, 0), 1), apiUrl: this.apiUrl } } diff --git a/src/components/table/helpers/mixin-pagination.js b/src/components/table/helpers/mixin-pagination.js index 9a46e0b6859..e775871feff 100644 --- a/src/components/table/helpers/mixin-pagination.js +++ b/src/components/table/helpers/mixin-pagination.js @@ -3,6 +3,7 @@ import { PROP_TYPE_NUMBER_STRING } from '../../../constants/props' import { mathMax } from '../../../utils/math' import { toInteger } from '../../../utils/number' import { makeProp } from '../../../utils/props' +import { safeVueInstance } from '../../../utils/safe-vue-instance' // --- Props --- @@ -21,7 +22,8 @@ export const paginationMixin = Vue.extend({ return this.hasProvider ? !!this.noProviderPaging : true }, paginatedItems() { - let items = this.sortedItems || this.filteredItems || this.localItems || [] + const { sortedItems, filteredItems, localItems } = safeVueInstance(this) + let items = sortedItems || filteredItems || localItems || [] const currentPage = mathMax(toInteger(this.currentPage, 1), 1) const perPage = mathMax(toInteger(this.perPage, 0), 0) // Apply local pagination diff --git a/src/components/table/helpers/mixin-provider.js b/src/components/table/helpers/mixin-provider.js index 2d5973f1699..a338aa10dba 100644 --- a/src/components/table/helpers/mixin-provider.js +++ b/src/components/table/helpers/mixin-provider.js @@ -11,6 +11,7 @@ import { isArray, isFunction, isPromise } from '../../../utils/inspect' import { looseEqual } from '../../../utils/loose-equal' import { clone } from '../../../utils/object' import { makeProp } from '../../../utils/props' +import { safeVueInstance } from '../../../utils/safe-vue-instance' import { warn } from '../../../utils/warn' import { listenOnRootMixin } from '../../../mixins/listen-on-root' @@ -100,11 +101,11 @@ export const providerMixin = Vue.extend({ }, methods: { refresh() { - const { items, refresh } = this + const { items, refresh, computedBusy } = safeVueInstance(this) // Public Method: Force a refresh of the provider function this.$off(EVENT_NAME_REFRESHED, refresh) - if (this.computedBusy) { + if (computedBusy) { // Can't force an update when forced busy by user (busy prop === true) if (this.localBusy && this.hasProvider) { // But if provider running (localBusy), re-schedule refresh once `refreshed` emitted @@ -137,7 +138,7 @@ export const providerMixin = Vue.extend({ return } // If table is busy, wait until refreshed before calling again - if (this.computedBusy) { + if (safeVueInstance(this).computedBusy) { // Schedule a new refresh once `refreshed` is emitted this.$nextTick(this.refresh) return diff --git a/src/components/table/helpers/mixin-sorting.js b/src/components/table/helpers/mixin-sorting.js index 494b582d816..b71a5b84218 100644 --- a/src/components/table/helpers/mixin-sorting.js +++ b/src/components/table/helpers/mixin-sorting.js @@ -14,6 +14,7 @@ import { import { arrayIncludes } from '../../../utils/array' import { isFunction, isUndefinedOrNull } from '../../../utils/inspect' import { makeProp } from '../../../utils/props' +import { safeVueInstance } from '../../../utils/safe-vue-instance' import { stableSort } from '../../../utils/stable-sort' import { trim } from '../../../utils/string' import { defaultSortCompare } from './default-sort-compare' @@ -93,9 +94,11 @@ export const sortingMixin = Vue.extend({ sortCompareLocale: locale, sortNullLast: nullLast, sortCompare, - localSorting - } = this - const items = (this.filteredItems || this.localItems || []).slice() + localSorting, + filteredItems, + localItems + } = safeVueInstance(this) + const items = (filteredItems || localItems || []).slice() const localeOptions = { ...this.sortCompareOptions, usage: 'sort' } if (sortBy && localSorting) { diff --git a/src/components/table/helpers/mixin-table-renderer.js b/src/components/table/helpers/mixin-table-renderer.js index 8075968bc6f..aee24480a69 100644 --- a/src/components/table/helpers/mixin-table-renderer.js +++ b/src/components/table/helpers/mixin-table-renderer.js @@ -8,6 +8,7 @@ import { import { identity } from '../../../utils/identity' import { isBoolean } from '../../../utils/inspect' import { makeProp } from '../../../utils/props' +import { safeVueInstance } from '../../../utils/safe-vue-instance' import { toString } from '../../../utils/string' import { attrsMixin } from '../../../mixins/attrs' @@ -49,6 +50,9 @@ export const tableRendererMixin = Vue.extend({ inheritAttrs: false, props, computed: { + isTableSimple() { + return false + }, // Layout related computed props isResponsive() { const { responsive } = this @@ -75,14 +79,19 @@ export const tableRendererMixin = Vue.extend({ return isStickyHeader && !isBoolean(isStickyHeader) ? { maxHeight: isStickyHeader } : {} }, tableClasses() { - let { hover, tableVariant } = this - hover = this.isTableSimple - ? hover - : hover && this.computedItems.length > 0 && !this.computedBusy + let { + hover, + tableVariant, + selectableTableClasses, + stackedTableClasses, + tableClass, + computedBusy + } = safeVueInstance(this) + hover = this.isTableSimple ? hover : hover && this.computedItems.length > 0 && !computedBusy return [ // User supplied classes - this.tableClass, + tableClass, // Styling classes { 'table-striped': this.striped, @@ -99,9 +108,9 @@ export const tableRendererMixin = Vue.extend({ }, tableVariant ? `${this.dark ? 'bg' : 'table'}-${tableVariant}` : '', // Stacked table classes - this.stackedTableClasses, + stackedTableClasses, // Selectable classes - this.selectableTableClasses + selectableTableClasses ] }, tableAttrs() { @@ -109,13 +118,14 @@ export const tableRendererMixin = Vue.extend({ computedItems: items, filteredItems, computedFields: fields, - selectableTableAttrs - } = this + selectableTableAttrs, + computedBusy + } = safeVueInstance(this) const ariaAttrs = this.isTableSimple ? {} : { - 'aria-busy': toString(this.computedBusy), + 'aria-busy': toString(computedBusy), 'aria-colcount': toString(fields.length), // Preserve user supplied `aria-describedby`, if provided 'aria-describedby': @@ -149,7 +159,7 @@ export const tableRendererMixin = Vue.extend({ renderThead, renderTbody, renderTfoot - } = this + } = safeVueInstance(this) const $content = [] if (this.isTableSimple) { diff --git a/src/components/table/helpers/mixin-tbody-row.js b/src/components/table/helpers/mixin-tbody-row.js index ffa0b73b189..2faf9e05faf 100644 --- a/src/components/table/helpers/mixin-tbody-row.js +++ b/src/components/table/helpers/mixin-tbody-row.js @@ -14,6 +14,7 @@ import { useParentMixin } from '../../../mixins/use-parent' import { get } from '../../../utils/get' import { isFunction, isString, isUndefinedOrNull } from '../../../utils/inspect' import { makeProp } from '../../../utils/props' +import { safeVueInstance } from '../../../utils/safe-vue-instance' import { toString } from '../../../utils/string' import { BTr } from '../tr' import { BTd } from '../td' @@ -160,7 +161,7 @@ export const tbodyRowMixin = Vue.extend({ } // If table supports selectable mode, then add in the following scope // this.supportsSelectableRows will be undefined if mixin isn't loaded - if (this.supportsSelectableRows) { + if (safeVueInstance(this).supportsSelectableRows) { slotScope.rowSelected = this.isRowSelected(rowIndex) slotScope.selectRow = () => this.selectRow(rowIndex) slotScope.unselectRow = () => this.unselectRow(rowIndex) @@ -193,13 +194,13 @@ export const tbodyRowMixin = Vue.extend({ currentPage, perPage, tbodyTrClass, - tbodyTrAttr - } = this + tbodyTrAttr, + hasSelectableRowClick + } = safeVueInstance(this) const h = this.$createElement const hasDetailsSlot = this.hasNormalizedSlot(SLOT_NAME_ROW_DETAILS) const rowShowDetails = item[FIELD_KEY_SHOW_DETAILS] && hasDetailsSlot - const hasRowClickHandler = - this.$listeners[EVENT_NAME_ROW_CLICKED] || this.hasSelectableRowClick + const hasRowClickHandler = this.$listeners[EVENT_NAME_ROW_CLICKED] || hasSelectableRowClick // We can return more than one TR if rowDetails enabled const $rows = [] @@ -232,8 +233,12 @@ export const tbodyRowMixin = Vue.extend({ const rowId = primaryKeyValue ? this.safeId(`_row_${primaryKeyValue}`) : null // Selectable classes and attributes - const selectableClasses = this.selectableRowClasses ? this.selectableRowClasses(rowIndex) : {} - const selectableAttrs = this.selectableRowAttrs ? this.selectableRowAttrs(rowIndex) : {} + const selectableClasses = safeVueInstance(this).selectableRowClasses + ? this.selectableRowClasses(rowIndex) + : {} + const selectableAttrs = safeVueInstance(this).selectableRowAttrs + ? this.selectableRowAttrs(rowIndex) + : {} // Additional classes and attributes const userTrClasses = isFunction(tbodyTrClass) ? tbodyTrClass(item, 'row') : tbodyTrClass @@ -282,7 +287,7 @@ export const tbodyRowMixin = Vue.extend({ } // If table supports selectable mode, then add in the following scope // this.supportsSelectableRows will be undefined if mixin isn't loaded - if (this.supportsSelectableRows) { + if (safeVueInstance(this).supportsSelectableRows) { detailsScope.rowSelected = this.isRowSelected(rowIndex) detailsScope.selectRow = () => this.selectRow(rowIndex) detailsScope.unselectRow = () => this.unselectRow(rowIndex) diff --git a/src/components/table/helpers/mixin-tbody.js b/src/components/table/helpers/mixin-tbody.js index cc6bf8a04ca..451a328776f 100644 --- a/src/components/table/helpers/mixin-tbody.js +++ b/src/components/table/helpers/mixin-tbody.js @@ -16,6 +16,7 @@ import { import { PROP_TYPE_ARRAY_OBJECT_STRING } from '../../../constants/props' import { arrayIncludes, from as arrayFrom } from '../../../utils/array' import { attemptFocus, closest, isActiveElement, isElement } from '../../../utils/dom' +import { safeVueInstance } from '../../../utils/safe-vue-instance' import { stopEvent } from '../../../utils/events' import { sortKeys } from '../../../utils/object' import { makeProp, pluckProps } from '../../../utils/props' @@ -157,10 +158,16 @@ export const tbodyMixin = Vue.extend({ // Row hover handlers are handled by the tbody-row mixin // As mouseenter/mouseleave events do not bubble renderTbody() { - const { computedItems: items, renderBusy, renderTopRow, renderEmpty, renderBottomRow } = this + const { + computedItems: items, + renderBusy, + renderTopRow, + renderEmpty, + renderBottomRow, + hasSelectableRowClick + } = safeVueInstance(this) const h = this.$createElement - const hasRowClickHandler = - this.hasListener(EVENT_NAME_ROW_CLICKED) || this.hasSelectableRowClick + const hasRowClickHandler = this.hasListener(EVENT_NAME_ROW_CLICKED) || hasSelectableRowClick // Prepare the tbody rows const $rows = [] diff --git a/src/components/table/helpers/mixin-thead.js b/src/components/table/helpers/mixin-thead.js index f5126f8ea61..c3321f97ff8 100644 --- a/src/components/table/helpers/mixin-thead.js +++ b/src/components/table/helpers/mixin-thead.js @@ -9,6 +9,7 @@ import { identity } from '../../../utils/identity' import { isUndefinedOrNull } from '../../../utils/inspect' import { noop } from '../../../utils/noop' import { makeProp } from '../../../utils/props' +import { safeVueInstance } from '../../../utils/safe-vue-instance' import { startCase } from '../../../utils/string' import { BThead } from '../thead' import { BTfoot } from '../tfoot' @@ -68,7 +69,7 @@ export const theadMixin = Vue.extend({ footVariant, headRowVariant, footRowVariant - } = this + } = safeVueInstance(this) const h = this.$createElement // In always stacked mode, we don't bother rendering the head/foot diff --git a/src/components/table/table-lite.js b/src/components/table/table-lite.js index 95c5e9f49a0..4302ec07d5e 100644 --- a/src/components/table/table-lite.js +++ b/src/components/table/table-lite.js @@ -58,5 +58,6 @@ export const BTableLite = /*#__PURE__*/ Vue.extend({ colgroupMixin ], props + // Render function is provided by `tableRendererMixin` }) diff --git a/src/mixins/form-state.js b/src/mixins/form-state.js index c9a3d09014e..14c81cb08c4 100644 --- a/src/mixins/form-state.js +++ b/src/mixins/form-state.js @@ -10,6 +10,7 @@ import { Vue } from '../vue' import { PROP_TYPE_BOOLEAN } from '../constants/props' import { isBoolean } from '../utils/inspect' import { makeProp, makePropsConfigurable } from '../utils/props' +import { safeVueInstance } from '../utils/safe-vue-instance' // --- Props --- @@ -36,7 +37,7 @@ export const formStateMixin = Vue.extend({ return state === true ? 'is-valid' : state === false ? 'is-invalid' : null }, computedAriaInvalid() { - const { ariaInvalid } = this + const ariaInvalid = safeVueInstance(this).ariaInvalid if (ariaInvalid === true || ariaInvalid === 'true' || ariaInvalid === '') { return 'true' } diff --git a/src/mixins/pagination.js b/src/mixins/pagination.js index 4192aaa1127..cb2dcbf64ba 100644 --- a/src/mixins/pagination.js +++ b/src/mixins/pagination.js @@ -33,6 +33,7 @@ import { makeModelMixin } from '../utils/model' import { toInteger } from '../utils/number' import { sortKeys } from '../utils/object' import { hasPropFunction, makeProp, makePropsConfigurable } from '../utils/props' +import { safeVueInstance } from '../utils/safe-vue-instance' import { toString } from '../utils/string' import { warn } from '../utils/warn' import { normalizeSlotMixin } from '../mixins/normalize-slot' @@ -398,7 +399,7 @@ export const paginationMixin = Vue.extend({ isNav, localNumberOfPages: numberOfPages, computedCurrentPage: currentPage - } = this + } = safeVueInstance(this) const pageNumbers = this.pageList.map(p => p.number) const { showFirstDots, showLastDots } = this.paginationParams const fill = this.align === 'fill' @@ -426,7 +427,7 @@ export const paginationMixin = Vue.extend({ type: isNav || isDisabled ? null : 'button', tabindex: isDisabled || isNav ? null : '-1', 'aria-label': ariaLabel, - 'aria-controls': this.ariaControls || null, + 'aria-controls': safeVueInstance(this).ariaControls || null, 'aria-disabled': isDisabled ? 'true' : null }, on: isDisabled @@ -491,7 +492,7 @@ export const paginationMixin = Vue.extend({ role: isNav ? null : 'menuitemradio', type: isNav || disabled ? null : 'button', 'aria-disabled': disabled ? 'true' : null, - 'aria-controls': this.ariaControls || null, + 'aria-controls': safeVueInstance(this).ariaControls || null, 'aria-label': hasPropFunction(labelPage) ? /* istanbul ignore next */ labelPage(pageNumber) : `${isFunction(labelPage) ? labelPage() : labelPage} ${pageNumber}`, diff --git a/src/utils/router.js b/src/utils/router.js index 0ee0e7e2433..85c41cf8bd2 100644 --- a/src/utils/router.js +++ b/src/utils/router.js @@ -2,6 +2,7 @@ import { RX_ENCODED_COMMA, RX_ENCODE_REVERSE, RX_PLUS, RX_QUERY_START } from '.. import { isTag } from './dom' import { isArray, isNull, isPlainObject, isString, isUndefined } from './inspect' import { keys } from './object' +import { safeVueInstance } from './safe-vue-instance' import { toString } from './string' const ANCHOR_TAG = 'a' @@ -88,7 +89,8 @@ export const isLink = props => !!(props.href || props.to) export const isRouterLink = tag => !!(tag && !isTag(tag, 'a')) export const computeTag = ({ to, disabled, routerComponentName }, thisOrParent) => { - const hasRouter = !!thisOrParent.$router + const hasRouter = !!safeVueInstance(thisOrParent).$router + const hasNuxt = !!safeVueInstance(thisOrParent).$nuxt if (!hasRouter || (hasRouter && (disabled || !to))) { return ANCHOR_TAG } @@ -101,7 +103,7 @@ export const computeTag = ({ to, disabled, routerComponentName }, thisOrParent) // exists = names.some(name => !!thisOrParent.$options.components[name]) // And may want to cache the result for performance or we just let the render fail // if the component is not registered - return routerComponentName || (thisOrParent.$nuxt ? 'nuxt-link' : 'router-link') + return routerComponentName || (hasNuxt ? 'nuxt-link' : 'router-link') } export const computeRel = ({ target, rel } = {}) => diff --git a/src/utils/safe-vue-instance.js b/src/utils/safe-vue-instance.js new file mode 100644 index 00000000000..dec86f7cba5 --- /dev/null +++ b/src/utils/safe-vue-instance.js @@ -0,0 +1,13 @@ +import { isVue3 } from '../vue' + +export function safeVueInstance(target) { + if (!isVue3) { + return target + } + + return new Proxy(target, { + get(target, prop) { + return prop in target ? target[prop] : undefined + } + }) +} From d03593779654247d7f6ad3c7b1d62a850cdacb69 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Sat, 20 Nov 2021 02:37:29 +0200 Subject: [PATCH 17/34] chore(compat): drop $children usage in tabs component --- src/components/tabs/tabs.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/tabs/tabs.js b/src/components/tabs/tabs.js index e745662b69e..ec9ff6e294f 100644 --- a/src/components/tabs/tabs.js +++ b/src/components/tabs/tabs.js @@ -356,9 +356,11 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ } }, getTabs() { - const $tabs = this.registeredTabs.filter( - $tab => $tab.$children.filter($t => $t && $t._isTab).length === 0 - ) + const $tabs = this.registeredTabs + // Dropped intentionally + // .filter( + // $tab => $tab.$children.filter($t => $t && $t._isTab).length === 0 + // ) // DOM Order of Tabs let order = [] From 05db323e6549de781b36bf73515d3ca1bc220050 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Sat, 20 Nov 2021 02:37:54 +0200 Subject: [PATCH 18/34] chore(compat): do not pass extra props in link if there is no nuxt --- src/components/link/link.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/link/link.js b/src/components/link/link.js index 5f2d16e8b8a..f3a5bdde76f 100644 --- a/src/components/link/link.js +++ b/src/components/link/link.js @@ -105,7 +105,10 @@ export const BLink = /*#__PURE__*/ Vue.extend({ return this.isRouterLink ? { ...pluckProps( - omit({ ...routerLinkProps, ...nuxtLinkProps }, ['event', 'prefetch', 'routerTag']), + omit( + { ...routerLinkProps, ...(this.computedTag === 'nuxt-link' ? nuxtLinkProps : {}) }, + ['event', 'prefetch', 'routerTag'] + ), this ), // Only add these props, when actually defined From c7d10656df73519e1d01961c47fac0b0968857f6 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Sat, 20 Nov 2021 02:43:51 +0200 Subject: [PATCH 19/34] chore(compat): do not pass false value in BVTransition --- src/components/transition/bv-transition.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/transition/bv-transition.js b/src/components/transition/bv-transition.js index 392d92c9c4d..006e848bd67 100644 --- a/src/components/transition/bv-transition.js +++ b/src/components/transition/bv-transition.js @@ -70,10 +70,13 @@ export const BVTransition = /*#__PURE__*/ Vue.extend({ // We always need `css` true css: true } + + const dataCopy = { ...data } + delete dataCopy.props return h( 'transition', // Any transition event listeners will get merged here - mergeData(data, { props: transProps }), + mergeData(dataCopy, { props: transProps }), children ) } From 7e16f96cb7d55c4298802e1b81b7ec19407c5221 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Sat, 20 Nov 2021 02:44:21 +0200 Subject: [PATCH 20/34] chore(compat): update hook event names for vue3 (now vnode events) --- src/constants/events.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/constants/events.js b/src/constants/events.js index 7e4b1fc4210..14b84b5f223 100644 --- a/src/constants/events.js +++ b/src/constants/events.js @@ -1,3 +1,5 @@ +import { isVue3 } from '../vue' + export const EVENT_NAME_ACTIVATE_TAB = 'activate-tab' export const EVENT_NAME_BLUR = 'blur' export const EVENT_NAME_CANCEL = 'cancel' @@ -54,8 +56,8 @@ export const EVENT_NAME_TOGGLE = 'toggle' export const EVENT_NAME_UNPAUSED = 'unpaused' export const EVENT_NAME_UPDATE = 'update' -export const HOOK_EVENT_NAME_BEFORE_DESTROY = 'hook:beforeDestroy' -export const HOOK_EVENT_NAME_DESTROYED = 'hook:destroyed' +export const HOOK_EVENT_NAME_BEFORE_DESTROY = isVue3 ? 'vnodeBeforeUnmount' : 'hook:beforeDestroy' +export const HOOK_EVENT_NAME_DESTROYED = isVue3 ? 'vNodeUnmounted' : 'hook:destroyed' export const MODEL_EVENT_NAME_PREFIX = 'update:' From 411e0e9acdbfb25cda5f489ac872ee1214b4782d Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Fri, 28 Jan 2022 18:51:19 +0200 Subject: [PATCH 21/34] chore(ci): add vue3 testing to pipeline --- .github/workflows/test.yml | 11 +++++++++++ .gitignore | 1 + jest.config.js | 10 +++++----- tests/setup.js | 4 ++-- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e84c1129df0..4185f1c5f1e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -125,8 +125,19 @@ jobs: - name: Test unit run: yarn run test:unit --coverage --maxWorkers=2 + - name: Test unit (Vue 3) + run: yarn run test:unit --coverage --maxWorkers=2 + env: + USE_VUE3: '1' + + - name: Merge coverage + run: + npx istanbul-merge --out ./coverage-final.json coverage/coverage-final.json + coverage-vue3/coverage-final.json + - name: CodeCov uses: codecov/codecov-action@v3.1.1 with: token: ${{ secrets.CODECOV_TOKEN }} flags: unittests + files: ./coverage-final.json diff --git a/.gitignore b/.gitignore index 91a43b70be3..38d10d68e50 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .vercel/ .vscode/ coverage/ +coverage-vue3/ dist/ docs-dist/ esm/ diff --git a/jest.config.js b/jest.config.js index c39accbb5e3..56b7921e99d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,11 +1,11 @@ -const useVue2 = 'USE_VUE2' in process.env +const useVue3 = 'USE_VUE3' in process.env -const moduleNameMapper = useVue2 - ? {} - : { +const moduleNameMapper = useVue3 + ? { '^vue$': '@vue/compat', '^@vue/test-utils$': '@vue/test-utils-vue3' } + : {} module.exports = { testRegex: 'spec.js$', @@ -15,7 +15,7 @@ module.exports = { '^.+\\.js$': 'babel-jest' }, transformIgnorePatterns: ['/node_modules(?![\\\\/]vue-test-utils-compat[\\\\/])'], - coverageDirectory: './coverage/', + coverageDirectory: useVue3 ? './coverage-vue3' : './coverage/', testEnvironmentOptions: { pretendToBeVisual: true }, diff --git a/tests/setup.js b/tests/setup.js index 36b35934858..45a63fdbf4d 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -3,8 +3,8 @@ import Vue from 'vue' import * as VTU from '@vue/test-utils' import { installCompat as installVTUCompat, fullCompatConfig } from 'vue-test-utils-compat' -const useVue2 = 'USE_VUE2' in process.env -if (!useVue2) { +const useVue3 = 'USE_VUE3' in process.env +if (useVue3) { Vue.configureCompat({ MODE: 2, ATTR_FALSE_VALUE: 'suppress-warning', From ae4bac8a4327a1f293afbcf571e84ed1de4497f8 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Sun, 2 Oct 2022 22:17:51 +0300 Subject: [PATCH 22/34] fix: update refs inside v-for to work for @vue/compat --- package.json | 6 +- .../table/helpers/mixin-tbody-row.js | 4 +- src/components/tabs/tabs.js | 4 +- src/components/time/time.js | 4 +- src/vue.js | 2 + tests/setup.js | 1 - yarn.lock | 59 +++++++++++-------- 7 files changed, 45 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 1beaf77d806..d603c00d1cf 100644 --- a/package.json +++ b/package.json @@ -99,10 +99,10 @@ "@nuxtjs/robots": "^2.5.0", "@nuxtjs/sitemap": "^2.4.0", "@testing-library/jest-dom": "^5.12.0", - "@vue/compat": "^3.2.24", - "@vue/compiler-dom": "^3.2.24", + "@vue/compat": "^3.2.40", + "@vue/compiler-dom": "^3.2.40", "@vue/test-utils": "^1.3.0", - "@vue/test-utils-vue3": "npm:@vue/test-utils@2.0.0-rc.18", + "@vue/test-utils-vue3": "npm:@vue/test-utils@2.1.0", "autoprefixer": "^10.4.0", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "^10.1.0", diff --git a/src/components/table/helpers/mixin-tbody-row.js b/src/components/table/helpers/mixin-tbody-row.js index 2faf9e05faf..b11642045b0 100644 --- a/src/components/table/helpers/mixin-tbody-row.js +++ b/src/components/table/helpers/mixin-tbody-row.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { Vue, REF_FOR_KEY } from '../../../vue' import { EVENT_NAME_ROW_CLICKED, EVENT_NAME_ROW_HOVERED, @@ -271,7 +271,7 @@ export const tbodyRowMixin = Vue.extend({ }, key: `__b-table-row-${rowKey}__`, ref: 'item-rows', - refInFor: true + [REF_FOR_KEY]: true }, $tds ) diff --git a/src/components/tabs/tabs.js b/src/components/tabs/tabs.js index ec9ff6e294f..28a4019ff8a 100644 --- a/src/components/tabs/tabs.js +++ b/src/components/tabs/tabs.js @@ -1,4 +1,4 @@ -import { COMPONENT_UID_KEY, Vue } from '../../vue' +import { COMPONENT_UID_KEY, REF_FOR_KEY, Vue } from '../../vue' import { NAME_TABS, NAME_TAB_BUTTON_HELPER } from '../../constants/components' import { IS_BROWSER } from '../../constants/env' import { @@ -598,7 +598,7 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ key: $tab[COMPONENT_UID_KEY] || index, ref: 'buttons', // Needed to make `this.$refs.buttons` an array - refInFor: true + [REF_FOR_KEY]: true }) }) diff --git a/src/components/time/time.js b/src/components/time/time.js index e94665ec06d..cb0c93ef2b3 100644 --- a/src/components/time/time.js +++ b/src/components/time/time.js @@ -1,5 +1,5 @@ // BTime control (not form input control) -import { Vue } from '../../vue' +import { Vue, REF_FOR_KEY } from '../../vue' import { NAME_TIME } from '../../constants/components' import { EVENT_NAME_CONTEXT } from '../../constants/events' import { CODE_LEFT, CODE_RIGHT } from '../../constants/key-codes' @@ -441,7 +441,7 @@ export const BTime = /*#__PURE__*/ Vue.extend({ }, key, ref: 'spinners', - refInFor: true + [REF_FOR_KEY]: true }) } diff --git a/src/vue.js b/src/vue.js index 6a2728fb486..95aa447db71 100644 --- a/src/vue.js +++ b/src/vue.js @@ -6,6 +6,8 @@ const COMPONENT_UID_KEY = '_uid' const isVue3 = Vue.version.startsWith('3') +export const REF_FOR_KEY = isVue3 ? 'ref_for' : 'refInFor' + const ALLOWED_FIELDS_IN_DATA = [ 'class', 'staticClass', diff --git a/tests/setup.js b/tests/setup.js index 45a63fdbf4d..78b128caed4 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -31,7 +31,6 @@ if (useVue3) { OPTIONS_DATA_MERGE: 'suppress-warning', OPTIONS_DESTROYED: 'suppress-warning', RENDER_FUNCTION: 'suppress-warning', - V_FOR_REF: 'suppress-warning', WATCH_ARRAY: 'suppress-warning' }) diff --git a/yarn.lock b/yarn.lock index 80202c98cdc..20b8a8e9183 100644 --- a/yarn.lock +++ b/yarn.lock @@ -617,11 +617,16 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.12.tgz#9474794f9a650cf5e2f892444227f98e28cdf8b6" integrity sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A== -"@babel/parser@^7.15.0", "@babel/parser@^7.16.0": +"@babel/parser@^7.16.0": version "7.16.2" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.2.tgz#3723cd5c8d8773eef96ce57ea1d9b7faaccd12ac" integrity sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw== +"@babel/parser@^7.16.4": + version "7.19.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.3.tgz#8dd36d17c53ff347f9e55c328710321b49479a9a" + integrity sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ== + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.13.12": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.13.12.tgz#a3484d84d0b549f3fc916b99ee4783f26fabad2a" @@ -2754,28 +2759,32 @@ "@vue/babel-plugin-transform-vue-jsx" "^1.2.1" camelcase "^5.0.0" -"@vue/compat@^3.2.24": - version "3.2.24" - resolved "https://registry.yarnpkg.com/@vue/compat/-/compat-3.2.24.tgz#6b10efb2773ccc8a59e625b4082bdc7cf2012549" - integrity sha512-fhnNc+SJ/hbhKZexVHVK+vZ0VstHm32VXgFEoiV1WWYNGRFJB5X7jbO/1a09IQgURiHwP0Km9jQQzN7/7sSbag== +"@vue/compat@^3.2.40": + version "3.2.40" + resolved "https://registry.yarnpkg.com/@vue/compat/-/compat-3.2.40.tgz#5ffa8999121daaff585eea1dce0352580e562bfd" + integrity sha512-PZl6tsjWC2KENXfeJ+hI+wbvN7lgLBVyf6fgE1bybxUtfDcw/Eon3RrapEHnp86zuZU++ThGqq1U03ZacznR0g== + dependencies: + "@babel/parser" "^7.16.4" + estree-walker "^2.0.2" + source-map "^0.6.1" -"@vue/compiler-core@3.2.24": - version "3.2.24" - resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.24.tgz#cadcda0e026e7f1cd453ce87160be51a5f313fe0" - integrity sha512-A0SxB2HAggKzP57LDin5gfgWOTwFyGCtQ5MTMNBADnfQYALWnYuC8kMI0DhRSplGTWRvn9Z2DAnG8f35BnojuA== +"@vue/compiler-core@3.2.40": + version "3.2.40" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.40.tgz#c785501f09536748121e937fb87605bbb1ada8e5" + integrity sha512-2Dc3Stk0J/VyQ4OUr2yEC53kU28614lZS+bnrCbFSAIftBJ40g/2yQzf4mPBiFuqguMB7hyHaujdgZAQ67kZYA== dependencies: - "@babel/parser" "^7.15.0" - "@vue/shared" "3.2.24" + "@babel/parser" "^7.16.4" + "@vue/shared" "3.2.40" estree-walker "^2.0.2" source-map "^0.6.1" -"@vue/compiler-dom@^3.2.24": - version "3.2.24" - resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.24.tgz#32235cb444660245be5cc58f4beb76747400505c" - integrity sha512-KQEm8r0JFsrNNIfbD28pcwMvHpcJcwjVR1XWFcD0yyQ8eREd7IXhT7J6j7iNCSE/TIo78NOvkwbyX+lnIm836w== +"@vue/compiler-dom@^3.2.40": + version "3.2.40" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.40.tgz#c225418773774db536174d30d3f25ba42a33e7e4" + integrity sha512-OZCNyYVC2LQJy4H7h0o28rtk+4v+HMQygRTpmibGoG9wZyomQiS5otU7qo3Wlq5UfHDw2RFwxb9BJgKjVpjrQw== dependencies: - "@vue/compiler-core" "3.2.24" - "@vue/shared" "3.2.24" + "@vue/compiler-core" "3.2.40" + "@vue/shared" "3.2.40" "@vue/component-compiler-utils@^3.1.0": version "3.2.0" @@ -2793,15 +2802,15 @@ optionalDependencies: prettier "^1.18.2" -"@vue/shared@3.2.24": - version "3.2.24" - resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.24.tgz#d74615e856013b17fb60b19b09d712729ad5e090" - integrity sha512-BUgRiZCkCrqDps5aQ9av05xcge3rn092ztKIh17tHkeEFgP4zfXMQWBA2zfdoCdCEdBL26xtOv+FZYiOp9RUDA== +"@vue/shared@3.2.40": + version "3.2.40" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.40.tgz#e57799da2a930b975321981fcee3d1e90ed257ae" + integrity sha512-0PLQ6RUtZM0vO3teRfzGi4ltLUO5aO+kLgwh4Um3THSR03rpQWLTuRCkuO5A41ITzwdWeKdPHtSARuPkoo5pCQ== -"@vue/test-utils-vue3@npm:@vue/test-utils@2.0.0-rc.18": - version "2.0.0-rc.18" - resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.0.0-rc.18.tgz#ff22b252424fe72e5462cbb3a8e7405cef11ffb6" - integrity sha512-aifolXjVdsogjaLmDoZ0FU8vN+R67aWmg9OuVeED4w5Ij5GFQLrlhM19uhWe/r5xXUL4fXMk3pX5wW6FJP1NcQ== +"@vue/test-utils-vue3@npm:@vue/test-utils@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.1.0.tgz#c2f646aa2d6ac779f79a83f18c5b82fc40952bfd" + integrity sha512-U4AxAD/tKJ3ajxYew1gkfEotpr96DE/gLXpbl+nPbsNRqGBfQZZA7YhwGoQNDPgon56v+IGZDrYq7pe3GDl9aw== "@vue/test-utils@^1.3.0": version "1.3.0" From 779dd69071401888a536aa9c3682bb6d3b4dda2d Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Mon, 3 Oct 2022 13:07:42 +0300 Subject: [PATCH 23/34] chore(tests): Update tests to work with latest @vue/test-utils --- .../button-toolbar/button-toolbar.spec.js | 42 ++------ src/components/button/button.js | 6 +- .../form-checkbox/form-checkbox-group.spec.js | 32 +++--- .../form-radio/form-radio-group.spec.js | 4 +- .../form-rating/form-rating.spec.js | 18 +--- .../form-select-option-group.spec.js | 21 +--- .../form-select/form-select.spec.js | 98 +++---------------- src/components/pagination/pagination.spec.js | 6 +- .../table/table-row-details.spec.js | 7 +- 9 files changed, 54 insertions(+), 180 deletions(-) diff --git a/src/components/button-toolbar/button-toolbar.spec.js b/src/components/button-toolbar/button-toolbar.spec.js index 0167a87d85d..dcb0ec5003c 100644 --- a/src/components/button-toolbar/button-toolbar.spec.js +++ b/src/components/button-toolbar/button-toolbar.spec.js @@ -108,42 +108,12 @@ describe('button-toolbar', () => { const $btns = wrapper.findAll('button') expect($btns).toBeDefined() expect($btns.length).toBe(6) - expect( - $btns - .at(0) - .find('button[tabindex="-1"') - .exists() - ).toBe(true) - expect( - $btns - .at(1) - .find('button[tabindex="-1"') - .exists() - ).toBe(true) - expect( - $btns - .at(2) - .find('button[tabindex="-1"') - .exists() - ).toBe(false) // Disabled button - expect( - $btns - .at(3) - .find('button[tabindex="-1"') - .exists() - ).toBe(true) - expect( - $btns - .at(4) - .find('button[tabindex="-1"') - .exists() - ).toBe(true) - expect( - $btns - .at(5) - .find('button[tabindex="-1"') - .exists() - ).toBe(true) + expect($btns.at(0).element.matches('button[tabindex="-1"')).toBe(true) + expect($btns.at(1).element.matches('button[tabindex="-1"')).toBe(true) + expect($btns.at(2).element.matches('button[tabindex="-1"')).toBe(false) // Disabled button + expect($btns.at(3).element.matches('button[tabindex="-1"')).toBe(true) + expect($btns.at(4).element.matches('button[tabindex="-1"')).toBe(true) + expect($btns.at(5).element.matches('button[tabindex="-1"')).toBe(true) wrapper.destroy() }) diff --git a/src/components/button/button.js b/src/components/button/button.js index 97b49883cef..fd6122308c9 100644 --- a/src/components/button/button.js +++ b/src/components/button/button.js @@ -170,6 +170,10 @@ export const BButton = /*#__PURE__*/ Vue.extend({ on } - return h(link ? BLink : props.tag, mergeData(data, componentData), children) + return h( + link ? BLink : props.tag, + mergeData({ ...data, props: undefined }, componentData), + children + ) } }) diff --git a/src/components/form-checkbox/form-checkbox-group.spec.js b/src/components/form-checkbox/form-checkbox-group.spec.js index 4ac74dd27d7..4c3f3c23bbb 100644 --- a/src/components/form-checkbox/form-checkbox-group.spec.js +++ b/src/components/form-checkbox/form-checkbox-group.spec.js @@ -370,7 +370,7 @@ describe('form-checkbox-group', () => { const $inputs = wrapper.findAll('input') expect($inputs.length).toBe(3) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) wrapper.destroy() }) @@ -389,7 +389,7 @@ describe('form-checkbox-group', () => { const $inputs = wrapper.findAll('input') expect($inputs.length).toBe(3) expect(wrapper.vm.localChecked).toEqual([]) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) expect($inputs.at(0).attributes('disabled')).toBeUndefined() expect($inputs.at(1).attributes('disabled')).toBeUndefined() expect($inputs.at(2).attributes('disabled')).toBeDefined() @@ -460,7 +460,7 @@ describe('form-checkbox-group', () => { const $inputs = wrapper.findAll('input') expect($inputs.length).toBe(3) expect(wrapper.vm.localChecked).toEqual(value) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) expect($inputs.at(0).element.checked).toBe(true) expect($inputs.at(1).element.checked).toBe(true) expect($inputs.at(2).element.checked).toBe(true) @@ -472,7 +472,7 @@ describe('form-checkbox-group', () => { await waitNT(wrapper.vm) expect(wrapper.vm.localChecked).toEqual(value) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) expect($inputs.at(0).element.checked).toBe(true) expect($inputs.at(1).element.checked).toBe(true) expect($inputs.at(2).element.checked).toBe(true) @@ -484,7 +484,7 @@ describe('form-checkbox-group', () => { await waitNT(wrapper.vm) expect(wrapper.vm.localChecked).toEqual(value.slice().reverse()) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) expect($inputs.at(0).element.checked).toBe(true) expect($inputs.at(1).element.checked).toBe(true) expect($inputs.at(2).element.checked).toBe(true) @@ -509,14 +509,14 @@ describe('form-checkbox-group', () => { const $inputs = wrapper.findAll('input') expect($inputs.length).toBe(3) expect(wrapper.vm.localChecked).toEqual(['two']) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) expect($inputs.at(0).element.checked).toBe(false) expect($inputs.at(1).element.checked).toBe(true) expect($inputs.at(2).element.checked).toBe(false) await wrapper.setProps({ checked: ['three', 'one'] }) expect(wrapper.vm.localChecked).toEqual(['three', 'one']) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) expect($inputs.at(0).element.checked).toBe(true) expect($inputs.at(1).element.checked).toBe(false) expect($inputs.at(2).element.checked).toBe(true) @@ -539,8 +539,8 @@ describe('form-checkbox-group', () => { const $inputs = wrapper.findAll('input') expect($inputs.length).toBe(3) expect(wrapper.vm.localChecked).toEqual([]) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) - expect($inputs.wrappers.every(c => c.find('input.is-valid').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input.is-valid'))).toBe(true) wrapper.destroy() }) @@ -558,8 +558,8 @@ describe('form-checkbox-group', () => { const $inputs = wrapper.findAll('input') expect($inputs.length).toBe(3) expect(wrapper.vm.localChecked).toEqual([]) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) - expect($inputs.wrappers.every(c => c.find('input.is-invalid').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input.is-invalid'))).toBe(true) wrapper.destroy() }) @@ -577,8 +577,8 @@ describe('form-checkbox-group', () => { const $inputs = wrapper.findAll('input') expect($inputs.length).toBe(3) expect(wrapper.vm.localChecked).toEqual([]) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) - expect($inputs.wrappers.every(c => c.find('input[disabled]').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[disabled]'))).toBe(true) wrapper.destroy() }) @@ -597,9 +597,9 @@ describe('form-checkbox-group', () => { const $inputs = wrapper.findAll('input') expect($inputs.length).toBe(3) expect(wrapper.vm.localChecked).toEqual([]) - expect($inputs.wrappers.every(c => c.find('input[type=checkbox]').exists())).toBe(true) - expect($inputs.wrappers.every(c => c.find('input[required]').exists())).toBe(true) - expect($inputs.wrappers.every(c => c.find('input[aria-required="true"]').exists())).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[type=checkbox]'))).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[required]'))).toBe(true) + expect($inputs.wrappers.every(c => c.element.matches('input[aria-required="true"]'))).toBe(true) wrapper.destroy() }) diff --git a/src/components/form-radio/form-radio-group.spec.js b/src/components/form-radio/form-radio-group.spec.js index 6e5f3f070ba..74421829129 100644 --- a/src/components/form-radio/form-radio-group.spec.js +++ b/src/components/form-radio/form-radio-group.spec.js @@ -348,7 +348,7 @@ describe('form-radio-group', () => { const radios = wrapper.findAll('input') expect(radios.length).toBe(3) - expect(radios.wrappers.every(c => c.find('input[type=radio]').exists())).toBe(true) + expect(radios.wrappers.every(c => c.element.matches('input[type=radio]'))).toBe(true) wrapper.destroy() }) @@ -365,7 +365,7 @@ describe('form-radio-group', () => { const radios = wrapper.findAll('input') expect(radios.length).toBe(3) expect(wrapper.vm.localChecked).toEqual('') - expect(radios.wrappers.every(c => c.find('input[type=radio]').exists())).toBe(true) + expect(radios.wrappers.every(c => c.element.matches('input[type=radio]'))).toBe(true) expect(radios.at(0).attributes('disabled')).toBeUndefined() expect(radios.at(1).attributes('disabled')).toBeUndefined() expect(radios.at(2).attributes('disabled')).toBeDefined() diff --git a/src/components/form-rating/form-rating.spec.js b/src/components/form-rating/form-rating.spec.js index 197a38e1ada..6a30c3e55ef 100644 --- a/src/components/form-rating/form-rating.spec.js +++ b/src/components/form-rating/form-rating.spec.js @@ -66,8 +66,8 @@ describe('form-rating', () => { const $icons = wrapper.findAll('.b-icon') expect($icons.length).toBe(5) - expect($icons.wrappers.every(i => i.find('.bi-star').exists())).toBe(true) - expect($icons.wrappers.every(i => i.find('.text-primary').exists())).toBe(true) + expect($icons.wrappers.every(i => i.element.matches('.bi-star'))).toBe(true) + expect($icons.wrappers.every(i => i.element.matches('.text-primary'))).toBe(true) expect($icons.wrappers.every(i => i.find('.text-warning').exists())).toBe(false) wrapper.destroy() @@ -322,18 +322,8 @@ describe('form-rating', () => { const $stars = wrapper.findAll('.b-rating-star') // The clear button is a "star" expect($stars.length).toBe(6) - expect( - $stars - .at(0) - .find('.b-rating-star-clear') - .exists() - ).toBe(true) - expect( - $stars - .at(1) - .find('.b-rating-star-clear') - .exists() - ).toBe(false) + expect($stars.at(0).element.matches('.b-rating-star-clear')).toBe(true) + expect($stars.at(1).element.matches('.b-rating-star-clear')).toBe(false) const $clear = wrapper.find('.b-rating-star-clear') expect($clear.exists()).toBe(true) diff --git a/src/components/form-select/form-select-option-group.spec.js b/src/components/form-select/form-select-option-group.spec.js index f4368efaeba..0212f845c32 100644 --- a/src/components/form-select/form-select-option-group.spec.js +++ b/src/components/form-select/form-select-option-group.spec.js @@ -70,24 +70,9 @@ describe('form-select-option-group', () => { expect($options.at(0).attributes('value')).toBe('1') expect($options.at(1).attributes('value')).toBe('2') expect($options.at(2).attributes('value')).toBe('3') - expect( - $options - .at(0) - .find('[disabled]') - .exists() - ).toBe(false) - expect( - $options - .at(1) - .find('[disabled]') - .exists() - ).toBe(true) - expect( - $options - .at(2) - .find('[disabled]') - .exists() - ).toBe(false) + expect($options.at(0).element.matches('[disabled]')).toBe(false) + expect($options.at(1).element.matches('[disabled]')).toBe(true) + expect($options.at(2).element.matches('[disabled]')).toBe(false) wrapper.destroy() }) diff --git a/src/components/form-select/form-select.spec.js b/src/components/form-select/form-select.spec.js index cb730eb98bc..0fa4d711e6a 100644 --- a/src/components/form-select/form-select.spec.js +++ b/src/components/form-select/form-select.spec.js @@ -336,24 +336,9 @@ describe('form-select', () => { expect($options.at(0).attributes('value')).toBe('1') expect($options.at(1).attributes('value')).toBe('2') expect($options.at(2).attributes('value')).toBe('3') - expect( - $options - .at(0) - .find('[disabled]') - .exists() - ).toBe(false) - expect( - $options - .at(1) - .find('[disabled]') - .exists() - ).toBe(true) - expect( - $options - .at(2) - .find('[disabled]') - .exists() - ).toBe(false) + expect($options.at(0).element.matches('[disabled]')).toBe(false) + expect($options.at(1).element.matches('[disabled]')).toBe(true) + expect($options.at(2).element.matches('[disabled]')).toBe(false) wrapper.destroy() }) @@ -402,24 +387,9 @@ describe('form-select', () => { expect($options.at(0).attributes('value')).toBe('1.5') expect($options.at(1).attributes('value')).toBe('5') expect($options.at(2).attributes('value')).toBe('50.75') - expect( - $options - .at(0) - .find('[disabled]') - .exists() - ).toBe(false) - expect( - $options - .at(1) - .find('[disabled]') - .exists() - ).toBe(false) - expect( - $options - .at(2) - .find('[disabled]') - .exists() - ).toBe(true) + expect($options.at(0).element.matches('[disabled]')).toBe(false) + expect($options.at(1).element.matches('[disabled]')).toBe(false) + expect($options.at(2).element.matches('[disabled]')).toBe(true) wrapper.destroy() }) @@ -457,30 +427,10 @@ describe('form-select', () => { expect($options.at(1).attributes('value')).toBe('2') expect($options.at(2).attributes('value')).toBe('3') expect($options.at(3).attributes('value')).toBe('4') - expect( - $options - .at(0) - .find('[disabled]') - .exists() - ).toBe(false) - expect( - $options - .at(1) - .find('[disabled]') - .exists() - ).toBe(false) - expect( - $options - .at(2) - .find('[disabled]') - .exists() - ).toBe(false) - expect( - $options - .at(3) - .find('[disabled]') - .exists() - ).toBe(true) + expect($options.at(0).element.matches('[disabled]')).toBe(false) + expect($options.at(1).element.matches('[disabled]')).toBe(false) + expect($options.at(2).element.matches('[disabled]')).toBe(false) + expect($options.at(3).element.matches('[disabled]')).toBe(true) wrapper.destroy() }) @@ -514,30 +464,10 @@ describe('form-select', () => { expect($options.at(1).attributes('value')).toBe('2') expect($options.at(2).attributes('value')).toBe('3') expect($options.at(3).attributes('value')).toBe('4') - expect( - $options - .at(0) - .find('[disabled]') - .exists() - ).toBe(false) - expect( - $options - .at(1) - .find('[disabled]') - .exists() - ).toBe(false) - expect( - $options - .at(2) - .find('[disabled]') - .exists() - ).toBe(false) - expect( - $options - .at(3) - .find('[disabled]') - .exists() - ).toBe(true) + expect($options.at(0).element.matches('[disabled]')).toBe(false) + expect($options.at(1).element.matches('[disabled]')).toBe(false) + expect($options.at(2).element.matches('[disabled]')).toBe(false) + expect($options.at(3).element.matches('[disabled]')).toBe(true) wrapper.destroy() }) diff --git a/src/components/pagination/pagination.spec.js b/src/components/pagination/pagination.spec.js index 8294d2b467b..00621803ac5 100644 --- a/src/components/pagination/pagination.spec.js +++ b/src/components/pagination/pagination.spec.js @@ -410,7 +410,7 @@ describe('pagination', () => { expect( wrapper .findAll('button.page-link') - .wrappers.every(w => w.find('[aria-controls="foo"]').exists()) + .wrappers.every(w => w.element.matches('[aria-controls="foo"]')) ).toBe(true) await wrapper.setProps({ @@ -480,10 +480,10 @@ describe('pagination', () => { expect(wrapper.findAll('li').length).toBe(7) expect(wrapper.findAll('.page-item').length).toBe(7) expect( - wrapper.findAll('.page-item').wrappers.every(w => w.find('li.page-item.disabled').exists()) + wrapper.findAll('.page-item').wrappers.every(w => w.element.matches('li.page-item.disabled')) ).toBe(true) expect( - wrapper.findAll('.page-link').wrappers.every(w => w.find('span.page-link').exists()) + wrapper.findAll('.page-link').wrappers.every(w => w.element.matches('span.page-link')) ).toBe(true) expect( wrapper diff --git a/src/components/table/table-row-details.spec.js b/src/components/table/table-row-details.spec.js index a12e80c9816..3af0a20ce95 100644 --- a/src/components/table/table-row-details.spec.js +++ b/src/components/table/table-row-details.spec.js @@ -331,12 +331,7 @@ describe('table > row details', () => { .find('tr.b-table-details') .exists() ).toBe(false) - expect( - $trs - .at(1) - .find('tr.d-none') - .exists() - ).toBe(true) + expect($trs.at(1).element.matches('tr.d-none')).toBe(true) expect( $trs .at(2) From d8edafc9ec10cb1bd134334425698e37969bcf28 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Mon, 3 Oct 2022 13:16:39 +0300 Subject: [PATCH 24/34] chore(test): simplify Vue3 detection --- tests/setup.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/setup.js b/tests/setup.js index 78b128caed4..065b8504a63 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -3,8 +3,7 @@ import Vue from 'vue' import * as VTU from '@vue/test-utils' import { installCompat as installVTUCompat, fullCompatConfig } from 'vue-test-utils-compat' -const useVue3 = 'USE_VUE3' in process.env -if (useVue3) { +if (Vue.configureCompat) { Vue.configureCompat({ MODE: 2, ATTR_FALSE_VALUE: 'suppress-warning', From fe13503f7aa6d0bd6f7e1ed4f4a2e7acff421106 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Mon, 3 Oct 2022 19:15:46 +0300 Subject: [PATCH 25/34] fix(vue3): do not rely on __vueParentComponent in tooltip --- src/components/link/link.js | 7 ++-- src/components/modal/modal.spec.js | 3 +- src/components/tooltip/helpers/bv-tooltip.js | 8 ++-- .../transporter/transporter.spec.js | 3 +- src/mixins/dropdown.js | 8 ++++ src/utils/element-to-vue-instance-registry.js | 39 +++++++++++++++++++ src/utils/get-instance-from-vnode.js | 4 -- tests/utils.js | 5 +++ 8 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 src/utils/element-to-vue-instance-registry.js delete mode 100644 src/utils/get-instance-from-vnode.js diff --git a/src/components/link/link.js b/src/components/link/link.js index f3a5bdde76f..9d37cafe148 100644 --- a/src/components/link/link.js +++ b/src/components/link/link.js @@ -14,7 +14,6 @@ import { isBoolean, isEvent, isFunction, isUndefined } from '../../utils/inspect import { omit, sortKeys } from '../../utils/object' import { makeProp, makePropsConfigurable, pluckProps } from '../../utils/props' import { computeHref, computeRel, computeTag, isRouterLink } from '../../utils/router' -import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode' import { attrsMixin } from '../../mixins/attrs' import { listenOnRootMixin } from '../../mixins/listen-on-root' import { listenersMixin } from '../../mixins/listeners' @@ -165,9 +164,11 @@ export const BLink = /*#__PURE__*/ Vue.extend({ } else { // Router links do not emit instance `click` events, so we // add in an `$emit('click', event)` on its Vue instance + // + // seems not to be required for Vue3 compat build /* istanbul ignore next: difficult to test, but we know it works */ - if (isRouterLink && getInstanceFromVNode(event.currentTarget)) { - getInstanceFromVNode(event.currentTarget).$emit(EVENT_NAME_CLICK, event) + if (isRouterLink) { + event.currentTarget.__vue__?.$emit(EVENT_NAME_CLICK, event) } // Call the suppliedHandler(s), if any provided concat(suppliedHandler) diff --git a/src/components/modal/modal.spec.js b/src/components/modal/modal.spec.js index 7275a16d474..7c7b4877944 100644 --- a/src/components/modal/modal.spec.js +++ b/src/components/modal/modal.spec.js @@ -1,7 +1,6 @@ import { createWrapper, mount } from '@vue/test-utils' import { isVue3 } from '../../vue' -import { waitNT, waitRAF } from '../../../tests/utils' -import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode' +import { waitNT, waitRAF, getInstanceFromVNode } from '../../../tests/utils' import { BModal } from './modal' import { BvModalEvent } from './helpers/bv-modal-event.class' diff --git a/src/components/tooltip/helpers/bv-tooltip.js b/src/components/tooltip/helpers/bv-tooltip.js index 686ad4a1507..7033d7bc60b 100644 --- a/src/components/tooltip/helpers/bv-tooltip.js +++ b/src/components/tooltip/helpers/bv-tooltip.js @@ -24,7 +24,7 @@ import { } from '../../../constants/events' import { useParentMixin } from '../../../mixins/use-parent' import { arrayIncludes, concat, from as arrayFrom } from '../../../utils/array' -import { getInstanceFromVNode } from '../../../utils/get-instance-from-vnode' +import { getInstanceFromElement } from '../../../utils/element-to-vue-instance-registry' import { attemptFocus, closest, @@ -796,8 +796,10 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ // Dropdown shown and hidden events will need to emit // Note: Dropdown auto-ID happens in a `$nextTick()` after mount // So the ID lookup would need to be done in a `$nextTick()` - if (getInstanceFromVNode(target)) { - getInstanceFromVNode(target)[on ? '$on' : '$off'](EVENT_NAME_SHOWN, this.forceHide) + const instance = getInstanceFromElement(target) + + if (instance) { + instance[on ? '$on' : '$off'](EVENT_NAME_SHOWN, this.forceHide) } }, // --- Event handlers --- diff --git a/src/components/transporter/transporter.spec.js b/src/components/transporter/transporter.spec.js index f4bc72816a5..dca24b996e4 100644 --- a/src/components/transporter/transporter.spec.js +++ b/src/components/transporter/transporter.spec.js @@ -1,7 +1,6 @@ import { isVue3 } from '../../vue' import { mount } from '@vue/test-utils' -import { waitNT } from '../../../tests/utils' -import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode' +import { waitNT, getInstanceFromVNode } from '../../../tests/utils' import { BVTransporter } from './transporter' describe('utils/transporter component', () => { diff --git a/src/mixins/dropdown.js b/src/mixins/dropdown.js index e533e790eb2..0546e4650cc 100644 --- a/src/mixins/dropdown.js +++ b/src/mixins/dropdown.js @@ -37,6 +37,10 @@ import { clickOutMixin } from './click-out' import { focusInMixin } from './focus-in' import { idMixin, props as idProps } from './id' import { listenOnRootMixin } from './listen-on-root' +import { + registerElementToInstance, + removeElementToInstance +} from '../utils/element-to-vue-instance-registry' // --- Constants --- @@ -181,11 +185,15 @@ export const dropdownMixin = Vue.extend({ this.whileOpenListen(false) this.destroyPopper() }, + mounted() { + registerElementToInstance(this.$el, this) + }, beforeDestroy() { this.visible = false this.whileOpenListen(false) this.destroyPopper() this.clearHideTimeout() + removeElementToInstance(this.$el) }, methods: { // Event emitter diff --git a/src/utils/element-to-vue-instance-registry.js b/src/utils/element-to-vue-instance-registry.js new file mode 100644 index 00000000000..a07c7f35598 --- /dev/null +++ b/src/utils/element-to-vue-instance-registry.js @@ -0,0 +1,39 @@ +import { isVue3 } from '../vue' + +let registry = null +if (isVue3) { + registry = new WeakMap() +} + +export const registerElementToInstance = (element, instance) => { + if (!isVue3) { + return + } + + registry.set(element, instance) +} + +export const removeElementToInstance = element => { + if (!isVue3) { + return + } + + registry.delete(element) +} + +export const getInstanceFromElement = element => { + if (!isVue3) { + return element.__vue__ + } + + let currentElement = element + + while (currentElement) { + if (registry.has(currentElement)) { + return registry.get(currentElement) + } + currentElement = currentElement.parentNode + } + + return null +} diff --git a/src/utils/get-instance-from-vnode.js b/src/utils/get-instance-from-vnode.js deleted file mode 100644 index efcfb122bea..00000000000 --- a/src/utils/get-instance-from-vnode.js +++ /dev/null @@ -1,4 +0,0 @@ -import { isVue3 } from '../vue' - -export const getInstanceFromVNode = vnode => - isVue3 ? vnode.__vueParentComponent.ctx : vnode.__vue__ diff --git a/tests/utils.js b/tests/utils.js index 6165c8bcf20..2910e13d975 100644 --- a/tests/utils.js +++ b/tests/utils.js @@ -1,3 +1,5 @@ +import { isVue3 } from '../src/vue' + // --- Utils for testing --- export const wrapWithMethods = (Component, methods) => ({ @@ -14,3 +16,6 @@ export const wrapWithMethods = (Component, methods) => ({ export const waitNT = ctx => new Promise(resolve => ctx.$nextTick(resolve)) export const waitRAF = () => new Promise(resolve => requestAnimationFrame(resolve)) + +export const getInstanceFromVNode = vnode => + isVue3 ? vnode.__vueParentComponent.ctx : vnode.__vue__ From 725d31b9a9fed29e0e7d0e2685ab89d8f1b9e98a Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Tue, 4 Oct 2022 16:08:02 +0300 Subject: [PATCH 26/34] fix(compat): correctly handle undefined in slots --- src/vue.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/vue.js b/src/vue.js index 95aa447db71..ae4bff7c7c3 100644 --- a/src/vue.js +++ b/src/vue.js @@ -49,7 +49,12 @@ if (isVue3) { const originalRender = definition.render definition.__alreadyPatched = true definition.render = function(h) { - const patchedH = function(tag, dataObjOrChildren, ...rest) { + const patchedH = function(tag, dataObjOrChildren, rawSlots) { + const slots = + rawSlots === undefined + ? [] + : [Array.isArray(rawSlots) ? rawSlots.filter(Boolean) : rawSlots] + const isTag = typeof tag === 'string' && !KNOWN_COMPONENTS.includes(tag) const isSecondArgumentDataObject = dataObjOrChildren && @@ -57,7 +62,7 @@ if (isVue3) { !Array.isArray(dataObjOrChildren) if (!isSecondArgumentDataObject) { - return h(tag, dataObjOrChildren, ...rest) + return h(tag, dataObjOrChildren, ...slots) } const { attrs, props, ...restData } = dataObjOrChildren @@ -70,7 +75,7 @@ if (isVue3) { // terrible workaround to fix router-link rendering with compat vue-router normalizedData.scopedSlots = { $hasNormal: () => {} } } - return h(tag, normalizedData, ...rest) + return h(tag, normalizedData, ...slots) } if (definition.functional) { From c7699c8e086f6625c9587e3ae0838ac47335c1b1 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Thu, 6 Oct 2022 17:42:11 +0300 Subject: [PATCH 27/34] chore(vue3): avoid patching global Vue.extend * use own extend instead --- .eslintrc.js | 3 --- src/components/alert/alert.js | 6 +++--- src/components/aspect/aspect.js | 4 ++-- src/components/avatar/avatar-group.js | 6 +++--- src/components/avatar/avatar.js | 4 ++-- src/components/badge/badge.js | 4 ++-- src/components/breadcrumb/breadcrumb-item.js | 4 ++-- src/components/breadcrumb/breadcrumb-link.js | 4 ++-- src/components/breadcrumb/breadcrumb.js | 4 ++-- src/components/button-group/button-group.js | 4 ++-- src/components/button-toolbar/button-toolbar.js | 4 ++-- src/components/button/button-close.js | 4 ++-- src/components/button/button.js | 4 ++-- src/components/calendar/calendar.js | 4 ++-- src/components/card/card-body.js | 4 ++-- src/components/card/card-footer.js | 4 ++-- src/components/card/card-group.js | 4 ++-- src/components/card/card-header.js | 4 ++-- src/components/card/card-img-lazy.js | 4 ++-- src/components/card/card-img.js | 4 ++-- src/components/card/card-sub-title.js | 4 ++-- src/components/card/card-text.js | 4 ++-- src/components/card/card-title.js | 4 ++-- src/components/card/card.js | 4 ++-- src/components/carousel/carousel-slide.js | 4 ++-- src/components/carousel/carousel.js | 4 ++-- src/components/collapse/collapse.js | 4 ++-- src/components/collapse/helpers/bv-collapse.js | 4 ++-- src/components/dropdown/dropdown-divider.js | 4 ++-- src/components/dropdown/dropdown-form.js | 4 ++-- src/components/dropdown/dropdown-group.js | 4 ++-- src/components/dropdown/dropdown-header.js | 4 ++-- src/components/dropdown/dropdown-item-button.js | 4 ++-- src/components/dropdown/dropdown-item.js | 4 ++-- src/components/dropdown/dropdown-text.js | 4 ++-- src/components/dropdown/dropdown.js | 4 ++-- src/components/embed/embed.js | 4 ++-- .../bv-form-btn-label-control.js | 4 ++-- src/components/form-checkbox/form-checkbox-group.js | 4 ++-- src/components/form-checkbox/form-checkbox.js | 4 ++-- src/components/form-datepicker/form-datepicker.js | 4 ++-- src/components/form-file/form-file.js | 4 ++-- src/components/form-group/form-group.js | 2 +- src/components/form-input/form-input.js | 4 ++-- src/components/form-radio/form-radio-group.js | 4 ++-- src/components/form-radio/form-radio.js | 4 ++-- src/components/form-rating/form-rating.js | 6 +++--- .../form-select/form-select-option-group.js | 4 ++-- src/components/form-select/form-select-option.js | 4 ++-- src/components/form-select/form-select.js | 4 ++-- src/components/form-select/helpers/mixin-options.js | 4 ++-- src/components/form-spinbutton/form-spinbutton.js | 4 ++-- src/components/form-tags/form-tag.js | 4 ++-- src/components/form-tags/form-tags.js | 4 ++-- src/components/form-textarea/form-textarea.js | 4 ++-- src/components/form-timepicker/form-timepicker.js | 4 ++-- src/components/form/form-datalist.js | 4 ++-- src/components/form/form-invalid-feedback.js | 4 ++-- src/components/form/form-text.js | 4 ++-- src/components/form/form-valid-feedback.js | 4 ++-- src/components/form/form.js | 4 ++-- src/components/image/img-lazy.js | 4 ++-- src/components/image/img.js | 4 ++-- src/components/input-group/input-group-addon.js | 4 ++-- src/components/input-group/input-group-append.js | 4 ++-- src/components/input-group/input-group-prepend.js | 4 ++-- src/components/input-group/input-group-text.js | 4 ++-- src/components/input-group/input-group.js | 4 ++-- src/components/jumbotron/jumbotron.js | 4 ++-- src/components/layout/col.js | 2 +- src/components/layout/container.js | 4 ++-- src/components/layout/form-row.js | 4 ++-- src/components/layout/row.js | 2 +- src/components/link/link.js | 4 ++-- src/components/list-group/list-group-item.js | 4 ++-- src/components/list-group/list-group.js | 4 ++-- src/components/media/README.md | 12 ++++++------ src/components/media/media-aside.js | 4 ++-- src/components/media/media-body.js | 4 ++-- src/components/media/media.js | 4 ++-- src/components/modal/helpers/modal-manager.js | 4 ++-- src/components/modal/modal.js | 4 ++-- src/components/nav/nav-form.js | 4 ++-- src/components/nav/nav-item-dropdown.js | 4 ++-- src/components/nav/nav-item.js | 4 ++-- src/components/nav/nav-text.js | 4 ++-- src/components/nav/nav.js | 4 ++-- src/components/navbar/navbar-brand.js | 4 ++-- src/components/navbar/navbar-nav.js | 4 ++-- src/components/navbar/navbar-toggle.js | 4 ++-- src/components/navbar/navbar.js | 4 ++-- src/components/overlay/overlay.js | 4 ++-- src/components/pagination-nav/pagination-nav.js | 4 ++-- src/components/pagination/pagination.js | 4 ++-- .../popover/helpers/bv-popover-template.js | 4 ++-- src/components/popover/helpers/bv-popover.js | 4 ++-- src/components/popover/popover.js | 4 ++-- src/components/progress/progress-bar.js | 4 ++-- src/components/progress/progress.js | 4 ++-- src/components/sidebar/sidebar.js | 4 ++-- src/components/skeleton/skeleton-icon.js | 4 ++-- src/components/skeleton/skeleton-img.js | 4 ++-- src/components/skeleton/skeleton-table.js | 4 ++-- src/components/skeleton/skeleton-wrapper.js | 4 ++-- src/components/skeleton/skeleton.js | 4 ++-- src/components/spinner/spinner.js | 4 ++-- src/components/table/helpers/mixin-bottom-row.js | 4 ++-- src/components/table/helpers/mixin-busy.js | 4 ++-- src/components/table/helpers/mixin-caption.js | 4 ++-- src/components/table/helpers/mixin-colgroup.js | 4 ++-- src/components/table/helpers/mixin-empty.js | 4 ++-- src/components/table/helpers/mixin-filtering.js | 4 ++-- src/components/table/helpers/mixin-items.js | 4 ++-- src/components/table/helpers/mixin-pagination.js | 4 ++-- src/components/table/helpers/mixin-provider.js | 4 ++-- src/components/table/helpers/mixin-selectable.js | 4 ++-- src/components/table/helpers/mixin-sorting.js | 4 ++-- src/components/table/helpers/mixin-stacked.js | 4 ++-- src/components/table/helpers/mixin-table-renderer.js | 4 ++-- src/components/table/helpers/mixin-tbody-row.js | 4 ++-- src/components/table/helpers/mixin-tbody.js | 4 ++-- src/components/table/helpers/mixin-tfoot.js | 4 ++-- src/components/table/helpers/mixin-thead.js | 4 ++-- src/components/table/helpers/mixin-top-row.js | 4 ++-- src/components/table/table-lite.js | 4 ++-- src/components/table/table-simple.js | 4 ++-- src/components/table/table.js | 4 ++-- src/components/table/tbody.js | 4 ++-- src/components/table/td.js | 4 ++-- src/components/table/tfoot.js | 4 ++-- src/components/table/th.js | 4 ++-- src/components/table/thead.js | 4 ++-- src/components/table/tr.js | 4 ++-- src/components/tabs/tab.js | 4 ++-- src/components/tabs/tabs.js | 6 +++--- src/components/time/time.js | 4 ++-- src/components/toast/toast.js | 4 ++-- src/components/toast/toaster.js | 6 +++--- src/components/tooltip/helpers/bv-popper.js | 4 ++-- .../tooltip/helpers/bv-tooltip-template.js | 4 ++-- src/components/tooltip/helpers/bv-tooltip.js | 4 ++-- src/components/tooltip/tooltip.js | 4 ++-- src/components/transition/bv-transition.js | 4 ++-- src/components/transporter/transporter.js | 8 ++++---- src/icons/helpers/icon-base.js | 4 ++-- src/icons/helpers/make-icon.js | 4 ++-- src/icons/icon.js | 4 ++-- src/icons/iconstack.js | 4 ++-- src/mixins/attrs.js | 4 ++-- src/mixins/card.js | 4 ++-- src/mixins/click-out.js | 4 ++-- src/mixins/dropdown.js | 4 ++-- src/mixins/focus-in.js | 4 ++-- src/mixins/form-control.js | 4 ++-- src/mixins/form-custom.js | 4 ++-- src/mixins/form-options.js | 4 ++-- src/mixins/form-radio-check-group.js | 4 ++-- src/mixins/form-radio-check.js | 4 ++-- src/mixins/form-selection.js | 4 ++-- src/mixins/form-size.js | 4 ++-- src/mixins/form-state.js | 4 ++-- src/mixins/form-text.js | 4 ++-- src/mixins/form-validity.js | 4 ++-- src/mixins/has-listener.js | 4 ++-- src/mixins/id.js | 4 ++-- src/mixins/listen-on-document.js | 4 ++-- src/mixins/listen-on-root.js | 4 ++-- src/mixins/listen-on-window.js | 4 ++-- src/mixins/listeners.js | 4 ++-- src/mixins/normalize-slot.js | 4 ++-- src/mixins/pagination.js | 4 ++-- src/mixins/scoped-style.js | 4 ++-- src/mixins/use-parent.js | 4 ++-- src/utils/cache.js | 4 ++-- src/utils/model.js | 4 ++-- src/vue.js | 8 +++++--- 176 files changed, 361 insertions(+), 362 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 0ba3d0ff0bd..1a064631871 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -15,9 +15,6 @@ module.exports = { es6: true, 'jest/globals': true }, - globals: { - Vue: true - }, rules: { 'no-unused-vars': [ 'error', diff --git a/src/components/alert/alert.js b/src/components/alert/alert.js index 89875b81b2f..e618006c35d 100644 --- a/src/components/alert/alert.js +++ b/src/components/alert/alert.js @@ -1,4 +1,3 @@ -import { COMPONENT_UID_KEY, Vue } from '../../vue' import { NAME_ALERT } from '../../constants/components' import { EVENT_NAME_DISMISSED, EVENT_NAME_DISMISS_COUNT_DOWN } from '../../constants/events' import { @@ -7,13 +6,14 @@ import { PROP_TYPE_STRING } from '../../constants/props' import { SLOT_NAME_DISMISS } from '../../constants/slots' +import { normalizeSlotMixin } from '../../mixins/normalize-slot' import { requestAF } from '../../utils/dom' import { isBoolean, isNumeric } from '../../utils/inspect' import { makeModelMixin } from '../../utils/model' import { toInteger } from '../../utils/number' import { sortKeys } from '../../utils/object' import { makeProp, makePropsConfigurable } from '../../utils/props' -import { normalizeSlotMixin } from '../../mixins/normalize-slot' +import { COMPONENT_UID_KEY, extend } from '../../vue' import { BButtonClose } from '../button/button-close' import { BVTransition } from '../transition/bv-transition' @@ -68,7 +68,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BAlert = /*#__PURE__*/ Vue.extend({ +export const BAlert = /*#__PURE__*/ extend({ name: NAME_ALERT, mixins: [modelMixin, normalizeSlotMixin], props, diff --git a/src/components/aspect/aspect.js b/src/components/aspect/aspect.js index d9fce4bb124..772cf59087f 100644 --- a/src/components/aspect/aspect.js +++ b/src/components/aspect/aspect.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_ASPECT } from '../../constants/components' import { PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props' import { RX_ASPECT, RX_ASPECT_SEPARATOR } from '../../constants/regex' @@ -26,7 +26,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BAspect = /*#__PURE__*/ Vue.extend({ +export const BAspect = /*#__PURE__*/ extend({ name: NAME_ASPECT, mixins: [normalizeSlotMixin], props, diff --git a/src/components/avatar/avatar-group.js b/src/components/avatar/avatar-group.js index 89772dd5339..2109bd46f1d 100644 --- a/src/components/avatar/avatar-group.js +++ b/src/components/avatar/avatar-group.js @@ -1,4 +1,3 @@ -import { Vue } from '../../vue' import { NAME_AVATAR_GROUP } from '../../constants/components' import { PROP_TYPE_BOOLEAN, @@ -6,10 +5,11 @@ import { PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props' +import { normalizeSlotMixin } from '../../mixins/normalize-slot' import { mathMax, mathMin } from '../../utils/math' import { toFloat } from '../../utils/number' import { makeProp, makePropsConfigurable } from '../../utils/props' -import { normalizeSlotMixin } from '../../mixins/normalize-slot' +import { extend } from '../../vue' import { computeSize } from './avatar' // --- Props --- @@ -33,7 +33,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BAvatarGroup = /*#__PURE__*/ Vue.extend({ +export const BAvatarGroup = /*#__PURE__*/ extend({ name: NAME_AVATAR_GROUP, mixins: [normalizeSlotMixin], provide() { diff --git a/src/components/avatar/avatar.js b/src/components/avatar/avatar.js index ec7a966c791..cea0423f1ab 100644 --- a/src/components/avatar/avatar.js +++ b/src/components/avatar/avatar.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_AVATAR } from '../../constants/components' import { EVENT_NAME_CLICK, EVENT_NAME_IMG_ERROR } from '../../constants/events' import { @@ -67,7 +67,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BAvatar = /*#__PURE__*/ Vue.extend({ +export const BAvatar = /*#__PURE__*/ extend({ name: NAME_AVATAR, mixins: [normalizeSlotMixin], inject: { diff --git a/src/components/badge/badge.js b/src/components/badge/badge.js index bff564a3fa4..37c6ffc12e8 100644 --- a/src/components/badge/badge.js +++ b/src/components/badge/badge.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_BADGE } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { omit, sortKeys } from '../../utils/object' @@ -25,7 +25,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BBadge = /*#__PURE__*/ Vue.extend({ +export const BBadge = /*#__PURE__*/ extend({ name: NAME_BADGE, functional: true, props, diff --git a/src/components/breadcrumb/breadcrumb-item.js b/src/components/breadcrumb/breadcrumb-item.js index 02cd6e13156..073fa4f577f 100644 --- a/src/components/breadcrumb/breadcrumb-item.js +++ b/src/components/breadcrumb/breadcrumb-item.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_BREADCRUMB_ITEM } from '../../constants/components' import { makePropsConfigurable } from '../../utils/props' import { BBreadcrumbLink, props as BBreadcrumbLinkProps } from './breadcrumb-link' @@ -10,7 +10,7 @@ export const props = makePropsConfigurable(BBreadcrumbLinkProps, NAME_BREADCRUMB // --- Main component --- // @vue/component -export const BBreadcrumbItem = /*#__PURE__*/ Vue.extend({ +export const BBreadcrumbItem = /*#__PURE__*/ extend({ name: NAME_BREADCRUMB_ITEM, functional: true, props, diff --git a/src/components/breadcrumb/breadcrumb-link.js b/src/components/breadcrumb/breadcrumb-link.js index 3fdd65652b0..da7338c7e1f 100644 --- a/src/components/breadcrumb/breadcrumb-link.js +++ b/src/components/breadcrumb/breadcrumb-link.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_BREADCRUMB_LINK } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { htmlOrText } from '../../utils/html' @@ -21,7 +21,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BBreadcrumbLink = /*#__PURE__*/ Vue.extend({ +export const BBreadcrumbLink = /*#__PURE__*/ extend({ name: NAME_BREADCRUMB_LINK, functional: true, props, diff --git a/src/components/breadcrumb/breadcrumb.js b/src/components/breadcrumb/breadcrumb.js index 0bb16805185..90c3235ec04 100644 --- a/src/components/breadcrumb/breadcrumb.js +++ b/src/components/breadcrumb/breadcrumb.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_BREADCRUMB } from '../../constants/components' import { PROP_TYPE_ARRAY } from '../../constants/props' import { isArray, isObject } from '../../utils/inspect' @@ -18,7 +18,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BBreadcrumb = /*#__PURE__*/ Vue.extend({ +export const BBreadcrumb = /*#__PURE__*/ extend({ name: NAME_BREADCRUMB, functional: true, props, diff --git a/src/components/button-group/button-group.js b/src/components/button-group/button-group.js index 16850a8e305..ea4e2d453da 100644 --- a/src/components/button-group/button-group.js +++ b/src/components/button-group/button-group.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_BUTTON_GROUP } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { pick, sortKeys } from '../../utils/object' @@ -21,7 +21,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BButtonGroup = /*#__PURE__*/ Vue.extend({ +export const BButtonGroup = /*#__PURE__*/ extend({ name: NAME_BUTTON_GROUP, functional: true, props, diff --git a/src/components/button-toolbar/button-toolbar.js b/src/components/button-toolbar/button-toolbar.js index af0d6eda7ea..092ed02ad33 100644 --- a/src/components/button-toolbar/button-toolbar.js +++ b/src/components/button-toolbar/button-toolbar.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_BUTTON_TOOLBAR } from '../../constants/components' import { PROP_TYPE_BOOLEAN } from '../../constants/props' import { CODE_DOWN, CODE_LEFT, CODE_RIGHT, CODE_UP } from '../../constants/key-codes' @@ -30,7 +30,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BButtonToolbar = /*#__PURE__*/ Vue.extend({ +export const BButtonToolbar = /*#__PURE__*/ extend({ name: NAME_BUTTON_TOOLBAR, mixins: [normalizeSlotMixin], props, diff --git a/src/components/button/button-close.js b/src/components/button/button-close.js index aa3f62ca717..667747cc8eb 100644 --- a/src/components/button/button-close.js +++ b/src/components/button/button-close.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_BUTTON_CLOSE } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { SLOT_NAME_DEFAULT } from '../../constants/slots' @@ -22,7 +22,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BButtonClose = /*#__PURE__*/ Vue.extend({ +export const BButtonClose = /*#__PURE__*/ extend({ name: NAME_BUTTON_CLOSE, functional: true, props, diff --git a/src/components/button/button.js b/src/components/button/button.js index fd6122308c9..b9723636e55 100644 --- a/src/components/button/button.js +++ b/src/components/button/button.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_BUTTON } from '../../constants/components' import { CODE_ENTER, CODE_SPACE } from '../../constants/key-codes' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' @@ -115,7 +115,7 @@ const computeAttrs = (props, data) => { // --- Main component --- // @vue/component -export const BButton = /*#__PURE__*/ Vue.extend({ +export const BButton = /*#__PURE__*/ extend({ name: NAME_BUTTON, functional: true, props, diff --git a/src/components/calendar/calendar.js b/src/components/calendar/calendar.js index 83eb336e246..880316c9b91 100644 --- a/src/components/calendar/calendar.js +++ b/src/components/calendar/calendar.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_CALENDAR } from '../../constants/components' import { CALENDAR_GREGORY, @@ -180,7 +180,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCalendar = Vue.extend({ +export const BCalendar = extend({ name: NAME_CALENDAR, // Mixin order is important! mixins: [attrsMixin, idMixin, modelMixin, normalizeSlotMixin], diff --git a/src/components/card/card-body.js b/src/components/card/card-body.js index ee6e99eb04e..4d181360961 100644 --- a/src/components/card/card-body.js +++ b/src/components/card/card-body.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CARD_BODY } from '../../constants/components' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_BOOLEAN } from '../../constants/props' import { sortKeys } from '../../utils/object' @@ -29,7 +29,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCardBody = /*#__PURE__*/ Vue.extend({ +export const BCardBody = /*#__PURE__*/ extend({ name: NAME_CARD_BODY, functional: true, props, diff --git a/src/components/card/card-footer.js b/src/components/card/card-footer.js index 93be2d16227..4540162b3c8 100644 --- a/src/components/card/card-footer.js +++ b/src/components/card/card-footer.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CARD_FOOTER } from '../../constants/components' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_STRING } from '../../constants/props' import { htmlOrText } from '../../utils/html' @@ -21,7 +21,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCardFooter = /*#__PURE__*/ Vue.extend({ +export const BCardFooter = /*#__PURE__*/ extend({ name: NAME_CARD_FOOTER, functional: true, props, diff --git a/src/components/card/card-group.js b/src/components/card/card-group.js index 9cc0eeb61f7..bbf6e869935 100644 --- a/src/components/card/card-group.js +++ b/src/components/card/card-group.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CARD_GROUP } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -17,7 +17,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCardGroup = /*#__PURE__*/ Vue.extend({ +export const BCardGroup = /*#__PURE__*/ extend({ name: NAME_CARD_GROUP, functional: true, props, diff --git a/src/components/card/card-header.js b/src/components/card/card-header.js index 945dd346b37..82d39d5da0c 100644 --- a/src/components/card/card-header.js +++ b/src/components/card/card-header.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CARD_HEADER } from '../../constants/components' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_STRING } from '../../constants/props' import { htmlOrText } from '../../utils/html' @@ -21,7 +21,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCardHeader = /*#__PURE__*/ Vue.extend({ +export const BCardHeader = /*#__PURE__*/ extend({ name: NAME_CARD_HEADER, functional: true, props, diff --git a/src/components/card/card-img-lazy.js b/src/components/card/card-img-lazy.js index 178f3c8d21d..208fb412182 100644 --- a/src/components/card/card-img-lazy.js +++ b/src/components/card/card-img-lazy.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CARD_IMG_LAZY } from '../../constants/components' import { keys, omit, sortKeys } from '../../utils/object' import { makePropsConfigurable } from '../../utils/props' @@ -19,7 +19,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCardImgLazy = /*#__PURE__*/ Vue.extend({ +export const BCardImgLazy = /*#__PURE__*/ extend({ name: NAME_CARD_IMG_LAZY, functional: true, props, diff --git a/src/components/card/card-img.js b/src/components/card/card-img.js index 900a6b4e4b1..ed2a7ef03de 100644 --- a/src/components/card/card-img.js +++ b/src/components/card/card-img.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CARD_IMG } from '../../constants/components' import { PROP_TYPE_BOOLEAN } from '../../constants/props' import { pick, sortKeys } from '../../utils/object' @@ -21,7 +21,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCardImg = /*#__PURE__*/ Vue.extend({ +export const BCardImg = /*#__PURE__*/ extend({ name: NAME_CARD_IMG, functional: true, props, diff --git a/src/components/card/card-sub-title.js b/src/components/card/card-sub-title.js index 14e79e40ed9..1b133c153b5 100644 --- a/src/components/card/card-sub-title.js +++ b/src/components/card/card-sub-title.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CARD_SUB_TITLE } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -18,7 +18,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCardSubTitle = /*#__PURE__*/ Vue.extend({ +export const BCardSubTitle = /*#__PURE__*/ extend({ name: NAME_CARD_SUB_TITLE, functional: true, props, diff --git a/src/components/card/card-text.js b/src/components/card/card-text.js index a9ebdee33e6..c82f8df39e7 100644 --- a/src/components/card/card-text.js +++ b/src/components/card/card-text.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CARD_TEXT } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -15,7 +15,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCardText = /*#__PURE__*/ Vue.extend({ +export const BCardText = /*#__PURE__*/ extend({ name: NAME_CARD_TEXT, functional: true, props, diff --git a/src/components/card/card-title.js b/src/components/card/card-title.js index 768efb10657..e2d46d79ad1 100644 --- a/src/components/card/card-title.js +++ b/src/components/card/card-title.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CARD_TITLE } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -17,7 +17,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCardTitle = /*#__PURE__*/ Vue.extend({ +export const BCardTitle = /*#__PURE__*/ extend({ name: NAME_CARD_TITLE, functional: true, props, diff --git a/src/components/card/card.js b/src/components/card/card.js index b2f7caef3b6..4837af66c61 100644 --- a/src/components/card/card.js +++ b/src/components/card/card.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CARD } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { SLOT_NAME_DEFAULT, SLOT_NAME_FOOTER, SLOT_NAME_HEADER } from '../../constants/slots' @@ -40,7 +40,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCard = /*#__PURE__*/ Vue.extend({ +export const BCard = /*#__PURE__*/ extend({ name: NAME_CARD, functional: true, props, diff --git a/src/components/carousel/carousel-slide.js b/src/components/carousel/carousel-slide.js index b958fe5af40..6a7e094f554 100644 --- a/src/components/carousel/carousel-slide.js +++ b/src/components/carousel/carousel-slide.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_CAROUSEL_SLIDE } from '../../constants/components' import { HAS_TOUCH_SUPPORT } from '../../constants/env' import { PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props' @@ -43,7 +43,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCarouselSlide = /*#__PURE__*/ Vue.extend({ +export const BCarouselSlide = /*#__PURE__*/ extend({ name: NAME_CAROUSEL_SLIDE, mixins: [idMixin, normalizeSlotMixin], inject: { diff --git a/src/components/carousel/carousel.js b/src/components/carousel/carousel.js index 83970ca4d95..0340734868d 100644 --- a/src/components/carousel/carousel.js +++ b/src/components/carousel/carousel.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_CAROUSEL } from '../../constants/components' import { IS_BROWSER, HAS_POINTER_EVENT_SUPPORT, HAS_TOUCH_SUPPORT } from '../../constants/env' import { @@ -132,7 +132,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCarousel = /*#__PURE__*/ Vue.extend({ +export const BCarousel = /*#__PURE__*/ extend({ name: NAME_CAROUSEL, mixins: [idMixin, modelMixin, normalizeSlotMixin], provide() { diff --git a/src/components/collapse/collapse.js b/src/components/collapse/collapse.js index 07e55ce891a..ca8bdba7228 100644 --- a/src/components/collapse/collapse.js +++ b/src/components/collapse/collapse.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_COLLAPSE } from '../../constants/components' import { CLASS_NAME_SHOW } from '../../constants/classes' import { IS_BROWSER } from '../../constants/env' @@ -55,7 +55,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BCollapse = /*#__PURE__*/ Vue.extend({ +export const BCollapse = /*#__PURE__*/ extend({ name: NAME_COLLAPSE, mixins: [idMixin, modelMixin, normalizeSlotMixin, listenOnRootMixin], props, diff --git a/src/components/collapse/helpers/bv-collapse.js b/src/components/collapse/helpers/bv-collapse.js index 5b4b6806379..ea96340db66 100644 --- a/src/components/collapse/helpers/bv-collapse.js +++ b/src/components/collapse/helpers/bv-collapse.js @@ -5,7 +5,7 @@ // during the enter/leave transition phases only // Although it appears that Vue may be leaving the classes // in-place after the transition completes -import { Vue, mergeData } from '../../../vue' +import { extend, mergeData } from '../../../vue' import { NAME_COLLAPSE_HELPER } from '../../../constants/components' import { PROP_TYPE_BOOLEAN } from '../../../constants/props' import { getBCR, reflow, removeStyle, requestAF, setStyle } from '../../../utils/dom' @@ -72,7 +72,7 @@ export const props = { // --- Main component --- // @vue/component -export const BVCollapse = /*#__PURE__*/ Vue.extend({ +export const BVCollapse = /*#__PURE__*/ extend({ name: NAME_COLLAPSE_HELPER, functional: true, props, diff --git a/src/components/dropdown/dropdown-divider.js b/src/components/dropdown/dropdown-divider.js index a5531bd8212..e1f4d27f6fa 100644 --- a/src/components/dropdown/dropdown-divider.js +++ b/src/components/dropdown/dropdown-divider.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_DROPDOWN_DIVIDER } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -16,7 +16,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BDropdownDivider = /*#__PURE__*/ Vue.extend({ +export const BDropdownDivider = /*#__PURE__*/ extend({ name: NAME_DROPDOWN_DIVIDER, functional: true, props, diff --git a/src/components/dropdown/dropdown-form.js b/src/components/dropdown/dropdown-form.js index 4c9109f458a..faf55523d40 100644 --- a/src/components/dropdown/dropdown-form.js +++ b/src/components/dropdown/dropdown-form.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_DROPDOWN_FORM } from '../../constants/components' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_BOOLEAN } from '../../constants/props' import { omit, sortKeys } from '../../utils/object' @@ -19,7 +19,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BDropdownForm = /*#__PURE__*/ Vue.extend({ +export const BDropdownForm = /*#__PURE__*/ extend({ name: NAME_DROPDOWN_FORM, functional: true, props, diff --git a/src/components/dropdown/dropdown-group.js b/src/components/dropdown/dropdown-group.js index a30c93c6dba..1c84e6167c0 100644 --- a/src/components/dropdown/dropdown-group.js +++ b/src/components/dropdown/dropdown-group.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_DROPDOWN_GROUP } from '../../constants/components' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_STRING } from '../../constants/props' import { SLOT_NAME_DEFAULT, SLOT_NAME_HEADER } from '../../constants/slots' @@ -25,7 +25,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BDropdownGroup = /*#__PURE__*/ Vue.extend({ +export const BDropdownGroup = /*#__PURE__*/ extend({ name: NAME_DROPDOWN_GROUP, functional: true, props, diff --git a/src/components/dropdown/dropdown-header.js b/src/components/dropdown/dropdown-header.js index f1721d937ea..600ad6ae4e9 100644 --- a/src/components/dropdown/dropdown-header.js +++ b/src/components/dropdown/dropdown-header.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_DROPDOWN_HEADER } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { isTag } from '../../utils/dom' @@ -19,7 +19,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BDropdownHeader = /*#__PURE__*/ Vue.extend({ +export const BDropdownHeader = /*#__PURE__*/ extend({ name: NAME_DROPDOWN_HEADER, functional: true, props, diff --git a/src/components/dropdown/dropdown-item-button.js b/src/components/dropdown/dropdown-item-button.js index 53599fc3296..8bb700ad9e4 100644 --- a/src/components/dropdown/dropdown-item-button.js +++ b/src/components/dropdown/dropdown-item-button.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_DROPDOWN_ITEM_BUTTON } from '../../constants/components' import { EVENT_NAME_CLICK } from '../../constants/events' import { @@ -26,7 +26,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BDropdownItemButton = /*#__PURE__*/ Vue.extend({ +export const BDropdownItemButton = /*#__PURE__*/ extend({ name: NAME_DROPDOWN_ITEM_BUTTON, mixins: [attrsMixin, normalizeSlotMixin], inject: { diff --git a/src/components/dropdown/dropdown-item.js b/src/components/dropdown/dropdown-item.js index e741b0fe35e..79cb76132d5 100644 --- a/src/components/dropdown/dropdown-item.js +++ b/src/components/dropdown/dropdown-item.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_DROPDOWN_ITEM } from '../../constants/components' import { EVENT_NAME_CLICK } from '../../constants/events' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_STRING } from '../../constants/props' @@ -25,7 +25,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BDropdownItem = /*#__PURE__*/ Vue.extend({ +export const BDropdownItem = /*#__PURE__*/ extend({ name: NAME_DROPDOWN_ITEM, mixins: [attrsMixin, normalizeSlotMixin], inject: { diff --git a/src/components/dropdown/dropdown-text.js b/src/components/dropdown/dropdown-text.js index d269ac4586f..e8426d19bb4 100644 --- a/src/components/dropdown/dropdown-text.js +++ b/src/components/dropdown/dropdown-text.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_DROPDOWN_TEXT } from '../../constants/components' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_STRING } from '../../constants/props' import { omit } from '../../utils/object' @@ -18,7 +18,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BDropdownText = /*#__PURE__*/ Vue.extend({ +export const BDropdownText = /*#__PURE__*/ extend({ name: NAME_DROPDOWN_TEXT, functional: true, props, diff --git a/src/components/dropdown/dropdown.js b/src/components/dropdown/dropdown.js index bc9ce938e9c..0e7a9e0e6d0 100644 --- a/src/components/dropdown/dropdown.js +++ b/src/components/dropdown/dropdown.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_DROPDOWN } from '../../constants/components' import { PROP_TYPE_ARRAY_OBJECT_STRING, @@ -54,7 +54,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BDropdown = /*#__PURE__*/ Vue.extend({ +export const BDropdown = /*#__PURE__*/ extend({ name: NAME_DROPDOWN, mixins: [idMixin, dropdownMixin, normalizeSlotMixin], props, diff --git a/src/components/embed/embed.js b/src/components/embed/embed.js index fdb54894301..fb1d0b0e50a 100644 --- a/src/components/embed/embed.js +++ b/src/components/embed/embed.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_EMBED } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { arrayIncludes } from '../../utils/array' @@ -25,7 +25,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BEmbed = /*#__PURE__*/ Vue.extend({ +export const BEmbed = /*#__PURE__*/ extend({ name: NAME_EMBED, functional: true, props, diff --git a/src/components/form-btn-label-control/bv-form-btn-label-control.js b/src/components/form-btn-label-control/bv-form-btn-label-control.js index e830ec9035b..10645ae5ece 100644 --- a/src/components/form-btn-label-control/bv-form-btn-label-control.js +++ b/src/components/form-btn-label-control/bv-form-btn-label-control.js @@ -1,7 +1,7 @@ // // Private component used by `b-form-datepicker` and `b-form-timepicker` // -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_BUTTON_LABEL_CONTROL } from '../../constants/components' import { PROP_TYPE_ARRAY_OBJECT_STRING, @@ -54,7 +54,7 @@ export const props = sortKeys({ // --- Main component --- // @vue/component -export const BVFormBtnLabelControl = /*#__PURE__*/ Vue.extend({ +export const BVFormBtnLabelControl = /*#__PURE__*/ extend({ name: NAME_FORM_BUTTON_LABEL_CONTROL, directives: { 'b-hover': VBHover diff --git a/src/components/form-checkbox/form-checkbox-group.js b/src/components/form-checkbox/form-checkbox-group.js index 4d607797bab..50e996ba8f3 100644 --- a/src/components/form-checkbox/form-checkbox-group.js +++ b/src/components/form-checkbox/form-checkbox-group.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_CHECKBOX_GROUP } from '../../constants/components' import { PROP_TYPE_ARRAY, PROP_TYPE_BOOLEAN } from '../../constants/props' import { sortKeys } from '../../utils/object' @@ -24,7 +24,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormCheckboxGroup = /*#__PURE__*/ Vue.extend({ +export const BFormCheckboxGroup = /*#__PURE__*/ extend({ name: NAME_FORM_CHECKBOX_GROUP, // Includes render function mixins: [formRadioCheckGroupMixin], diff --git a/src/components/form-checkbox/form-checkbox.js b/src/components/form-checkbox/form-checkbox.js index ac86517fd3e..b2bfba2660d 100644 --- a/src/components/form-checkbox/form-checkbox.js +++ b/src/components/form-checkbox/form-checkbox.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_CHECKBOX } from '../../constants/components' import { EVENT_NAME_CHANGE, MODEL_EVENT_NAME_PREFIX } from '../../constants/events' import { PROP_TYPE_ANY, PROP_TYPE_BOOLEAN } from '../../constants/props' @@ -37,7 +37,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormCheckbox = /*#__PURE__*/ Vue.extend({ +export const BFormCheckbox = /*#__PURE__*/ extend({ name: NAME_FORM_CHECKBOX, mixins: [formRadioCheckMixin], inject: { diff --git a/src/components/form-datepicker/form-datepicker.js b/src/components/form-datepicker/form-datepicker.js index 942bd87bf82..197fb14c5d0 100644 --- a/src/components/form-datepicker/form-datepicker.js +++ b/src/components/form-datepicker/form-datepicker.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_DATEPICKER } from '../../constants/components' import { EVENT_NAME_CONTEXT, EVENT_NAME_HIDDEN, EVENT_NAME_SHOWN } from '../../constants/events' import { PROP_TYPE_BOOLEAN, PROP_TYPE_DATE_STRING, PROP_TYPE_STRING } from '../../constants/props' @@ -75,7 +75,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormDatepicker = /*#__PURE__*/ Vue.extend({ +export const BFormDatepicker = /*#__PURE__*/ extend({ name: NAME_FORM_DATEPICKER, mixins: [idMixin, modelMixin], props, diff --git a/src/components/form-file/form-file.js b/src/components/form-file/form-file.js index 82ed44cdb9b..0820e7f2a1c 100644 --- a/src/components/form-file/form-file.js +++ b/src/components/form-file/form-file.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_FILE } from '../../constants/components' import { HAS_PROMISE_SUPPORT } from '../../constants/env' import { EVENT_NAME_CHANGE, EVENT_OPTIONS_PASSIVE } from '../../constants/events' @@ -176,7 +176,7 @@ const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormFile = /*#__PURE__*/ Vue.extend({ +export const BFormFile = /*#__PURE__*/ extend({ name: NAME_FORM_FILE, mixins: [ attrsMixin, diff --git a/src/components/form-group/form-group.js b/src/components/form-group/form-group.js index ed16deccf76..e00f92da44b 100644 --- a/src/components/form-group/form-group.js +++ b/src/components/form-group/form-group.js @@ -85,7 +85,7 @@ export const generateProps = () => // --- Main component --- -// We do not use `Vue.extend()` here as that would evaluate the props +// We do not use `extend()` here as that would evaluate the props // immediately, which we do not want to happen // @vue/component export const BFormGroup = { diff --git a/src/components/form-input/form-input.js b/src/components/form-input/form-input.js index 853e1ae758d..10243ac83a0 100644 --- a/src/components/form-input/form-input.js +++ b/src/components/form-input/form-input.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_INPUT } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props' import { arrayIncludes } from '../../utils/array' @@ -61,7 +61,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormInput = /*#__PURE__*/ Vue.extend({ +export const BFormInput = /*#__PURE__*/ extend({ name: NAME_FORM_INPUT, // Mixin order is important! mixins: [ diff --git a/src/components/form-radio/form-radio-group.js b/src/components/form-radio/form-radio-group.js index 5fef309ae5b..d7745bbc256 100644 --- a/src/components/form-radio/form-radio-group.js +++ b/src/components/form-radio/form-radio-group.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_RADIO_GROUP } from '../../constants/components' import { makePropsConfigurable } from '../../utils/props' import { @@ -13,7 +13,7 @@ export const props = makePropsConfigurable(formRadioCheckGroupProps, NAME_FORM_R // --- Main component --- // @vue/component -export const BFormRadioGroup = /*#__PURE__*/ Vue.extend({ +export const BFormRadioGroup = /*#__PURE__*/ extend({ name: NAME_FORM_RADIO_GROUP, mixins: [formRadioCheckGroupMixin], provide() { diff --git a/src/components/form-radio/form-radio.js b/src/components/form-radio/form-radio.js index c4ac840668c..f6565751c85 100644 --- a/src/components/form-radio/form-radio.js +++ b/src/components/form-radio/form-radio.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_RADIO } from '../../constants/components' import { looseEqual } from '../../utils/loose-equal' import { makePropsConfigurable } from '../../utils/props' @@ -15,7 +15,7 @@ export const props = makePropsConfigurable(formRadioCheckProps, NAME_FORM_RADIO) // --- Main component --- // @vue/component -export const BFormRadio = /*#__PURE__*/ Vue.extend({ +export const BFormRadio = /*#__PURE__*/ extend({ name: NAME_FORM_RADIO, mixins: [formRadioCheckMixin], inject: { diff --git a/src/components/form-rating/form-rating.js b/src/components/form-rating/form-rating.js index 97953c45455..964ca44ed97 100644 --- a/src/components/form-rating/form-rating.js +++ b/src/components/form-rating/form-rating.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_RATING, NAME_FORM_RATING_STAR } from '../../constants/components' import { EVENT_NAME_CHANGE, EVENT_NAME_SELECTED } from '../../constants/events' import { @@ -58,7 +58,7 @@ const clampValue = (value, min, max) => mathMax(mathMin(value, max), min) // --- Helper components --- // @vue/component -const BVFormRatingStar = Vue.extend({ +const BVFormRatingStar = extend({ name: NAME_FORM_RATING_STAR, mixins: [normalizeSlotMixin], props: { @@ -140,7 +140,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormRating = /*#__PURE__*/ Vue.extend({ +export const BFormRating = /*#__PURE__*/ extend({ name: NAME_FORM_RATING, components: { BIconStar, BIconStarHalf, BIconStarFill, BIconX }, mixins: [idMixin, modelMixin, formSizeMixin], diff --git a/src/components/form-select/form-select-option-group.js b/src/components/form-select/form-select-option-group.js index 546de2749ed..eb18bc7c60e 100644 --- a/src/components/form-select/form-select-option-group.js +++ b/src/components/form-select/form-select-option-group.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_SELECT_OPTION_GROUP } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { SLOT_NAME_FIRST } from '../../constants/slots' @@ -22,7 +22,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormSelectOptionGroup = /*#__PURE__*/ Vue.extend({ +export const BFormSelectOptionGroup = /*#__PURE__*/ extend({ name: NAME_FORM_SELECT_OPTION_GROUP, mixins: [normalizeSlotMixin, formOptionsMixin], props, diff --git a/src/components/form-select/form-select-option.js b/src/components/form-select/form-select-option.js index eece9980add..9a012b65bd3 100644 --- a/src/components/form-select/form-select-option.js +++ b/src/components/form-select/form-select-option.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_FORM_SELECT_OPTION } from '../../constants/components' import { PROP_TYPE_ANY, PROP_TYPE_BOOLEAN } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -16,7 +16,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormSelectOption = /*#__PURE__*/ Vue.extend({ +export const BFormSelectOption = /*#__PURE__*/ extend({ name: NAME_FORM_SELECT_OPTION, functional: true, props, diff --git a/src/components/form-select/form-select.js b/src/components/form-select/form-select.js index 63b4cde5665..00dbb071adf 100644 --- a/src/components/form-select/form-select.js +++ b/src/components/form-select/form-select.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_SELECT } from '../../constants/components' import { EVENT_NAME_CHANGE } from '../../constants/events' import { @@ -51,7 +51,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormSelect = /*#__PURE__*/ Vue.extend({ +export const BFormSelect = /*#__PURE__*/ extend({ name: NAME_FORM_SELECT, mixins: [ idMixin, diff --git a/src/components/form-select/helpers/mixin-options.js b/src/components/form-select/helpers/mixin-options.js index b623c161dee..4d5a7d26fcc 100644 --- a/src/components/form-select/helpers/mixin-options.js +++ b/src/components/form-select/helpers/mixin-options.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { PROP_TYPE_STRING } from '../../../constants/props' import { get } from '../../../utils/get' import { isNull, isPlainObject, isUndefined } from '../../../utils/inspect' @@ -20,7 +20,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const optionsMixin = Vue.extend({ +export const optionsMixin = extend({ mixins: [formOptionsMixin], props, methods: { diff --git a/src/components/form-spinbutton/form-spinbutton.js b/src/components/form-spinbutton/form-spinbutton.js index aa8617e7f23..25c148b01f9 100644 --- a/src/components/form-spinbutton/form-spinbutton.js +++ b/src/components/form-spinbutton/form-spinbutton.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_SPINBUTTON } from '../../constants/components' import { EVENT_NAME_CHANGE } from '../../constants/events' import { @@ -100,7 +100,7 @@ export const props = makePropsConfigurable( // --- Main Component --- // @vue/component -export const BFormSpinbutton = /*#__PURE__*/ Vue.extend({ +export const BFormSpinbutton = /*#__PURE__*/ extend({ name: NAME_FORM_SPINBUTTON, // Mixin order is important! mixins: [attrsMixin, idMixin, modelMixin, formSizeMixin, formStateMixin, normalizeSlotMixin], diff --git a/src/components/form-tags/form-tag.js b/src/components/form-tags/form-tag.js index f1a8d69d437..37f1c8686a7 100644 --- a/src/components/form-tags/form-tag.js +++ b/src/components/form-tags/form-tag.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_TAG } from '../../constants/components' import { EVENT_NAME_REMOVE } from '../../constants/events' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' @@ -29,7 +29,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormTag = /*#__PURE__*/ Vue.extend({ +export const BFormTag = /*#__PURE__*/ extend({ name: NAME_FORM_TAG, mixins: [idMixin, normalizeSlotMixin], props, diff --git a/src/components/form-tags/form-tags.js b/src/components/form-tags/form-tags.js index ad15e7067d7..d1028122b48 100644 --- a/src/components/form-tags/form-tags.js +++ b/src/components/form-tags/form-tags.js @@ -1,6 +1,6 @@ // Tagged input form control // Based loosely on https://adamwathan.me/renderless-components-in-vuejs/ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_TAGS } from '../../constants/components' import { EVENT_NAME_BLUR, @@ -141,7 +141,7 @@ const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormTags = /*#__PURE__*/ Vue.extend({ +export const BFormTags = /*#__PURE__*/ extend({ name: NAME_FORM_TAGS, mixins: [ listenersMixin, diff --git a/src/components/form-textarea/form-textarea.js b/src/components/form-textarea/form-textarea.js index 54699051fa9..fa64a4ef69a 100644 --- a/src/components/form-textarea/form-textarea.js +++ b/src/components/form-textarea/form-textarea.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_TEXTAREA } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props' import { getCS, getStyle, isVisible, requestAF, setStyle } from '../../utils/dom' @@ -43,7 +43,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormTextarea = /*#__PURE__*/ Vue.extend({ +export const BFormTextarea = /*#__PURE__*/ extend({ name: NAME_FORM_TEXTAREA, directives: { 'b-visible': VBVisible diff --git a/src/components/form-timepicker/form-timepicker.js b/src/components/form-timepicker/form-timepicker.js index d8f6ed6963e..830110fa067 100644 --- a/src/components/form-timepicker/form-timepicker.js +++ b/src/components/form-timepicker/form-timepicker.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_TIMEPICKER } from '../../constants/components' import { EVENT_NAME_CONTEXT, EVENT_NAME_SHOWN, EVENT_NAME_HIDDEN } from '../../constants/events' import { PROP_TYPE_BOOLEAN, PROP_TYPE_DATE_STRING, PROP_TYPE_STRING } from '../../constants/props' @@ -64,7 +64,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormTimepicker = /*#__PURE__*/ Vue.extend({ +export const BFormTimepicker = /*#__PURE__*/ extend({ name: NAME_FORM_TIMEPICKER, mixins: [idMixin, modelMixin], props, diff --git a/src/components/form/form-datalist.js b/src/components/form/form-datalist.js index d371c825d39..7793b82b120 100644 --- a/src/components/form/form-datalist.js +++ b/src/components/form/form-datalist.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_FORM_DATALIST } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { htmlOrText } from '../../utils/html' @@ -20,7 +20,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormDatalist = /*#__PURE__*/ Vue.extend({ +export const BFormDatalist = /*#__PURE__*/ extend({ name: NAME_FORM_DATALIST, mixins: [formOptionsMixin, normalizeSlotMixin], props, diff --git a/src/components/form/form-invalid-feedback.js b/src/components/form/form-invalid-feedback.js index 8292d9154db..0cbefb74330 100644 --- a/src/components/form/form-invalid-feedback.js +++ b/src/components/form/form-invalid-feedback.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_FORM_INVALID_FEEDBACK } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -22,7 +22,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormInvalidFeedback = /*#__PURE__*/ Vue.extend({ +export const BFormInvalidFeedback = /*#__PURE__*/ extend({ name: NAME_FORM_INVALID_FEEDBACK, functional: true, props, diff --git a/src/components/form/form-text.js b/src/components/form/form-text.js index 0d92d8e58e6..82505040330 100644 --- a/src/components/form/form-text.js +++ b/src/components/form/form-text.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_FORM_TEXT } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -18,7 +18,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormText = /*#__PURE__*/ Vue.extend({ +export const BFormText = /*#__PURE__*/ extend({ name: NAME_FORM_TEXT, functional: true, props, diff --git a/src/components/form/form-valid-feedback.js b/src/components/form/form-valid-feedback.js index 40453eee9f1..c20316ebc6a 100644 --- a/src/components/form/form-valid-feedback.js +++ b/src/components/form/form-valid-feedback.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_FORM_VALID_FEEDBACK } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -22,7 +22,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormValidFeedback = /*#__PURE__*/ Vue.extend({ +export const BFormValidFeedback = /*#__PURE__*/ extend({ name: NAME_FORM_VALID_FEEDBACK, functional: true, props, diff --git a/src/components/form/form.js b/src/components/form/form.js index bc8daa42fdd..4c80769ac8d 100644 --- a/src/components/form/form.js +++ b/src/components/form/form.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_FORM } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -18,7 +18,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BForm = /*#__PURE__*/ Vue.extend({ +export const BForm = /*#__PURE__*/ extend({ name: NAME_FORM, functional: true, props, diff --git a/src/components/image/img-lazy.js b/src/components/image/img-lazy.js index bf1c3b505b8..e705906ae27 100644 --- a/src/components/image/img-lazy.js +++ b/src/components/image/img-lazy.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_IMG_LAZY } from '../../constants/components' import { HAS_INTERACTION_OBSERVER_SUPPORT } from '../../constants/env' import { MODEL_EVENT_NAME_PREFIX } from '../../constants/events' @@ -39,7 +39,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BImgLazy = /*#__PURE__*/ Vue.extend({ +export const BImgLazy = /*#__PURE__*/ extend({ name: NAME_IMG_LAZY, directives: { 'b-visible': VBVisible diff --git a/src/components/image/img.js b/src/components/image/img.js index a55fea50bfc..6c585b02ea2 100644 --- a/src/components/image/img.js +++ b/src/components/image/img.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_IMG } from '../../constants/components' import { PROP_TYPE_ARRAY_STRING, @@ -72,7 +72,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BImg = /*#__PURE__*/ Vue.extend({ +export const BImg = /*#__PURE__*/ extend({ name: NAME_IMG, functional: true, props, diff --git a/src/components/input-group/input-group-addon.js b/src/components/input-group/input-group-addon.js index 4b5a8ca8af9..092e3348b80 100644 --- a/src/components/input-group/input-group-addon.js +++ b/src/components/input-group/input-group-addon.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_INPUT_GROUP_ADDON } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -19,7 +19,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BInputGroupAddon = /*#__PURE__*/ Vue.extend({ +export const BInputGroupAddon = /*#__PURE__*/ extend({ name: NAME_INPUT_GROUP_ADDON, functional: true, props, diff --git a/src/components/input-group/input-group-append.js b/src/components/input-group/input-group-append.js index fa5a9b22eb7..cb02f970925 100644 --- a/src/components/input-group/input-group-append.js +++ b/src/components/input-group/input-group-append.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_INPUT_GROUP_APPEND } from '../../constants/components' import { omit } from '../../utils/object' import { makePropsConfigurable } from '../../utils/props' @@ -14,7 +14,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BInputGroupAppend = /*#__PURE__*/ Vue.extend({ +export const BInputGroupAppend = /*#__PURE__*/ extend({ name: NAME_INPUT_GROUP_APPEND, functional: true, props, diff --git a/src/components/input-group/input-group-prepend.js b/src/components/input-group/input-group-prepend.js index 25f3f8294f3..ce63d01c7d4 100644 --- a/src/components/input-group/input-group-prepend.js +++ b/src/components/input-group/input-group-prepend.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_INPUT_GROUP_PREPEND } from '../../constants/components' import { omit } from '../../utils/object' import { makePropsConfigurable } from '../../utils/props' @@ -14,7 +14,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BInputGroupPrepend = /*#__PURE__*/ Vue.extend({ +export const BInputGroupPrepend = /*#__PURE__*/ extend({ name: NAME_INPUT_GROUP_PREPEND, functional: true, props, diff --git a/src/components/input-group/input-group-text.js b/src/components/input-group/input-group-text.js index cfe4ac4d3fa..69f35271cb8 100644 --- a/src/components/input-group/input-group-text.js +++ b/src/components/input-group/input-group-text.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_INPUT_GROUP_TEXT } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -15,7 +15,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BInputGroupText = /*#__PURE__*/ Vue.extend({ +export const BInputGroupText = /*#__PURE__*/ extend({ name: NAME_INPUT_GROUP_TEXT, functional: true, props, diff --git a/src/components/input-group/input-group.js b/src/components/input-group/input-group.js index ce2e8041ad6..c51855ff433 100644 --- a/src/components/input-group/input-group.js +++ b/src/components/input-group/input-group.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_INPUT_GROUP } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { SLOT_NAME_APPEND, SLOT_NAME_DEFAULT, SLOT_NAME_PREPEND } from '../../constants/slots' @@ -27,7 +27,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BInputGroup = /*#__PURE__*/ Vue.extend({ +export const BInputGroup = /*#__PURE__*/ extend({ name: NAME_INPUT_GROUP, functional: true, props, diff --git a/src/components/jumbotron/jumbotron.js b/src/components/jumbotron/jumbotron.js index cc5966ce371..d7715ecae15 100644 --- a/src/components/jumbotron/jumbotron.js +++ b/src/components/jumbotron/jumbotron.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_JUMBOTRON } from '../../constants/components' import { PROP_TYPE_BOOLEAN, @@ -36,7 +36,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BJumbotron = /*#__PURE__*/ Vue.extend({ +export const BJumbotron = /*#__PURE__*/ extend({ name: NAME_JUMBOTRON, functional: true, props, diff --git a/src/components/layout/col.js b/src/components/layout/col.js index df773d92a5a..2c48e655a65 100644 --- a/src/components/layout/col.js +++ b/src/components/layout/col.js @@ -106,7 +106,7 @@ export const generateProps = () => { // --- Main component --- -// We do not use Vue.extend here as that would evaluate the props +// We do not use extend here as that would evaluate the props // immediately, which we do not want to happen // @vue/component export const BCol = { diff --git a/src/components/layout/container.js b/src/components/layout/container.js index ec2c48781de..a9c78046abc 100644 --- a/src/components/layout/container.js +++ b/src/components/layout/container.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_CONTAINER } from '../../constants/components' import { PROP_TYPE_BOOLEAN_STRING, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -17,7 +17,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BContainer = /*#__PURE__*/ Vue.extend({ +export const BContainer = /*#__PURE__*/ extend({ name: NAME_CONTAINER, functional: true, props, diff --git a/src/components/layout/form-row.js b/src/components/layout/form-row.js index 70d9af5cfc4..89a4a3533b1 100644 --- a/src/components/layout/form-row.js +++ b/src/components/layout/form-row.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_FORM_ROW } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -15,7 +15,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BFormRow = /*#__PURE__*/ Vue.extend({ +export const BFormRow = /*#__PURE__*/ extend({ name: NAME_FORM_ROW, functional: true, props, diff --git a/src/components/layout/row.js b/src/components/layout/row.js index 4a1d6eb969f..8e9743c2668 100644 --- a/src/components/layout/row.js +++ b/src/components/layout/row.js @@ -65,7 +65,7 @@ export const generateProps = () => { // --- Main component --- -// We do not use `Vue.extend()` here as that would evaluate the props +// We do not use `extend()` here as that would evaluate the props // immediately, which we do not want to happen // @vue/component export const BRow = { diff --git a/src/components/link/link.js b/src/components/link/link.js index 9d37cafe148..b0a7d38c737 100644 --- a/src/components/link/link.js +++ b/src/components/link/link.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_LINK } from '../../constants/components' import { EVENT_NAME_CLICK } from '../../constants/events' import { @@ -74,7 +74,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BLink = /*#__PURE__*/ Vue.extend({ +export const BLink = /*#__PURE__*/ extend({ name: NAME_LINK, // Mixin order is important! mixins: [attrsMixin, listenersMixin, listenOnRootMixin, normalizeSlotMixin], diff --git a/src/components/list-group/list-group-item.js b/src/components/list-group/list-group-item.js index bf591af27b7..62fe63758c8 100644 --- a/src/components/list-group/list-group-item.js +++ b/src/components/list-group/list-group-item.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_LIST_GROUP_ITEM } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { arrayIncludes } from '../../utils/array' @@ -32,7 +32,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BListGroupItem = /*#__PURE__*/ Vue.extend({ +export const BListGroupItem = /*#__PURE__*/ extend({ name: NAME_LIST_GROUP_ITEM, functional: true, props, diff --git a/src/components/list-group/list-group.js b/src/components/list-group/list-group.js index 93ceda15779..986332a288d 100644 --- a/src/components/list-group/list-group.js +++ b/src/components/list-group/list-group.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_LIST_GROUP } from '../../constants/components' import { PROP_TYPE_BOOLEAN, @@ -22,7 +22,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BListGroup = /*#__PURE__*/ Vue.extend({ +export const BListGroup = /*#__PURE__*/ extend({ name: NAME_LIST_GROUP, functional: true, props, diff --git a/src/components/media/README.md b/src/components/media/README.md index 5cacc78ff3b..0b32c4135c9 100644 --- a/src/components/media/README.md +++ b/src/components/media/README.md @@ -124,15 +124,15 @@ You can easily nest media objects by including another `` inside parent ## Vertical align -Aside can be vertically aligned using `vertical-align` prop, set to `top`, `center` or `end`. -The default alignment is `top`. +Aside can be vertically aligned using `vertical-align` prop, set to `top`, `center` or `end`. The +default alignment is `top`. ## Media list -Because the media object has few structural requirements, you can use this component as -a list item in HTML lists. On your `
    ` or `
      `, add the class `list-unstyled` to remove any browser -default list styles, and then use the `` component with `tag` prop set to `li`. As always, -use spacing utilities wherever needed to fine tune. +Because the media object has few structural requirements, you can use this component as a list item +in HTML lists. On your `
        ` or `
          `, add the class `list-unstyled` to remove any browser default +list styles, and then use the `` component with `tag` prop set to `li`. As always, use +spacing utilities wherever needed to fine tune. ```html
          diff --git a/src/components/media/media-aside.js b/src/components/media/media-aside.js index d14c39f6760..e9bf5c4dd58 100644 --- a/src/components/media/media-aside.js +++ b/src/components/media/media-aside.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_MEDIA_ASIDE } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -17,7 +17,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BMediaAside = /*#__PURE__*/ Vue.extend({ +export const BMediaAside = /*#__PURE__*/ extend({ name: NAME_MEDIA_ASIDE, functional: true, props, diff --git a/src/components/media/media-body.js b/src/components/media/media-body.js index 5695b29884f..95818403a41 100644 --- a/src/components/media/media-body.js +++ b/src/components/media/media-body.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_MEDIA_BODY } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -15,7 +15,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BMediaBody = /*#__PURE__*/ Vue.extend({ +export const BMediaBody = /*#__PURE__*/ extend({ name: NAME_MEDIA_BODY, functional: true, props, diff --git a/src/components/media/media.js b/src/components/media/media.js index 9ab4b0515d1..da2419acf79 100644 --- a/src/components/media/media.js +++ b/src/components/media/media.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_MEDIA } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { SLOT_NAME_ASIDE, SLOT_NAME_DEFAULT } from '../../constants/slots' @@ -22,7 +22,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BMedia = /*#__PURE__*/ Vue.extend({ +export const BMedia = /*#__PURE__*/ extend({ name: NAME_MEDIA, functional: true, props, diff --git a/src/components/modal/helpers/modal-manager.js b/src/components/modal/helpers/modal-manager.js index af4e23a9fa0..edb4e34780d 100644 --- a/src/components/modal/helpers/modal-manager.js +++ b/src/components/modal/helpers/modal-manager.js @@ -3,7 +3,7 @@ * Handles controlling modal stacking zIndexes and body adjustments/classes */ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { IS_BROWSER } from '../../../constants/env' import { addClass, @@ -35,7 +35,7 @@ const SELECTOR_NAVBAR_TOGGLER = '.navbar-toggler' // --- Main component --- // @vue/component -const ModalManager = /*#__PURE__*/ Vue.extend({ +const ModalManager = /*#__PURE__*/ extend({ data() { return { modals: [], diff --git a/src/components/modal/modal.js b/src/components/modal/modal.js index a66eabf0bda..071c9933c78 100644 --- a/src/components/modal/modal.js +++ b/src/components/modal/modal.js @@ -1,4 +1,4 @@ -import { COMPONENT_UID_KEY, Vue } from '../../vue' +import { COMPONENT_UID_KEY, extend } from '../../vue' import { NAME_MODAL } from '../../constants/components' import { IS_BROWSER } from '../../constants/env' import { @@ -176,7 +176,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BModal = /*#__PURE__*/ Vue.extend({ +export const BModal = /*#__PURE__*/ extend({ name: NAME_MODAL, mixins: [ attrsMixin, diff --git a/src/components/nav/nav-form.js b/src/components/nav/nav-form.js index 2a95547019f..bb236016358 100644 --- a/src/components/nav/nav-form.js +++ b/src/components/nav/nav-form.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_NAV_FORM } from '../../constants/components' import { PROP_TYPE_ARRAY_OBJECT_STRING } from '../../constants/props' import { omit, sortKeys } from '../../utils/object' @@ -20,7 +20,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BNavForm = /*#__PURE__*/ Vue.extend({ +export const BNavForm = /*#__PURE__*/ extend({ name: NAME_NAV_FORM, functional: true, props, diff --git a/src/components/nav/nav-item-dropdown.js b/src/components/nav/nav-item-dropdown.js index 2de02dadc54..0b8cee92287 100644 --- a/src/components/nav/nav-item-dropdown.js +++ b/src/components/nav/nav-item-dropdown.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_NAV_ITEM_DROPDOWN } from '../../constants/components' import { SLOT_NAME_BUTTON_CONTENT, SLOT_NAME_DEFAULT, SLOT_NAME_TEXT } from '../../constants/slots' import { htmlOrText } from '../../utils/html' @@ -32,7 +32,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BNavItemDropdown = /*#__PURE__*/ Vue.extend({ +export const BNavItemDropdown = /*#__PURE__*/ extend({ name: NAME_NAV_ITEM_DROPDOWN, mixins: [idMixin, dropdownMixin, normalizeSlotMixin], props, diff --git a/src/components/nav/nav-item.js b/src/components/nav/nav-item.js index c634f9c556b..f84ecbf941f 100644 --- a/src/components/nav/nav-item.js +++ b/src/components/nav/nav-item.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_NAV_ITEM } from '../../constants/components' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_OBJECT } from '../../constants/props' import { omit, sortKeys } from '../../utils/object' @@ -21,7 +21,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BNavItem = /*#__PURE__*/ Vue.extend({ +export const BNavItem = /*#__PURE__*/ extend({ name: NAME_NAV_ITEM, functional: true, props, diff --git a/src/components/nav/nav-text.js b/src/components/nav/nav-text.js index 98ad5f29f6a..e392c27dc5d 100644 --- a/src/components/nav/nav-text.js +++ b/src/components/nav/nav-text.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_NAV_TEXT } from '../../constants/components' // --- Props --- @@ -8,7 +8,7 @@ export const props = {} // --- Main component --- // @vue/component -export const BNavText = /*#__PURE__*/ Vue.extend({ +export const BNavText = /*#__PURE__*/ extend({ name: NAME_NAV_TEXT, functional: true, props, diff --git a/src/components/nav/nav.js b/src/components/nav/nav.js index 195ac940a5f..173924536dc 100644 --- a/src/components/nav/nav.js +++ b/src/components/nav/nav.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_NAV } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -31,7 +31,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BNav = /*#__PURE__*/ Vue.extend({ +export const BNav = /*#__PURE__*/ extend({ name: NAME_NAV, functional: true, props, diff --git a/src/components/navbar/navbar-brand.js b/src/components/navbar/navbar-brand.js index 65f0387c4e5..39f005d297f 100644 --- a/src/components/navbar/navbar-brand.js +++ b/src/components/navbar/navbar-brand.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_NAVBAR_BRAND } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { omit, sortKeys } from '../../utils/object' @@ -22,7 +22,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BNavbarBrand = /*#__PURE__*/ Vue.extend({ +export const BNavbarBrand = /*#__PURE__*/ extend({ name: NAME_NAVBAR_BRAND, functional: true, props, diff --git a/src/components/navbar/navbar-nav.js b/src/components/navbar/navbar-nav.js index 19684ee8a53..3b049267f10 100644 --- a/src/components/navbar/navbar-nav.js +++ b/src/components/navbar/navbar-nav.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_NAVBAR_NAV } from '../../constants/components' import { pick } from '../../utils/object' import { makePropsConfigurable } from '../../utils/props' @@ -21,7 +21,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BNavbarNav = /*#__PURE__*/ Vue.extend({ +export const BNavbarNav = /*#__PURE__*/ extend({ name: NAME_NAVBAR_NAV, functional: true, props, diff --git a/src/components/navbar/navbar-toggle.js b/src/components/navbar/navbar-toggle.js index 044664569f7..8b0363a5e21 100644 --- a/src/components/navbar/navbar-toggle.js +++ b/src/components/navbar/navbar-toggle.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_COLLAPSE, NAME_NAVBAR_TOGGLE } from '../../constants/components' import { EVENT_NAME_CLICK } from '../../constants/events' import { PROP_TYPE_ARRAY_STRING, PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' @@ -30,7 +30,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BNavbarToggle = /*#__PURE__*/ Vue.extend({ +export const BNavbarToggle = /*#__PURE__*/ extend({ name: NAME_NAVBAR_TOGGLE, directives: { VBToggle }, mixins: [listenOnRootMixin, normalizeSlotMixin], diff --git a/src/components/navbar/navbar.js b/src/components/navbar/navbar.js index 0c6d7e1afc3..c4add85e11b 100644 --- a/src/components/navbar/navbar.js +++ b/src/components/navbar/navbar.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_NAVBAR } from '../../constants/components' import { PROP_TYPE_BOOLEAN, @@ -29,7 +29,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BNavbar = /*#__PURE__*/ Vue.extend({ +export const BNavbar = /*#__PURE__*/ extend({ name: NAME_NAVBAR, mixins: [normalizeSlotMixin], provide() { diff --git a/src/components/overlay/overlay.js b/src/components/overlay/overlay.js index 99e56568450..016c1c77e7d 100644 --- a/src/components/overlay/overlay.js +++ b/src/components/overlay/overlay.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_OVERLAY } from '../../constants/components' import { EVENT_NAME_CLICK, EVENT_NAME_HIDDEN, EVENT_NAME_SHOWN } from '../../constants/events' import { @@ -52,7 +52,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BOverlay = /*#__PURE__*/ Vue.extend({ +export const BOverlay = /*#__PURE__*/ extend({ name: NAME_OVERLAY, mixins: [normalizeSlotMixin], props, diff --git a/src/components/pagination-nav/pagination-nav.js b/src/components/pagination-nav/pagination-nav.js index 5ce0f129c4e..ae4031f886c 100644 --- a/src/components/pagination-nav/pagination-nav.js +++ b/src/components/pagination-nav/pagination-nav.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_PAGINATION_NAV } from '../../constants/components' import { IS_BROWSER } from '../../constants/env' import { EVENT_NAME_CHANGE, EVENT_NAME_PAGE_CLICK } from '../../constants/events' @@ -64,7 +64,7 @@ const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BPaginationNav = /*#__PURE__*/ Vue.extend({ +export const BPaginationNav = /*#__PURE__*/ extend({ name: NAME_PAGINATION_NAV, // The render function is brought in via the pagination mixin mixins: [paginationMixin], diff --git a/src/components/pagination/pagination.js b/src/components/pagination/pagination.js index 9bd58c66bd4..d43b19e30b1 100644 --- a/src/components/pagination/pagination.js +++ b/src/components/pagination/pagination.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_PAGINATION } from '../../constants/components' import { EVENT_NAME_CHANGE, EVENT_NAME_PAGE_CLICK } from '../../constants/events' import { PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props' @@ -39,7 +39,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BPagination = /*#__PURE__*/ Vue.extend({ +export const BPagination = /*#__PURE__*/ extend({ name: NAME_PAGINATION, // The render function is brought in via the `paginationMixin` mixins: [paginationMixin], diff --git a/src/components/popover/helpers/bv-popover-template.js b/src/components/popover/helpers/bv-popover-template.js index 4eca3b1b3ef..7b497ea005b 100644 --- a/src/components/popover/helpers/bv-popover-template.js +++ b/src/components/popover/helpers/bv-popover-template.js @@ -1,10 +1,10 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { NAME_POPOVER_TEMPLATE } from '../../../constants/components' import { isFunction, isUndefinedOrNull } from '../../../utils/inspect' import { BVTooltipTemplate } from '../../tooltip/helpers/bv-tooltip-template' // @vue/component -export const BVPopoverTemplate = /*#__PURE__*/ Vue.extend({ +export const BVPopoverTemplate = /*#__PURE__*/ extend({ name: NAME_POPOVER_TEMPLATE, extends: BVTooltipTemplate, computed: { diff --git a/src/components/popover/helpers/bv-popover.js b/src/components/popover/helpers/bv-popover.js index 4f523ed59bd..b146e3ea1e8 100644 --- a/src/components/popover/helpers/bv-popover.js +++ b/src/components/popover/helpers/bv-popover.js @@ -4,13 +4,13 @@ // Handles trigger events, etc. // Instantiates template on demand -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { NAME_POPOVER_HELPER } from '../../../constants/components' import { BVTooltip } from '../../tooltip/helpers/bv-tooltip' import { BVPopoverTemplate } from './bv-popover-template' // @vue/component -export const BVPopover = /*#__PURE__*/ Vue.extend({ +export const BVPopover = /*#__PURE__*/ extend({ name: NAME_POPOVER_HELPER, extends: BVTooltip, computed: { diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index f70123e3ab5..e68f75cf773 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_POPOVER } from '../../constants/components' import { EVENT_NAME_CLICK } from '../../constants/events' import { PROP_TYPE_ARRAY_STRING, PROP_TYPE_STRING } from '../../constants/props' @@ -23,7 +23,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BPopover = /*#__PURE__*/ Vue.extend({ +export const BPopover = /*#__PURE__*/ extend({ name: NAME_POPOVER, extends: BTooltip, inheritAttrs: false, diff --git a/src/components/progress/progress-bar.js b/src/components/progress/progress-bar.js index ae8ced02ec2..02af3d0d4e3 100644 --- a/src/components/progress/progress-bar.js +++ b/src/components/progress/progress-bar.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_PROGRESS_BAR } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props' import { htmlOrText } from '../../utils/html' @@ -30,7 +30,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BProgressBar = /*#__PURE__*/ Vue.extend({ +export const BProgressBar = /*#__PURE__*/ extend({ name: NAME_PROGRESS_BAR, mixins: [normalizeSlotMixin], inject: { diff --git a/src/components/progress/progress.js b/src/components/progress/progress.js index 341b3d6669f..d0c50723c96 100644 --- a/src/components/progress/progress.js +++ b/src/components/progress/progress.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_PROGRESS } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props' import { omit, sortKeys } from '../../utils/object' @@ -27,7 +27,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BProgress = /*#__PURE__*/ Vue.extend({ +export const BProgress = /*#__PURE__*/ extend({ name: NAME_PROGRESS, mixins: [normalizeSlotMixin], provide() { diff --git a/src/components/sidebar/sidebar.js b/src/components/sidebar/sidebar.js index 5d676ebc22f..62af71634dd 100644 --- a/src/components/sidebar/sidebar.js +++ b/src/components/sidebar/sidebar.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_COLLAPSE, NAME_SIDEBAR } from '../../constants/components' import { IS_BROWSER } from '../../constants/env' import { EVENT_NAME_CHANGE, EVENT_NAME_HIDDEN, EVENT_NAME_SHOWN } from '../../constants/events' @@ -201,7 +201,7 @@ const renderBackdrop = (h, ctx) => { // --- Main component --- // @vue/component -export const BSidebar = /*#__PURE__*/ Vue.extend({ +export const BSidebar = /*#__PURE__*/ extend({ name: NAME_SIDEBAR, mixins: [attrsMixin, idMixin, modelMixin, listenOnRootMixin, normalizeSlotMixin], inheritAttrs: false, diff --git a/src/components/skeleton/skeleton-icon.js b/src/components/skeleton/skeleton-icon.js index a0234706988..c14fbfce4e6 100644 --- a/src/components/skeleton/skeleton-icon.js +++ b/src/components/skeleton/skeleton-icon.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_SKELETON_ICON } from '../../constants/components' import { PROP_TYPE_OBJECT, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -18,7 +18,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BSkeletonIcon = /*#__PURE__*/ Vue.extend({ +export const BSkeletonIcon = /*#__PURE__*/ extend({ name: NAME_SKELETON_ICON, functional: true, props, diff --git a/src/components/skeleton/skeleton-img.js b/src/components/skeleton/skeleton-img.js index 3b6d6dd1363..eb8367fd219 100644 --- a/src/components/skeleton/skeleton-img.js +++ b/src/components/skeleton/skeleton-img.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_SKELETON_IMG } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -23,7 +23,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BSkeletonImg = /*#__PURE__*/ Vue.extend({ +export const BSkeletonImg = /*#__PURE__*/ extend({ name: NAME_SKELETON_IMG, functional: true, props, diff --git a/src/components/skeleton/skeleton-table.js b/src/components/skeleton/skeleton-table.js index 29251228fb4..3371a872c0e 100644 --- a/src/components/skeleton/skeleton-table.js +++ b/src/components/skeleton/skeleton-table.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_SKELETON_TABLE } from '../../constants/components' import { PROP_TYPE_BOOLEAN, @@ -32,7 +32,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BSkeletonTable = /*#__PURE__*/ Vue.extend({ +export const BSkeletonTable = /*#__PURE__*/ extend({ name: NAME_SKELETON_TABLE, functional: true, props, diff --git a/src/components/skeleton/skeleton-wrapper.js b/src/components/skeleton/skeleton-wrapper.js index 59d0b32f2fa..9a9159d7b21 100644 --- a/src/components/skeleton/skeleton-wrapper.js +++ b/src/components/skeleton/skeleton-wrapper.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_SKELETON_WRAPPER } from '../../constants/components' import { PROP_TYPE_BOOLEAN } from '../../constants/props' import { SLOT_NAME_DEFAULT, SLOT_NAME_LOADING } from '../../constants/slots' @@ -17,7 +17,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BSkeletonWrapper = /*#__PURE__*/ Vue.extend({ +export const BSkeletonWrapper = /*#__PURE__*/ extend({ name: NAME_SKELETON_WRAPPER, functional: true, props, diff --git a/src/components/skeleton/skeleton.js b/src/components/skeleton/skeleton.js index 42fd56ee25e..f62679806a4 100644 --- a/src/components/skeleton/skeleton.js +++ b/src/components/skeleton/skeleton.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_SKELETON } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -20,7 +20,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BSkeleton = /*#__PURE__*/ Vue.extend({ +export const BSkeleton = /*#__PURE__*/ extend({ name: NAME_SKELETON, functional: true, props, diff --git a/src/components/spinner/spinner.js b/src/components/spinner/spinner.js index ac8568e1868..ebf2f5047a4 100644 --- a/src/components/spinner/spinner.js +++ b/src/components/spinner/spinner.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_SPINNER } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props' import { SLOT_NAME_LABEL } from '../../constants/slots' @@ -22,7 +22,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BSpinner = /*#__PURE__*/ Vue.extend({ +export const BSpinner = /*#__PURE__*/ extend({ name: NAME_SPINNER, functional: true, props, diff --git a/src/components/table/helpers/mixin-bottom-row.js b/src/components/table/helpers/mixin-bottom-row.js index 0a425bb010b..73a268a765a 100644 --- a/src/components/table/helpers/mixin-bottom-row.js +++ b/src/components/table/helpers/mixin-bottom-row.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { SLOT_NAME_BOTTOM_ROW } from '../../../constants/slots' import { isFunction } from '../../../utils/inspect' import { BTr } from '../tr' @@ -10,7 +10,7 @@ export const props = {} // --- Mixin --- // @vue/component -export const bottomRowMixin = Vue.extend({ +export const bottomRowMixin = extend({ props, methods: { renderBottomRow() { diff --git a/src/components/table/helpers/mixin-busy.js b/src/components/table/helpers/mixin-busy.js index 59781330b89..bb0e161a34e 100644 --- a/src/components/table/helpers/mixin-busy.js +++ b/src/components/table/helpers/mixin-busy.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { MODEL_EVENT_NAME_PREFIX } from '../../../constants/events' import { PROP_TYPE_BOOLEAN } from '../../../constants/props' import { SLOT_NAME_TABLE_BUSY } from '../../../constants/slots' @@ -22,7 +22,7 @@ export const props = { // --- Mixin --- // @vue/component -export const busyMixin = Vue.extend({ +export const busyMixin = extend({ props, data() { return { diff --git a/src/components/table/helpers/mixin-caption.js b/src/components/table/helpers/mixin-caption.js index 377a65deb5b..ace7eb5a5b7 100644 --- a/src/components/table/helpers/mixin-caption.js +++ b/src/components/table/helpers/mixin-caption.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { PROP_TYPE_STRING } from '../../../constants/props' import { SLOT_NAME_TABLE_CAPTION } from '../../../constants/slots' import { htmlOrText } from '../../../utils/html' @@ -16,7 +16,7 @@ export const props = { // --- Mixin --- // @vue/component -export const captionMixin = Vue.extend({ +export const captionMixin = extend({ props, computed: { captionId() { diff --git a/src/components/table/helpers/mixin-colgroup.js b/src/components/table/helpers/mixin-colgroup.js index 1d2cf988bb1..575bca8a681 100644 --- a/src/components/table/helpers/mixin-colgroup.js +++ b/src/components/table/helpers/mixin-colgroup.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { SLOT_NAME_TABLE_COLGROUP } from '../../../constants/slots' // --- Props --- @@ -8,7 +8,7 @@ export const props = {} // --- Mixin --- // @vue/component -export const colgroupMixin = Vue.extend({ +export const colgroupMixin = extend({ methods: { renderColgroup() { const { computedFields: fields } = this diff --git a/src/components/table/helpers/mixin-empty.js b/src/components/table/helpers/mixin-empty.js index de4fad4ad66..eeac5ddf8e8 100644 --- a/src/components/table/helpers/mixin-empty.js +++ b/src/components/table/helpers/mixin-empty.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../../constants/props' import { SLOT_NAME_EMPTY, @@ -25,7 +25,7 @@ export const props = { // --- Mixin --- // @vue/component -export const emptyMixin = Vue.extend({ +export const emptyMixin = extend({ props, methods: { renderEmpty() { diff --git a/src/components/table/helpers/mixin-filtering.js b/src/components/table/helpers/mixin-filtering.js index 6e6a2e9ff0c..62b6097df6d 100644 --- a/src/components/table/helpers/mixin-filtering.js +++ b/src/components/table/helpers/mixin-filtering.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { NAME_TABLE } from '../../../constants/components' import { EVENT_NAME_FILTERED } from '../../../constants/events' import { @@ -40,7 +40,7 @@ export const props = { // --- Mixin --- // @vue/component -export const filteringMixin = Vue.extend({ +export const filteringMixin = extend({ props, data() { return { diff --git a/src/components/table/helpers/mixin-items.js b/src/components/table/helpers/mixin-items.js index f1f1045b810..6fdeba7170b 100644 --- a/src/components/table/helpers/mixin-items.js +++ b/src/components/table/helpers/mixin-items.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { EVENT_NAME_CONTEXT_CHANGED } from '../../../constants/events' import { PROP_TYPE_ARRAY, PROP_TYPE_STRING } from '../../../constants/props' import { useParentMixin } from '../../../mixins/use-parent' @@ -44,7 +44,7 @@ export const props = sortKeys({ // --- Mixin --- // @vue/component -export const itemsMixin = Vue.extend({ +export const itemsMixin = extend({ mixins: [modelMixin, useParentMixin], props, data() { diff --git a/src/components/table/helpers/mixin-pagination.js b/src/components/table/helpers/mixin-pagination.js index e775871feff..e06796d0562 100644 --- a/src/components/table/helpers/mixin-pagination.js +++ b/src/components/table/helpers/mixin-pagination.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { PROP_TYPE_NUMBER_STRING } from '../../../constants/props' import { mathMax } from '../../../utils/math' import { toInteger } from '../../../utils/number' @@ -15,7 +15,7 @@ export const props = { // --- Mixin --- // @vue/component -export const paginationMixin = Vue.extend({ +export const paginationMixin = extend({ props, computed: { localPaging() { diff --git a/src/components/table/helpers/mixin-provider.js b/src/components/table/helpers/mixin-provider.js index a338aa10dba..3a126dd278f 100644 --- a/src/components/table/helpers/mixin-provider.js +++ b/src/components/table/helpers/mixin-provider.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { NAME_TABLE } from '../../../constants/components' import { EVENT_NAME_REFRESH, EVENT_NAME_REFRESHED } from '../../../constants/events' import { @@ -36,7 +36,7 @@ export const props = { // --- Mixin --- // @vue/component -export const providerMixin = Vue.extend({ +export const providerMixin = extend({ mixins: [listenOnRootMixin], props, computed: { diff --git a/src/components/table/helpers/mixin-selectable.js b/src/components/table/helpers/mixin-selectable.js index 5629caf4fcc..a0a6fd32102 100644 --- a/src/components/table/helpers/mixin-selectable.js +++ b/src/components/table/helpers/mixin-selectable.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { EVENT_NAME_CONTEXT_CHANGED, EVENT_NAME_FILTERED, @@ -36,7 +36,7 @@ export const props = { // --- Mixin --- // @vue/component -export const selectableMixin = Vue.extend({ +export const selectableMixin = extend({ props, data() { return { diff --git a/src/components/table/helpers/mixin-sorting.js b/src/components/table/helpers/mixin-sorting.js index b71a5b84218..b8b24f2e8d0 100644 --- a/src/components/table/helpers/mixin-sorting.js +++ b/src/components/table/helpers/mixin-sorting.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { EVENT_NAME_HEAD_CLICKED, EVENT_NAME_SORT_CHANGED, @@ -70,7 +70,7 @@ export const props = { // --- Mixin --- // @vue/component -export const sortingMixin = Vue.extend({ +export const sortingMixin = extend({ props, data() { return { diff --git a/src/components/table/helpers/mixin-stacked.js b/src/components/table/helpers/mixin-stacked.js index ab5c4d69757..2499805cba6 100644 --- a/src/components/table/helpers/mixin-stacked.js +++ b/src/components/table/helpers/mixin-stacked.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { PROP_TYPE_BOOLEAN_STRING } from '../../../constants/props' import { makeProp } from '../../../utils/props' @@ -11,7 +11,7 @@ export const props = { // --- Mixin --- // @vue/component -export const stackedMixin = Vue.extend({ +export const stackedMixin = extend({ props, computed: { isStacked() { diff --git a/src/components/table/helpers/mixin-table-renderer.js b/src/components/table/helpers/mixin-table-renderer.js index aee24480a69..f88c3f0282a 100644 --- a/src/components/table/helpers/mixin-table-renderer.js +++ b/src/components/table/helpers/mixin-table-renderer.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_BOOLEAN, @@ -38,7 +38,7 @@ export const props = { // --- Mixin --- // @vue/component -export const tableRendererMixin = Vue.extend({ +export const tableRendererMixin = extend({ mixins: [attrsMixin], provide() { return { diff --git a/src/components/table/helpers/mixin-tbody-row.js b/src/components/table/helpers/mixin-tbody-row.js index b11642045b0..02733509e55 100644 --- a/src/components/table/helpers/mixin-tbody-row.js +++ b/src/components/table/helpers/mixin-tbody-row.js @@ -1,4 +1,4 @@ -import { Vue, REF_FOR_KEY } from '../../../vue' +import { extend, REF_FOR_KEY } from '../../../vue' import { EVENT_NAME_ROW_CLICKED, EVENT_NAME_ROW_HOVERED, @@ -32,7 +32,7 @@ export const props = { // --- Mixin --- // @vue/component -export const tbodyRowMixin = Vue.extend({ +export const tbodyRowMixin = extend({ mixins: [useParentMixin], props, methods: { diff --git a/src/components/table/helpers/mixin-tbody.js b/src/components/table/helpers/mixin-tbody.js index 451a328776f..a40f3493348 100644 --- a/src/components/table/helpers/mixin-tbody.js +++ b/src/components/table/helpers/mixin-tbody.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { EVENT_NAME_ROW_CLICKED, EVENT_NAME_ROW_CONTEXTMENU, @@ -40,7 +40,7 @@ export const props = sortKeys({ // --- Mixin --- // @vue/component -export const tbodyMixin = Vue.extend({ +export const tbodyMixin = extend({ mixins: [tbodyRowMixin], props, beforeDestroy() { diff --git a/src/components/table/helpers/mixin-tfoot.js b/src/components/table/helpers/mixin-tfoot.js index 222d524b3ec..5248642cd1e 100644 --- a/src/components/table/helpers/mixin-tfoot.js +++ b/src/components/table/helpers/mixin-tfoot.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_BOOLEAN, @@ -24,7 +24,7 @@ export const props = { // --- Mixin --- // @vue/component -export const tfootMixin = Vue.extend({ +export const tfootMixin = extend({ props, methods: { renderTFootCustom() { diff --git a/src/components/table/helpers/mixin-thead.js b/src/components/table/helpers/mixin-thead.js index c3321f97ff8..62690080194 100644 --- a/src/components/table/helpers/mixin-thead.js +++ b/src/components/table/helpers/mixin-thead.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { EVENT_NAME_HEAD_CLICKED } from '../../../constants/events' import { CODE_ENTER, CODE_SPACE } from '../../../constants/key-codes' import { PROP_TYPE_ARRAY_OBJECT_STRING, PROP_TYPE_STRING } from '../../../constants/props' @@ -38,7 +38,7 @@ export const props = { // --- Mixin --- // @vue/component -export const theadMixin = Vue.extend({ +export const theadMixin = extend({ props, methods: { fieldClasses(field) { diff --git a/src/components/table/helpers/mixin-top-row.js b/src/components/table/helpers/mixin-top-row.js index ee27d18de4a..df77f19e2ea 100644 --- a/src/components/table/helpers/mixin-top-row.js +++ b/src/components/table/helpers/mixin-top-row.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { SLOT_NAME_TOP_ROW } from '../../../constants/slots' import { isFunction } from '../../../utils/inspect' import { BTr } from '../tr' @@ -10,7 +10,7 @@ export const props = {} // --- Mixin --- // @vue/component -export const topRowMixin = Vue.extend({ +export const topRowMixin = extend({ methods: { renderTopRow() { const { computedFields: fields, stacked, tbodyTrClass, tbodyTrAttr } = this diff --git a/src/components/table/table-lite.js b/src/components/table/table-lite.js index 4302ec07d5e..c31f63aa117 100644 --- a/src/components/table/table-lite.js +++ b/src/components/table/table-lite.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TABLE_LITE } from '../../constants/components' import { sortKeys } from '../../utils/object' import { makePropsConfigurable } from '../../utils/props' @@ -35,7 +35,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BTableLite = /*#__PURE__*/ Vue.extend({ +export const BTableLite = /*#__PURE__*/ extend({ name: NAME_TABLE_LITE, // Order of mixins is important! // They are merged from first to last, followed by this component diff --git a/src/components/table/table-simple.js b/src/components/table/table-simple.js index 1852d0bb074..c7d59256ce6 100644 --- a/src/components/table/table-simple.js +++ b/src/components/table/table-simple.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TABLE_SIMPLE } from '../../constants/components' import { sortKeys } from '../../utils/object' import { makePropsConfigurable } from '../../utils/props' @@ -23,7 +23,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BTableSimple = /*#__PURE__*/ Vue.extend({ +export const BTableSimple = /*#__PURE__*/ extend({ name: NAME_TABLE_SIMPLE, // Order of mixins is important! // They are merged from first to last, followed by this component diff --git a/src/components/table/table.js b/src/components/table/table.js index 03bea65798d..ea32d30562f 100644 --- a/src/components/table/table.js +++ b/src/components/table/table.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TABLE } from '../../constants/components' import { sortKeys } from '../../utils/object' import { makePropsConfigurable } from '../../utils/props' @@ -53,7 +53,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BTable = /*#__PURE__*/ Vue.extend({ +export const BTable = /*#__PURE__*/ extend({ name: NAME_TABLE, // Order of mixins is important! // They are merged from first to last, followed by this component diff --git a/src/components/table/tbody.js b/src/components/table/tbody.js index f42fc613064..5e6702742e0 100644 --- a/src/components/table/tbody.js +++ b/src/components/table/tbody.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TBODY } from '../../constants/components' import { PROP_TYPE_OBJECT } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -22,7 +22,7 @@ export const props = makePropsConfigurable( // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component -export const BTbody = /*#__PURE__*/ Vue.extend({ +export const BTbody = /*#__PURE__*/ extend({ name: NAME_TBODY, mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide() { diff --git a/src/components/table/td.js b/src/components/table/td.js index 26c8047b5f2..d5f181f4cf2 100644 --- a/src/components/table/td.js +++ b/src/components/table/td.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TABLE_CELL } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props' import { isTag } from '../../utils/dom' @@ -40,7 +40,7 @@ export const props = makePropsConfigurable( // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component -export const BTd = /*#__PURE__*/ Vue.extend({ +export const BTd = /*#__PURE__*/ extend({ name: NAME_TABLE_CELL, // Mixin order is important! mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], diff --git a/src/components/table/tfoot.js b/src/components/table/tfoot.js index 669f2474a6f..8f052c16ea3 100644 --- a/src/components/table/tfoot.js +++ b/src/components/table/tfoot.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TFOOT } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -22,7 +22,7 @@ export const props = makePropsConfigurable( // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component -export const BTfoot = /*#__PURE__*/ Vue.extend({ +export const BTfoot = /*#__PURE__*/ extend({ name: NAME_TFOOT, mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide() { diff --git a/src/components/table/th.js b/src/components/table/th.js index d67a799a2e7..6e8dad6a0b9 100644 --- a/src/components/table/th.js +++ b/src/components/table/th.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TH } from '../../constants/components' import { makePropsConfigurable } from '../../utils/props' import { BTd, props as BTdProps } from './td' @@ -13,7 +13,7 @@ export const props = makePropsConfigurable(BTdProps, NAME_TH) // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component -export const BTh = /*#__PURE__*/ Vue.extend({ +export const BTh = /*#__PURE__*/ extend({ name: NAME_TH, extends: BTd, props, diff --git a/src/components/table/thead.js b/src/components/table/thead.js index 3ffd55fa308..670ddef212c 100644 --- a/src/components/table/thead.js +++ b/src/components/table/thead.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_THEAD } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -23,7 +23,7 @@ export const props = makePropsConfigurable( // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component -export const BThead = /*#__PURE__*/ Vue.extend({ +export const BThead = /*#__PURE__*/ extend({ name: NAME_THEAD, mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide() { diff --git a/src/components/table/tr.js b/src/components/table/tr.js index e9f0c61f7da..d9de0e29947 100644 --- a/src/components/table/tr.js +++ b/src/components/table/tr.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TR } from '../../constants/components' import { PROP_TYPE_STRING } from '../../constants/props' import { makeProp, makePropsConfigurable } from '../../utils/props' @@ -26,7 +26,7 @@ export const props = makePropsConfigurable( // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component -export const BTr = /*#__PURE__*/ Vue.extend({ +export const BTr = /*#__PURE__*/ extend({ name: NAME_TR, mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide() { diff --git a/src/components/tabs/tab.js b/src/components/tabs/tab.js index f75f813af59..f6bc51e9781 100644 --- a/src/components/tabs/tab.js +++ b/src/components/tabs/tab.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TAB } from '../../constants/components' import { MODEL_EVENT_NAME_PREFIX } from '../../constants/events' import { @@ -43,7 +43,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BTab = /*#__PURE__*/ Vue.extend({ +export const BTab = /*#__PURE__*/ extend({ name: NAME_TAB, mixins: [idMixin, normalizeSlotMixin], inject: { diff --git a/src/components/tabs/tabs.js b/src/components/tabs/tabs.js index 28a4019ff8a..ced573478e4 100644 --- a/src/components/tabs/tabs.js +++ b/src/components/tabs/tabs.js @@ -1,4 +1,4 @@ -import { COMPONENT_UID_KEY, REF_FOR_KEY, Vue } from '../../vue' +import { COMPONENT_UID_KEY, REF_FOR_KEY, extend } from '../../vue' import { NAME_TABS, NAME_TAB_BUTTON_HELPER } from '../../constants/components' import { IS_BROWSER } from '../../constants/env' import { @@ -67,7 +67,7 @@ const notDisabled = tab => !tab.disabled // --- Helper components --- // @vue/component -const BVTabButton = /*#__PURE__*/ Vue.extend({ +const BVTabButton = /*#__PURE__*/ extend({ name: NAME_TAB_BUTTON_HELPER, inject: { getBvTabs: { @@ -218,7 +218,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BTabs = /*#__PURE__*/ Vue.extend({ +export const BTabs = /*#__PURE__*/ extend({ name: NAME_TABS, mixins: [idMixin, modelMixin, normalizeSlotMixin], provide() { diff --git a/src/components/time/time.js b/src/components/time/time.js index cb0c93ef2b3..be2bcd17e49 100644 --- a/src/components/time/time.js +++ b/src/components/time/time.js @@ -1,5 +1,5 @@ // BTime control (not form input control) -import { Vue, REF_FOR_KEY } from '../../vue' +import { extend, REF_FOR_KEY } from '../../vue' import { NAME_TIME } from '../../constants/components' import { EVENT_NAME_CONTEXT } from '../../constants/events' import { CODE_LEFT, CODE_RIGHT } from '../../constants/key-codes' @@ -107,7 +107,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BTime = /*#__PURE__*/ Vue.extend({ +export const BTime = /*#__PURE__*/ extend({ name: NAME_TIME, mixins: [idMixin, modelMixin, normalizeSlotMixin], props, diff --git a/src/components/toast/toast.js b/src/components/toast/toast.js index 73ad6325bc3..25ad463a818 100644 --- a/src/components/toast/toast.js +++ b/src/components/toast/toast.js @@ -1,5 +1,5 @@ import { Portal, Wormhole } from 'portal-vue' -import { COMPONENT_UID_KEY, Vue } from '../../vue' +import { COMPONENT_UID_KEY, extend } from '../../vue' import { NAME_TOAST, NAME_TOASTER } from '../../constants/components' import { EVENT_NAME_CHANGE, @@ -86,7 +86,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BToast = /*#__PURE__*/ Vue.extend({ +export const BToast = /*#__PURE__*/ extend({ name: NAME_TOAST, mixins: [ attrsMixin, diff --git a/src/components/toast/toaster.js b/src/components/toast/toaster.js index 07a741fc9fa..f0196a81b7c 100644 --- a/src/components/toast/toaster.js +++ b/src/components/toast/toaster.js @@ -1,5 +1,5 @@ import { PortalTarget, Wormhole } from 'portal-vue' -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TOASTER } from '../../constants/components' import { EVENT_NAME_DESTROYED } from '../../constants/events' import { PROP_TYPE_STRING } from '../../constants/props' @@ -13,7 +13,7 @@ import { normalizeSlotMixin } from '../../mixins/normalize-slot' // --- Helper components --- // @vue/component -export const DefaultTransition = /*#__PURE__*/ Vue.extend({ +export const DefaultTransition = /*#__PURE__*/ extend({ mixins: [normalizeSlotMixin], data() { return { @@ -62,7 +62,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BToaster = /*#__PURE__*/ Vue.extend({ +export const BToaster = /*#__PURE__*/ extend({ name: NAME_TOASTER, mixins: [listenOnRootMixin], props, diff --git a/src/components/tooltip/helpers/bv-popper.js b/src/components/tooltip/helpers/bv-popper.js index 0d00bc2d409..ebcff40fc5e 100644 --- a/src/components/tooltip/helpers/bv-popper.js +++ b/src/components/tooltip/helpers/bv-popper.js @@ -6,7 +6,7 @@ // import Popper from 'popper.js' -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { NAME_POPPER } from '../../../constants/components' import { EVENT_NAME_HIDDEN, @@ -82,7 +82,7 @@ export const props = { // --- Main component --- // @vue/component -export const BVPopper = /*#__PURE__*/ Vue.extend({ +export const BVPopper = /*#__PURE__*/ extend({ name: NAME_POPPER, mixins: [useParentMixin], props, diff --git a/src/components/tooltip/helpers/bv-tooltip-template.js b/src/components/tooltip/helpers/bv-tooltip-template.js index 22813b7e3d2..84bae8aa2ec 100644 --- a/src/components/tooltip/helpers/bv-tooltip-template.js +++ b/src/components/tooltip/helpers/bv-tooltip-template.js @@ -1,4 +1,4 @@ -import { Vue } from '../../../vue' +import { extend } from '../../../vue' import { NAME_TOOLTIP_TEMPLATE } from '../../../constants/components' import { EVENT_NAME_FOCUSIN, @@ -24,7 +24,7 @@ export const props = { // --- Main component --- // @vue/component -export const BVTooltipTemplate = /*#__PURE__*/ Vue.extend({ +export const BVTooltipTemplate = /*#__PURE__*/ extend({ name: NAME_TOOLTIP_TEMPLATE, extends: BVPopper, mixins: [scopedStyleMixin], diff --git a/src/components/tooltip/helpers/bv-tooltip.js b/src/components/tooltip/helpers/bv-tooltip.js index 7033d7bc60b..3688229ccb5 100644 --- a/src/components/tooltip/helpers/bv-tooltip.js +++ b/src/components/tooltip/helpers/bv-tooltip.js @@ -3,7 +3,7 @@ // Handles trigger events, etc. // Instantiates template on demand -import { COMPONENT_UID_KEY, Vue } from '../../../vue' +import { COMPONENT_UID_KEY, extend } from '../../../vue' import { NAME_MODAL, NAME_TOOLTIP_HELPER } from '../../../constants/components' import { EVENT_NAME_DISABLE, @@ -140,7 +140,7 @@ const templateData = { // --- Main component --- // @vue/component -export const BVTooltip = /*#__PURE__*/ Vue.extend({ +export const BVTooltip = /*#__PURE__*/ extend({ name: NAME_TOOLTIP_HELPER, mixins: [listenOnRootMixin, useParentMixin], data() { diff --git a/src/components/tooltip/tooltip.js b/src/components/tooltip/tooltip.js index 7ea687edfdd..a0aace1b646 100644 --- a/src/components/tooltip/tooltip.js +++ b/src/components/tooltip/tooltip.js @@ -1,4 +1,4 @@ -import { Vue } from '../../vue' +import { extend } from '../../vue' import { NAME_TOOLTIP } from '../../constants/components' import { EVENT_NAME_CLOSE, @@ -83,7 +83,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BTooltip = /*#__PURE__*/ Vue.extend({ +export const BTooltip = /*#__PURE__*/ extend({ name: NAME_TOOLTIP, mixins: [normalizeSlotMixin, useParentMixin], inheritAttrs: false, diff --git a/src/components/transition/bv-transition.js b/src/components/transition/bv-transition.js index 006e848bd67..c2977391c5b 100644 --- a/src/components/transition/bv-transition.js +++ b/src/components/transition/bv-transition.js @@ -4,7 +4,7 @@ // the transition has finished the enter transition // (show and fade classes are only applied during transition) -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_TRANSITION } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_OBJECT, PROP_TYPE_STRING } from '../../constants/props' import { isPlainObject } from '../../utils/inspect' @@ -45,7 +45,7 @@ export const props = { // --- Main component --- // @vue/component -export const BVTransition = /*#__PURE__*/ Vue.extend({ +export const BVTransition = /*#__PURE__*/ extend({ name: NAME_TRANSITION, functional: true, props, diff --git a/src/components/transporter/transporter.js b/src/components/transporter/transporter.js index b3fd778b481..9f0892f6e7f 100644 --- a/src/components/transporter/transporter.js +++ b/src/components/transporter/transporter.js @@ -1,4 +1,4 @@ -import { Vue, isVue3 } from '../../vue' +import { Vue, extend, isVue3 } from '../../vue' import { NAME_TRANSPORTER, NAME_TRANSPORTER_TARGET } from '../../constants/components' import { IS_BROWSER } from '../../constants/env' import { @@ -31,7 +31,7 @@ import { createNewChildComponent } from '../../utils/create-new-child-component' // Transporter target used by BVTransporter // Supports only a single root element // @vue/component -const BVTransporterTarget = /*#__PURE__*/ Vue.extend({ +const BVTransporterTarget = /*#__PURE__*/ extend({ // As an abstract component, it doesn't appear in the $parent chain of // components, which means the next parent of any component rendered inside // of this one will be the parent from which is was portal'd @@ -79,7 +79,7 @@ export const props = { // --- Main component --- // @vue/component -const BVTransporterVue2 = /*#__PURE__*/ Vue.extend({ +const BVTransporterVue2 = /*#__PURE__*/ extend({ name: NAME_TRANSPORTER, mixins: [normalizeSlotMixin], props, @@ -178,7 +178,7 @@ const BVTransporterVue2 = /*#__PURE__*/ Vue.extend({ } }) -const BVTransporterVue3 = /*#__PURE__*/ Vue.extend({ +const BVTransporterVue3 = /*#__PURE__*/ extend({ name: NAME_TRANSPORTER, mixins: [normalizeSlotMixin], props, diff --git a/src/icons/helpers/icon-base.js b/src/icons/helpers/icon-base.js index a33ff8ac32d..7fc8e2f818c 100644 --- a/src/icons/helpers/icon-base.js +++ b/src/icons/helpers/icon-base.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { NAME_ICON_BASE } from '../../constants/components' import { PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props' import { identity } from '../../utils/identity' @@ -49,7 +49,7 @@ export const props = { // Shared private base component to reduce bundle/runtime size // @vue/component -export const BVIconBase = /*#__PURE__*/ Vue.extend({ +export const BVIconBase = /*#__PURE__*/ extend({ name: NAME_ICON_BASE, functional: true, props, diff --git a/src/icons/helpers/make-icon.js b/src/icons/helpers/make-icon.js index 48c76020b0b..30765a7e438 100644 --- a/src/icons/helpers/make-icon.js +++ b/src/icons/helpers/make-icon.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../../vue' +import { extend, mergeData } from '../../vue' import { omit } from '../../utils/object' import { kebabCase, pascalCase, trim } from '../../utils/string' import { BVIconBase, props as BVIconBaseProps } from './icon-base' @@ -21,7 +21,7 @@ export const makeIcon = (name, content) => { const iconTitle = kebabName.replace(/-/g, ' ') const svgContent = trim(content || '') - return /*#__PURE__*/ Vue.extend({ + return /*#__PURE__*/ extend({ name: iconName, functional: true, props: iconProps, diff --git a/src/icons/icon.js b/src/icons/icon.js index 98959fa4781..04854a4320a 100644 --- a/src/icons/icon.js +++ b/src/icons/icon.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../vue' +import { Vue, extend, mergeData } from '../vue' import { NAME_ICON } from '../constants/components' import { PROP_TYPE_STRING } from '../constants/props' import { RX_ICON_PREFIX } from '../constants/regex' @@ -36,7 +36,7 @@ export const props = makePropsConfigurable( // Helper BIcon component // Requires the requested icon component to be installed // @vue/component -export const BIcon = /*#__PURE__*/ Vue.extend({ +export const BIcon = /*#__PURE__*/ extend({ name: NAME_ICON, functional: true, props, diff --git a/src/icons/iconstack.js b/src/icons/iconstack.js index f0411fc74a8..0a480489b8e 100644 --- a/src/icons/iconstack.js +++ b/src/icons/iconstack.js @@ -1,4 +1,4 @@ -import { Vue, mergeData } from '../vue' +import { extend, mergeData } from '../vue' import { NAME_ICONSTACK } from '../constants/components' import { omit } from '../utils/object' import { makePropsConfigurable } from '../utils/props' @@ -14,7 +14,7 @@ export const props = makePropsConfigurable( // --- Main component --- // @vue/component -export const BIconstack = /*#__PURE__*/ Vue.extend({ +export const BIconstack = /*#__PURE__*/ extend({ name: NAME_ICONSTACK, functional: true, props, diff --git a/src/mixins/attrs.js b/src/mixins/attrs.js index 80eb3818b6f..972f5a760f4 100644 --- a/src/mixins/attrs.js +++ b/src/mixins/attrs.js @@ -1,8 +1,8 @@ import { makePropCacheMixin } from '../utils/cache' -import { Vue, isVue3 } from '../vue' +import { extend, isVue3 } from '../vue' const attrsMixinVue2 = makePropCacheMixin('$attrs', 'bvAttrs') -const attrsMixinVue3 = Vue.extend({ +const attrsMixinVue3 = extend({ computed: { bvAttrs() { const bvAttrs = { ...this.$attrs } diff --git a/src/mixins/card.js b/src/mixins/card.js index f5f48b9f953..7628a5d1646 100644 --- a/src/mixins/card.js +++ b/src/mixins/card.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { NAME_CARD } from '../constants/components' import { PROP_TYPE_STRING } from '../constants/props' import { makeProp, makePropsConfigurable } from '../utils/props' @@ -18,6 +18,6 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const cardMixin = Vue.extend({ +export const cardMixin = extend({ props }) diff --git a/src/mixins/click-out.js b/src/mixins/click-out.js index ee4f98fbdf1..921dbc0fff9 100644 --- a/src/mixins/click-out.js +++ b/src/mixins/click-out.js @@ -1,10 +1,10 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { EVENT_OPTIONS_NO_CAPTURE } from '../constants/events' import { contains } from '../utils/dom' import { eventOn, eventOff } from '../utils/events' // @vue/component -export const clickOutMixin = Vue.extend({ +export const clickOutMixin = extend({ data() { return { listenForClickOut: false diff --git a/src/mixins/dropdown.js b/src/mixins/dropdown.js index 0546e4650cc..59292e198ec 100644 --- a/src/mixins/dropdown.js +++ b/src/mixins/dropdown.js @@ -1,5 +1,5 @@ import Popper from 'popper.js' -import { Vue } from '../vue' +import { extend } from '../vue' import { NAME_DROPDOWN } from '../constants/components' import { HAS_TOUCH_SUPPORT } from '../constants/env' import { @@ -88,7 +88,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const dropdownMixin = Vue.extend({ +export const dropdownMixin = extend({ mixins: [idMixin, listenOnRootMixin, clickOutMixin, focusInMixin], provide() { return { getBvDropdown: () => this } diff --git a/src/mixins/focus-in.js b/src/mixins/focus-in.js index b30cbedeeaf..855f78dbf40 100644 --- a/src/mixins/focus-in.js +++ b/src/mixins/focus-in.js @@ -1,9 +1,9 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { EVENT_OPTIONS_NO_CAPTURE } from '../constants/events' import { eventOn, eventOff } from '../utils/events' // @vue/component -export const focusInMixin = Vue.extend({ +export const focusInMixin = extend({ data() { return { listenForFocusIn: false diff --git a/src/mixins/form-control.js b/src/mixins/form-control.js index e0f2e53a147..92370cca766 100644 --- a/src/mixins/form-control.js +++ b/src/mixins/form-control.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../constants/props' import { attemptFocus, isVisible, matches, requestAF, select } from '../utils/dom' import { makeProp, makePropsConfigurable } from '../utils/props' @@ -24,7 +24,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const formControlMixin = Vue.extend({ +export const formControlMixin = extend({ props, mounted() { this.handleAutofocus() diff --git a/src/mixins/form-custom.js b/src/mixins/form-custom.js index 0d1b226c0b8..2cb33ce7b07 100644 --- a/src/mixins/form-custom.js +++ b/src/mixins/form-custom.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { PROP_TYPE_BOOLEAN } from '../constants/props' import { makeProp, makePropsConfigurable } from '../utils/props' @@ -14,7 +14,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const formCustomMixin = Vue.extend({ +export const formCustomMixin = extend({ props, computed: { custom() { diff --git a/src/mixins/form-options.js b/src/mixins/form-options.js index eacc54ed349..6b23c568699 100644 --- a/src/mixins/form-options.js +++ b/src/mixins/form-options.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { PROP_TYPE_ARRAY_OBJECT, PROP_TYPE_STRING } from '../constants/props' import { get } from '../utils/get' import { stripTags } from '../utils/html' @@ -28,7 +28,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const formOptionsMixin = Vue.extend({ +export const formOptionsMixin = extend({ props, computed: { formOptions() { diff --git a/src/mixins/form-radio-check-group.js b/src/mixins/form-radio-check-group.js index 3a0735eaabe..2ca8c03629e 100644 --- a/src/mixins/form-radio-check-group.js +++ b/src/mixins/form-radio-check-group.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { PROP_TYPE_BOOLEAN, PROP_TYPE_BOOLEAN_STRING, PROP_TYPE_STRING } from '../constants/props' import { SLOT_NAME_FIRST } from '../constants/slots' import { htmlOrText } from '../utils/html' @@ -55,7 +55,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const formRadioCheckGroupMixin = Vue.extend({ +export const formRadioCheckGroupMixin = extend({ mixins: [ idMixin, modelMixin, diff --git a/src/mixins/form-radio-check.js b/src/mixins/form-radio-check.js index f02d213ec48..c053560853f 100644 --- a/src/mixins/form-radio-check.js +++ b/src/mixins/form-radio-check.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { PROP_TYPE_ANY, PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../constants/props' import { EVENT_NAME_CHANGE } from '../constants/events' import { attemptBlur, attemptFocus } from '../utils/dom' @@ -51,7 +51,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const formRadioCheckMixin = Vue.extend({ +export const formRadioCheckMixin = extend({ mixins: [ attrsMixin, idMixin, diff --git a/src/mixins/form-selection.js b/src/mixins/form-selection.js index 894928e85c6..c41f117cd75 100644 --- a/src/mixins/form-selection.js +++ b/src/mixins/form-selection.js @@ -1,7 +1,7 @@ -import { Vue } from '../vue' +import { extend } from '../vue' // @vue/component -export const formSelectionMixin = Vue.extend({ +export const formSelectionMixin = extend({ computed: { selectionStart: { // Expose selectionStart for formatters, etc diff --git a/src/mixins/form-size.js b/src/mixins/form-size.js index e2f333f974e..b380bce453f 100644 --- a/src/mixins/form-size.js +++ b/src/mixins/form-size.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { PROP_TYPE_STRING } from '../constants/props' import { makeProp, makePropsConfigurable } from '../utils/props' @@ -14,7 +14,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const formSizeMixin = Vue.extend({ +export const formSizeMixin = extend({ props, computed: { sizeFormClass() { diff --git a/src/mixins/form-state.js b/src/mixins/form-state.js index 14c81cb08c4..b17c7609f67 100644 --- a/src/mixins/form-state.js +++ b/src/mixins/form-state.js @@ -6,7 +6,7 @@ * - false for is-invalid * - null for no contextual state */ -import { Vue } from '../vue' +import { extend } from '../vue' import { PROP_TYPE_BOOLEAN } from '../constants/props' import { isBoolean } from '../utils/inspect' import { makeProp, makePropsConfigurable } from '../utils/props' @@ -25,7 +25,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const formStateMixin = Vue.extend({ +export const formStateMixin = extend({ props, computed: { computedState() { diff --git a/src/mixins/form-text.js b/src/mixins/form-text.js index f6102689a88..cf9606da856 100644 --- a/src/mixins/form-text.js +++ b/src/mixins/form-text.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { EVENT_NAME_BLUR, EVENT_NAME_CHANGE, @@ -61,7 +61,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const formTextMixin = Vue.extend({ +export const formTextMixin = extend({ mixins: [modelMixin], props, data() { diff --git a/src/mixins/form-validity.js b/src/mixins/form-validity.js index e928a69c25b..c3676b59777 100644 --- a/src/mixins/form-validity.js +++ b/src/mixins/form-validity.js @@ -1,7 +1,7 @@ -import { Vue } from '../vue' +import { extend } from '../vue' // @vue/component -export const formValidityMixin = Vue.extend({ +export const formValidityMixin = extend({ computed: { validity: { // Expose validity property diff --git a/src/mixins/has-listener.js b/src/mixins/has-listener.js index 62184fc686f..51967ca6a83 100644 --- a/src/mixins/has-listener.js +++ b/src/mixins/has-listener.js @@ -2,11 +2,11 @@ // either via `v-on:name` (in the parent) or programmatically // via `vm.$on('name', ...)` // See: https://github.com/vuejs/vue/issues/10825 -import { isVue3, Vue } from '../vue' +import { isVue3, extend } from '../vue' import { isArray, isUndefined } from '../utils/inspect' // @vue/component -export const hasListenerMixin = Vue.extend({ +export const hasListenerMixin = extend({ methods: { hasListener(name) { if (isVue3) { diff --git a/src/mixins/id.js b/src/mixins/id.js index 2e5afe7bc0c..2e7e328a18d 100644 --- a/src/mixins/id.js +++ b/src/mixins/id.js @@ -1,7 +1,7 @@ // SSR safe client-side ID attribute generation // ID's can only be generated client-side, after mount // `this._uid` is not synched between server and client -import { COMPONENT_UID_KEY, Vue } from '../vue' +import { COMPONENT_UID_KEY, extend } from '../vue' import { PROP_TYPE_STRING } from '../constants/props' import { makeProp } from '../utils/props' @@ -14,7 +14,7 @@ export const props = { // --- Mixin --- // @vue/component -export const idMixin = Vue.extend({ +export const idMixin = extend({ props, data() { return { diff --git a/src/mixins/listen-on-document.js b/src/mixins/listen-on-document.js index 25c9a04fca8..82841b74934 100644 --- a/src/mixins/listen-on-document.js +++ b/src/mixins/listen-on-document.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { IS_BROWSER } from '../constants/env' import { EVENT_OPTIONS_NO_CAPTURE } from '../constants/events' import { arrayIncludes } from '../utils/array' @@ -12,7 +12,7 @@ const PROP = '$_documentListeners' // --- Mixin --- // @vue/component -export const listenOnDocumentMixin = Vue.extend({ +export const listenOnDocumentMixin = extend({ created() { // Define non-reactive property // Object of arrays, keyed by event name, diff --git a/src/mixins/listen-on-root.js b/src/mixins/listen-on-root.js index 5d8fb95f764..53c28d86e1d 100644 --- a/src/mixins/listen-on-root.js +++ b/src/mixins/listen-on-root.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { arrayIncludes } from '../utils/array' import { keys } from '../utils/object' import { getEventRoot } from '../utils/get-event-root' @@ -9,7 +9,7 @@ const PROP = '$_rootListeners' // --- Mixin --- // @vue/component -export const listenOnRootMixin = Vue.extend({ +export const listenOnRootMixin = extend({ computed: { bvEventRoot() { return getEventRoot(this) diff --git a/src/mixins/listen-on-window.js b/src/mixins/listen-on-window.js index 644ee8a177b..39211f4613b 100644 --- a/src/mixins/listen-on-window.js +++ b/src/mixins/listen-on-window.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { IS_BROWSER } from '../constants/env' import { EVENT_OPTIONS_NO_CAPTURE } from '../constants/events' import { arrayIncludes } from '../utils/array' @@ -12,7 +12,7 @@ const PROP = '$_windowListeners' // --- Mixin --- // @vue/component -export const listenOnWindowMixin = Vue.extend({ +export const listenOnWindowMixin = extend({ created() { // Define non-reactive property // Object of arrays, keyed by event name, diff --git a/src/mixins/listeners.js b/src/mixins/listeners.js index dbe828f898c..846760a98dc 100644 --- a/src/mixins/listeners.js +++ b/src/mixins/listeners.js @@ -1,9 +1,9 @@ import { makePropCacheMixin } from '../utils/cache' -import { Vue, isVue3 } from '../vue' +import { extend, isVue3 } from '../vue' const listenersMixinVue2 = makePropCacheMixin('$listeners', 'bvListeners') -const listenersMixinVue3 = Vue.extend({ +const listenersMixinVue3 = extend({ data() { return { bvListeners: {} diff --git a/src/mixins/normalize-slot.js b/src/mixins/normalize-slot.js index 91662658098..386ec3f9ef2 100644 --- a/src/mixins/normalize-slot.js +++ b/src/mixins/normalize-slot.js @@ -1,10 +1,10 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { SLOT_NAME_DEFAULT } from '../constants/slots' import { hasNormalizedSlot, normalizeSlot } from '../utils/normalize-slot' import { concat } from '../utils/array' // @vue/component -export const normalizeSlotMixin = Vue.extend({ +export const normalizeSlotMixin = extend({ methods: { // Returns `true` if the either a `$scopedSlot` or `$slot` exists with the specified name // `name` can be a string name or an array of names diff --git a/src/mixins/pagination.js b/src/mixins/pagination.js index cb2dcbf64ba..15c540d177b 100644 --- a/src/mixins/pagination.js +++ b/src/mixins/pagination.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { NAME_PAGINATION } from '../constants/components' import { CODE_DOWN, CODE_LEFT, CODE_RIGHT, CODE_SPACE, CODE_UP } from '../constants/key-codes' import { @@ -148,7 +148,7 @@ export const props = makePropsConfigurable( // --- Mixin --- // @vue/component -export const paginationMixin = Vue.extend({ +export const paginationMixin = extend({ mixins: [modelMixin, normalizeSlotMixin], props, data() { diff --git a/src/mixins/scoped-style.js b/src/mixins/scoped-style.js index f99f5e58b2d..b59570ed4fd 100644 --- a/src/mixins/scoped-style.js +++ b/src/mixins/scoped-style.js @@ -1,9 +1,9 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { useParentMixin } from '../mixins/use-parent' import { getScopeId } from '../utils/get-scope-id' // @vue/component -export const scopedStyleMixin = Vue.extend({ +export const scopedStyleMixin = extend({ mixins: [useParentMixin], computed: { scopedStyleAttrs() { diff --git a/src/mixins/use-parent.js b/src/mixins/use-parent.js index aeb3808a85f..577bfa923d0 100644 --- a/src/mixins/use-parent.js +++ b/src/mixins/use-parent.js @@ -1,9 +1,9 @@ -import { Vue } from '../vue' +import { extend } from '../vue' // --- Mixin --- // @vue/component -export const useParentMixin = Vue.extend({ +export const useParentMixin = extend({ computed: { bvParent() { return this.$parent || (this.$root === this && this.$options.bvParent) diff --git a/src/utils/cache.js b/src/utils/cache.js index 87cc48fa3e0..51675e3c72f 100644 --- a/src/utils/cache.js +++ b/src/utils/cache.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { cloneDeep } from './clone-deep' import { looseEqual } from './loose-equal' import { hasOwnProperty, keys } from './object' @@ -26,7 +26,7 @@ export const makePropWatcher = propName => ({ }) export const makePropCacheMixin = (propName, proxyPropName) => - Vue.extend({ + extend({ data() { return { [proxyPropName]: cloneDeep(this[propName]) } }, diff --git a/src/utils/model.js b/src/utils/model.js index 0a48c316a94..7b857c732e0 100644 --- a/src/utils/model.js +++ b/src/utils/model.js @@ -1,4 +1,4 @@ -import { Vue } from '../vue' +import { extend } from '../vue' import { EVENT_NAME_INPUT } from '../constants/events' import { PROP_TYPE_ANY } from '../constants/props' import { makeProp } from './props' @@ -17,7 +17,7 @@ export const makeModelMixin = ( } // @vue/component - const mixin = Vue.extend({ + const mixin = extend({ model: { prop, event diff --git a/src/vue.js b/src/vue.js index ae4bff7c7c3..fe15c52bf42 100644 --- a/src/vue.js +++ b/src/vue.js @@ -25,6 +25,8 @@ const ALLOWED_FIELDS_IN_DATA = [ 'refInFor' ] +let extend = Vue.extend.bind(Vue) + if (isVue3) { const { extend: originalExtend } = Vue const KNOWN_COMPONENTS = ['router-link', 'transition'] @@ -44,7 +46,7 @@ if (isVue3) { el._assign = () => {} } } - Vue.extend = function(definition) { + extend = function patchedBootstrapVueExtend(definition) { if (typeof definition === 'object' && definition.render && !definition.__alreadyPatched) { const originalRender = definition.render definition.__alreadyPatched = true @@ -116,9 +118,9 @@ if (isVue3) { } } return originalExtend.call(this, definition) - } + }.bind(Vue) } const nextTick = Vue.nextTick -export { COMPONENT_UID_KEY, Vue, mergeData, isVue3, nextTick } +export { COMPONENT_UID_KEY, Vue, mergeData, isVue3, nextTick, extend } From 56cdff4233ff80aaf203a65d935b96268d88605c Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Thu, 6 Oct 2022 17:45:31 +0300 Subject: [PATCH 28/34] chore(form-radio): remove useless watcher --- src/components/form-radio/form-radio.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/components/form-radio/form-radio.js b/src/components/form-radio/form-radio.js index f6565751c85..a040cf5529a 100644 --- a/src/components/form-radio/form-radio.js +++ b/src/components/form-radio/form-radio.js @@ -29,12 +29,5 @@ export const BFormRadio = /*#__PURE__*/ extend({ bvGroup() { return this.getBvGroup() } - }, - watch: { - computedLocalChecked(newValue, oldValue) { - if (!looseEqual(newValue, oldValue)) { - this.$emit(MODEL_EVENT_NAME, newValue) - } - } } }) From 975e4de022f2eec136d366758d0818066d12f1ab Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Wed, 12 Oct 2022 22:57:55 +0300 Subject: [PATCH 29/34] chore(ci): update prepare scripts --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d603c00d1cf..a494ebcd0c7 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "docs-gen": "cross-env NODE_ENV=docs nuxt generate -c docs/nuxt.config.js", "lint": "eslint --ext .js,.md,.vue ./", "postinstall": "opencollective || exit 0", - "prepare": "husky install", + "prepare": "husky install && yarn run build", "prettify": "prettier --write '**/*.{js,json,md,scss,ts,vue}'", "release": "yarn run prettify && yarn run test && yarn run build && yarn run release-notes && standard-version", "release-notes": "jiti ./scripts/release-notes", From d9cd8601ab562c13619b0e08af1acbf92c5abf1d Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Sat, 15 Oct 2022 22:14:31 +0300 Subject: [PATCH 30/34] chore: bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a494ebcd0c7..a3cc8499a39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bootstrap-vue", - "version": "2.22.0", + "version": "2.23.0", "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", From 7462a497915818795bd056a2f64fcf82e41ff783 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Mon, 24 Oct 2022 15:12:13 +0300 Subject: [PATCH 31/34] chore: bump @vue/test-utils version --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a3cc8499a39..01d925e89f6 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "@vue/compat": "^3.2.40", "@vue/compiler-dom": "^3.2.40", "@vue/test-utils": "^1.3.0", - "@vue/test-utils-vue3": "npm:@vue/test-utils@2.1.0", + "@vue/test-utils-vue3": "npm:@vue/test-utils@2.2.0", "autoprefixer": "^10.4.0", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "^10.1.0", diff --git a/yarn.lock b/yarn.lock index 20b8a8e9183..5182e828749 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2807,10 +2807,10 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.40.tgz#e57799da2a930b975321981fcee3d1e90ed257ae" integrity sha512-0PLQ6RUtZM0vO3teRfzGi4ltLUO5aO+kLgwh4Um3THSR03rpQWLTuRCkuO5A41ITzwdWeKdPHtSARuPkoo5pCQ== -"@vue/test-utils-vue3@npm:@vue/test-utils@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.1.0.tgz#c2f646aa2d6ac779f79a83f18c5b82fc40952bfd" - integrity sha512-U4AxAD/tKJ3ajxYew1gkfEotpr96DE/gLXpbl+nPbsNRqGBfQZZA7YhwGoQNDPgon56v+IGZDrYq7pe3GDl9aw== +"@vue/test-utils-vue3@npm:@vue/test-utils@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.2.0.tgz#3d8fc020802db9b726e2d91b6e3fb5b21aa0bf0c" + integrity sha512-EKp5/N7ieNZdoLTkD16j/irUjIEDN63QUIc41vLUMqGvSsTQN0QxbFiQqh5v49RPfS5vZH+DhjNUEkijCMOCSg== "@vue/test-utils@^1.3.0": version "1.3.0" From b69b4c5ad8c39780fb2eca4c7b63e11b0d80559e Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Mon, 24 Oct 2022 23:00:09 +0300 Subject: [PATCH 32/34] chore(vue3): use vue-test-utils-compat v0.0.6 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 01d925e89f6..a1fcd547bec 100644 --- a/package.json +++ b/package.json @@ -154,7 +154,7 @@ "vue-router": "^3.5.1", "vue-server-renderer": "^2.6.12", "vue-template-compiler": "^2.6.12", - "vue-test-utils-compat": "0.0.3" + "vue-test-utils-compat": "0.0.6" }, "keywords": [ "Bootstrap", diff --git a/yarn.lock b/yarn.lock index 5182e828749..9ffe8e662d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14876,10 +14876,10 @@ vue-template-es2015-compiler@^1.9.0: resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== -vue-test-utils-compat@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/vue-test-utils-compat/-/vue-test-utils-compat-0.0.3.tgz#d3efb08b049e97fc4577bdb1a93e417f546c2651" - integrity sha512-2zFkkcoirkp2FTrO7y2y4fZ9ZJ3WaoPoxwAZ7MmptlUhLchxbcay1KJ8t9qdJS1PHnu6aF98mD0Dn0jMQGoDGQ== +vue-test-utils-compat@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/vue-test-utils-compat/-/vue-test-utils-compat-0.0.6.tgz#3600c63dc8175167641f7af170918e59354e6a79" + integrity sha512-yr/PpRQeJU0xkV7d0OVThE+YeY6FgsB8+Bj9X7Z3vY6PUFthDXNfOJPHx2JIPO4l1TQ0kZ7mlOVQmDduLiBP1Q== vue@^2.6.12: version "2.6.12" From b4424713dc7f0719a7c3a74a2d39ef26593e206f Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Mon, 24 Oct 2022 23:10:01 +0300 Subject: [PATCH 33/34] chore: remove unused vars --- src/components/form-radio/form-radio.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/form-radio/form-radio.js b/src/components/form-radio/form-radio.js index a040cf5529a..02b75dd9d10 100644 --- a/src/components/form-radio/form-radio.js +++ b/src/components/form-radio/form-radio.js @@ -1,12 +1,7 @@ import { extend } from '../../vue' import { NAME_FORM_RADIO } from '../../constants/components' -import { looseEqual } from '../../utils/loose-equal' import { makePropsConfigurable } from '../../utils/props' -import { - MODEL_EVENT_NAME, - formRadioCheckMixin, - props as formRadioCheckProps -} from '../../mixins/form-radio-check' +import { formRadioCheckMixin, props as formRadioCheckProps } from '../../mixins/form-radio-check' // --- Props --- From 6ef2ba4cc161125a703c8953975bd68020ab3807 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Tue, 25 Oct 2022 00:08:38 +0300 Subject: [PATCH 34/34] chore: ignore vue3-specific code --- src/utils/element-to-vue-instance-registry.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/element-to-vue-instance-registry.js b/src/utils/element-to-vue-instance-registry.js index a07c7f35598..b6956de09c2 100644 --- a/src/utils/element-to-vue-instance-registry.js +++ b/src/utils/element-to-vue-instance-registry.js @@ -30,6 +30,7 @@ export const getInstanceFromElement = element => { while (currentElement) { if (registry.has(currentElement)) { + /* istanbul ignore next */ return registry.get(currentElement) } currentElement = currentElement.parentNode