Skip to content
Permalink
Browse files
feat(config): improved defaults handling (closes #4507, #5138, #5291, #…
…5459, #5958) (#5981)

* specify support of sidebar + array

* Initial Concept

* remove test code

* Remove `config-default.js`

* Update componentdoc.vue

* Update bootstrap-vue.js

* feat(config): code improvements

* fix: fallback config handling for date/time components

* update calendar.js

* feat(config): make all props configurable [WIP]

* Update aspect.js

* Update avatar-group.js

* Update avatar.js

* Update form-datepicker.js

* fix(config): default value handling in `makePropsConfigurable()`

* Update config.spec.js

* Update config.js

* Update componentdoc.vue

* Apply `makePropsConfigurable` to all components

* Update object.js

* Update object.js

* fix linting errors

* Revert "fix linting errors"

This reverts commit 786886f.

* Update form-input.js

* Update form-spinbutton.js

* fix(form-file): `fileNameFormatter` prop handling

* fix: property `validator` context

* Update form-tags.js

* Update pagination-nav.js

* Update toast.js

* Update button.js

* Update calendar.js

* Update bv-modal.js

* Update form-size.js

* Update mixin-selectable.js

* Update mixin-tfoot.js

* Update mixin-thead.js

* Update bv-toast.js

* Update popover.js

* Update tooltip.js

* Update tbody.js

* Update td.js

* Update tfoot.js

* Update thead.js

* Update tr.js

* Update pagination.js

* Update button-group.js

* Update button.js

* Update form-datepicker.js

* Update form-timepicker.js

* Update time.js

* Update button-toolbar.js

* Update calendar.js

* Update form-file.js

* Update form-rating.js

* Update mixin-options.js

* Update form-spinbutton.js

* Update form-tags.js

* Update nav-item.js

* Update mixin-busy.js

* Update mixin-caption.js

* Update mixin-empty.js

* Update mixin-filtering.js

* Update mixin-items.js

* Update mixin-pagination.js

* Update mixin-provider.js

* Update mixin-sorting.js

* Update mixin-stacked.js

* Update mixin-table-renderer.js

* Update mixin-tbody-row.js

* Update icon.js

* Update iconstack.js

* Update card.js

* Update dropdown.js

* Update form-options.js

* Update form-radio-check-group.js

* Update form-radio-check.js

* Update form-text.js

* Update form.js

* Update mixin-filtering.js

* Update pagination.js

* Update form-text.js

* Update modal.js

* chore: remove redundant istanbul ignores

* fix: add back some istanbul ignore

* fix(config): ensure props from mixins are configurabel via component config

* fix: resuse `form-plain` mixin everywhere

* feat: improve form control mixins

* Update README.md

* Update componentdoc.vue

* Update SECURITY.md

* Update README.md

* Update breadcrumb.js

* fix: size prop default value

* Update input-group.js

* fix(config): `makePropsConfigurable()` usage without key

* Update config.js

* Update config.js

* Update button-close.js

* Update toaster.js

* Update calendar.js

* Update carousel.js

* Update dropdown.js

* Update dropdown.spec.js

* Update img-lazy.js

* Update config.spec.js

* Update avatar.js

* feat: further improve shared form props usage

Co-authored-by: Jacob Müller <jacob.mueller.elz@gmail.com>
  • Loading branch information
Hiws and jacobmllr95 committed Nov 7, 2020
1 parent 84366bf commit 7ea0cc4a16d27b179eca47d351eaa9fe6fdfd56e
Show file tree
Hide file tree
Showing 164 changed files with 4,999 additions and 5,121 deletions.
@@ -10,8 +10,11 @@

## Reporting a Vulnerability

The BootstrapVue team takes security issues very seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
The BootstrapVue team takes security issues very seriously. We appreciate your efforts to
responsibly disclose your findings, and will make every effort to acknowledge your contributions.

To report a security issue, email [bootstrapvue.js@gmail.com](mailto:security@bootstrapvue.js@gmail.com) and include the word "SECURITY" in the subject line.
To report a security issue, email
[bootstrapvue.js@gmail.com](mailto:security@bootstrapvue.js@gmail.com) and include the word
"SECURITY" in the subject line.

We'll endeavor to respond quickly, and will keep you updated throughout the process.
@@ -85,6 +85,11 @@
<anchored-heading :id="`comp-ref-${componentName}-props`" level="4" class="mb-3">
Properties
</anchored-heading>

<p>
All property default values are <b-link href="/docs/reference/settings">globally configurable</b-link>.
</p>

<b-table
:items="propsItems"
:fields="propsFields"
@@ -98,7 +103,6 @@
<template #cell(prop)="{ value, item }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code><br>
<b-badge v-if="item.required" variant="info">Required</b-badge>
<b-badge v-if="item.settings" variant="dark" href="/docs/reference/settings" title="Configurable in settings">Settings</b-badge>
<b-badge v-if="item.version" variant="secondary">v{{ item.version }}+</b-badge>
<b-badge v-if="item.isVModel" variant="primary">v-model</b-badge>
<b-badge v-if="item.xss" variant="warning">Use with caution</b-badge>
@@ -298,7 +302,6 @@
<script>
import Vue from 'vue'
import commonProps from '../common-props.json'
import { defaultConfig } from '../content'
import { getComponentName, getCleanComponentName, kebabCase } from '../utils'
import AnchoredHeading from './anchored-heading'
@@ -425,7 +428,6 @@ export default {
propsItems() {
const props = this.componentProps
const propsMetaObj = this.componentPropsMetaObj
const componentSettings = defaultConfig[this.componentOptions.name] || {}
return Object.keys(props).map(prop => {
const p = props[prop]
@@ -457,16 +459,13 @@ export default {
? ''
: String(JSON.stringify(defaultValue, undefined, 1)).replace(/"/g, "'")
const settings = Object.prototype.hasOwnProperty.call(componentSettings, prop)
return {
prop: kebabCase(prop),
type,
defaultValue,
required: p.required || false,
description: meta.description || '',
version: meta.version || '',
settings,
xss: /[a-z]Html$/.test(prop),
isVModel: this.componentVModel && this.componentVModel.prop === prop,
deprecated: p.deprecated || false,
@@ -1,6 +1,5 @@
import { importAll, parseVersion, parseFullVersion } from '~/utils'
import { version, dependencies, devDependencies, description } from '~/../package.json'
import DEFAULT_CONFIG from '~/../src/utils/config-defaults'

const componentsContext = require.context('~/../src/components/', true, /package.json/)
export const components = importAll(componentsContext)
@@ -92,7 +91,6 @@ export const vueVersion = parseVersion(devDependencies.vue)
export const vueVersionMinor = vueVersion.replace(minorRE, '$1')
export const vueVersionMajor = vueVersion.replace(majorRE, '$1')

export const defaultConfig = DEFAULT_CONFIG
export const bvDescription = description

export { version }
@@ -14,14 +14,76 @@ Note that it is not possible to change the defaults when using BootstrapVue via

### Default configuration

Default breakpoint names are stored in the `breakpoints` property, default form control size is
stored under the `formControls` property, while component specific defaults are keyed by their
<samp>PascalCase</samp> name with the props as <samp>camelCase</samp> properties. Only properties
defined in the default configuration can be overridden. Attempting to set a config property that is
not defined in the default will generate a console warning.
Default breakpoint names are stored in the `breakpoints` property and all other shared component
configurations (like `formControls`) are listed below.

Component specific defaults are keyed by their `PascalCase` name with the props as `camelCase`
properties.

```json
{{ defaultConfig }}
{
// Breakpoint configuration
"breakpoints": ["xs", "sm", "md", "lg", "xl"],
// Shared component configuration
"formControls": {
"disabled": undefined,
"required": false,
"form": undefined,
"autofocus": false,
"plain": false,
"size": undefined
},
"formOptionControls": {
"options": [],
"valueField": "value",
"textField": "text",
"htmlField": "html",
"disabledField": "disabled"
},
"formRadioCheckGroups": {
"validated": false,
"ariaInvalid": false,
"stacked": false,
"buttons": false,
"buttonVariant": undefined,
"plain": false
},
"formRadioCheckControls": {
"value": undefined,
"checked": undefined,
"inline": false,
"button": false,
"buttonVariant": undefined,
"ariaLabel": undefined,
"ariaLabelledby": undefined,
"plain": false
},
"formState": {
"state": null
},
"formTextControls": {
"value": "",
"ariaInvalid": false,
"readonly": false,
"plaintext": false,
"autocomplete": undefined,
"placeholder": undefined,
"formatter": undefined,
"lazyFormatter": false,
"trim": false,
"number": false,
"lazy": false,
"debounce": 0
},
// Component configuration
"BAlert": {
"variant": "info"
// ...
}
// ...
}
```

### Setting new configuration values
@@ -30,11 +92,12 @@ When you `Vue.use(BootstrapVue)`, you can optionally pass a configuration object
values to replace the default values. For example if you wish to define new breakpoint names (which
will generate appropriate properties on components such as `<b-col>` and `<b-form-group>`), so that
the new breakpoints are `['aa', 'bb', 'cc', 'dd']` then `<b-col>` will now have `bb`, `cc`, and `dd`
props instead of `sm`, `md`, `lg` and `xl` props (Similar for the `label-cols-{breakpoint}` and
`label-align-{breakpoint}`props on `<b-form-group>`):
props instead of `sm`, `md`, `lg` and `xl` props (similar for the `label-cols-{breakpoint}` and
`label-align-{breakpoint}` props on `<b-form-group>`):

```js
import BootstrapVue from 'bootstrap-vue'
Vue.use(BootstrapVue, {
breakpoints: [`xs`, 'sm', 'md', 'lg', 'xl', 'xxl']
})
@@ -44,6 +107,7 @@ Or if changing the default variants for `<b-button>` and `<b-alert>`:

```js
import BootstrapVue from 'bootstrap-vue'
Vue.use(BootstrapVue, {
BAlert: { variant: 'danger' },
BButton: { variant: 'primary' }
@@ -72,7 +136,6 @@ and subsequent changes to the breakpoints will **not** be reflected.
<!-- eslint-disable import/first, import/no-duplicates -->

```js
// Component group plugins
import { LayoutPlugin, AlertPlugin, ButtonPlugin } from 'bootstrap-vue'
// Supply configs via each plugin as it is `Vue.use()`'d
@@ -86,7 +149,6 @@ Vue.use(ButtonPlugin, { BButton: { variant: 'primary' } })
<!-- eslint-disable import/first, import/no-duplicates -->

```js
// Component group plugins
import { LayoutPlugin, AlertPlugin, ButtonPlugin } from 'bootstrap-vue'
// Supply complete config to first `Vue.use()`'d plugin
@@ -104,7 +166,6 @@ Vue.use(ButtonPlugin)
<!-- eslint-disable import/first, import/no-duplicates -->

```js
// BootstrapVue configuration helper plugin and Component group plugins
import { BVConfigPlugin, LayoutPlugin, AlertPlugin, ButtonPlugin } from 'bootstrap-vue'
// Supply complete config to the BVConfigPlugin helper plugin
@@ -125,7 +186,6 @@ Vue.use(ButtonPlugin)
<!-- eslint-disable import/first, import/no-duplicates -->

```js
// Import BootstrapVue configuration helper plugin and Individual components
import { BVConfigPlugin, BAlert, BButton, BRow, BCol } from 'bootstrap-vue'
// Supply complete config to the BVConfig helper plugin
@@ -161,12 +221,12 @@ in **Example 3** and **Example 4** above. The `BVConfigPlugin` plugin should be
entry point of your app, and **before** any `Vue.use()` of component plugins or `Vue.component()` or
individual components.

### Setting the config via Nuxt.js BootstrapVue plugin
### Setting the config via Nuxt.js module

Refer to the [Getting Started](/docs/#nuxtjs-plugin-module) documentation for information on passing
the config object to the Nuxt.js plugin module.
Refer to the [Getting Started](/docs/#nuxtjs-module) documentation for information on passing the
config object to the BootstrapVue Nuxt.js module.

## Disabling BootstrapVue console warnings
## Disabling console warnings

BootstrapVue will warn (via `console.warn()`) when you try and use a deprecated prop, or pass an
invalid value to certain props. These warnings are provided to help you ensure that your application
@@ -8,7 +8,6 @@ import {
bootstrapVersion,
bootstrapVersionMajor,
bootstrapVersionMinor,
defaultConfig,
nuxtVersion,
nuxtVersionMajor,
nuxtVersionMinor,
@@ -45,7 +44,6 @@ export default {
bootstrapVersionMinor,
bootstrapVersionMajor,
bootstrapIconsCount,
defaultConfig,
nuxtVersion,
nuxtVersionMinor,
nuxtVersionMajor,
@@ -1,7 +1,6 @@
import hljs from '~/utils/hljs'
import MainDocs from '~/components/main-docs'
import docsMixin from '~/plugins/docs-mixin'
import { reference as referenceMeta, defaultConfig } from '~/content'
import { reference as referenceMeta } from '~/content'

const getReadmeData = name => {
try {
@@ -11,8 +10,6 @@ const getReadmeData = name => {
}
}

const replacer = (key, value) => (typeof value === 'undefined' ? null : value)

// @vue/component
export default {
name: 'BDVReference',
@@ -25,11 +22,8 @@ export default {
const name = params.slug
const meta = referenceMeta[name]
const readmeData = (await getReadmeData(name)).default
let { titleLead = '', body = '', baseTOC = {}, loadError = false } = readmeData
body = body.replace(
'{{ defaultConfig }}',
hljs.highlight('json', JSON.stringify(defaultConfig || {}, replacer, 2)).value
)
const { titleLead = '', body = '', baseTOC = {}, loadError = false } = readmeData

return { meta, titleLead, body, baseTOC, loadError }
},
render(h) {
@@ -1,6 +1,6 @@
import Vue from '../../vue'
import { NAME_ALERT } from '../../constants/components'
import { getComponentConfig } from '../../utils/config'
import { makePropsConfigurable } from '../../utils/config'
import { requestAF } from '../../utils/dom'
import { isBoolean, isNumeric } from '../../utils/inspect'
import { toInteger } from '../../utils/number'
@@ -37,28 +37,31 @@ export const BAlert = /*#__PURE__*/ Vue.extend({
prop: 'show',
event: 'input'
},
props: {
variant: {
type: String,
default: () => getComponentConfig(NAME_ALERT, 'variant')
},
dismissible: {
type: Boolean,
default: false
},
dismissLabel: {
type: String,
default: () => getComponentConfig(NAME_ALERT, 'dismissLabel')
},
show: {
type: [Boolean, Number, String],
default: false
props: makePropsConfigurable(
{
variant: {
type: String,
default: 'info'
},
dismissible: {
type: Boolean,
default: false
},
dismissLabel: {
type: String,
default: 'Close'
},
show: {
type: [Boolean, Number, String],
default: false
},
fade: {
type: Boolean,
default: false
}
},
fade: {
type: Boolean,
default: false
}
},
NAME_ALERT
),
data() {
return {
countDown: 0,
@@ -1,6 +1,7 @@
import Vue from '../../vue'
import { NAME_ASPECT } from '../../constants/components'
import { RX_ASPECT, RX_ASPECT_SEPARATOR } from '../../constants/regex'
import { makePropsConfigurable } from '../../utils/config'
import { mathAbs } from '../../utils/math'
import { toFloat } from '../../utils/number'
import normalizeSlotMixin from '../../mixins/normalize-slot'
@@ -12,18 +13,21 @@ const CLASS_NAME = 'b-aspect'
export const BAspect = /*#__PURE__*/ Vue.extend({
name: NAME_ASPECT,
mixins: [normalizeSlotMixin],
props: {
aspect: {
// Accepts a number (i.e. `16 / 9`, `1`, `4 / 3`)
// Or a string (i.e. '16/9', '16:9', '4:3' '1:1')
type: [Number, String],
default: '1:1'
props: makePropsConfigurable(
{
aspect: {
// Accepts a number (i.e. `16 / 9`, `1`, `4 / 3`)
// Or a string (i.e. '16/9', '16:9', '4:3' '1:1')
type: [Number, String],
default: '1:1'
},
tag: {
type: String,
default: 'div'
}
},
tag: {
type: String,
default: 'div'
}
},
NAME_ASPECT
),
computed: {
padding() {
const aspect = this.aspect

0 comments on commit 7ea0cc4

Please sign in to comment.