update to antd3.8.3 (#159)

* refactor: align

* feat:  update align to 2.4.3

* feat: update trigger 2.5.4

* feat: update tooltip 3.7.2

* fix: align

* feat: update vc-calendar to 9.6.2

* feat: update vc-checkbox to 2.1.5

* feat: update vc-dialog to 7.1.8

* feat: update vc-from to 2.2.1

* feat: update vc-notification to 3.1.1

* test: update snapshots

* feat: update vc-tree to 1.12.6

* feat: update vc-table to 6.2.8

* feat: update vc-upload to 2.5.1

* feat: update vc-input-number to 4.0.12

* feat: update vc-tabs to 9.2.6

* refactor: vc-menu

* refactor: update vc-menu to 7.0.5

* style: remove unused

* feat: update pagination to 1.16.5

* feat: add vc-progress 2.2.5 tag

* feat: add vc-rate 2.4.0 tag

* feat: update vc-slider to 8.6.1

* fix: tooltip error

* style: delete conosle

* feat: update vc-steps to 3.1.1

* add vc-switch tag 1.6.0

* feat: update upload to 2.5.1

* fix: update vc-menu

* fix: update store

* fix: add ref dir

* fix: trigger mock shouldComponentUpdate

* fix: update vc-select

* revert: trigger lazyrenderbox

* fix: update vc-select

* fix: update vc-select

* fix: update vc-select

* fix: update vc-menu

* fix: update vc-slick ref

* update style to 3.8.2

* test: update snapshots

* update vc-select

* update util & affix

* feat: add drawer

* fix: support title add slot mode

* test: update affix test

* update alert

* update anchor

* update snapshots

* fix: doc and vc-drawer

* update select & auto-complete

* update back-top & grid

* feractor: avatar

* test: add drawer test

* update badge

* update button

* update card

* update divider

* feat: update vc-tabs to 9.3.6 and tabs

* add afterEnter callback

* update form

* fix: update drawer

* test: update snapshots

* update modal & notification

* test: update snapshots

* update message

* update locale-provider

* update dropdown

* update layout popconfirm popover

* update time-picker

* update menu

* update date-picker

* docs: update input docs

* update input

* update snapshots

* update table

* update test snapshots

* feat: update progress

* update checkbox

* feat: update spin

* update radio

* docs: slider steps timeline

* update list

* update transfer

* update collapse

* update cascader

* update upload
pull/165/head 1.1.0-beta.0
tangjinzhou 2018-09-05 21:28:54 +08:00 committed by GitHub
parent 0b31163a6a
commit 5b55bac064
602 changed files with 16211 additions and 8236 deletions

View File

@ -1,2 +1,3 @@
node_modules/
**/*.spec.*
**/style/

View File

@ -1,7 +1,26 @@
import { getOptionProps } from './props-util'
export default {
directives: {
ref: {
bind: function (el, binding, vnode) {
binding.value(vnode.componentInstance ? vnode.componentInstance : vnode.elm)
},
update: function (el, binding, vnode) {
binding.value(vnode.componentInstance ? vnode.componentInstance : vnode.elm)
},
unbind: function (el, binding, vnode) {
binding.value(null)
},
},
},
methods: {
setState (state, callback) {
Object.assign(this.$data, typeof state === 'function' ? state(this.$data) : state)
const newState = typeof state === 'function' ? state(this.$data) : state
if (this.getDerivedStateFromProps) {
Object.assign(newState, this.getDerivedStateFromProps(getOptionProps(this), this.$data, true) || {})
}
Object.assign(this.$data, newState)
this.$nextTick(() => {
callback && callback()
})

View File

@ -2,10 +2,10 @@ export default {
install: (Vue, options) => {
Vue.directive('ant-ref', {
bind: function (el, binding, vnode) {
binding.value(vnode)
binding.value(vnode.componentInstance ? vnode.componentInstance : vnode.elm)
},
update: function (el, binding, vnode) {
binding.value(vnode)
binding.value(vnode.componentInstance ? vnode.componentInstance : vnode.elm)
},
unbind: function (el, binding, vnode) {
binding.value(null)

View File

@ -1,7 +1,7 @@
import animate from './css-animation'
const noop = () => {}
const getTransitionProps = (transitionName, opt = {}) => {
const { beforeEnter, enter, leave, afterLeave, appear = true, tag } = opt
const { beforeEnter, enter, afterEnter, leave, afterLeave, appear = true, tag } = opt
const transitionProps = {
props: {
appear,
@ -12,6 +12,7 @@ const getTransitionProps = (transitionName, opt = {}) => {
enter: enter || ((el, done) => {
animate(el, `${transitionName}-enter`, done)
}),
afterEnter: afterEnter || noop,
leave: leave || ((el, done) => {
animate(el, `${transitionName}-leave`, done)
}),

View File

@ -0,0 +1,4 @@
const isNumeric = (value) => {
return !isNaN(parseFloat(value)) && isFinite(value)
}
export default isNumeric

View File

@ -1,7 +1,5 @@
import cssAnimation from './css-animation'
import getRequestAnimationFrame, { cancelRequestAnimationFrame } from './getRequestAnimationFrame'
const reqAnimFrame = getRequestAnimationFrame()
import raf from 'raf'
function animate (node, show, done) {
let height
@ -19,16 +17,16 @@ function animate (node, show, done) {
},
active () {
if (requestAnimationFrameId) {
cancelRequestAnimationFrame(requestAnimationFrameId)
raf.cancel(requestAnimationFrameId)
}
requestAnimationFrameId = reqAnimFrame(() => {
requestAnimationFrameId = raf(() => {
node.style.height = `${show ? height : 0}px`
node.style.opacity = show ? 1 : 0
})
},
end () {
if (requestAnimationFrameId) {
cancelRequestAnimationFrame(requestAnimationFrameId)
raf.cancel(requestAnimationFrameId)
}
node.style.height = ''
node.style.opacity = ''

View File

@ -0,0 +1,47 @@
import PropTypes from './vue-types'
import { getOptionProps } from './props-util'
function getDisplayName (WrappedComponent) {
return WrappedComponent.name || 'Component'
}
export default function wrapWithConnect (WrappedComponent) {
const tempProps = WrappedComponent.props || {}
const methods = WrappedComponent.methods || {}
const props = {}
Object.keys(tempProps).forEach(k => { props[k] = PropTypes.any })
WrappedComponent.props.__propsSymbol__ = PropTypes.any
WrappedComponent.props.children = PropTypes.array.def([])
const ProxyWrappedComponent = {
props,
model: WrappedComponent.model,
name: `Proxy_${getDisplayName(WrappedComponent)}`,
methods: {
getProxyWrappedInstance () {
return this.$refs.wrappedInstance
},
},
render () {
const { $listeners, $slots = {}, $attrs } = this
const props = getOptionProps(this)
const wrapProps = {
props: {
...props,
__propsSymbol__: Symbol(),
children: $slots.default || [],
},
on: $listeners,
attrs: $attrs,
}
return (
<WrappedComponent {...wrapProps} ref='wrappedInstance'/>
)
},
}
Object.keys(methods).map(m => {
ProxyWrappedComponent.methods[m] = function () {
this.getProxyWrappedInstance()[m](...arguments)
}
})
return ProxyWrappedComponent
}

View File

@ -7,7 +7,7 @@ export default {
},
provide () {
return {
_store: this.$props,
storeContext: this.$props,
}
},
render () {

View File

@ -19,13 +19,16 @@ export default function connect (mapStateToProps) {
name: `Connect_${getDisplayName(WrappedComponent)}`,
props,
inject: {
_store: { default: {}},
storeContext: { default: {}},
},
data () {
this.store = this._store.store
this.store = this.storeContext.store
return {
subscribed: finnalMapStateToProps(this.store.getState(), this.$props),
}
},
watch: {
},
mounted () {
this.trySubscribe()
@ -41,8 +44,7 @@ export default function connect (mapStateToProps) {
}
const nextState = finnalMapStateToProps(this.store.getState(), this.$props)
if (!shallowEqual(this.nextState, nextState)) {
this.nextState = nextState
if (!shallowEqual(this.subscribed, nextState)) {
this.subscribed = nextState
}
},
@ -60,9 +62,12 @@ export default function connect (mapStateToProps) {
this.unsubscribe = null
}
},
getWrappedInstance () {
return this.$refs.wrappedInstance
},
},
render () {
const { $listeners, $slots, $attrs, $scopedSlots, subscribed, store } = this
const { $listeners, $slots = {}, $attrs, $scopedSlots, subscribed, store } = this
const props = getOptionProps(this)
const wrapProps = {
props: {
@ -72,11 +77,14 @@ export default function connect (mapStateToProps) {
},
on: $listeners,
attrs: $attrs,
slots: $slots,
scopedSlots: $scopedSlots,
}
return (
<WrappedComponent {...wrapProps}/>
<WrappedComponent {...wrapProps} ref='wrappedInstance'>
{Object.keys($slots).map(name => {
return <template slot={name}>{$slots[name]}</template>
})}
</WrappedComponent>
)
},
}

View File

@ -1,6 +1,4 @@
import getRequestAnimationFrame, { cancelRequestAnimationFrame } from '../_util/getRequestAnimationFrame'
const reqAnimFrame = getRequestAnimationFrame()
import raf from 'raf'
export default function throttleByAnimationFrame (fn) {
let requestId
@ -12,11 +10,11 @@ export default function throttleByAnimationFrame (fn) {
const throttled = (...args) => {
if (requestId == null) {
requestId = reqAnimFrame(later(args))
requestId = raf(later(args))
}
}
throttled.cancel = () => cancelRequestAnimationFrame(requestId)
throttled.cancel = () => raf.cancel(requestId)
return throttled
}

101
components/_util/wave.jsx Normal file
View File

@ -0,0 +1,101 @@
import TransitionEvents from './css-animation/Event'
export default {
name: 'Wave',
props: ['insertExtraNode'],
mounted () {
this.$nextTick(() => {
this.instance = this.bindAnimationEvent(this.$el)
})
},
beforeDestroy () {
if (this.instance) {
this.instance.cancel()
}
},
methods: {
isNotGrey (color) {
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/)
if (match && match[1] && match[2] && match[3]) {
return !(match[1] === match[2] && match[2] === match[3])
}
return true
},
onClick (node) {
if (node.className.indexOf('-leave') >= 0) {
return
}
this.removeExtraStyleNode()
const { insertExtraNode } = this.$props
const extraNode = document.createElement('div')
extraNode.className = 'ant-click-animating-node'
const attributeName = insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node'
node.removeAttribute(attributeName)
node.setAttribute(attributeName, 'true')
// Get wave color from target
const waveColor =
getComputedStyle(node).getPropertyValue('border-top-color') || // Firefox Compatible
getComputedStyle(node).getPropertyValue('border-color') ||
getComputedStyle(node).getPropertyValue('background-color')
// Not white or transparnt or grey
if (waveColor &&
waveColor !== '#ffffff' &&
waveColor !== 'rgb(255, 255, 255)' &&
this.isNotGrey(waveColor) &&
!/rgba\(\d*, \d*, \d*, 0\)/.test(waveColor) && // any transparent rgba color
waveColor !== 'transparent') {
extraNode.style.borderColor = waveColor
this.styleForPesudo = document.createElement('style')
this.styleForPesudo.innerHTML =
`[ant-click-animating-without-extra-node]:after { border-color: ${waveColor}; }`
document.body.appendChild(this.styleForPesudo)
}
if (insertExtraNode) {
node.appendChild(extraNode)
}
const transitionEnd = () => {
node.removeAttribute(attributeName)
this.removeExtraStyleNode()
if (insertExtraNode) {
node.removeChild(extraNode)
}
TransitionEvents.removeEndEventListener(node, transitionEnd)
}
TransitionEvents.addEndEventListener(node, transitionEnd)
},
bindAnimationEvent (node) {
if (node.getAttribute('disabled') ||
node.className.indexOf('disabled') >= 0) {
return
}
const onClick = (e) => {
// Fix radio button click twice
if (e.target.tagName === 'INPUT') {
return
}
setTimeout(() => this.onClick(node), 0)
}
node.addEventListener('click', onClick, true)
return {
cancel: () => {
node.removeEventListener('click', onClick, true)
},
}
},
removeExtraStyleNode () {
if (this.styleForPesudo && document.body.contains(this.styleForPesudo)) {
document.body.removeChild(this.styleForPesudo)
this.styleForPesudo = null
}
},
},
render () {
return this.$slots.default && this.$slots.default[0]
},
}

View File

@ -4,8 +4,8 @@ import { mount } from '@vue/test-utils'
const events = {}
const AffixMounter = {
props: ['offsetBottom', 'offsetTop'],
mounted () {
this.$refs.container.scrollTop = 100
this.$refs.container.addEventListener = jest.fn().mockImplementation((event, cb) => {
events[event] = cb
})
@ -35,6 +35,7 @@ const AffixMounter = {
<Affix
target={() => this.$refs.container}
ref='affix'
{...{ props: this.$props }}
>
<Button type='primary' >
Fixed at the top of container
@ -46,26 +47,70 @@ const AffixMounter = {
},
}
describe('Affix Render', () => {
let wrapper
beforeAll(() => {
document.body.innerHTML = ''
jest.useFakeTimers()
})
afterAll(() => {
jest.useRealTimers()
})
it('Affix render perfectly', () => {
const wrapper = mount(AffixMounter, { attachToDocument: true })
jest.runAllTimers()
const scrollTo = (top) => {
wrapper.vm.$refs.affix.$refs.fixedNode.parentNode.getBoundingClientRect = jest.fn(() => {
return {
bottom: 100, height: 28, left: 0, right: 0, top: -50, width: 195,
bottom: 100, height: 28, left: 0, right: 0, top: 50 - top, width: 195,
}
})
wrapper.vm.$refs.container.scrollTop = top
events.scroll({
type: 'scroll',
})
jest.runAllTimers()
}
it('Anchor render perfectly', () => {
wrapper = mount(AffixMounter, { attachToDocument: true })
jest.runAllTimers()
scrollTo(0)
expect(wrapper.vm.$refs.affix.affixStyle).toBe(null)
scrollTo(100)
expect(wrapper.vm.$refs.affix.affixStyle).not.toBe(null)
scrollTo(0)
expect(wrapper.vm.$refs.affix.affixStyle).toBe(null)
})
it('support offsetBottom', () => {
wrapper = mount(AffixMounter, { attachToDocument: true, propsData: {
offsetBottom: 0,
}})
jest.runAllTimers()
scrollTo(0)
expect(wrapper.vm.$refs.affix.affixStyle).not.toBe(null)
scrollTo(100)
expect(wrapper.vm.$refs.affix.affixStyle).toBe(null)
scrollTo(0)
expect(wrapper.vm.$refs.affix.affixStyle).not.toBe(null)
})
it('updatePosition when offsetTop changed', () => {
wrapper = mount(AffixMounter, { attachToDocument: true, propsData: {
offsetTop: 0,
}})
jest.runAllTimers()
scrollTo(100)
expect(wrapper.vm.$refs.affix.affixStyle.top).toBe('0px')
wrapper.setProps({
offsetTop: 10,
})
jest.runAllTimers()
expect(wrapper.vm.$refs.affix.affixStyle.top).toBe('10px')
})
})

View File

@ -11,13 +11,24 @@ The simplest usage.
```html
<template>
<div>
<a-affix>
<a-button type="primary">Affix top</a-button>
<a-affix :offsetTop="this.top">
<a-button type="primary" @click="()=>{this.top += 10}">Affix top</a-button>
</a-affix>
<br />
<a-affix :offsetBottom="0">
<a-button type="primary">Affix bottom</a-button>
<a-affix :offsetBottom="this.bottom">
<a-button type="primary" @click="()=>{this.bottom += 10}">Affix bottom</a-button>
</a-affix>
</div>
</template>
<script>
export default {
data() {
return {
top: 10,
bottom: 10,
}
}
}
</script>
```

View File

@ -36,8 +36,7 @@ function getOffset (element, target) {
}
function getDefaultTarget () {
return typeof window !== 'undefined'
? window : null
return typeof window !== 'undefined' ? window : null
}
// Affix
@ -88,12 +87,16 @@ export default {
},
watch: {
target (val) {
this.$nextTick(() => {
this.clearEventListeners()
this.setTargetEventListeners(val)
// Mock Event object.
this.updatePosition({})
})
this.clearEventListeners()
this.setTargetEventListeners(val)
// Mock Event object.
this.updatePosition({})
},
offsetTop (val) {
this.updatePosition({})
},
offsetBottom (val) {
this.updatePosition({})
},
},
beforeDestroy () {
@ -149,7 +152,9 @@ export default {
const targetNode = target()
// Backwards support
offsetTop = offsetTop || offset
// Fix: if offsetTop === 0, it will get undefined,
// if offsetBottom is type of number, offsetMode will be { top: false, ... }
offsetTop = typeof offsetTop === 'undefined' ? offset : offsetTop
const scrollTop = getScroll(targetNode, true)
const affixNode = this.$el
const elemOffset = getOffset(affixNode, targetNode)

View File

@ -1,2 +1,2 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';

View File

@ -2,33 +2,33 @@
exports[`renders ./components/alert/demo/banner.md correctly 1`] = `
<div>
<div class="ant-alert ant-alert-warning ant-alert-banner">
<div data-show="true" class="ant-alert ant-alert-warning ant-alert-banner">
<i class="anticon anticon-exclamation-circle ant-alert-icon"></i><span class="ant-alert-message">Warning text</span><span class="ant-alert-description"></span></div>
<br>
<div class="ant-alert ant-alert-warning ant-alert-banner">
<div data-show="true" class="ant-alert ant-alert-warning ant-alert-banner">
<i class="anticon anticon-exclamation-circle ant-alert-icon"></i><span class="ant-alert-message">Very long warning text warning text text text text text text text</span><span class="ant-alert-description"></span>
<a class="ant-alert-close-icon">
<i class="anticon anticon-cross"></i>
</a>
</div>
<br>
<div class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-banner"><span class="ant-alert-message">Warning text without icon</span><span class="ant-alert-description"></span></div>
<div data-show="true" class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-banner"><span class="ant-alert-message">Warning text without icon</span><span class="ant-alert-description"></span></div>
<br>
<div class="ant-alert ant-alert-error ant-alert-banner">
<div data-show="true" class="ant-alert ant-alert-error ant-alert-banner">
<i class="anticon anticon-cross-circle ant-alert-icon"></i><span class="ant-alert-message">Error text</span><span class="ant-alert-description"></span></div>
</div>
`;
exports[`renders ./components/alert/demo/basic.md correctly 1`] = `<div class="ant-alert ant-alert-success ant-alert-no-icon"><span class="ant-alert-message">Success Text</span><span class="ant-alert-description"></span></div>`;
exports[`renders ./components/alert/demo/basic.md correctly 1`] = `<div data-show="true" class="ant-alert ant-alert-success ant-alert-no-icon"><span class="ant-alert-message">Success Text</span><span class="ant-alert-description"></span></div>`;
exports[`renders ./components/alert/demo/closable.md correctly 1`] = `
<div>
<div class="ant-alert ant-alert-warning ant-alert-no-icon"><span class="ant-alert-message">Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text</span><span class="ant-alert-description"></span>
<div data-show="true" class="ant-alert ant-alert-warning ant-alert-no-icon"><span class="ant-alert-message">Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text</span><span class="ant-alert-description"></span>
<a class="ant-alert-close-icon">
<i class="anticon anticon-cross"></i>
</a>
</div>
<div class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon"><span class="ant-alert-message">Error Text</span><span class="ant-alert-description">Error Description Error Description Error Description Error Description Error Description Error Description</span>
<div data-show="true" class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon"><span class="ant-alert-message">Error Text</span><span class="ant-alert-description">Error Description Error Description Error Description Error Description Error Description Error Description</span>
<a class="ant-alert-close-icon">
<i class="anticon anticon-cross"></i>
</a>
@ -37,50 +37,60 @@ exports[`renders ./components/alert/demo/closable.md correctly 1`] = `
`;
exports[`renders ./components/alert/demo/close-text.md correctly 1`] = `
<div class="ant-alert ant-alert-info ant-alert-no-icon"><span class="ant-alert-message">Info Text</span><span class="ant-alert-description"></span>
<div data-show="true" class="ant-alert ant-alert-info ant-alert-no-icon"><span class="ant-alert-message">Info Text</span><span class="ant-alert-description"></span>
<a class="ant-alert-close-icon">Close Now</a>
</div>
`;
exports[`renders ./components/alert/demo/description.md correctly 1`] = `
<div>
<div class="ant-alert ant-alert-success ant-alert-with-description ant-alert-no-icon"><span class="ant-alert-message">Success Text</span><span class="ant-alert-description"><p>
<div data-show="true" class="ant-alert ant-alert-success ant-alert-with-description ant-alert-no-icon"><span class="ant-alert-message">Success Text</span><span class="ant-alert-description"><p>
Success Description <span style="color: red;">Success</span> Description Success Description
</p>
</span>
</div>
<div class="ant-alert ant-alert-info ant-alert-with-description ant-alert-no-icon"><span class="ant-alert-message">Info Text</span><span class="ant-alert-description">Info Description Info Description Info Description Info Description</span></div>
<div class="ant-alert ant-alert-warning ant-alert-with-description ant-alert-no-icon"><span class="ant-alert-message">Warning Text</span><span class="ant-alert-description">Warning Description Warning Description Warning Description Warning Description</span></div>
<div class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon"><span class="ant-alert-message">Error Text</span><span class="ant-alert-description">Error Description Error Description Error Description Error Description</span></div>
<div data-show="true" class="ant-alert ant-alert-info ant-alert-with-description ant-alert-no-icon"><span class="ant-alert-message">Info Text</span><span class="ant-alert-description">Info Description Info Description Info Description Info Description</span></div>
<div data-show="true" class="ant-alert ant-alert-warning ant-alert-with-description ant-alert-no-icon"><span class="ant-alert-message">Warning Text</span><span class="ant-alert-description">Warning Description Warning Description Warning Description Warning Description</span></div>
<div data-show="true" class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon"><span class="ant-alert-message">Error Text</span><span class="ant-alert-description">Error Description Error Description Error Description Error Description</span></div>
</div>
`;
exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
<div>
<div class="ant-alert ant-alert-success">
<div data-show="true" class="ant-alert ant-alert-success">
<i class="anticon anticon-check-circle ant-alert-icon"></i><span class="ant-alert-message">Success Tips</span><span class="ant-alert-description"></span></div>
<div class="ant-alert ant-alert-info">
<div data-show="true" class="ant-alert ant-alert-info">
<i class="anticon anticon-info-circle ant-alert-icon"></i><span class="ant-alert-message">Informational Notes</span><span class="ant-alert-description"></span></div>
<div class="ant-alert ant-alert-warning">
<div data-show="true" class="ant-alert ant-alert-warning">
<i class="anticon anticon-exclamation-circle ant-alert-icon"></i><span class="ant-alert-message">Warning</span><span class="ant-alert-description"></span></div>
<div class="ant-alert ant-alert-error">
<div data-show="true" class="ant-alert ant-alert-error">
<i class="anticon anticon-cross-circle ant-alert-icon"></i><span class="ant-alert-message">Error</span><span class="ant-alert-description"></span></div>
<div class="ant-alert ant-alert-success ant-alert-with-description">
<div data-show="true" class="ant-alert ant-alert-success ant-alert-with-description">
<i class="anticon anticon-check-circle-o ant-alert-icon"></i><span class="ant-alert-message">Success Tips</span><span class="ant-alert-description">Detailed description and advices about successful copywriting.</span></div>
<div class="ant-alert ant-alert-info ant-alert-with-description">
<div data-show="true" class="ant-alert ant-alert-info ant-alert-with-description">
<i class="anticon anticon-info-circle-o ant-alert-icon"></i><span class="ant-alert-message">Informational Notes</span><span class="ant-alert-description">Additional description and informations about copywriting.</span></div>
<div class="ant-alert ant-alert-warning ant-alert-with-description">
<div data-show="true" class="ant-alert ant-alert-warning ant-alert-with-description">
<i class="anticon anticon-exclamation-circle-o ant-alert-icon"></i><span class="ant-alert-message">Warning</span><span class="ant-alert-description">This is a warning notice about copywriting.</span></div>
<div class="ant-alert ant-alert-error ant-alert-with-description">
<div data-show="true" class="ant-alert ant-alert-error ant-alert-with-description">
<i class="anticon anticon-cross-circle-o ant-alert-icon"></i><span class="ant-alert-message">Error</span><span class="ant-alert-description">This is an error message about copywriting.</span></div>
</div>
`;
exports[`renders ./components/alert/demo/smooth-closed.md correctly 1`] = `
<div>
<div data-show="true" class="ant-alert ant-alert-success ant-alert-no-icon"><span class="ant-alert-message">Alert Message Text</span><span class="ant-alert-description"></span>
<a class="ant-alert-close-icon">
<i class="anticon anticon-cross"></i>
</a>
</div>
</div>
`;
exports[`renders ./components/alert/demo/style.md correctly 1`] = `
<div>
<div class="ant-alert ant-alert-success ant-alert-no-icon"><span class="ant-alert-message">Success Text</span><span class="ant-alert-description"></span></div>
<div class="ant-alert ant-alert-info ant-alert-no-icon"><span class="ant-alert-message">Info Text</span><span class="ant-alert-description"></span></div>
<div class="ant-alert ant-alert-warning ant-alert-no-icon"><span class="ant-alert-message">Warning Text</span><span class="ant-alert-description"></span></div>
<div class="ant-alert ant-alert-error ant-alert-no-icon"><span class="ant-alert-message">Error Text</span><span class="ant-alert-description"></span></div>
<div data-show="true" class="ant-alert ant-alert-success ant-alert-no-icon"><span class="ant-alert-message">Success Text</span><span class="ant-alert-description"></span></div>
<div data-show="true" class="ant-alert ant-alert-info ant-alert-no-icon"><span class="ant-alert-message">Info Text</span><span class="ant-alert-description"></span></div>
<div data-show="true" class="ant-alert ant-alert-warning ant-alert-no-icon"><span class="ant-alert-message">Warning Text</span><span class="ant-alert-description"></span></div>
<div data-show="true" class="ant-alert ant-alert-error ant-alert-no-icon"><span class="ant-alert-message">Error Text</span><span class="ant-alert-description"></span></div>
</div>
`;

View File

@ -0,0 +1,69 @@
import { mount } from '@vue/test-utils'
import Alert from '..'
describe('Alert', () => {
beforeAll(() => {
jest.useFakeTimers()
})
afterAll(() => {
jest.useRealTimers()
})
it('could be closed', () => {
const onClose = jest.fn()
const afterClose = jest.fn()
const wrapper = mount({
render () {
return <Alert
message='Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text'
type='warning'
closable
onClose={onClose}
afterClose={afterClose}
ref='alert'
/>
},
})
wrapper.find('.ant-alert-close-icon').trigger('click')
expect(onClose).toBeCalled()
jest.runAllTimers()
wrapper.vm.$refs.alert.animationEnd()
expect(afterClose).toBeCalled()
})
describe('data and aria props', () => {
it('sets data attributes on input', () => {
const wrapper = mount({
render () {
return <Alert data-test='test-id' data-id='12345' />
},
})
const input = wrapper.find('.ant-alert').element
expect(input.getAttribute('data-test')).toBe('test-id')
expect(input.getAttribute('data-id')).toBe('12345')
})
it('sets aria attributes on input', () => {
const wrapper = mount({
render () {
return <Alert aria-describedby='some-label' />
},
})
const input = wrapper.find('.ant-alert').element
expect(input.getAttribute('aria-describedby')).toBe('some-label')
})
it('sets role attribute on input', () => {
const wrapper = mount({
render () {
return <Alert role='status' />
},
})
const input = wrapper.find('.ant-alert').element
expect(input.getAttribute('role')).toBe('status')
})
})
})

View File

@ -6,6 +6,7 @@ import CloseText from './close-text'
import Description from './description'
import Icon from './icon'
import Style from './style'
import SmoothClosed from './smooth-closed'
import CN from '../index.zh-CN.md'
import US from '../index.en-US.md'
@ -21,7 +22,7 @@ const md = {
## When To Use
- When you need to show alert messages to users.
- When you need a persistent static container which is closable by user actions.
## Examples
## Examples
`,
}
export default {
@ -33,13 +34,14 @@ export default {
return (
<div id='components-alert-demo'>
<md cn={md.cn} us={md.us}/>
< Banner/>
<Banner/>
<Basic/>
<Closable/>
<CloseText/>
<Description/>
<Icon/>
<Style/>
<SmoothClosed/>
<api>
<CN slot='cn' />
<US/>

View File

@ -0,0 +1,37 @@
<cn>
#### 平滑地卸载
平滑、自然的卸载提示
</cn>
<us>
#### Smoothly Unmount
Smoothly and unaffectedly unmount Alert.
</us>
```html
<template>
<div>
<a-alert
v-if="visible"
message="Alert Message Text"
type="success"
closable
:afterClose="handleClose"
/>
</div>
</template>
<script>
export default {
data() {
return {
visible: true,
}
},
methods: {
handleClose(){
this.visible = false
}
}
}
</script>
```

View File

@ -8,9 +8,9 @@
| closable | Whether Alert can be closed | boolean | - |
| closeText | Close text to show | string\|slot | - |
| description | Additional content of Alert | string\|slot | - |
| iconType | Icon type, effective when `showIcon` is `true` | string | - |
| message | Content of Alert | string\|slot | - |
| showIcon | Whether to show icon | boolean | false, in `banner` mode default is true |
| iconType | Icon type, effective when `showIcon` is `true` | string | - |
| type | Type of Alert styles, options: `success`, `info`, `warning`, `error` | string | `info`, in `banner` mode default is `warning` |
### events

View File

@ -122,7 +122,7 @@ export default {
})
return closed ? null : (
<transition {...transitionProps}>
<div v-show={closing} class={alertCls}>
<div v-show={closing} class={alertCls} data-show={closing}>
{showIcon ? <Icon class={`${prefixCls}-icon`} type={iconType} /> : null}
<span class={`${prefixCls}-message`}>{message}</span>
<span class={`${prefixCls}-description`}>{description}</span>

View File

@ -3,14 +3,14 @@
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| afterClose | 关闭动画结束后的回掉 | () => void | - |
| afterClose | 关闭动画结束后触发的回调函数 | () => void | - |
| banner | 是否用作顶部公告 | boolean | false |
| closable | 默认不显示关闭按钮 | boolean | 无 |
| closeText | 自定义关闭按钮 | string\|slot | 无 |
| description | 警告提示的辅助性文字介绍 | string\|slot | 无 |
| iconType | 自定义图标类型,`showIcon` 为 `true` 时有效 | string | - |
| message | 警告提示内容 | string\|slot | 无 |
| showIcon | 是否显示辅助图标 | boolean | false`banner` 模式下默认值为 true |
| iconType | 自定义图标类型,`showIcon` 为 `true` 时有效 | string | - |
| type | 指定警告提示的样式,有四种选择 `success`、`info`、`warning`、`error` | string | `info``banner` 模式下默认值为 `warning` |
### 事件

View File

@ -1,2 +1,2 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';

View File

@ -5,6 +5,7 @@
@alert-message-color: @heading-color;
@alert-text-color: @text-color;
@alert-close-color: @text-color-secondary;
.@{alert-prefix-cls} {
.reset-component;
@ -70,7 +71,7 @@
cursor: pointer;
.@{iconfont-css-prefix}-cross {
color: @text-color-secondary;
color: @alert-close-color;
transition: color .3s;
&:hover {
color: #404040;
@ -87,7 +88,7 @@
padding: 15px 15px 15px 64px;
position: relative;
border-radius: @border-radius-base;
color: @text-color;
color: @alert-text-color;
line-height: @line-height-base;
}

View File

@ -1,39 +1,29 @@
import PropTypes from '../_util/vue-types'
import align from 'dom-align'
import { alignElement, alignPoint } from 'dom-align'
import addEventListener from '../_util/Dom/addEventListener'
import { isWindow, buffer, isSamePoint } from './util'
import { cloneElement } from '../_util/vnode.js'
import isWindow from './isWindow'
import clonedeep from 'lodash/cloneDeep'
import shallowequal from 'shallowequal'
function noop () {
function getElement (func) {
if (typeof func !== 'function' || !func) return null
return func()
}
function buffer (fn, ms) {
let timer
function clear () {
if (timer) {
clearTimeout(timer)
timer = null
}
}
function bufferFn () {
clear()
timer = setTimeout(fn, ms)
}
bufferFn.clear = clear
return bufferFn
function getPoint (point) {
if (typeof point !== 'object' || !point) return null
return point
}
export default {
props: {
childrenProps: PropTypes.object,
align: PropTypes.object.isRequired,
target: PropTypes.func.def(noop),
target: PropTypes.oneOfType([
PropTypes.func,
PropTypes.object,
]).def(() => window),
monitorBufferTime: PropTypes.number.def(50),
monitorWindowResize: PropTypes.bool.def(false),
disabled: PropTypes.bool.def(false),
@ -60,18 +50,36 @@ export default {
const prevProps = this.prevProps
const props = this.$props
let reAlign = false
if (!props.disabled && this.visible) {
if (prevProps.disabled || !shallowequal(prevProps.align, props.align)) {
if (!props.disabled && props.visible) {
const source = this.$el
const sourceRect = source ? source.getBoundingClientRect() : null
if (prevProps.disabled) {
reAlign = true
} else {
const lastTarget = prevProps.target()
const currentTarget = props.target()
if (isWindow(lastTarget) && isWindow(currentTarget)) {
const lastElement = getElement(prevProps.target)
const currentElement = getElement(props.target)
const lastPoint = getPoint(prevProps.target)
const currentPoint = getPoint(props.target)
if (isWindow(lastElement) && isWindow(currentElement)) {
// Skip if is window
reAlign = false
} else if (lastTarget !== currentTarget) {
} else if (
lastElement !== currentElement || // Element change
(lastElement && !currentElement && currentPoint) || // Change from element to point
(lastPoint && currentPoint && currentElement) || // Change from point to element
(currentPoint && !isSamePoint(lastPoint, currentPoint))
) {
reAlign = true
}
// If source element size changed
const preRect = this.sourceRect || {}
if (!reAlign && source && (preRect.width !== sourceRect.width || preRect.height !== sourceRect.height)) {
reAlign = true
}
}
this.sourceRect = sourceRect
}
if (reAlign) {
@ -106,11 +114,21 @@ export default {
},
forceAlign () {
const props = this.$props
if (!props.disabled) {
const { disabled, target, align } = this.$props
if (!disabled && target) {
const source = this.$el
let result
const element = getElement(target)
const point = getPoint(target)
if (element) {
result = alignElement(source, element, align)
} else if (point) {
result = alignPoint(source, point, align)
}
this.aligned = true
this.$listeners.align && this.$listeners.align(source, align(source, props.target(), props.align))
this.$listeners.align && this.$listeners.align(source, result)
}
},
},

View File

@ -0,0 +1,45 @@
<script>
import Align from '../index'
const align = {
points: ['cc', 'cc'],
}
export default {
data () {
return {
point: null,
}
},
methods: {
onClick ({ pageX, pageY }) {
this.point = { pageX, pageY }
},
},
render () {
return (
<div style={{ marginBottom: '170px' }}>
<div
style={{ margin: '20px', border: '1px solid red', padding: '100px 0', textAlign: 'center' }}
onClick={this.onClick}
>
Click this region please : )
</div>
<Align
target={this.point}
align={align}
>
<div
style={{ position: 'absolute', width: '100px', height: '100px', background: 'rgba(0, 255, 0, 0.5)', pointerEvents: 'none' }}
>Align</div>
</Align>
</div>
)
},
}
</script>

View File

@ -15,10 +15,10 @@ export default {
methods: {
getTarget () {
const ref = this.$refs.container
// if (!ref) {
// // parent ref not attached
// ref = document.getElementById('container')
// }
if (!ref) {
// parent ref not attached
return document.getElementById('container')
}
return ref
},
@ -29,9 +29,7 @@ export default {
},
forceAlign () {
this.setState({
align: Object.assign({}, this.$data.align),
})
this.$refs.align.forceAlign()
},
},
@ -43,9 +41,13 @@ export default {
}}
>
<p>
<button onClick={this.forceAlign}>force align</button>
<button onClick={this.forceAlign}>Force align</button>
&nbsp;&nbsp;&nbsp;
<button onClick={this.toggleMonitor}>toggle monitor</button>
<label>
<input type='checkbox' checked={this.monitor} onInput={this.toggleMonitor} />
&nbsp;
Monitor window resize
</label>
</p>
<div
ref='container'
@ -57,6 +59,7 @@ export default {
}}
>
<Align
ref='align'
target={this.getTarget}
monitorWindowResize={this.$data.monitor}
align={this.$data.align}

View File

@ -1,3 +1,3 @@
// based on vc-align 2.3.6
// based on vc-align 2.4.3
import Align from './Align'
export default Align

View File

@ -1,5 +0,0 @@
export default function isWindow (obj) {
/* eslint no-eq-null: 0 */
/* eslint eqeqeq: 0 */
return obj != null && obj == obj.window
}

38
components/align/util.js Normal file
View File

@ -0,0 +1,38 @@
export function buffer (fn, ms) {
let timer
function clear () {
if (timer) {
clearTimeout(timer)
timer = null
}
}
function bufferFn () {
clear()
timer = setTimeout(fn, ms)
}
bufferFn.clear = clear
return bufferFn
}
export function isSamePoint (prev, next) {
if (prev === next) return true
if (!prev || !next) return false
if ('pageX' in next && 'pageY' in next) {
return prev.pageX === next.pageX && prev.pageY === next.pageY
}
if ('clientX' in next && 'clientY' in next) {
return prev.clientX === next.clientX && prev.clientY === next.clientY
}
return false
}
export function isWindow (obj) {
return obj && typeof obj === 'object' && obj.window === obj
}

View File

@ -3,7 +3,7 @@ import classNames from 'classnames'
import addEventListener from '../_util/Dom/addEventListener'
import Affix from '../affix'
import getScroll from '../_util/getScroll'
import getRequestAnimationFrame from '../_util/getRequestAnimationFrame'
import raf from 'raf'
import { initDefaultProps, getClass, getStyle } from '../_util/props-util'
import BaseMixin from '../_util/BaseMixin'
@ -42,7 +42,6 @@ function easeInOutCubic (t, b, c, d) {
return cc / 2 * ((t -= 2) * t * t + 2) + b
}
const reqAnimFrame = getRequestAnimationFrame()
const sharpMatcherRegx = /#([^#]+)$/
function scrollTo (href, offsetTop = 0, getContainer, callback = () => { }) {
const container = getContainer()
@ -66,12 +65,12 @@ function scrollTo (href, offsetTop = 0, getContainer, callback = () => { }) {
container.scrollTop = nextScrollTop
}
if (time < 450) {
reqAnimFrame(frameFunc)
raf(frameFunc)
} else {
callback()
}
}
reqAnimFrame(frameFunc)
raf(frameFunc)
history.pushState(null, '', href)
}
@ -211,6 +210,7 @@ export default {
showInkInFixed,
activeLink,
$slots,
getContainer,
} = this
const inkClass = classNames(`${prefixCls}-ink-ball`, {
@ -243,7 +243,7 @@ export default {
)
return !affix ? anchorContent : (
<Affix offsetTop={offsetTop}>
<Affix offsetTop={offsetTop} target={getContainer}>
{anchorContent}
</Affix>
)

View File

@ -26,8 +26,8 @@ export default {
this.antAnchor.unregisterLink(this.href)
},
watch: {
href (val) {
this.antAnchor.unregisterLink(val)
href (val, oldVal) {
this.antAnchor.unregisterLink(oldVal)
this.antAnchor.registerLink(val)
},
},

View File

@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils'
import Vue from 'vue'
import { asyncExpect } from '@/tests/utils'
import Anchor from '..'
const { Link } = Anchor
@ -42,7 +43,7 @@ describe('Anchor Render', () => {
})
})
it('Anchor render perfectly for complete href - scoll', (done) => {
it('Anchor render perfectly for complete href - scroll', (done) => {
const wrapper = mount({
render () {
return (
@ -62,7 +63,8 @@ describe('Anchor Render', () => {
})
})
it('Anchor render perfectly for complete href - scollTo', (done) => {
it('Anchor render perfectly for complete href - scrollTo', async () => {
const scrollToSpy = jest.spyOn(window, 'scrollTo')
const wrapper = mount({
render () {
return (
@ -75,10 +77,78 @@ describe('Anchor Render', () => {
)
},
}, { sync: false, attachToDocument: true })
Vue.nextTick(() => {
await asyncExpect(() => {
wrapper.vm.$refs.anchor.handleScrollTo('##API')
expect(wrapper.vm.$refs.anchor.$data.activeLink).toBe('##API')
done()
expect(scrollToSpy).not.toHaveBeenCalled()
})
await asyncExpect(() => {
expect(scrollToSpy).toHaveBeenCalled()
}, 1000)
})
it('should remove listener when unmount', async () => {
const wrapper = mount({
render () {
return (
<Anchor ref='anchor'>
<Link href='#API' title='API' />
</Anchor>
)
},
}, { sync: false, attachToDocument: true })
await asyncExpect(() => {
const removeListenerSpy = jest.spyOn(wrapper.vm.$refs.anchor.scrollEvent, 'remove')
wrapper.destroy()
expect(removeListenerSpy).toHaveBeenCalled()
})
})
it('should unregister link when unmount children', async () => {
const wrapper = mount({
props: {
showLink: {
type: Boolean,
default: true,
},
},
render () {
return (
<Anchor ref='anchor'>
{this.showLink ? <Link href='#API' title='API' /> : null}
</Anchor>
)
},
}, { sync: false, attachToDocument: true })
await asyncExpect(() => {
expect(wrapper.vm.$refs.anchor.links).toEqual(['#API'])
wrapper.setProps({ showLink: false })
})
await asyncExpect(() => {
expect(wrapper.vm.$refs.anchor.links).toEqual([])
})
})
it('should update links when link href update', async () => {
const wrapper = mount({
props: ['href'],
render () {
return <Anchor ref='anchor'>
<Link href={this.href} title='API' />
</Anchor>
},
}, {
sync: false,
attachToDocument: true,
propsData: {
href: '#API',
}})
await asyncExpect(() => {
expect(wrapper.vm.$refs.anchor.links).toEqual(['#API'])
wrapper.setProps({ href: '#API_1' })
})
await asyncExpect(() => {
expect(wrapper.vm.$refs.anchor.links).toEqual(['#API_1'])
})
})
})

View File

@ -7,7 +7,7 @@
| -------- | ----------- | ---- | ------- |
| affix | Fixed mode of Anchor | boolean | true |
| bounds | Bounding distance of anchor area | number | 5(px) |
| getContainer | Scrolling container | () => HTMLElement | () => window |
| getContainer | Scrolling container | () => HTMLElement | () => window |
| offsetBottom | Pixels to offset from bottom when calculating position of scroll | number | - |
| offsetTop | Pixels to offset from top when calculating position of scroll | number | 0 |
| showInkInFixed | Whether show ink-balls in Fixed mode | boolean | false |

View File

@ -1,2 +1,2 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';

View File

@ -2,9 +2,9 @@
exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
<div class="ant-select ant-select-combobox ant-select-enabled ant-select-show-search ant-select-auto-complete" style="width: 200px;">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div unselectable="unselectable" class="ant-select-selection__placeholder" style="display: block;">input here</div>
<div unselectable="on" class="ant-select-selection__placeholder" style="display: block;">input here</div>
<ul>
<li class="ant-select-search ant-select-search--inline">
<div class="ant-select-search__field__wrap">
@ -17,10 +17,10 @@ exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
exports[`renders ./components/auto-complete/demo/certain-category.md correctly 1`] = `
<div class="certain-category-search-wrapper" style="width: 250px;">
<div class="certain-category-search ant-select-lg ant-select ant-select-combobox ant-select-enabled ant-select-lg ant-select-lg ant-select-show-search ant-select-auto-complete" style="width: 100%;">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" class="ant-select-selection ant-select-selection--single">
<div class="certain-category-search ant-select ant-select-combobox ant-select-enabled ant-select-lg ant-select-lg ant-select-show-search ant-select-auto-complete" style="width: 100%;">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div unselectable="unselectable" class="ant-select-selection__placeholder" style="display: block;">input here</div>
<div unselectable="on" class="ant-select-selection__placeholder" style="display: block;">input here</div>
<ul>
<li class="ant-select-search ant-select-search--inline">
<div class="ant-select-search__field__wrap"><span class="ant-input-affix-wrapper ant-select-search__field" value=""><input value="" type="text" class="ant-input"><span class="ant-input-suffix"><i class="certain-category-icon anticon anticon-search"></i></span></span><span class="ant-select-search__field__mirror">&nbsp;</span></div>
@ -33,7 +33,7 @@ exports[`renders ./components/auto-complete/demo/certain-category.md correctly 1
exports[`renders ./components/auto-complete/demo/custom.md correctly 1`] = `
<div class="ant-select ant-select-combobox ant-select-enabled ant-select-show-search ant-select-auto-complete" style="width: 200px;">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<ul>
<li class="ant-select-search ant-select-search--inline">
@ -47,9 +47,9 @@ exports[`renders ./components/auto-complete/demo/custom.md correctly 1`] = `
exports[`renders ./components/auto-complete/demo/non-case-sensitive.md correctly 1`] = `
<div class="ant-select ant-select-combobox ant-select-enabled ant-select-show-search ant-select-auto-complete" style="width: 200px;">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div unselectable="unselectable" class="ant-select-selection__placeholder" style="display: block;">input here</div>
<div unselectable="on" class="ant-select-selection__placeholder" style="display: block;">input here</div>
<ul>
<li class="ant-select-search ant-select-search--inline">
<div class="ant-select-search__field__wrap">
@ -62,9 +62,9 @@ exports[`renders ./components/auto-complete/demo/non-case-sensitive.md correctly
exports[`renders ./components/auto-complete/demo/options.md correctly 1`] = `
<div class="ant-select ant-select-combobox ant-select-enabled ant-select-show-search ant-select-auto-complete" style="width: 200px;">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div unselectable="unselectable" class="ant-select-selection__placeholder" style="display: block;">input here</div>
<div unselectable="on" class="ant-select-selection__placeholder" style="display: block;">input here</div>
<ul>
<li class="ant-select-search ant-select-search--inline">
<div class="ant-select-search__field__wrap">
@ -77,10 +77,10 @@ exports[`renders ./components/auto-complete/demo/options.md correctly 1`] = `
exports[`renders ./components/auto-complete/demo/uncertain-category.md correctly 1`] = `
<div class="global-search-wrapper" style="width: 300px;">
<div class="global-search ant-select-lg ant-select ant-select-combobox ant-select-enabled ant-select-lg ant-select-lg ant-select-show-search ant-select-auto-complete" style="width: 100%;">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" class="ant-select-selection ant-select-selection--single">
<div class="global-search ant-select ant-select-combobox ant-select-enabled ant-select-lg ant-select-lg ant-select-show-search ant-select-auto-complete" style="width: 100%;">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div unselectable="unselectable" class="ant-select-selection__placeholder" style="display: block;">input here</div>
<div unselectable="on" class="ant-select-selection__placeholder" style="display: block;">input here</div>
<ul>
<li class="ant-select-search ant-select-search--inline">
<div class="ant-select-search__field__wrap"><span class="ant-input-affix-wrapper ant-select-search__field" value=""><input value="" type="text" class="ant-input"><span class="ant-input-suffix"><button type="button" class="search-btn ant-btn ant-btn-primary ant-btn-lg"><i class="anticon anticon-search"></i></button></span></span>

View File

@ -22,9 +22,11 @@
### events
| Events Name | Description | Arguments |
| --- | --- | --- |
| onChange | Called when select an option or input value change, or value of input is changed | function(value) | - |
| onSearch | Called when searching items. | function(value) | - |
| onSelect | Called when a option is selected. param is option's value and option instance. | function(value, option) | - |
| change | Called when select an option or input value change, or value of input is changed | function(value) |
| blur | Called when leaving the component. | function() |
| focus | Called when entering the component | function() |
| search | Called when searching items. | function(value) | - |
| select | Called when a option is selected. param is option's value and option instance. | function(value, option) |
## Methods

View File

@ -39,6 +39,8 @@ export default {
showSearch: PropTypes.bool.def(false),
transitionName: PropTypes.string.def('slide-up'),
choiceTransitionName: PropTypes.string.def('zoom'),
autoFocus: PropTypes.bool,
backfill: PropTypes.bool,
optionLabelProp: PropTypes.string.def('children'),
filterOption: PropTypes.oneOfType([
PropTypes.bool,
@ -113,7 +115,7 @@ export default {
const selectProps = {
props: {
...getOptionProps(this),
mode: 'combobox',
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
optionLabelProp,
getInputElement: this.getInputElement,
notFoundContent: getComponentFromProp(this, 'notFoundContent'),

View File

@ -22,9 +22,11 @@
### 事件
| 事件名称 | 说明 | 回调参数 |
| --- | --- | --- |
| @change | 选中 option或 input 的 value 变化时,调用此函数 | function(value) |
| @search | 搜索补全项的时候调用 | function(value) |
| @select | 被选中时调用,参数为选中项的 value 值 | function(value, option) |
| change | 选中 option或 input 的 value 变化时,调用此函数 | function(value) |
| blur | 失去焦点时的回调 | function() |
| focus | 获得焦点时的回调 | function() |
| search | 搜索补全项的时候调用 | function(value) |
| select | 被选中时调用,参数为选中项的 value 值 | function(value, option) |
## 方法

View File

@ -1,4 +1,4 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';
import '../../select/style'
import '../../select/style';

View File

@ -13,85 +13,137 @@ export default {
default: 'circle',
},
size: {
validator: (val) => (['small', 'large', 'default'].includes(val)),
validator: (val) => {
return typeof val === 'number' || ['small', 'large', 'default'].includes(val)
},
default: 'default',
},
src: String,
icon: String,
alt: String,
loadError: Function,
},
data () {
return {
isExistSlot: false,
childrenWidth: 0,
isImgExist: true,
scale: 1,
}
},
computed: {
classes () {
const { prefixCls, shape, size, src, icon } = this
return {
[`${prefixCls}`]: true,
[`${prefixCls}-image`]: !!src,
[`${prefixCls}-icon`]: !!icon,
[`${prefixCls}-${shape}`]: true,
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-sm`]: size === 'small',
}
},
childrenStyle () {
let style = {}
const { scale, isExistSlot, childrenWidth } = this
if (isExistSlot) {
style = {
msTransform: `scale(${scale})`,
WebkitTransform: `scale(${scale})`,
transform: `scale(${scale})`,
position: 'absolute',
display: 'inline-block',
left: `calc(50% - ${Math.round(childrenWidth / 2)}px)`,
}
}
return style
},
},
methods: {
setScale () {
const { src, icon, $refs, $el } = this
const children = $refs.avatorChildren
this.isExistSlot = !src && !icon
if (children) {
this.childrenWidth = children.offsetWidth
const avatarWidth = $el.getBoundingClientRect().width
if (avatarWidth - 8 < this.childrenWidth) {
this.scale = (avatarWidth - 8) / this.childrenWidth
} else {
this.scale = 1
}
}
},
},
mounted () {
this.prevChildren = this.$slots.default
this.prevState = { ...this.$data }
this.$nextTick(() => {
this.setScale()
})
},
updated () {
this.$nextTick(() => {
this.setScale()
})
if (this.preChildren !== this.$slots.default ||
(this.prevState.scale !== this.$data.scale && this.$data.scale === 1) ||
(this.prevState.isImgExist !== this.$data.isImgExist)) {
this.$nextTick(() => {
this.setScale()
})
}
this.preChildren = this.$slots.default
this.prevState = { ...this.$data }
},
methods: {
setScale () {
const childrenNode = this.$refs.avatarChildren
if (childrenNode) {
const childrenWidth = childrenNode.offsetWidth
const avatarWidth = this.$el.getBoundingClientRect().width
if (avatarWidth - 8 < childrenWidth) {
this.scale = (avatarWidth - 8) / childrenWidth
} else {
this.scale = 1
}
this.$forceUpdate()
}
},
handleImgLoadError () {
const { loadError } = this.$props
const errorFlag = loadError ? loadError() : undefined
if (errorFlag !== false) {
this.isImgExist = false
}
},
},
render () {
const { classes, prefixCls, src, icon, childrenStyle, $slots, $listeners } = this
const {
prefixCls, shape, size, src, icon, alt,
} = this.$props
const { isImgExist, scale } = this.$data
const sizeCls = {
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-sm`]: size === 'small',
}
const classString = {
[prefixCls]: true,
...sizeCls,
[`${prefixCls}-${shape}`]: shape,
[`${prefixCls}-image`]: src && isImgExist,
[`${prefixCls}-icon`]: icon,
}
const sizeStyle = typeof size === 'number' ? {
width: `${size}px`,
height: `${size}px`,
lineHeight: `${size}px`,
fontSize: icon ? `${size / 2}px` : '18px',
} : {}
let children = this.$slots.default
if (src && isImgExist) {
children = (
<img
src={src}
onError={this.handleImgLoadError}
alt={alt}
/>
)
} else if (icon) {
children = <Icon type={icon} />
} else {
const childrenNode = this.$refs.avatarChildren
if (childrenNode || (scale !== 1 && childrenNode)) {
const childrenStyle = {
msTransform: `scale(${scale})`,
WebkitTransform: `scale(${scale})`,
transform: `scale(${scale})`,
position: 'absolute',
display: 'inline-block',
left: `calc(50% - ${Math.round(childrenNode.offsetWidth / 2)}px)`,
}
const sizeChildrenStyle = typeof size === 'number' ? {
lineHeight: `${size}px`,
} : {}
children = (
<span
class={`${prefixCls}-string`}
ref='avatarChildren'
style={{ ...sizeChildrenStyle, ...childrenStyle }}
>
{children}
</span>
)
} else {
children = (
<span
class={`${prefixCls}-string`}
ref='avatarChildren'
>
{children}
</span>
)
}
}
return (
<span {...{ on: $listeners, class: classes }}>
{src ? <img src={src}/>
: (icon ? <Icon type={icon} />
: <span
ref='avatorChildren'
class={prefixCls + '-string'}
style={childrenStyle}>
{$slots.default}
</span>) }
<span {...{ on: this.$listeners, class: classString, style: sizeStyle }}>
{children}
</span>
)
},

View File

@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils'
import { asyncExpect } from '@/tests/utils'
import Avatar from '..'
describe('Avatar Render', () => {
@ -11,4 +12,66 @@ describe('Avatar Render', () => {
const children = wrapper.findAll('.ant-avatar-string')
expect(children.length).toBe(1)
})
it('should render fallback string correctly', async () => {
global.document.body.innerHTML = ''
const wrapper = mount(Avatar, {
slots: {
default: 'Fallback',
},
propsData: {
src: 'http://error.url',
},
sync: false, attachToDocument: true,
})
wrapper.vm.setScale = jest.fn(() => { wrapper.setData({ scale: 0.5 }) })
await asyncExpect(() => {
wrapper.find('img').trigger('error')
}, 0)
await asyncExpect(() => {
const children = wrapper.findAll('.ant-avatar-string')
expect(children.length).toBe(1)
expect(children.at(0).text()).toBe('Fallback')
expect(wrapper.vm.setScale).toBeCalled()
})
// await asyncExpect(() => {
// console.log(wrapper.vm.scale, document.body.querySelector('.ant-avatar-string'))
// expect(global.document.body.querySelector('.ant-avatar-string').style.transform).toBe('scale(0.5)')
// global.document.body.innerHTML = ''
// }, 1000)
await asyncExpect(() => {
})
})
it('should handle onError correctly', () => {
global.document.body.innerHTML = ''
const LOAD_FAILURE_SRC = 'http://error.url'
const LOAD_SUCCESS_SRC = 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png'
const Foo = {
data () {
return {
src: LOAD_FAILURE_SRC,
}
},
methods: {
handleImgError () {
this.src = LOAD_SUCCESS_SRC
return false
},
},
render () {
const { src } = this
return <Avatar src={src} loadError={this.handleImgError} />
},
}
const wrapper = mount(Foo, { attachToDocument: true })
// mock img load Error, since jsdom do not load resource by default
// https://github.com/jsdom/jsdom/issues/1816
wrapper.find('img').trigger('error')
expect(wrapper.find({ name: 'AAvatar' }).vm.isImgExist).toBe(true)
expect(global.document.body.querySelector('img').getAttribute('src')).toBe(LOAD_SUCCESS_SRC)
})
})

View File

@ -1,31 +1,32 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
<div><span style="margin-right: 24px;"><span class="ant-badge"><span class="ant-avatar ant-avatar-icon ant-avatar-square"><i class="anticon anticon-user"></i></span>
<sup class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1100%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="current">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
<div><span style="margin-right: 24px;"><span class="ant-badge"><span class="ant-avatar ant-avatar-square ant-avatar-icon"><i class="anticon anticon-user"></i></span>
<sup title="1" class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1100%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="current">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
</span>
</span> <span class="ant-badge"><span class="ant-avatar ant-avatar-icon ant-avatar-square"><i class="anticon anticon-user"></i></span>
</span> <span><span class="ant-badge"><span class="ant-avatar ant-avatar-square ant-avatar-icon"><i class="anticon anticon-user"></i></span>
<sup class="ant-scroll-number ant-badge-dot ant-badge-zoom-enter"></sup>
</span>
</span>
</div>
`;
exports[`renders ./components/avatar/demo/basic.md correctly 1`] = `
<div>
<div><span class="ant-avatar ant-avatar-icon ant-avatar-circle ant-avatar-lg"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-icon ant-avatar-circle"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-icon ant-avatar-circle ant-avatar-sm"><i class="anticon anticon-user"></i></span></div>
<div><span class="ant-avatar ant-avatar-circle ant-avatar-icon" style="width: 64px; height: 64px; line-height: 64px; font-size: 32px;"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-lg ant-avatar-circle ant-avatar-icon"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-circle ant-avatar-icon"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-sm ant-avatar-circle ant-avatar-icon"><i class="anticon anticon-user"></i></span></div>
<br>
<div><span class="ant-avatar ant-avatar-icon ant-avatar-square ant-avatar-lg"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-icon ant-avatar-square"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-icon ant-avatar-square ant-avatar-sm"><i class="anticon anticon-user"></i></span></div>
<div><span class="ant-avatar ant-avatar-square ant-avatar-icon" style="width: 64px; height: 64px; line-height: 64px; font-size: 32px;"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-lg ant-avatar-square ant-avatar-icon"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-square ant-avatar-icon"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-sm ant-avatar-square ant-avatar-icon"><i class="anticon anticon-user"></i></span></div>
</div>
`;
exports[`renders ./components/avatar/demo/dynamic.md correctly 1`] = `
<div><span class="ant-avatar ant-avatar-square ant-avatar-lg" style="background-color: rgb(245, 106, 0);"><span class="ant-avatar-string">U</span></span>
<button type="button" class="ant-btn ant-btn-default"><span>改 变</span></button>
<div><span class="ant-avatar ant-avatar-lg ant-avatar-square" style="background-color: rgb(245, 106, 0); vertical-align: middle;"><span class="ant-avatar-string">U</span></span>
<button type="button" class="ant-btn ant-btn-default ant-btn-sm" style="vertical-align: middle;"><span>改 变</span></button>
</div>
`;
exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
<div><span class="ant-avatar ant-avatar-icon ant-avatar-circle"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-circle"><span class="ant-avatar-string">U</span></span> <span class="ant-avatar ant-avatar-circle"><span class="ant-avatar-string">USER</span></span>
<span class="ant-avatar ant-avatar-image ant-avatar-circle"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span> <span class="ant-avatar ant-avatar-circle" style="color: rgb(245, 106, 0); background-color: rgb(253, 227, 207);"><span class="ant-avatar-string">U</span></span>
<span class="ant-avatar ant-avatar-icon ant-avatar-circle" style="background-color: rgb(135, 208, 104);"><i class="anticon anticon-user"></i></span></div>
<div><span class="ant-avatar ant-avatar-circle ant-avatar-icon"><i class="anticon anticon-user"></i></span> <span class="ant-avatar ant-avatar-circle"><span class="ant-avatar-string">U</span></span> <span class="ant-avatar ant-avatar-circle"><span class="ant-avatar-string">USER</span></span>
<span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span> <span class="ant-avatar ant-avatar-circle" style="color: rgb(245, 106, 0); background-color: rgb(253, 227, 207);"><span class="ant-avatar-string">U</span></span>
<span class="ant-avatar ant-avatar-circle ant-avatar-icon" style="background-color: rgb(135, 208, 104);"><i class="anticon anticon-user"></i></span></div>
`;

View File

@ -11,8 +11,12 @@ Usually used for messages remind.
```html
<template>
<div>
<span style="marginRight:24px"><a-badge count=1><a-avatar shape="square" icon="user" /></a-badge></span>
<a-badge dot><a-avatar shape="square" icon="user" /></a-badge>
<span style="margin-right:24px">
<a-badge :count="1"><a-avatar shape="square" icon="user" /></a-badge>
</span>
<span>
<a-badge dot><a-avatar shape="square" icon="user" /></a-badge>
</span>
</div>
</template>
```

View File

@ -12,12 +12,14 @@ Three sizes and two shapes are available.
<template>
<div>
<div>
<a-avatar :size="64" icon="user" />
<a-avatar size="large" icon="user"/>
<a-avatar icon="user"/>
<a-avatar size="small" icon="user"/>
</div>
<br/>
<div>
<a-avatar shape="square" :size="64" icon="user" />
<a-avatar shape="square" size="large" icon="user" />
<a-avatar shape="square" icon="user" />
<a-avatar shape="square" size="small" icon="user" />

View File

@ -11,8 +11,8 @@ For letter type Avatar, when the letters are too long to display, the font size
```html
<template>
<div>
<a-avatar shape="square" size="large" :style="{'backgroundColor': color}">{{avatarValue}}</a-avatar>
<a-button @click="changeValue">改变</a-button>
<a-avatar shape="square" size="large" :style="{backgroundColor: color, verticalAlign: 'middle'}">{{avatarValue}}</a-avatar>
<a-button size="small" :style="{ marginLeft: 16, verticalAlign: 'middle' }" @click="changeValue">改变</a-button>
</div>
</template>
<script>

View File

@ -4,5 +4,8 @@
| -------- | ----------- | ---- | ------- |
| icon | the `Icon` type for an icon avatar, see `Icon` Component | string | - |
| shape | the shape of avatar | `circle` \| `square` | `circle` |
| size | the size of the avatar | `large` \| `small` \| `default` | `default` |
| size | the size of the avatar | number \| string: `large` `small` `default` | `default` |
| src | the address of the image for an image avatar | string | - |
| alt | This attribute defines the alternative text describing the image | string | - |
| loadError | handler when img load errorreturn false to prevent default fallback behavior | () => boolean | - |

View File

@ -4,5 +4,8 @@
| --- | --- | --- | --- |
| icon | 设置头像的图标类型,参考 `Icon` 组件 | string | - |
| shape | 指定头像的形状 | Enum{ 'circle', 'square' } | `circle` |
| size | 设置头像的大小 | Enum{ 'large', 'small', 'default' } | `default` |
| size | 设置头像的大小 | number \| Enum{ 'large', 'small', 'default' } | `default` |
| src | 图片类头像的资源地址 | string | - |
| alt | 图像无法显示时的替代文本 | string | - |
| loadError | 图片加载失败的事件,返回 false 会关闭组件默认的 fallback 行为 | () => boolean | - |

View File

@ -1,2 +1,2 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';

View File

@ -12,6 +12,11 @@
white-space: nowrap;
position: relative;
overflow: hidden;
vertical-align: middle;
&-image {
background: transparent;
}
.avatar-size(@avatar-size-base, @avatar-font-size-base);
@ -38,7 +43,7 @@
width: @size;
height: @size;
line-height: @size;
border-radius: @size / 2;
border-radius: 50%;
& > * {
line-height: @size;

View File

@ -1,13 +1,10 @@
import raf from 'raf'
import PropTypes from '../_util/vue-types'
import addEventListener from '../_util/Dom/addEventListener'
import getScroll from '../_util/getScroll'
import getRequestAnimationFrame from '../_util/getRequestAnimationFrame'
import BaseMixin from '../_util/BaseMixin'
import getTransitionProps from '../_util/getTransitionProps'
const reqAnimFrame = getRequestAnimationFrame()
const easeInOutCubic = (t, b, c, d) => {
const cc = c - b
t /= d / 2
@ -74,10 +71,12 @@ export default {
const time = timestamp - startTime
this.setScrollTop(easeInOutCubic(time, scrollTop, 0, 450))
if (time < 450) {
reqAnimFrame(frameFunc)
raf(frameFunc)
} else {
this.setScrollTop(0)
}
}
reqAnimFrame(frameFunc)
raf(frameFunc)
this.$emit('click', e)
},

View File

@ -1,2 +1,2 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';

View File

@ -19,6 +19,7 @@ export const BadgeProps = {
text: PropTypes.string,
offset: PropTypes.array,
numberStyle: PropTypes.object.def({}),
title: PropTypes.string,
}
export default {
@ -45,6 +46,7 @@ export default {
offset,
$slots,
numberStyle,
title,
} = this
let displayCount = count > overflowCount ? `${overflowCount}+` : count
const isZero = displayCount === '0' || displayCount === 0
@ -79,7 +81,7 @@ export default {
if (!children.length && status) {
return (
<span class={badgeCls} style={styleWithOffset}>
<span {...{ on: this.$listeners }} class={badgeCls} style={styleWithOffset}>
<span class={statusCls} />
<span class={`${prefixCls}-status-text`}>{text}</span>
</span>
@ -92,8 +94,9 @@ export default {
v-show={!hidden}
class={scrollNumberCls}
count={displayCount}
title={count}
title={title || count}
style={styleWithOffset}
key='scrollNumber'
/>
)
@ -102,7 +105,7 @@ export default {
)
const transitionProps = getTransitionProps(children.length ? `${prefixCls}-zoom` : '')
return (<span class={badgeCls}>
return (<span {...{ on: this.$listeners }} class={badgeCls}>
{children}
<transition {...transitionProps}>
{scrollNumber}

View File

@ -16,7 +16,7 @@ const ScrollNumberProps = {
prefixCls: PropTypes.string.def('ant-scroll-number'),
count: PropTypes.oneOfType([PropTypes.number, PropTypes.string, null]).def(null),
component: PropTypes.string,
title: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
title: PropTypes.oneOfType([PropTypes.number, PropTypes.string, null]),
}
export default {
@ -116,6 +116,8 @@ export default {
const newProps = {
props: {
...restProps,
},
attrs: {
title,
},
class: prefixCls,
@ -128,7 +130,7 @@ export default {
newProps.style.boxShadow = `0 0 0 1px ${style.borderColor} inset`
}
return (
<Tag {...newProps}>
<Tag {...newProps} >
{ this.renderNumberElement()}
</Tag>
)

View File

@ -1,16 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./components/badge/demo/basic.md correctly 1`] = `
<div><span class="ant-badge"><a href="#" class="head-example"></a><sup class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1500%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="current">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
<div><span class="ant-badge"><a href="#" class="head-example"></a><sup title="5" class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1500%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="current">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
</span>
<span class="ant-badge"><a href="#" class="head-example"></a><sup class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1000%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="current">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
<span class="ant-badge"><a href="#" class="head-example"></a><sup title="0" class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1000%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="current">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
</span>
</div>
`;
exports[`renders ./components/badge/demo/change.md correctly 1`] = `
<div>
<div><span class="ant-badge"><a href="#" class="head-example"></a><sup class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1500%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="current">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
<div><span class="ant-badge"><a href="#" class="head-example"></a><sup title="5" class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1500%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="current">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
</span>
<div class="ant-btn-group">
<button type="button" class="ant-btn ant-btn-default">
@ -30,13 +30,13 @@ exports[`renders ./components/badge/demo/dot.md correctly 1`] = `<div id="compon
exports[`renders ./components/badge/demo/link.md correctly 1`] = `
<a href="#"><span class="ant-badge"><span class="head-example"></span>
<sup class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1500%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="current">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
<sup title="5" class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1500%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="current">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
</span>
</a>
`;
exports[`renders ./components/badge/demo/no-wrapper.md correctly 1`] = `
<div><span class="ant-badge ant-badge-not-a-wrapper"><sup class="ant-scroll-number ant-badge-count ant-badge-multiple-words -enter"><span class="ant-scroll-number-only" style="transform: translateY(-1200%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="current">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span>
<div><span class="ant-badge ant-badge-not-a-wrapper"><sup title="25" class="ant-scroll-number ant-badge-count ant-badge-multiple-words -enter"><span class="ant-scroll-number-only" style="transform: translateY(-1200%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="current">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span>
<span
class="ant-scroll-number-only" style="transform: translateY(-1500%);">
<p class="">0</p>
@ -71,13 +71,13 @@ exports[`renders ./components/badge/demo/no-wrapper.md correctly 1`] = `
<p class="">9</p>
</span>
</sup>
</span> <span class="ant-badge ant-badge-not-a-wrapper"><sup class="ant-scroll-number ant-badge-count -enter" style="background-color: rgb(255, 255, 255); color: rgb(153, 153, 153); box-shadow: 0 0 0 1px #d9d9d9 inset;"><span class="ant-scroll-number-only" style="transform: translateY(-1400%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="current">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
</span> <span class="ant-badge ant-badge-not-a-wrapper"><sup title="4" class="ant-scroll-number ant-badge-count -enter" style="background-color: rgb(255, 255, 255); color: rgb(153, 153, 153); box-shadow: 0 0 0 1px #d9d9d9 inset;"><span class="ant-scroll-number-only" style="transform: translateY(-1400%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="current">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
</span>
<span class="ant-badge ant-badge-not-a-wrapper"><sup class="ant-scroll-number ant-badge-count ant-badge-multiple-words -enter" style="background-color: rgb(82, 196, 26);">99+</sup></span></div>
<span class="ant-badge ant-badge-not-a-wrapper"><sup title="109" class="ant-scroll-number ant-badge-count ant-badge-multiple-words -enter" style="background-color: rgb(82, 196, 26);">99+</sup></span></div>
`;
exports[`renders ./components/badge/demo/overflow.md correctly 1`] = `
<div><span class="ant-badge"><a href="#" class="head-example"></a><sup class="ant-scroll-number ant-badge-count ant-badge-multiple-words ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1900%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="current">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span>
<div><span class="ant-badge"><a href="#" class="head-example"></a><sup title="99" class="ant-scroll-number ant-badge-count ant-badge-multiple-words ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1900%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="current">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span>
<span
class="ant-scroll-number-only" style="transform: translateY(-1900%);">
<p class="">0</p>
@ -112,7 +112,7 @@ exports[`renders ./components/badge/demo/overflow.md correctly 1`] = `
<p class="">9</p>
</span>
</sup>
</span> <span class="ant-badge"><a href="#" class="head-example"></a><sup class="ant-scroll-number ant-badge-count ant-badge-multiple-words ant-badge-zoom-enter">99+</sup></span> <span class="ant-badge"><a href="#" class="head-example"></a><sup class="ant-scroll-number ant-badge-count ant-badge-multiple-words ant-badge-zoom-enter">10+</sup></span> <span class="ant-badge"><a href="#" class="head-example"></a><sup class="ant-scroll-number ant-badge-count ant-badge-multiple-words ant-badge-zoom-enter">999+</sup></span></div>
</span> <span class="ant-badge"><a href="#" class="head-example"></a><sup title="100" class="ant-scroll-number ant-badge-count ant-badge-multiple-words ant-badge-zoom-enter">99+</sup></span> <span class="ant-badge"><a href="#" class="head-example"></a><sup title="99" class="ant-scroll-number ant-badge-count ant-badge-multiple-words ant-badge-zoom-enter">10+</sup></span> <span class="ant-badge"><a href="#" class="head-example"></a><sup title="1000" class="ant-scroll-number ant-badge-count ant-badge-multiple-words ant-badge-zoom-enter">999+</sup></span></div>
`;
exports[`renders ./components/badge/demo/status.md correctly 1`] = `
@ -130,3 +130,9 @@ exports[`renders ./components/badge/demo/status.md correctly 1`] = `
<br> <span class="ant-badge ant-badge-status ant-badge-not-a-wrapper"><span class="ant-badge-status-dot ant-badge-status-warning"></span><span class="ant-badge-status-text">warning</span></span>
</div>
`;
exports[`renders ./components/badge/demo/title.md correctly 1`] = `
<div id="components-badge-demo-title"><span class="ant-badge"><a href="#" class="head-example"></a><sup title="Custom hover text" class="ant-scroll-number ant-badge-count ant-badge-zoom-enter"><span class="ant-scroll-number-only" style="transform: translateY(-1500%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="current">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
</span>
</div>
`;

View File

@ -0,0 +1,167 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Badge should be compatible with borderColor style 1`] = `
<span class="ant-badge ant-badge-not-a-wrapper" style="background-color: rgb(255, 255, 255); color: rgb(153, 153, 153); border-color: #d9d9d9;"><sup title="4" class="ant-scroll-number ant-badge-count"><span class="ant-scroll-number-only" style="transform: translateY(-1400%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="current">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
</span>
`;
exports[`Badge should render when count is changed 1`] = `
<span class="ant-badge ant-badge-not-a-wrapper"><sup title="10" class="ant-scroll-number ant-badge-count ant-badge-multiple-words"><span class="ant-scroll-number-only" style="transform: translateY(-2100%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="current">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span>
<span
class="ant-scroll-number-only" style="transform: translateY(-2000%);">
<p class="">0</p>
<p class="">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
<p class="">0</p>
<p class="">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
<p class="current">0</p>
<p class="">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
</span>
</sup>
</span>
`;
exports[`Badge should render when count is changed 2`] = `
<span class="ant-badge ant-badge-not-a-wrapper"><sup title="11" class="ant-scroll-number ant-badge-count ant-badge-multiple-words"><span class="ant-scroll-number-only" style="transform: translateY(-1100%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="current">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span>
<span
class="ant-scroll-number-only" style="transform: translateY(-1100%);">
<p class="">0</p>
<p class="">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
<p class="">0</p>
<p class="current">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
<p class="">0</p>
<p class="">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
</span>
</sup>
</span>
`;
exports[`Badge should render when count is changed 3`] = `
<span class="ant-badge ant-badge-not-a-wrapper"><sup title="11" class="ant-scroll-number ant-badge-count ant-badge-multiple-words"><span class="ant-scroll-number-only" style="transform: translateY(-1100%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="current">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span>
<span
class="ant-scroll-number-only" style="transform: translateY(-1100%);">
<p class="">0</p>
<p class="">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
<p class="">0</p>
<p class="current">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
<p class="">0</p>
<p class="">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
</span>
</sup>
</span>
`;
exports[`Badge should render when count is changed 4`] = `
<span class="ant-badge ant-badge-not-a-wrapper"><sup title="10" class="ant-scroll-number ant-badge-count ant-badge-multiple-words"><span class="ant-scroll-number-only" style="transform: translateY(-1100%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="current">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span>
<span
class="ant-scroll-number-only" style="transform: translateY(-1000%);">
<p class="">0</p>
<p class="">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
<p class="current">0</p>
<p class="">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
<p class="">0</p>
<p class="">1</p>
<p class="">2</p>
<p class="">3</p>
<p class="">4</p>
<p class="">5</p>
<p class="">6</p>
<p class="">7</p>
<p class="">8</p>
<p class="">9</p>
</span>
</sup>
</span>
`;
exports[`Badge should render when count is changed 5`] = `
<span class="ant-badge ant-badge-not-a-wrapper"><sup title="9" class="ant-scroll-number ant-badge-count"><span class="ant-scroll-number-only" style="transform: translateY(-900%);"><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="current">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p><p class="">0</p><p class="">1</p><p class="">2</p><p class="">3</p><p class="">4</p><p class="">5</p><p class="">6</p><p class="">7</p><p class="">8</p><p class="">9</p></span></sup>
</span>
`;

View File

@ -1,8 +1,9 @@
import { mount } from '@vue/test-utils'
import Badge from '../index'
import { asyncExpect } from '@/tests/utils'
describe('Badge', () => {
test('badge dot not scaling count > 9', () => {
it('badge dot not scaling count > 9', () => {
const badge = mount({
render () {
return <Badge count={10} dot />
@ -10,7 +11,7 @@ describe('Badge', () => {
})
expect(badge.findAll('.ant-card-multiple-words').length).toBe(0)
})
test('badge dot not showing count == 0', () => {
it('badge dot not showing count == 0', () => {
const badge = mount({
render () {
return <Badge count={0} dot />
@ -18,4 +19,70 @@ describe('Badge', () => {
})
expect(badge.findAll('.ant-badge-dot').length).toBe(0)
})
it('should have an overriden title attribute', () => {
const badge = mount({
render () {
return <Badge count={10} title='Custom title' />
},
})
expect(badge.find('.ant-scroll-number').element.attributes.getNamedItem('title').value).toEqual('Custom title')
})
// https://github.com/ant-design/ant-design/issues/10626
// it('should be composable with Tooltip', async () => {
// const wrapper = mount({
// render () {
// return <Tooltip ref='tooltip' title='Fix the error'>
// <Badge status='error' />
// </Tooltip>
// },
// }, { sync: false })
// await asyncExpect(() => {
// wrapper.find({ name: 'ABadge' }).trigger('mouseenter')
// }, 0)
// expect(wrapper.vm.$refs.tooltip.sVisible).toBe(true)
// })
it('should render when count is changed', async () => {
const wrapper = mount(Badge, {
propsData: {
count: 9,
},
sync: false,
})
await asyncExpect(() => {
wrapper.setProps({ count: 10 })
}, 100)
await asyncExpect(() => {
expect(wrapper.html()).toMatchSnapshot()
wrapper.setProps({ count: 11 })
}, 100)
await asyncExpect(() => {
expect(wrapper.html()).toMatchSnapshot()
wrapper.setProps({ count: 11 })
}, 100)
await asyncExpect(() => {
expect(wrapper.html()).toMatchSnapshot()
wrapper.setProps({ count: 10 })
}, 100)
await asyncExpect(() => {
expect(wrapper.html()).toMatchSnapshot()
wrapper.setProps({ count: 9 })
}, 100)
await asyncExpect(() => {
expect(wrapper.html()).toMatchSnapshot()
}, 100)
})
it('should be compatible with borderColor style', () => {
const wrapper = mount({
render () {
return <Badge count={4} style={{ backgroundColor: '#fff', color: '#999', borderColor: '#d9d9d9' }} />
},
})
expect(wrapper.html()).toMatchSnapshot()
})
})

View File

@ -5,6 +5,7 @@
import Change from './change'
import Overflow from './overflow'
import Status from './status'
import Title from './title'
import CN from './../index.zh-CN.md'
import US from './../index.en_US.md'
@ -39,6 +40,7 @@
<Dot />
<Status />
<Change />
<Title />
<api>
<CN slot='cn' />
<US />

View File

@ -0,0 +1,31 @@
<cn>
#### 自定义标题
设置鼠标放在状态点上时显示的文字
</cn>
<us>
#### Title
The badge will display `title` when hovered over, instead of `count`.
</us>
```html
<template>
<div id="components-badge-demo-title">
<a-badge :count="5" title="Custom hover text">
<a href="#" class="head-example" />
</a-badge>
</div>
</template>
<style scoped>
#components-badge-demo-title .ant-badge:not(.ant-badge-status) {
margin-right: 20px;
}
.head-example {
width: 42px;
height: 42px;
border-radius: 4px;
background: #eee;
display: inline-block;
}
</style>
```

View File

@ -20,3 +20,4 @@
| status | Set Badge as a status dot | `success` \| `processing` \| `default` \| `error` \| `warning` | `''` |
| text | If `status` is set, `text` sets the display text of the status `dot` | string | `''` |
| numberStyle | sets the display style of the status `dot` | object | '' |
| title | Text to show when hovering over the badge | string | `count` |

View File

@ -21,3 +21,4 @@
| status | 设置 Badge 为状态点 | Enum{ 'success', 'processing, 'default', 'error', 'warning' } | '' |
| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | string | '' |
| numberStyle | 设置状态点的样式 | object | '' |
| title | 设置鼠标放在状态点上时显示的文字 | string | `count` |

View File

@ -1,2 +1,2 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';

View File

@ -10,11 +10,13 @@
display: inline-block;
line-height: 1;
vertical-align: middle;
color: unset;
&-count {
position: absolute;
transform: translateX(-50%);
top: -@badge-height / 2;
transform: translate(50%, -50%);
top: 0;
right: 0;
height: @badge-height;
border-radius: @badge-height / 2;
min-width: @badge-height;
@ -26,7 +28,7 @@
font-size: @badge-font-size;
font-weight: @badge-font-weight;
white-space: nowrap;
transform-origin: -10% center;
transform-origin: 0 center;
box-shadow: 0 0 0 1px #fff;
a,
a:hover {
@ -40,9 +42,10 @@
&-dot {
position: absolute;
transform: translateX(-50%);
transform: translate(50%, -50%);
transform-origin: 0 center;
top: -@badge-dot-size / 2;
top: 0;
right: 0;
height: @badge-dot-size;
width: @badge-dot-size;
border-radius: 100%;
@ -114,6 +117,7 @@
display: block;
position: relative;
}
&-not-a-wrapper .@{badge-prefix-cls}-count {
transform: none;
}

View File

@ -1,2 +1,2 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';

View File

@ -9,6 +9,15 @@ exports[`renders ./components/button/demo/basic.md correctly 1`] = `
</div>
`;
exports[`renders ./components/button/demo/block.md correctly 1`] = `
<div>
<button type="button" class="ant-btn ant-btn-primary ant-btn-block"><span>Primary</span></button>
<button type="button" class="ant-btn ant-btn-default ant-btn-block"><span>Default</span></button>
<button type="button" class="ant-btn ant-btn-dashed ant-btn-block"><span>Dashed</span></button>
<button type="button" class="ant-btn ant-btn-danger ant-btn-block"><span>danger</span></button>
</div>
`;
exports[`renders ./components/button/demo/button-group.md correctly 1`] = `
<div id="components-button-demo-button-group">
<h4>Basic</h4>
@ -56,11 +65,12 @@ exports[`renders ./components/button/demo/disabled.md correctly 1`] = `
<button type="button" class="ant-btn ant-btn-default"><span>Default</span></button>
<button type="button" disabled="disabled" class="ant-btn ant-btn-default"><span>Default(disabled)</span></button>
<br>
<button type="button" class="ant-btn ant-btn-default"><span>Ghost</span></button>
<button type="button" disabled="disabled" class="ant-btn ant-btn-default"><span>Ghost(disabled)</span></button>
<br>
<button type="button" class="ant-btn ant-btn-dashed"><span>Dashed</span></button>
<button type="button" disabled="disabled" class="ant-btn ant-btn-dashed"><span>Dashed(disabled)</span></button>
<div style="padding: 8px 8px 0px 8px; background: rgb(190, 200, 200);">
<button type="button" class="ant-btn ant-btn-default ant-btn-background-ghost"><span>Ghost</span></button>
<button type="button" disabled="disabled" class="ant-btn ant-btn-default ant-btn-background-ghost"><span>Ghost(disabled)</span></button>
</div>
</div>
`;
@ -131,10 +141,10 @@ exports[`renders ./components/button/demo/multiple.md correctly 1`] = `
exports[`renders ./components/button/demo/size.md correctly 1`] = `
<div>
<div class="ant-radio-group ant-radio-group-default">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Large</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Default</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Small</span></label>
<div class="ant-radio-group ant-radio-group-outline ant-radio-group-default">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input" value="large"><span class="ant-radio-button-inner"></span></span><span>Large</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input" value="default"><span class="ant-radio-button-inner"></span></span><span>Default</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input" value="small"><span class="ant-radio-button-inner"></span></span><span>Small</span></label>
</div>
<br>
<br>

View File

@ -16,6 +16,21 @@ exports[`Button renders Chinese characters correctly 2`] = `
<i class="anticon anticon-search"></i>按钮</button>
`;
exports[`Button renders Chinese characters correctly 3`] = `
<button type="button" class="ant-btn ant-btn-default">
<i class="anticon anticon-search"></i><span>按钮</span></button>
`;
exports[`Button renders Chinese characters correctly 4`] = `
<button type="button" class="ant-btn ant-btn-default ant-btn-loading">
<i class="anticon anticon-loading anticon-spin"></i><span>按钮</span></button>
`;
exports[`Button renders Chinese characters correctly 5`] = `
<button type="button" class="ant-btn ant-btn-default ant-btn-loading">
<i class="anticon anticon-loading anticon-spin"></i><span>按 钮</span></button>
`;
exports[`Button renders correctly 1`] = `<button type="button" class="ant-btn ant-btn-default"><span>Follow</span></button>`;
exports[`Button should support link button 1`] = `<button target="_blank" href="http://ant.design" type="button" class="ant-btn ant-btn-default"><span>link button</span></button>`;
exports[`Button should support link button 1`] = `<a target="_blank" href="http://ant.design" type="button" class="ant-btn ant-btn-default"><span>link button</span></a>`;

View File

@ -1,17 +1,17 @@
import Button from '../index'
import Icon from '../../icon'
import { mount } from '@vue/test-utils'
import { renderToString } from '@vue/server-test-utils'
import Vue from 'vue'
import { asyncExpect } from '@/tests/utils'
describe('Button', () => {
it('renders correctly', () => {
const wrapper = renderToString({
const wrapper = mount({
render () {
return <Button>Follow</Button>
},
})
expect(wrapper).toMatchSnapshot()
expect(wrapper.html()).toMatchSnapshot()
})
it('create primary button', () => {
@ -33,25 +33,52 @@ describe('Button', () => {
)
expect(wrapper.text()).toBe('按 钮')
const wrapper1 = renderToString(
const wrapper1 = mount(
{
render (h) {
return <Button icon='search'>按钮</Button>
},
}
)
expect(wrapper1).toMatchSnapshot()
const wrapper2 = renderToString(
expect(wrapper1.html()).toMatchSnapshot()
const wrapper2 = mount(
{
render (h) {
return <Button><Icon type='search' />按钮</Button>
},
}
)
expect(wrapper2).toMatchSnapshot()
expect(wrapper2.html()).toMatchSnapshot()
// should not insert space when there is icon
const wrapper3 = mount(
{
render (h) {
return <Button icon='search'>按钮</Button>
},
}
)
expect(wrapper3.html()).toMatchSnapshot()
// should not insert space when there is icon while loading
const wrapper4 = mount(
{
render (h) {
return <Button icon='search' loading>按钮</Button>
},
}
)
expect(wrapper4.html()).toMatchSnapshot()
// should insert space while loading
const wrapper5 = mount(
{
render (h) {
return <Button loading>按钮</Button>
},
}
)
expect(wrapper5.html()).toMatchSnapshot()
const wrapper6 = mount(
{
render (h) {
return <Button><span>按钮</span></Button>
@ -59,11 +86,11 @@ describe('Button', () => {
}
)
Vue.nextTick(() => {
expect(wrapper3.find('.ant-btn').contains('.ant-btn-two-chinese-chars')).toBe(true)
expect(wrapper6.find('.ant-btn').contains('.ant-btn-two-chinese-chars')).toBe(true)
done()
})
})
it('should change loading state instantly by default', () => {
it('should change loading state instantly by default', async () => {
const DefaultButton = {
data () {
return {
@ -80,14 +107,16 @@ describe('Button', () => {
return <Button loading={this.loading} onClick={this.enterLoading}>Button</Button>
},
}
const wrapper = mount(DefaultButton)
wrapper.trigger('click')
Vue.nextTick(() => {
const wrapper = mount(DefaultButton, { sync: false })
await asyncExpect(() => {
wrapper.trigger('click')
})
await asyncExpect(() => {
expect(wrapper.findAll('.ant-btn-loading').length).toBe(1)
})
})
it('should change loading state with delay', (done) => {
it('should change loading state with delay', async () => {
const DefaultButton = {
data () {
return {
@ -104,11 +133,12 @@ describe('Button', () => {
return <Button loading={this.loading} onClick={this.enterLoading}>Button</Button>
},
}
const wrapper = mount(DefaultButton)
wrapper.trigger('click')
Vue.nextTick(() => {
const wrapper = mount(DefaultButton, { sync: false })
await asyncExpect(() => {
wrapper.trigger('click')
})
await asyncExpect(() => {
expect(wrapper.contains('.ant-btn-loading')).toBe(false)
done()
})
})

View File

@ -1,4 +1,4 @@
import Wave from '../_util/wave'
import Icon from '../icon'
const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/
const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar)
@ -16,7 +16,7 @@ export default {
large: 'lg',
small: 'sm',
},
clicked: false,
// clicked: false,
sLoading: !!this.loading,
hasTwoCNChar: false,
}
@ -27,6 +27,14 @@ export default {
updated () {
this.fixTwoCNChar()
},
beforeDestroy () {
// if (this.timeout) {
// clearTimeout(this.timeout)
// }
if (this.delayTimeout) {
clearTimeout(this.delayTimeout)
}
},
watch: {
loading (val) {
clearTimeout(this.delayTimeout)
@ -40,7 +48,7 @@ export default {
computed: {
classes () {
const { prefixCls, type, shape, size, hasTwoCNChar,
sLoading, ghost, clicked, sizeMap } = this
sLoading, ghost, block, sizeMap } = this
const sizeCls = sizeMap[size] || ''
return {
[`${prefixCls}`]: true,
@ -48,15 +56,11 @@ export default {
[`${prefixCls}-${shape}`]: shape,
[`${prefixCls}-${sizeCls}`]: sizeCls,
[`${prefixCls}-loading`]: sLoading,
[`${prefixCls}-clicked`]: clicked,
[`${prefixCls}-background-ghost`]: ghost || type === 'ghost',
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar,
[`${prefixCls}-block`]: block,
}
},
iconType () {
const { sLoading, icon } = this
return sLoading ? 'loading' : icon
},
},
methods: {
fixTwoCNChar () {
@ -72,9 +76,9 @@ export default {
}
},
handleClick (event) {
this.clicked = true
clearTimeout(this.timeout)
this.timeout = setTimeout(() => (this.clicked = false), 500)
// this.clicked = true
// clearTimeout(this.timeout)
// this.timeout = setTimeout(() => (this.clicked = false), 500)
this.$emit('click', event)
},
insertSpace (child, needInserted) {
@ -89,15 +93,14 @@ export default {
return child
},
isNeedInserted () {
const { loading, icon, $slots } = this
const iconType = loading ? 'loading' : icon
return $slots.default && $slots.default.length === 1 && (!iconType || iconType === 'loading')
const { icon, $slots } = this
return $slots.default && $slots.default.length === 1 && !icon
},
},
render () {
const { htmlType, classes,
disabled, handleClick, iconType,
$slots, $attrs, $listeners } = this
const { htmlType, classes, icon,
disabled, handleClick,
sLoading, $slots, $attrs, $listeners } = this
const buttonProps = {
props: {
},
@ -112,21 +115,25 @@ export default {
click: handleClick,
},
}
const iconType = sLoading ? 'loading' : icon
const iconNode = iconType ? <Icon type={iconType} /> : null
const kids = $slots.default && $slots.default.length === 1 ? this.insertSpace($slots.default[0], this.isNeedInserted()) : $slots.default
return (
<button {...buttonProps}>
{iconType ? <Icon type={iconType}></Icon> : null}
{kids}
</button>
)
},
beforeDestroy () {
if (this.timeout) {
clearTimeout(this.timeout)
}
if (this.delayTimeout) {
clearTimeout(this.delayTimeout)
if ('href' in $attrs) {
return (
<a {...buttonProps}>
{iconNode}{kids}
</a>
)
} else {
return (
<Wave>
<button {...buttonProps}>
{iconNode}{kids}
</button>
</Wave>
)
}
},
}

View File

@ -9,4 +9,5 @@ export default () => ({
loading: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
disabled: PropTypes.bool,
ghost: PropTypes.bool,
block: PropTypes.bool,
})

View File

@ -0,0 +1,22 @@
<cn>
#### block 按钮
`block`属性将使按钮适合其父宽度。
</cn>
<us>
#### block Button
`block` property will make the button fit to its parent width.
</us>
```html
<template>
<div>
<a-button type="primary" block>Primary</a-button>
<a-button block>Default</a-button>
<a-button type="dashed" block>Dashed</a-button>
<a-button type="danger" block>danger</a-button>
</div>
</template>
```

View File

@ -18,11 +18,12 @@ To mark a button as disabled, add the `disabled` property to the `Button`.
<a-button>Default</a-button>
<a-button disabled>Default(disabled)</a-button>
<br />
<a-button>Ghost</a-button>
<a-button disabled>Ghost(disabled)</a-button>
<br />
<a-button type="dashed">Dashed</a-button>
<a-button type="dashed" disabled>Dashed(disabled)</a-button>
<div :style="{ padding: '8px 8px 0 8px', background: 'rgb(190, 200, 200)' }">
<a-button ghost>Ghost</a-button>
<a-button ghost disabled>Ghost(disabled)</a-button>
</div>
</div>
</template>
```

View File

@ -7,6 +7,7 @@ import Icon from './icon'
import Loading from './loading'
import Multiple from './multiple'
import Size from './size'
import Block from './block'
import CN from '../index.zh-CN.md'
import US from '../index.en-US.md'
const md = {
@ -19,7 +20,7 @@ const md = {
To trigger an operation.
## When To Use
A button means an operation (or a series of operations). Clicking a button will trigger corresponding business logic.
## Examples
## Examples
`,
}
export default {
@ -39,6 +40,7 @@ export default {
<Loading />
<Multiple />
<Size />
<Block />
<api>
<CN slot='cn' />
<US/>

View File

@ -4,6 +4,7 @@ To get a customized button, just set `type`/`shape`/`size`/`loading`/`disabled`.
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| disabled | disabled state of button | boolean | `false` |
| ghost | make background transparent and invert text and border colors, added in 2.7 | boolean | false |
| htmlType | set the original html `type` of `button`, see: [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type) | string | `button` |
| icon | set the icon of button, see: Icon component | string | - |
@ -11,12 +12,12 @@ To get a customized button, just set `type`/`shape`/`size`/`loading`/`disabled`.
| shape | can be set to `circle` or omitted | string | - |
| size | can be set to `small` `large` or omitted | string | `default` |
| type | can be set to `primary` `ghost` `dashed` `danger`(added in 2.7) or omitted (meaning `default`) | string | `default` |
| onClick | set the handler to handle `click` event | function | - |
| block | option to fit button width to its parent width | boolean | `false` |
### events
| Events Name | Description | Arguments |
| --- | --- | --- |
| click | handle `click` event | function(e) |
| click | set the handler to handle `click` event | function(e) |
`<Button>Hello world!</Button>` will be rendered into `<button><span>Hello world!</span></button>`, and all the properties which are not listed above will be transferred to the `<button>` tag.

View File

@ -6,6 +6,7 @@
| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| disabled | 按钮失效状态 | boolean | `false` |
| ghost | 幽灵属性,使按钮背景透明 | boolean | false |
| htmlType | 设置 `button` 原生的 `type` 值,可选值请参考 [HTML 标准](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type) | string | `button` |
| icon | 设置按钮的图标类型 | string | - |
@ -13,6 +14,7 @@
| shape | 设置按钮形状,可选值为 `circle` 或者不设 | string | - |
| size | 设置按钮大小,可选值为 `small` `large` 或者不设 | string | `default` |
| type | 设置按钮类型,可选值为 `primary` `dashed` `danger` | string | - |
| block | 将按钮宽度调整为其父宽度的选项 | boolean | `false` |
### 事件
| 事件名称 | 说明 | 回调参数 |

View File

@ -1,2 +1,2 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';

View File

@ -131,24 +131,6 @@
margin-left: 8px;
}
&-clicked:after {
content: '';
position: absolute;
top: -1px;
left: -1px;
bottom: -1px;
right: -1px;
border-radius: inherit;
border: 0 solid @primary-color;
opacity: 0.4;
animation: buttonEffect .4s;
display: block;
}
&-danger&-clicked:after {
border-color: @btn-danger-color;
}
&-background-ghost {
background: transparent !important;
border-color: #fff;
@ -171,16 +153,9 @@
letter-spacing: .34em;
margin-right: -.34em;
}
}
@keyframes buttonEffect {
to {
opacity: 0;
top: -6px;
left: -6px;
bottom: -6px;
right: -6px;
border-width: 6px;
&-block {
width: 100%;
}
}

View File

@ -4,20 +4,20 @@ exports[`renders ./components/calendar/demo/basic.md correctly 1`] = `
<div class=" ant-fullcalendar-fullscreen">
<div class="ant-fullcalendar-header">
<div class="ant-select ant-select-enabled ant-fullcalendar-year-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="2016" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">2016</div>
</div><span unselectable="unselectable" class="ant-select-arrow"><b></b></span></div>
</div>
<div class="ant-select ant-select-enabled ant-fullcalendar-month-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="Nov" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">Nov</div>
</div><span unselectable="unselectable" class="ant-select-arrow"><b></b></span></div>
</div>
<div class="ant-radio-group ant-radio-group-default">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Month</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Year</span></label>
<div class="ant-radio-group ant-radio-group-outline ant-radio-group-default">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input" value="date"><span class="ant-radio-button-inner"></span></span><span>Month</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input" value="month"><span class="ant-radio-button-inner"></span></span><span>Year</span></label>
</div>
</div>
<div tabindex="0" class="ant-fullcalendar ant-fullcalendar-full ant-fullcalendar-fullscreen">
@ -310,21 +310,21 @@ exports[`renders ./components/calendar/demo/card.md correctly 1`] = `
<div style="width: 300px; border: 1px solid #d9d9d9; border-radius: 4px;">
<div class="">
<div class="ant-fullcalendar-header">
<div class="ant-select-sm ant-select ant-select-enabled ant-select-sm ant-fullcalendar-year-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select ant-select-enabled ant-select-sm ant-fullcalendar-year-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="2016" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">2016</div>
</div><span unselectable="unselectable" class="ant-select-arrow"><b></b></span></div>
</div>
<div class="ant-select-sm ant-select ant-select-enabled ant-select-sm ant-fullcalendar-month-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select ant-select-enabled ant-select-sm ant-fullcalendar-month-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="Nov" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">Nov</div>
</div><span unselectable="unselectable" class="ant-select-arrow"><b></b></span></div>
</div>
<div class="ant-radio-group ant-radio-group-small">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Month</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Year</span></label>
<div class="ant-radio-group ant-radio-group-outline ant-radio-group-small">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input" value="date"><span class="ant-radio-button-inner"></span></span><span>Month</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input" value="month"><span class="ant-radio-button-inner"></span></span><span>Year</span></label>
</div>
</div>
<div tabindex="0" class="ant-fullcalendar ant-fullcalendar-full">
@ -618,20 +618,20 @@ exports[`renders ./components/calendar/demo/notice-calendar.md correctly 1`] = `
<div class=" ant-fullcalendar-fullscreen">
<div class="ant-fullcalendar-header">
<div class="ant-select ant-select-enabled ant-fullcalendar-year-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="2016" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">2016</div>
</div><span unselectable="unselectable" class="ant-select-arrow"><b></b></span></div>
</div>
<div class="ant-select ant-select-enabled ant-fullcalendar-month-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="Nov" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">Nov</div>
</div><span unselectable="unselectable" class="ant-select-arrow"><b></b></span></div>
</div>
<div class="ant-radio-group ant-radio-group-default">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Month</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Year</span></label>
<div class="ant-radio-group ant-radio-group-outline ant-radio-group-default">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input" value="date"><span class="ant-radio-button-inner"></span></span><span>Month</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input" value="month"><span class="ant-radio-button-inner"></span></span><span>Year</span></label>
</div>
</div>
<div tabindex="0" class="ant-fullcalendar ant-fullcalendar-full ant-fullcalendar-fullscreen">
@ -1043,25 +1043,25 @@ exports[`renders ./components/calendar/demo/notice-calendar.md correctly 1`] = `
exports[`renders ./components/calendar/demo/select.md correctly 1`] = `
<div>
<div class="ant-alert ant-alert-info ant-alert-no-icon"><span class="ant-alert-message">You selected date: 2017-01-25</span><span class="ant-alert-description"></span></div>
<div data-show="true" class="ant-alert ant-alert-info ant-alert-no-icon"><span class="ant-alert-message">You selected date: 2017-01-25</span><span class="ant-alert-description"></span></div>
<div style="display: inline-block; width: 500px; border: 1px solid #d9d9d9; border-radius: 4px;">
<div class=" ant-fullcalendar-fullscreen">
<div class="ant-fullcalendar-header">
<div class="ant-select ant-select-enabled ant-fullcalendar-year-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="2017" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">2017</div>
</div><span unselectable="unselectable" class="ant-select-arrow"><b></b></span></div>
</div>
<div class="ant-select ant-select-enabled ant-fullcalendar-month-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="Jan" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">Jan</div>
</div><span unselectable="unselectable" class="ant-select-arrow"><b></b></span></div>
</div>
<div class="ant-radio-group ant-radio-group-default">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Month</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Year</span></label>
<div class="ant-radio-group ant-radio-group-outline ant-radio-group-default">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input" value="date"><span class="ant-radio-button-inner"></span></span><span>Month</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input" value="month"><span class="ant-radio-button-inner"></span></span><span>Year</span></label>
</div>
</div>
<div tabindex="0" class="ant-fullcalendar ant-fullcalendar-full ant-fullcalendar-fullscreen">
@ -1353,20 +1353,20 @@ exports[`renders ./components/calendar/demo/select.md correctly 1`] = `
<div class=" ant-fullcalendar-fullscreen">
<div class="ant-fullcalendar-header">
<div class="ant-select ant-select-enabled ant-fullcalendar-year-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="2017" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">2017</div>
</div><span unselectable="unselectable" class="ant-select-arrow"><b></b></span></div>
</div>
<div class="ant-select ant-select-enabled ant-fullcalendar-month-select">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" tabindex="0" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="Jan" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">Jan</div>
</div><span unselectable="unselectable" class="ant-select-arrow"><b></b></span></div>
</div>
<div class="ant-radio-group ant-radio-group-default">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Month</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Year</span></label>
<div class="ant-radio-group ant-radio-group-outline ant-radio-group-default">
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input" value="date"><span class="ant-radio-button-inner"></span></span><span>Month</span></label>
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input" value="month"><span class="ant-radio-button-inner"></span></span><span>Year</span></label>
</div>
</div>
<div tabindex="0" class="ant-fullcalendar ant-fullcalendar-full ant-fullcalendar-fullscreen">

View File

@ -1,6 +1,6 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';
// style dependencies
import '../../select/style'
import '../../radio/style'
import '../../select/style';
import '../../radio/style';

View File

@ -235,7 +235,7 @@
}
&-fullscreen &-content {
height: 90px;
height: 88px;
overflow-y: auto;
position: static;
width: auto;

View File

@ -1,8 +1,10 @@
import omit from 'omit.js'
import Tabs from '../tabs'
import Row from '../row'
import Col from '../col'
import PropTypes from '../_util/vue-types'
import addEventListener from '../_util/Dom/addEventListener'
import { getComponentFromProp, getComponentName } from '../_util/props-util'
import { getComponentFromProp, getSlotOptions, isEmptyElement, filterEmpty } from '../_util/props-util'
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame'
import BaseMixin from '../_util/BaseMixin'
@ -16,6 +18,7 @@ export default {
extra: PropTypes.any,
bordered: PropTypes.bool.def(true),
bodyStyle: PropTypes.object,
headStyle: PropTypes.object,
loading: PropTypes.bool.def(false),
hoverable: PropTypes.bool.def(false),
type: PropTypes.string,
@ -49,14 +52,14 @@ export default {
if (!cardContainerRef) {
return
}
// 936 is a magic card width pixer number indicated by designer
const WIDTH_BOUDARY_PX = 936
if (cardContainerRef.offsetWidth >= WIDTH_BOUDARY_PX && !this.widerPadding) {
// 936 is a magic card width pixel number indicated by designer
const WIDTH_BOUNDARY_PX = 936
if (cardContainerRef.offsetWidth >= WIDTH_BOUNDARY_PX && !this.widerPadding) {
this.setState({ widerPadding: true }, () => {
this.updateWiderPaddingCalled = true // first render without css transition
})
}
if (cardContainerRef.offsetWidth < WIDTH_BOUDARY_PX && this.widerPadding) {
if (cardContainerRef.offsetWidth < WIDTH_BOUNDARY_PX && this.widerPadding) {
this.setState({ widerPadding: false }, () => {
this.updateWiderPaddingCalled = true // first render without css transition
})
@ -69,23 +72,32 @@ export default {
let containGrid
obj.forEach((element) => {
if (
element &&
element.componentOptions &&
getComponentName(element.componentOptions) === 'Grid'
element && getSlotOptions(element).__ANT_CARD_GRID
) {
containGrid = true
}
})
return containGrid
},
getAction (actions) {
if (!actions || !actions.length) {
return null
}
const actionList = actions.map((action, index) => (
<li style={{ width: `${100 / actions.length}%` }} key={`action-${index}`}>
<span>{action}</span>
</li>
))
return actionList
},
},
render () {
const {
prefixCls = 'ant-card', bodyStyle, loading,
prefixCls = 'ant-card', headStyle = {}, bodyStyle = {}, loading,
bordered = true, type, tabList, hoverable, activeTabKey, defaultActiveTabKey,
} = this.$props
const { $slots, $scopedSlots } = this
const { $slots, $scopedSlots, $listeners } = this
const classString = {
[`${prefixCls}`]: true,
@ -99,26 +111,62 @@ export default {
[`${prefixCls}-type-${type}`]: !!type,
}
const loadingBlockStyle = (bodyStyle.padding === 0 || bodyStyle.padding === '0px')
? { padding: 24 } : undefined
const loadingBlock = (
<div class={`${prefixCls}-loading-content`}>
<p class={`${prefixCls}-loading-block`} style={{ width: '94%' }} />
<p>
<span class={`${prefixCls}-loading-block`} style={{ width: '28%' }} />
<span class={`${prefixCls}-loading-block`} style={{ width: '62%' }} />
</p>
<p>
<span class={`${prefixCls}-loading-block`} style={{ width: '22%' }} />
<span class={`${prefixCls}-loading-block`} style={{ width: '66%' }} />
</p>
<p>
<span class={`${prefixCls}-loading-block`} style={{ width: '56%' }} />
<span class={`${prefixCls}-loading-block`} style={{ width: '39%' }} />
</p>
<p>
<span class={`${prefixCls}-loading-block`} style={{ width: '21%' }} />
<span class={`${prefixCls}-loading-block`} style={{ width: '15%' }} />
<span class={`${prefixCls}-loading-block`} style={{ width: '40%' }} />
</p>
<div class={`${prefixCls}-loading-content`} style={loadingBlockStyle}>
<Row gutter={8}>
<Col span={22}>
<div class={`${prefixCls}-loading-block`} />
</Col>
</Row>
<Row gutter={8}>
<Col span={8}>
<div class={`${prefixCls}-loading-block`} />
</Col>
<Col span={15}>
<div class={`${prefixCls}-loading-block`} />
</Col>
</Row>
<Row gutter={8}>
<Col span={6}>
<div class={`${prefixCls}-loading-block`} />
</Col>
<Col span={18}>
<div class={`${prefixCls}-loading-block`} />
</Col>
</Row>
<Row gutter={8}>
<Col span={13}>
<div class={`${prefixCls}-loading-block`} />
</Col>
<Col span={9}>
<div class={`${prefixCls}-loading-block`} />
</Col>
</Row>
<Row gutter={8}>
<Col span={4}>
<div class={`${prefixCls}-loading-block`} />
</Col>
<Col span={3}>
<div class={`${prefixCls}-loading-block`} />
</Col>
<Col span={16}>
<div class={`${prefixCls}-loading-block`} />
</Col>
</Row>
<Row gutter={8}>
<Col span={8}>
<div class={`${prefixCls}-loading-block`} />
</Col>
<Col span={6}>
<div class={`${prefixCls}-loading-block`} />
</Col>
<Col span={8}>
<div class={`${prefixCls}-loading-block`} />
</Col>
</Row>
</div>
)
@ -143,7 +191,7 @@ export default {
const { tab: temp, scopedSlots = {}} = item
const name = scopedSlots.tab
const tab = temp !== undefined ? temp : ($scopedSlots[name] ? $scopedSlots[name](item) : null)
return <TabPane tab={tab} key={item.key} />
return <TabPane tab={tab} key={item.key} disabled={item.disabled}/>
})}
</Tabs>
) : null
@ -151,7 +199,7 @@ export default {
const extraDom = getComponentFromProp(this, 'extra')
if (titleDom || extraDom || tabs) {
head = (
<div class={`${prefixCls}-head`}>
<div class={`${prefixCls}-head`} style={headStyle}>
<div class={`${prefixCls}-head-wrapper`}>
{titleDom && <div class={`${prefixCls}-head-title`}>{titleDom}</div>}
{extraDom && <div class={`${prefixCls}-extra`}>{extraDom}</div>}
@ -169,11 +217,12 @@ export default {
{loading ? loadingBlock : children}
</div>
)
const actions = getComponentFromProp(this, 'actions')
const actionDom = actions || null
const actions = filterEmpty(this.$slots.actions)
const actionDom = actions && actions.length
? <ul class={`${prefixCls}-actions`}>{this.getAction(actions)}</ul> : null
return (
<div class={classString} ref='cardContainerRef'>
<div class={classString} ref='cardContainerRef' {...{ on: omit($listeners, ['tabChange', 'tab-change']) }}>
{head}
{coverDom}
{children ? body : null}

View File

@ -3,6 +3,7 @@ import PropTypes from '../_util/vue-types'
export default {
name: 'ACardGrid',
__ANT_CARD_GRID: true,
props: {
prefixCls: PropTypes.string.def('ant-card'),
},

View File

@ -18,7 +18,69 @@ exports[`renders ./components/card/demo/basic.md correctly 1`] = `
</div>
`;
exports[`renders ./components/card/demo/colRowCard.md correctly 1`] = `
exports[`renders ./components/card/demo/border-less.md correctly 1`] = `
<div style="background: rgb(236, 236, 236); padding: 30px;">
<div class="ant-card" style="width: 300px;">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Card title</div>
</div>
</div>
<div class="ant-card-body">
<p>Card content</p>
<p>Card content</p>
<p>Card content</p>
</div>
</div>
</div>
`;
exports[`renders ./components/card/demo/concise.md correctly 1`] = `
<div class="ant-card ant-card-bordered" style="width: 300px;">
<div class="ant-card-body">
<p>Card content</p>
<p>Card content</p>
<p>Card content</p>
</div>
</div>
`;
exports[`renders ./components/card/demo/flexible-content.md correctly 1`] = `
<div class="ant-card ant-card-bordered ant-card-hoverable" style="width: 240px;">
<div class="ant-card-cover">
<img alt="example" src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png">
</div>
<div class="ant-card-body">
<div class="ant-card-meta">
<div class="ant-card-meta-detail">
<div class="ant-card-meta-title">Europe Street beat</div>
<div class="ant-card-meta-description">www.instagram.com</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/card/demo/grid-card.md correctly 1`] = `
<div class="ant-card ant-card-bordered ant-card-contain-grid">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Card Title</div>
</div>
</div>
<div class="ant-card-body">
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
</div>
</div>
`;
exports[`renders ./components/card/demo/in-column.md correctly 1`] = `
<div style="background-color: rgb(236, 236, 236); padding: 20px;">
<div class="ant-row" style="margin-left: -8px; margin-right: -8px;">
<div class="ant-col-8" style="padding-left: 8px; padding-right: 8px;">
@ -61,52 +123,7 @@ exports[`renders ./components/card/demo/colRowCard.md correctly 1`] = `
</div>
`;
exports[`renders ./components/card/demo/concise.md correctly 1`] = `
<div class="ant-card ant-card-bordered" style="width: 300px;">
<div class="ant-card-body">
<p>Card content</p>
<p>Card content</p>
<p>Card content</p>
</div>
</div>
`;
exports[`renders ./components/card/demo/flexible-content.md correctly 1`] = `
<div class="ant-card ant-card-bordered ant-card-hoverable" style="width: 240px;">
<div class="ant-card-cover">
<img alt="example" src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png">
</div>
<div class="ant-card-body">
<div class="ant-card-meta">
<div class="ant-card-meta-detail">
<div class="ant-card-meta-title">Europe Street beat</div>
<div class="ant-card-meta-description">www.instagram.com</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/card/demo/grid.md correctly 1`] = `
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Card Title</div>
</div>
</div>
<div class="ant-card-body">
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
<div class="ant-card-grid" style="width: 25%; text-align: 'center';">Content</div>
</div>
</div>
`;
exports[`renders ./components/card/demo/inline.md correctly 1`] = `
exports[`renders ./components/card/demo/inner.md correctly 1`] = `
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
@ -114,7 +131,9 @@ exports[`renders ./components/card/demo/inline.md correctly 1`] = `
</div>
</div>
<div class="ant-card-body">
<p style="font-size: 14px; color: rgba(0, 0, 0, 0.85); margin-bottom: 16px; font-weight: 500;">Group title</p>
<p style="font-size: 14px; color: rgba(0, 0, 0, 0.85); margin-bottom: 16px; font-weight: 500;">
Group title
</p>
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
@ -128,7 +147,7 @@ exports[`renders ./components/card/demo/inline.md correctly 1`] = `
Inner Card content
</div>
</div>
<div class="ant-card ant-card-bordered">
<div class="ant-card ant-card-bordered" style="margin-top: 16px;">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Inner card title</div>
@ -155,11 +174,57 @@ exports[`renders ./components/card/demo/loading.md correctly 1`] = `
</div>
<div class="ant-card-body">
<div class="ant-card-loading-content">
<p class="ant-card-loading-block" style="width: 94%;"></p>
<p><span class="ant-card-loading-block" style="width: 28%;"></span><span class="ant-card-loading-block" style="width: 62%;"></span></p>
<p><span class="ant-card-loading-block" style="width: 22%;"></span><span class="ant-card-loading-block" style="width: 66%;"></span></p>
<p><span class="ant-card-loading-block" style="width: 56%;"></span><span class="ant-card-loading-block" style="width: 39%;"></span></p>
<p><span class="ant-card-loading-block" style="width: 21%;"></span><span class="ant-card-loading-block" style="width: 15%;"></span><span class="ant-card-loading-block" style="width: 40%;"></span></p>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-22" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-8" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-15" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-6" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-18" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-13" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-9" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-4" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-3" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-16" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-8" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-6" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-8" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
</div>
</div>
</div>
@ -167,14 +232,14 @@ exports[`renders ./components/card/demo/loading.md correctly 1`] = `
</div>
`;
exports[`renders ./components/card/demo/moreConfigs.md correctly 1`] = `
exports[`renders ./components/card/demo/meta.md correctly 1`] = `
<div class="ant-card ant-card-bordered ant-card-hoverable" style="width: 300px;">
<div class="ant-card-cover">
<img alt="example" src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png">
</div>
<div class="ant-card-body">
<div class="ant-card-meta">
<div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-image ant-avatar-circle"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span></div>
<div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span></div>
<div class="ant-card-meta-detail">
<div class="ant-card-meta-title">Card title</div>
<div class="ant-card-meta-description">This is the description</div>
@ -182,37 +247,24 @@ exports[`renders ./components/card/demo/moreConfigs.md correctly 1`] = `
</div>
</div>
<ul class="ant-card-actions">
<li style="width: 33.3333%;">
<i class="anticon anticon-setting"></i>
</li>
<li style="width: 33.3333%;">
<i class="anticon anticon-edit"></i>
</li>
<li style="width: 33.3333%;">
<i class="anticon anticon-ellipsis"></i>
</li>
<li style="width: 33.333333333333336%;"><span><i class="anticon anticon-setting"></i></span></li>
<li style="width: 33.333333333333336%;"><span><i class="anticon anticon-edit"></i></span></li>
<li style="width: 33.333333333333336%;"><span><i class="anticon anticon-ellipsis"></i></span></li>
</ul>
</div>
`;
exports[`renders ./components/card/demo/noBorder.md correctly 1`] = `
<div style="background: rgb(236, 236, 236); padding: 30px;">
<div class="ant-card" style="width: 300px;">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Card title</div>
</div>
</div>
<div class="ant-card-body">
<p>Card content</p>
<p>Card content</p>
<p>Card content</p>
</div>
exports[`renders ./components/card/demo/simple.md correctly 1`] = `
<div class="ant-card ant-card-bordered" style="width: 300px;">
<div class="ant-card-body">
<p>Card content</p>
<p>Card content</p>
<p>Card content</p>
</div>
</div>
`;
exports[`renders ./components/card/demo/tabsCard.md correctly 1`] = `
exports[`renders ./components/card/demo/tabs.md correctly 1`] = `
<div>
<div class="ant-card ant-card-bordered ant-card-contain-tabs" style="width: 100%;">
<div class="ant-card-head">
@ -224,16 +276,17 @@ exports[`renders ./components/card/demo/tabsCard.md correctly 1`] = `
</div>
<div class="ant-tabs ant-tabs-top ant-tabs-large ant-tabs-line ant-card-head-tabs no-flex">
<div role="tablist" tabindex="0" class="ant-tabs-bar">
<div class="ant-tabs-extra-content" style="float: right;"></div>
<div class="ant-tabs-nav-container"><span unselectable="unselectable" class="ant-tabs-tab-prev ant-tabs-tab-btn-disabled"><span class="ant-tabs-tab-prev-icon"></span></span><span unselectable="unselectable" class="ant-tabs-tab-next ant-tabs-tab-btn-disabled"><span class="ant-tabs-tab-next-icon"></span></span>
<div
class="ant-tabs-nav-wrap">
<div class="ant-tabs-nav-scroll">
<div class="ant-tabs-nav ant-tabs-nav-animated">
<div class="ant-tabs-ink-bar ant-tabs-ink-bar-animated" style="display: block; transform: translate3d(0px,0,0); -webkit-transform: translate3d(0px,0,0); width: 0px;"></div>
<div role="tab" aria-disabled="false" aria-selected="true" class="ant-tabs-tab-active ant-tabs-tab"><span><i class="anticon anticon-home"></i>tab1
<div>
<div role="tab" aria-disabled="false" aria-selected="true" class="ant-tabs-tab-active ant-tabs-tab"><span><i class="anticon anticon-home"></i>tab1
</span></div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">tab2</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">tab2</div>
</div>
<div class="ant-tabs-ink-bar ant-tabs-ink-bar-animated" style="display: block; transform: translate3d(0px,0,0); -webkit-transform: translate3d(0px,0,0); width: 0px;"></div>
</div>
</div>
</div>
@ -256,16 +309,17 @@ exports[`renders ./components/card/demo/tabsCard.md correctly 1`] = `
<div class="ant-card-head-wrapper"></div>
<div class="ant-tabs ant-tabs-top ant-tabs-large ant-tabs-line ant-card-head-tabs no-flex">
<div role="tablist" tabindex="0" class="ant-tabs-bar">
<div class="ant-tabs-extra-content" style="float: right;"></div>
<div class="ant-tabs-nav-container"><span unselectable="unselectable" class="ant-tabs-tab-prev ant-tabs-tab-btn-disabled"><span class="ant-tabs-tab-prev-icon"></span></span><span unselectable="unselectable" class="ant-tabs-tab-next ant-tabs-tab-btn-disabled"><span class="ant-tabs-tab-next-icon"></span></span>
<div
class="ant-tabs-nav-wrap">
<div class="ant-tabs-nav-scroll">
<div class="ant-tabs-nav ant-tabs-nav-animated">
<div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">article</div>
<div role="tab" aria-disabled="false" aria-selected="true" class="ant-tabs-tab-active ant-tabs-tab">app</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">project</div>
</div>
<div class="ant-tabs-ink-bar ant-tabs-ink-bar-animated" style="display: block; transform: translate3d(0px,0,0); -webkit-transform: translate3d(0px,0,0); width: 0px;"></div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">article</div>
<div role="tab" aria-disabled="false" aria-selected="true" class="ant-tabs-tab-active ant-tabs-tab">app</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">project</div>
</div>
</div>
</div>

View File

@ -0,0 +1,61 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Card should still have padding when card which set padding to 0 is loading 1`] = `
<div class="ant-card ant-card-loading ant-card-bordered">
<div class="ant-card-body" style="padding: 0px;">
<div class="ant-card-loading-content">
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-22" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-8" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-15" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-6" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-18" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-13" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-9" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-4" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-3" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-16" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
<div class="ant-row" style="margin-left: -4px; margin-right: -4px;">
<div class="ant-col-8" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-6" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
<div class="ant-col-8" style="padding-left: 4px; padding-right: 4px;">
<div class="ant-card-loading-block"></div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -38,4 +38,12 @@ describe('Card', () => {
wrapper.vm.$forceUpdate()
expect(wrapper.findAll('.ant-card-wider-padding').length).toBe(0)
})
it('should still have padding when card which set padding to 0 is loading', () => {
const wrapper = mount({
render () {
return <Card loading bodyStyle={{ padding: 0 }}>xxx</Card>
},
})
expect(wrapper.html()).toMatchSnapshot()
})
})

View File

@ -1,14 +1,15 @@
<script>
import Basic from './basic'
import NoBorder from './noBorder'
import Concise from './concise'
import ColRowCard from './colRowCard'
import Loading from './loading'
import Grid from './grid'
import Inline from './inline'
import TabsCard from './tabsCard'
import MoreConfigs from './moreConfigs'
import FlexibleContent from './flexible-content'
import Basic from './basic.md'
import BorderLess from './border-less.md'
import Concise from './concise.md'
import FlexibleContent from './flexible-content.md'
import GridCard from './grid-card.md'
import InColumn from './in-column.md'
import Inner from './inner.md'
import Loading from './loading.md'
import Meta from './meta.md'
import Simple from './simple.md'
import Tabs from './tabs.md'
import CN from './../index.zh-CN.md'
import US from './../index.en-US.md'
@ -39,16 +40,17 @@ export default {
return (
<div>
<md cn={md.cn} us={md.us} />
<Basic />
<NoBorder />
<Concise />
<FlexibleContent />
<ColRowCard />
<Loading />
<Grid />
<Inline />
<TabsCard />
<MoreConfigs />
<Basic/>
<BorderLess/>
<Concise/>
<FlexibleContent/>
<GridCard/>
<InColumn/>
<Inner/>
<Loading/>
<Meta/>
<Simple/>
<Tabs/>
<api>
<CN slot='cn' />
<US />

View File

@ -12,16 +12,18 @@
<template>
<a-card title="Card title">
<p style="fontSize: 14px;color: rgba(0, 0, 0, 0.85); marginBottom: 16px;fontWeight: 500"
>Group title</p>
>
Group title
</p>
<a-card title="Inner card title">
<a href="#" slot="extra">More</a>
Inner Card content
</a-card>
<a-card title="Inner card title">
<a-card title="Inner card title" :style="{ marginTop: '16px' }">
<a href="#" slot="extra">More</a>
Inner Card content
</a-card>
</a-card>
</template>
```
```

View File

@ -19,11 +19,11 @@
src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
slot="cover"
/>
<ul class="ant-card-actions" slot="actions">
<li style="width: 33.3333%;"><a-icon type="setting" /></li>
<li style="width: 33.3333%;"><a-icon type="edit" /></li>
<li style="width: 33.3333%;"> <a-icon type="ellipsis" /></li>
</ul>
<template class="ant-card-actions" slot="actions">
<a-icon type="setting" />
<a-icon type="edit" />
<a-icon type="ellipsis" />
</template>
<a-card-meta
title="Card title"
description="This is the description">

View File

@ -0,0 +1,19 @@
<cn>
#### 简洁卡片
只包含内容区域。
</cn>
<us>
#### Simple card
A simple card only containing a content area.
</us>
```html
<template>
<a-card style="width: 300px">
<p>Card content</p>
<p>Card content</p>
<p>Card content</p>
</a-card>
</template>
```

View File

@ -15,6 +15,7 @@
style="width:100%"
title="Card title"
:tabList="tabList"
:activeTabKey="key"
@tabChange="key => onTabChange(key, 'key')"
>
<span slot="customRender" slot-scope="item">

View File

@ -4,19 +4,19 @@
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| actions | The action list, shows at the bottom of the Card. | slot | - |
| actions | The action list, shows at the bottom of the Card. | slots | - |
| activeTabKey | Current TabPane's key | string | - |
| headStyle | Inline style to apply to the card head | object | - |
| bodyStyle | Inline style to apply to the card content | object | - |
| bordered | Toggles rendering of the border around the card | boolean | `true` |
| cover | Card cover | slot | - |
| defaultActiveTabKey | Initial active TabPane's key, if `activeTabKey` is not set. | string | - |
| extra | Content to render in the top-right corner of the card | string\|slot | - |
| hoverable | Lift up when hovering card | boolean | false |
| loading | Shows a loading indicator while the contents of the card are being fetched | boolean | false |
| tabList | List of TabPane's head, Custom tabs can be created with the scopedSlots property | Array<{key: string, tab: any, scopedSlots: {tab: 'XXX'}}> | - |
| activeTabKey | Current TabPane's key | string | - |
| defaultActiveTabKey | Initial active TabPane's key, if `activeTabKey` is not set. | string | - |
| title | Card title | string\|slot | - |
| type | Card style type, can be set to `inner` or not set | string | - |
| onTabChange | Callback when tab is switched | (key) => void | - |
### events
| Events Name | Description | Arguments |

View File

@ -5,19 +5,19 @@
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| actions | 卡片操作组,位置在卡片底部 |slot | - |
| actions | 卡片操作组,位置在卡片底部 |slots | - |
| activeTabKey | 当前激活页签的 key | string | - |
| headStyle | 自定义标题区域样式 | object | - |
| bodyStyle | 内容区域自定义样式 | object | - |
| bordered | 是否有边框 | boolean | true |
| cover | 卡片封面 | slot | - |
| defaultActiveTabKey | 初始化选中页签的 key如果没有设置 activeTabKey | string | 第一个页签 |
| extra | 卡片右上角的操作区域 | string\|slot | - |
| hoverable | 鼠标移过时可浮起 | boolean | false |
| loading | 当卡片内容还在加载中时,可以用 loading 展示一个占位 | boolean | false |
| tabList | 页签标题列表, 可以通过scopedSlots属性自定义tab | Array<{key: string, tab: any, scopedSlots: {tab: 'XXX'}}> | - |
| activeTabKey | 当前激活页签的 key | string | - |
| defaultActiveTabKey | 初始化选中页签的 key如果没有设置 activeTabKey | string | 第一个页签 |
| title | 卡片标题 | string\|slot | - |
| type | 卡片类型,可设置为 `inner` 或 不设置 | string | - |
| onTabChange | 页签切换的回调 | (key) => void | - |
### 事件
| 事件名称 | 说明 | 回调参数 |

View File

@ -1,5 +1,5 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';
// style dependencies
import '../../tabs/style'
import '../../tabs/style';

View File

@ -72,7 +72,7 @@
.clearfix;
}
&-contain-grid &-body {
&-contain-grid:not(&-loading) {
margin: -1px 0 0 -1px;
padding: 0;
}
@ -171,10 +171,6 @@
transition: padding .3s;
}
&-padding-transition &-extra {
transition: right .3s;
}
&-type-inner &-head {
padding: 0 @card-padding-base;
background: @background-color-light;
@ -225,20 +221,17 @@
&-loading &-body {
user-select: none;
padding: 0;
}
&-loading-content {
padding: @card-padding-base;
p {
margin: 0;
}
}
&-loading-block {
display: inline-block;
margin: 5px 2% 0 0;
height: 14px;
margin: 4px 0;
border-radius: @border-radius-sm;
background: linear-gradient(90deg, rgba(207, 216, 220, .2), rgba(207, 216, 220, .4), rgba(207, 216, 220, .2));
animation: card-loading 1.4s ease infinite;

View File

@ -12,7 +12,8 @@ import US from '../index.en-US.md'
import '../style'
const md = {
cn: `# 旋转木马,一组轮播的区域。
cn: `# Carousel 走马灯
旋转木马一组轮播的区域
## 何时使用
- 当有一组平级的内容
@ -20,7 +21,8 @@ const md = {
- 常用于一组图片或卡片轮播
## 代码演示
`,
us: `# A carousel component. Scales with its container.
us: `# Carousel
A carousel component. Scales with its container.
## When To Use
- When there is a group of content on the same level.

View File

@ -1,2 +1,2 @@
import '../../style/index.less'
import './index.less'
import '../../style/index.less';
import './index.less';

View File

@ -46,6 +46,12 @@ exports[`renders ./components/cascader/demo/disabled-option.md correctly 1`] = `
</span>
`;
exports[`renders ./components/cascader/demo/fields-name.md correctly 1`] = `
<span tabindex="0" class="ant-cascader-picker"><input value="" placeholder="Please select" type="text" readonly="true" class="ant-input ant-cascader-input ant-cascader-input "><span class="ant-cascader-picker-label"></span>
<i class="anticon anticon-down ant-cascader-picker-arrow"></i>
</span>
`;
exports[`renders ./components/cascader/demo/hover.md correctly 1`] = `
<span tabindex="0" class="ant-cascader-picker"><input value="" placeholder="Please select" type="text" readonly="true" class="ant-input ant-cascader-input ant-cascader-input "><span class="ant-cascader-picker-label"></span>
<i class="anticon anticon-down ant-cascader-picker-arrow"></i>
@ -59,7 +65,7 @@ exports[`renders ./components/cascader/demo/lazy.md correctly 1`] = `
`;
exports[`renders ./components/cascader/demo/search.md correctly 1`] = `
<span tabindex="0" class="ant-cascader-picker"><span class="ant-cascader-picker-label"></span>
<span tabindex="0" class="ant-cascader-picker ant-cascader-picker-show-search"><span class="ant-cascader-picker-label"></span>
<input value="" placeholder="Please select" type="text" class="ant-input ant-cascader-input ant-cascader-input ">
<i class="anticon anticon-down ant-cascader-picker-arrow"></i>
</span>

View File

@ -0,0 +1,54 @@
<cn>
#### 自定义字段名
自定义字段名。
</cn>
<us>
#### Custom Field Names
Custom Field Names.
</us>
```html
<template>
<a-cascader :fieldNames="{ label: 'name', value: 'code', children: 'items' }" :options="options" @change="onChange" placeholder="Please select" />
</template>
<script>
const options = [{
code: 'zhejiang',
name: 'Zhejiang',
items: [{
code: 'hangzhou',
name: 'Hangzhou',
items: [{
code: 'xihu',
name: 'West Lake',
}],
}],
}, {
code: 'jiangsu',
name: 'Jiangsu',
items: [{
code: 'nanjing',
name: 'Nanjing',
items: [{
code: 'zhonghuamen',
name: 'Zhong Hua Men',
}],
}],
}]
export default {
data() {
return {
options,
}
},
methods: {
onChange(value) {
console.log(value);
}
}
}
</script>
```

Some files were not shown because too many files have changed in this diff Show More