🌐 AI搜索 & 代理 主页
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
834a4a2
feat(b-aspect): new custom component `<b-aspect>`
tmorehouse Mar 25, 2020
0c4c2d8
Update aspect.js
tmorehouse Mar 25, 2020
b163bb7
Update aspect.js
tmorehouse Mar 25, 2020
e74022e
Update aspect.spec.js
tmorehouse Mar 25, 2020
c13e65d
Update aspect.spec.js
tmorehouse Mar 25, 2020
f77f434
Update aspect.js
tmorehouse Mar 25, 2020
5878eb0
Update aspect.spec.js
tmorehouse Mar 25, 2020
3465799
Update aspect.spec.js
tmorehouse Mar 25, 2020
4f93b8d
Update index.d.ts
tmorehouse Mar 25, 2020
e23d563
Update index.js
tmorehouse Mar 25, 2020
06f1c43
Update index.js
tmorehouse Mar 25, 2020
31e1f05
Update package.json
tmorehouse Mar 25, 2020
f1c2896
Update package.json
tmorehouse Mar 25, 2020
9ba4a17
Update README.md
tmorehouse Mar 25, 2020
e998b03
Update aspect.js
tmorehouse Mar 25, 2020
7beb145
Update aspect.js
tmorehouse Mar 25, 2020
b72bbe9
Update aspect.spec.js
tmorehouse Mar 25, 2020
a842110
Update package.json
tmorehouse Mar 25, 2020
4250072
Update README.md
tmorehouse Mar 25, 2020
8c3022b
Update README.md
tmorehouse Mar 25, 2020
cc27794
Update README.md
tmorehouse Mar 25, 2020
c6afe70
Update README.md
tmorehouse Mar 25, 2020
ebe560c
Update README.md
tmorehouse Mar 25, 2020
39699a3
Update README.md
tmorehouse Mar 25, 2020
cbda7ad
Update README.md
tmorehouse Mar 25, 2020
f1628ee
Update README.md
tmorehouse Mar 25, 2020
a06d252
Update README.md
tmorehouse Mar 25, 2020
0d32c81
Update package.json
tmorehouse Mar 25, 2020
071029d
Update README.md
tmorehouse Mar 25, 2020
9f1a587
Update README.md
tmorehouse Mar 25, 2020
86c5097
Update README.md
tmorehouse Mar 25, 2020
b241015
Merge branch 'dev' into feat-aspect
jacobmllr95 Mar 25, 2020
afdd7f1
Update aspect.js
jacobmllr95 Mar 25, 2020
794f603
Update README.md
jacobmllr95 Mar 25, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/components/aspect/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Aspect

> The `<b-aspect>` component can be used to maintain a minimum responsive aspect ratio for content.
> When the content is longer than the available height, then the component will expand vertically to
> fit all content. If the content is shorter than the computed aspect height, the component will
> ensure a minimum height is maintained.

## Overview

The `<b-aspect>` component was introduced in BootstrapVue `v2.9.0`.

The default [aspect](<https://en.wikipedia.org/wiki/Aspect_ratio_(image)>) ratio is `1:1` (ratio of
`1`), which makes the height always be at least the same as the width. The `aspect` prop can be used
to specify an arbitrary aspect ratio (i.e. `1.5`) or a ratio as a string such as `'16:9'` or
`'4:3'`.

The width will always be 100% of the available width in the parent element/component.

```html
<template>
<div>
<b-form-group label="Aspect ratio" label-for="ratio" label-cols-md="auto" class="mb-3">
<b-form-select id="ratio" v-model="aspect" :options="aspects"></b-form-input>
</b-form-group>
<b-card>
<b-aspect :aspect="aspect">
This will always be an aspect of "{{ aspect }}",
except when the content is too tall.
</b-aspect>
</b-card>
</div>
</template>

<script>
export default {
data() {
return {
aspect: '16:9',
aspects: [
{ text: '4:3 (SD)', value: '4:3' },
{ text: '1:1 (Square)', value: '1:1' },
{ text: '16:9 (HD)', value: '16:9' },
{ text: '1.85:1 (Widescreen)', value: '1.85:1' },
{ text: '2:1 (Univisium/Superscope)', value: '2:1' },
{ text: '21:9 (Anamorphic)', value: '21:9' },
{ text: '1.43:1 (IMAX)', value: '1.43:1' },
{ text: '3:2 (35mm Film)', value: '3:2' },
{ text: '3:1 (APS-P)', value: '3:1' },
{ text: '4/3 (Same as 4:3)', value: 4 / 3 },
{ text: '16/9 (Same as 16:9)', value: 16 / 9 },
{ text: '3 (Same as 3:1)', value: 3 },
{ text: '2 (Same as 2:1)', value: 2 },
{ text: '1.85 (Same as 1.85:1)', value: 1.85 },
{ text: '1.5', value: 1.5 },
{ text: '1 (Same as 1:1)', value: 1 }
]
}
}
}
</script>

<!-- b-aspect.vue -->
```

## See also

- [`<b-embed>` component](/docs/components/embed) for responsive embeds (videos, iframes, etc)
56 changes: 56 additions & 0 deletions src/components/aspect/aspect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Vue from '../../utils/vue'
import { toFloat } from '../../utils/number'
import normalizeSlotMixin from '../../mixins/normalize-slot'

// --- Constants ---
const NAME = 'BAspect'
const CLASS_NAME = 'b-aspect'

const RX_ASPECT = /^\d+(\.\d*)?[/:]\d+(\.\d*)?$/
const RX_SEPARATOR = /[/:]/

// --- Main Component ---
export const BAspect = /*#__PURE__*/ Vue.extend({
name: NAME,
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'
},
tag: {
type: String,
default: 'div'
}
},
computed: {
padding() {
const aspect = this.aspect
let ratio = 1
if (RX_ASPECT.test(aspect)) {
const [width, height] = aspect.split(RX_SEPARATOR).map(v => toFloat(v) || 1)
ratio = width / height
} else {
ratio = toFloat(aspect) || 1
}
return `${100 / Math.abs(ratio)}%`
}
},
render(h) {
const $sizer = h('div', {
staticClass: `${CLASS_NAME}-sizer flex-grow-1`,
style: { paddingBottom: this.padding, height: 0 }
})
const $content = h(
'div',
{
staticClass: `${CLASS_NAME}-content flex-grow-1 w-100 mw-100`,
style: { marginLeft: '-100%' }
},
[this.normalizeSlot('default')]
)
return h(this.tag, { staticClass: `${CLASS_NAME} d-flex` }, [$sizer, $content])
}
})
117 changes: 117 additions & 0 deletions src/components/aspect/aspect.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { mount } from '@vue/test-utils'
import { BAspect } from './aspect'

describe('aspect', () => {
it('should have expected default structure', async () => {
const wrapper = mount(BAspect)
expect(wrapper.isVueInstance()).toBe(true)
expect(wrapper.is('div')).toBe(true)
expect(wrapper.classes()).toContain('b-aspect')
expect(wrapper.classes()).toContain('d-flex')
expect(wrapper.classes().length).toBe(2)

const $sizer = wrapper.find('.b-aspect-sizer')
expect($sizer.exists()).toBe(true)
expect($sizer.is('div')).toBe(true)
expect($sizer.classes()).toContain('flex-grow-1')
// Default aspect ratio is 1:1
expect($sizer.attributes('style')).toContain('padding-bottom: 100%;')

const $content = wrapper.find('.b-aspect-content')
expect($content.exists()).toBe(true)
expect($content.is('div')).toBe(true)
expect($content.classes()).toContain('flex-grow-1')
expect($content.classes()).toContain('w-100')
expect($content.classes()).toContain('mw-100')
expect($content.attributes('style')).toContain('margin-left: -100%;')

wrapper.destroy()
})

it('should have expected structure when prop `tag` is set', async () => {
const wrapper = mount(BAspect, {
propsData: {
tag: 'section'
}
})
expect(wrapper.isVueInstance()).toBe(true)
expect(wrapper.is('section')).toBe(true)
expect(wrapper.classes()).toContain('b-aspect')
expect(wrapper.classes()).toContain('d-flex')
expect(wrapper.classes().length).toBe(2)

const $sizer = wrapper.find('.b-aspect-sizer')
expect($sizer.exists()).toBe(true)
expect($sizer.is('div')).toBe(true)
expect($sizer.classes()).toContain('flex-grow-1')
// Default aspect ratio is 1:1
expect($sizer.attributes('style')).toContain('padding-bottom: 100%;')

const $content = wrapper.find('.b-aspect-content')
expect($content.exists()).toBe(true)
expect($content.is('div')).toBe(true)
expect($content.classes()).toContain('flex-grow-1')
expect($content.classes()).toContain('w-100')
expect($content.classes()).toContain('mw-100')
expect($content.attributes('style')).toContain('margin-left: -100%;')

wrapper.destroy()
})

it('should have expected structure when aspect is set to "4:3"', async () => {
const wrapper = mount(BAspect, {
propsData: {
aspect: '4:3'
}
})
expect(wrapper.isVueInstance()).toBe(true)
expect(wrapper.is('div')).toBe(true)
expect(wrapper.classes()).toContain('b-aspect')
expect(wrapper.classes()).toContain('d-flex')
expect(wrapper.classes().length).toBe(2)

const $sizer = wrapper.find('.b-aspect-sizer')
expect($sizer.exists()).toBe(true)
expect($sizer.is('div')).toBe(true)
expect($sizer.classes()).toContain('flex-grow-1')
expect($sizer.attributes('style')).toContain('padding-bottom: 75%;')

const $content = wrapper.find('.b-aspect-content')
expect($content.exists()).toBe(true)
expect($content.is('div')).toBe(true)
expect($content.classes()).toContain('flex-grow-1')
expect($content.classes()).toContain('w-100')
expect($content.classes()).toContain('mw-100')
expect($content.attributes('style')).toContain('margin-left: -100%;')

wrapper.destroy()
})
it('should have expected structure when aspect is set to `16/9`', async () => {
const wrapper = mount(BAspect, {
propsData: {
aspect: 16 / 9
}
})
expect(wrapper.isVueInstance()).toBe(true)
expect(wrapper.is('div')).toBe(true)
expect(wrapper.classes()).toContain('b-aspect')
expect(wrapper.classes()).toContain('d-flex')
expect(wrapper.classes().length).toBe(2)

const $sizer = wrapper.find('.b-aspect-sizer')
expect($sizer.exists()).toBe(true)
expect($sizer.is('div')).toBe(true)
expect($sizer.classes()).toContain('flex-grow-1')
expect($sizer.attributes('style')).toContain('padding-bottom: 56.25%;')

const $content = wrapper.find('.b-aspect-content')
expect($content.exists()).toBe(true)
expect($content.is('div')).toBe(true)
expect($content.classes()).toContain('flex-grow-1')
expect($content.classes()).toContain('w-100')
expect($content.classes()).toContain('mw-100')
expect($content.attributes('style')).toContain('margin-left: -100%;')

wrapper.destroy()
})
})
11 changes: 11 additions & 0 deletions src/components/aspect/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// Aspect
//
import Vue from 'vue'
import { BvPlugin, BvComponent } from '../../'

// Plugin
export declare const AspectPlugin: BvPlugin

// Component: b-aspect
export declare class BAspect extends BvComponent {}
8 changes: 8 additions & 0 deletions src/components/aspect/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { BAspect } from './aspect'
import { pluginFactory } from '../../utils/plugins'

const AspectPlugin = /*#__PURE__*/ pluginFactory({
components: { BAspect }
})

export { AspectPlugin, BAspect }
21 changes: 21 additions & 0 deletions src/components/aspect/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@bootstrap-vue/aspect",
"version": "1.0.0",
"meta": {
"title": "Aspect",
"new": true,
"version": "2.9.0",
"description": "The `<b-aspect>` component can be used to maintain a minimum responsive aspect ratio for content.",
"components": [
{
"component": "BAspect",
"props": [
{
"prop": "aspect",
"description": "Aspect as a width to height numeric ratio (such as `1.5`) or `width:height` string (such as '16:9')"
}
]
}
]
}
}
4 changes: 4 additions & 0 deletions src/components/embed/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,8 @@ embedded element. Note that the type `iframe` does not support any children.
</div>
```

## See also

- [`<b-aspect>` component](/docs/components/aspect)

<!-- Component reference added automatically from component package.json -->
8 changes: 5 additions & 3 deletions src/components/form-spinbutton/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
> incrementing or decrementing a numerical value within a range of a minimum and maximum number,
> with optional step value.

`<b-form-spinbutton>` is
## Overview

`<b-form-spinbutton>` was introduced in BootstrapVue `v2.5.0`.

The component `<b-form-spinbutton>` is
[WAI-ARIA compliant](https://www.w3.org/TR/wai-aria-practices-1.2/#spinbutton), allowing for
[keyboard control](#accessibility), and supports both horizontal (default) and vertical layout.

Expand Down Expand Up @@ -33,8 +37,6 @@ Similar to [range type inputs](/docs/components/form-input#range-type-input), Bo
<!-- b-form-spinbutton-demo.vue -->
```

## Overview

The <kbd>ArrowUp</kbd> and <kbd>ArrowDown</kbd> keys can be used to increment or decrement the
value.

Expand Down
1 change: 0 additions & 1 deletion src/components/form-spinbutton/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"version": "1.0.0",
"meta": {
"title": "Form Spinbutton",
"new": true,
"version": "2.5.0",
"description": "BootstrapVue custom numerical spinbutton form input component, featuring WAI-ARIA accessibility (a11y) and internationalization (i18n)",
"components": [
Expand Down
1 change: 1 addition & 0 deletions src/components/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export declare const componentsPlugin: BvPlugin

// Export all components as named exports
export * from './alert'
export * from './aspect'
export * from './avatar'
export * from './badge'
export * from './breadcrumb'
Expand Down
2 changes: 2 additions & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { pluginFactory } from '../utils/plugins'

// Component group plugins
import { AlertPlugin } from './alert'
import { AspectPlugin } from './aspect'
import { AvatarPlugin } from './avatar'
import { BadgePlugin } from './badge'
import { BreadcrumbPlugin } from './breadcrumb'
Expand Down Expand Up @@ -53,6 +54,7 @@ import { TooltipPlugin } from './tooltip'
export const componentsPlugin = /*#__PURE__*/ pluginFactory({
plugins: {
AlertPlugin,
AspectPlugin,
AvatarPlugin,
BadgePlugin,
BreadcrumbPlugin,
Expand Down
4 changes: 4 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ export * from './icons/icons'
export { AlertPlugin } from './components/alert'
export { BAlert } from './components/alert/alert'

// export * from './components/aspect'
export { AspectPlugin } from './components/aspect'
export { BAspect } from './components/aspect/aspect'

// export * from './components/avatar'
export { AvatarPlugin } from './components/avatar'
export { BAvatar } from './components/avatar/avatar'
Expand Down