feat(image, avatar): add onError and objectFit props (#485)

* feat: add onError and object-fit

* fix: change objectFit to fill

* fix: onError add event and objectFit set default value

* fix: change some error

Co-authored-by: yugang.cao <yugang.cao@tusimple.ai>
This commit is contained in:
caoyugang_1 2021-07-14 23:46:47 +08:00 committed by GitHub
parent 8201231292
commit 95270c3f98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 83 additions and 5 deletions

View File

@ -9,6 +9,10 @@
- `n-slider` add `format-tooltip` prop.
- `n-upload` add `event` in `on-finish` callback params.
- `n-rate` add `readonly` prop.
- `n-avatar` add `on-error` prop, closes [#394](https://github.com/TuSimple/naive-ui/issues/394).
- `n-image` add `on-error` prop, closes [#394](https://github.com/TuSimple/naive-ui/issues/394).
- `n-image` add `object-fit` prop, closes [#394](https://github.com/TuSimple/naive-ui/issues/394).
- `n-avatar` add `object-fit` prop, closes [#394](https://github.com/TuSimple/naive-ui/issues/394).
### Fixes

View File

@ -10,6 +10,10 @@
- `n-upload``on-finish` 回调参数中新增 `event`
- `n-slider` 新增 `format-tooltip` 属性
- `n-rate` 新增 `readonly` 属性
- `n-avatar` 新增 `on-error` 属性,关闭[#394](https://github.com/TuSimple/naive-ui/issues/394)
- `n-image` 新增 `on-error` 属性,关闭[#394](https://github.com/TuSimple/naive-ui/issues/394)
- `n-image` 新增 `object-fit` 属性,关闭[#394](https://github.com/TuSimple/naive-ui/issues/394)
- `n-avatar` 新增 `object-fit` 属性,关闭[#394](https://github.com/TuSimple/naive-ui/issues/394)
### Fixes

View File

@ -26,11 +26,18 @@ const avatarProps = {
type: Boolean,
default: false
},
color: String,
objectFit: {
type: String as PropType<
'fill' | 'contain' | 'cover' | 'none' | 'scale-down'
>,
default: 'fill'
},
round: {
type: Boolean,
default: false
},
color: String
onError: Function as PropType<(e: Event) => void>
} as const
export type AvatarProps = ExtractPublicPropTypes<typeof avatarProps>
@ -112,7 +119,11 @@ export default defineComponent({
style={this.cssVars as any}
>
{!$slots.default && src ? (
<img src={src} />
<img
src={src}
onError={this.onError}
style={{ objectFit: this.objectFit }}
/>
) : (
<span
ref="textRef"

View File

@ -118,4 +118,28 @@ describe('n-avatar', () => {
)
expect(wrapper.html()).toMatchSnapshot()
})
it('image avatar error handle when load failed', async () => {
const onError = jest.fn()
const wrapper = mount(NAvatar, {
props: {
src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',
onError
}
})
await wrapper.find('img').trigger('error')
expect(onError).toHaveBeenCalled()
})
it('should work with `objectFit` prop', () => {
const wrapper = mount(NAvatar, {
props: {
src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',
objectFit: 'contain'
}
})
expect(wrapper.find('img').attributes('style')).toContain(
'object-fit: contain;'
)
})
})

View File

@ -6,7 +6,7 @@ exports[`n-avatar custom style 1`] = `"<span class=\\"n-avatar\\" style=\\"--fon
exports[`n-avatar icon avatar 1`] = `"<span class=\\"n-avatar\\" style=\\"--font-size: 14px; --border-radius: 3px; --color: rgba(204, 204, 204, 1); --bezier: cubic-bezier(.4, 0, .2, 1); --size: 34px;\\"><span class=\\"n-avatar__text\\" style=\\"transform: translateX(-50%) translateY(-50%) scale(1);\\"><i role=\\"img\\" class=\\"n-icon\\" style=\\"--bezier: cubic-bezier(.4, 0, .2, 1);\\"><svg xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" viewBox=\\"0 0 512 512\\"><rect x=\\"32\\" y=\\"80\\" width=\\"448\\" height=\\"256\\" rx=\\"16\\" ry=\\"16\\" transform=\\"rotate(180 256 208)\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-linejoin=\\"round\\" stroke-width=\\"32\\"></rect><path fill=\\"none\\" stroke=\\"currentColor\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" stroke-width=\\"32\\" d=\\"M64 384h384\\"></path><path fill=\\"none\\" stroke=\\"currentColor\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" stroke-width=\\"32\\" d=\\"M96 432h320\\"></path><circle cx=\\"256\\" cy=\\"208\\" r=\\"80\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" stroke-width=\\"32\\"></circle><path d=\\"M480 160a80 80 0 0 1-80-80\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" stroke-width=\\"32\\"></path><path d=\\"M32 160a80 80 0 0 0 80-80\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" stroke-width=\\"32\\"></path><path d=\\"M480 256a80 80 0 0 0-80 80\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" stroke-width=\\"32\\"></path><path d=\\"M32 256a80 80 0 0 1 80 80\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" stroke-width=\\"32\\"></path></svg></i></span></span>"`;
exports[`n-avatar image avatar 1`] = `"<span class=\\"n-avatar\\" style=\\"--font-size: 14px; --border-radius: 3px; --color: rgba(204, 204, 204, 1); --bezier: cubic-bezier(.4, 0, .2, 1); --size: 34px;\\"><img src=\\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\\"></span>"`;
exports[`n-avatar image avatar 1`] = `"<span class=\\"n-avatar\\" style=\\"--font-size: 14px; --border-radius: 3px; --color: rgba(204, 204, 204, 1); --bezier: cubic-bezier(.4, 0, .2, 1); --size: 34px;\\"><img src=\\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\\" style=\\"object-fit: fill;\\"></span>"`;
exports[`n-avatar round avatar 1`] = `"<span class=\\"n-avatar\\" style=\\"--font-size: 14px; --border-radius: 50%; --color: rgba(204, 204, 204, 1); --bezier: cubic-bezier(.4, 0, .2, 1); --size: 34px;\\"><span class=\\"n-avatar__text\\" style=\\"transform: translateX(-50%) translateY(-50%) scale(1);\\"></span></span>"`;

View File

@ -29,9 +29,16 @@ const imageProps = {
alt: String,
height: [String, Number] as PropType<string | number>,
imgProps: Object as PropType<imgProps>,
objectFit: {
type: String as PropType<
'fill' | 'contain' | 'cover' | 'none' | 'scale-down'
>,
default: 'fill'
},
width: [String, Number] as PropType<string | number>,
src: String,
showToolbar: { type: Boolean, default: true }
showToolbar: { type: Boolean, default: true },
onError: Function as PropType<(e: Event) => void>
}
export type ImageProps = ExtractPublicPropTypes<typeof imageProps>
@ -86,6 +93,8 @@ export default defineComponent({
alt={this.alt ? this.alt : imgProps.alt}
aria-label={this.alt ? this.alt : imgProps.alt}
onClick={this.handleClick}
onError={this.onError}
style={{ objectFit: this.objectFit }}
/>
)

View File

@ -73,6 +73,8 @@ export default c([
display: inline-flex;
cursor: pointer;
`, [
c('img', 'border-radius: inherit;')
c('img', `
border-radius: inherit;
`)
])
])

View File

@ -91,4 +91,28 @@ describe('n-image', () => {
})
expect(wrapper.find('[data-cool]').exists()).toEqual(true)
})
it('should work with `onError` prop', async () => {
const onError = jest.fn()
const wrapper = mount(NImage, {
props: {
src: 'https:// 07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',
onError
}
})
await wrapper.find('img').trigger('error')
expect(onError).toHaveBeenCalled()
})
it('should work with `objectFit` prop', () => {
const wrapper = mount(NImage, {
props: {
src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',
objectFit: 'contain'
}
})
expect(wrapper.find('img').attributes('style')).toContain(
'object-fit: contain;'
)
})
})