Skip to content

Commit

Permalink
feat(config): improved defaults handling (closes #4507, #5138, #5291, #…
Browse files Browse the repository at this point in the history
…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 authored Nov 7, 2020
1 parent 84366bf commit 7ea0cc4
Show file tree
Hide file tree
Showing 164 changed files with 4,999 additions and 5,121 deletions.
7 changes: 5 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
11 changes: 5 additions & 6 deletions docs/components/componentdoc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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>
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 0 additions & 2 deletions docs/content.js
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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 }
92 changes: 76 additions & 16 deletions docs/markdown/reference/settings/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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']
})
Expand All @@ -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' }
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions docs/pages/docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
bootstrapVersion,
bootstrapVersionMajor,
bootstrapVersionMinor,
defaultConfig,
nuxtVersion,
nuxtVersionMajor,
nuxtVersionMinor,
Expand Down Expand Up @@ -45,7 +44,6 @@ export default {
bootstrapVersionMinor,
bootstrapVersionMajor,
bootstrapIconsCount,
defaultConfig,
nuxtVersion,
nuxtVersionMinor,
nuxtVersionMajor,
Expand Down
12 changes: 3 additions & 9 deletions docs/pages/docs/reference/_slug.js
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -11,8 +10,6 @@ const getReadmeData = name => {
}
}

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

// @vue/component
export default {
name: 'BDVReference',
Expand All @@ -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) {
Expand Down
47 changes: 25 additions & 22 deletions src/components/alert/alert.js
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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,