Merge pull request #792 from TuSimple/main

sync main
This commit is contained in:
07akioni 2021-08-06 02:39:34 +08:00 committed by GitHub
commit 5021deae87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 384 additions and 81 deletions

View File

@ -1,5 +1,21 @@
# CHANGELOG
## 2.16.1 (2020-08-06)
### Feats
- `n-loading-bar` add `loading-bar-style` props, closes [#457](https://github.com/TuSimple/naive-ui/issues/457).
- `n-button` add `text-color` prop.
- `n-form` export `FormValidationError` type.
### Fixes
- Fix `n-slider` loss floating point decimal precision, closes [#751](https://github.com/TuSimple/naive-ui/issues/751).
- Fix `n-data-table` `onUpdatePage` and `onUpdatePageSize` not triggered while using jsx.
- Fix `n-progress`'s `percentage` prop default value doesn't work with different types.
- Fix `n-select` hide close icon when option is disabled.
- Fix `n-modal` can't be closed when using custom content, closes [#788](https://github.com/TuSimple/naive-ui/issues/788).
## 2.16.0 (2021-08-02)
### Breaking Changes

View File

@ -1,5 +1,21 @@
# CHANGELOG
## 2.16.1 (2020-08-06)
### Feats
- `n-loading-bar` 新增 `loading-bar-style` 属性,关闭 [#457](https://github.com/TuSimple/naive-ui/issues/457)
- `n-button` 新增 `text-color` 属性
- `n-form` 导出 `FormValidationError` 类型
### Fixes
- 修复 `n-slider` 丢失浮点数小数精度,关闭 [#751](https://github.com/TuSimple/naive-ui/issues/751)
- 修复 `n-data-table` `onUpdatePage``onUpdatePageSize` 在使用 jsx 时不触发的问题
- 修复 `n-progress``percentage` 属性默认值不能适应多种类型
- 修复 `n-select` 当选项禁用时未隐藏关闭图标
- 修复 `n-modal` 使用自定义内容无法正常关闭,关闭 [#788](https://github.com/TuSimple/naive-ui/issues/788)
## 2.16.0 (2021-08-02)
### Breaking Changes

View File

@ -1,6 +1,6 @@
{
"name": "naive-ui",
"version": "2.16.0",
"version": "2.16.1",
"description": "A Vue 3 Component Library. Fairly Complete, Customizable Themes, Uses TypeScript, Not Too Slow",
"main": "lib/index.js",
"module": "es/index.js",
@ -72,9 +72,9 @@
"@types/jest": "^26.0.20",
"@typescript-eslint/eslint-plugin": "^4.15.1",
"@typescript-eslint/parser": "^4.15.1",
"@vicons/fluent": "^0.10.0",
"@vicons/ionicons4": "^0.10.0",
"@vicons/ionicons5": "^0.10.0",
"@vicons/fluent": "^0.11.0",
"@vicons/ionicons4": "^0.11.0",
"@vicons/ionicons5": "^0.11.0",
"@vitejs/plugin-vue": "^1.2.1",
"@vue/compiler-sfc": "^3.0.10",
"@vue/eslint-config-standard": "^6.0.0",

View File

@ -505,7 +505,7 @@ export default defineComponent({
) : (
<NTag
size={size}
closable
closable={!option.disabled}
disabled={disabled}
internalStopClickPropagation
onClose={() => this.handleDeleteOption(option)}

View File

@ -5,4 +5,53 @@ describe('n-badge', () => {
it('should work with import on demand', () => {
mount(NBadge)
})
it('should work with `dot` prop', async () => {
const wrapper = mount(NBadge, { props: { value: 5 } })
expect(wrapper.find('.n-badge').classes('n-badge--dot')).not.toBe(true)
expect(wrapper.find('.n-base-slot-machine').exists()).toBe(true)
await wrapper.setProps({ dot: true })
expect(wrapper.find('.n-badge').classes('n-badge--dot')).toBe(true)
expect(wrapper.find('.n-base-slot-machine').exists()).not.toBe(true)
})
it('should work with `color` prop', async () => {
const wrapper = mount(NBadge, { props: { value: 5, color: 'grey' } })
expect(wrapper.find('.n-badge').attributes('style')).toContain(
'--color: grey;'
)
})
it('should work with `max` prop', async () => {
const wrapper = mount(NBadge, { props: { value: 5, max: 5 } })
expect(
wrapper
.find('.n-base-slot-machine-current-number__inner--not-number')
.exists()
).not.toBe(true)
await wrapper.setProps({ value: 6 })
expect(
wrapper
.find('.n-base-slot-machine-current-number__inner--not-number')
.exists()
).toBe(true)
})
it('should work with `processing` prop', async () => {
const wrapper = mount(NBadge, { props: { value: 5 } })
expect(wrapper.find('.n-base-wave').exists()).not.toBe(true)
await wrapper.setProps({ processing: true })
expect(wrapper.find('.n-base-wave').exists()).toBe(true)
})
it('should work with `show-zero` prop', async () => {
const wrapper = mount(NBadge, { props: { value: 0 } })
expect(wrapper.find('.n-badge-sup').exists()).not.toBe(true)
await wrapper.setProps({ 'show-zero': true })
expect(wrapper.find('.n-badge-sup').exists()).toBe(true)
})
})

View File

@ -31,7 +31,7 @@ icon-button
| block | `boolean` | `false` | Whether the button is displayed as block. |
| bordered | `boolean` | `true` | Whether the button shows the border. |
| circle | `boolean` | `false` | Whether the button is round. |
| color | `string` | `undefined` | Button color(support `#FFF`, `#FFFFFF`, `yellow`,`rgb(0, 0, 0)` formatted colors). |
| color | `string` | `undefined` | Button color (support `#FFF`, `#FFFFFF`, `yellow`,`rgb(0, 0, 0)` formatted colors). |
| dashed | `boolean` | `false` | Whether the button's border is a dashed line. |
| disabled | `boolean` | `false` | Whether the button is disabled. |
| ghost | `boolean` | `false` | Whether the button is ghost. |
@ -41,6 +41,7 @@ icon-button
| round | `boolean` | `false` | Whether the button shows rounded corners. |
| size | `'tiny' \| 'small' \| 'medium' \| 'large'` | `'medium'` | Button size. |
| text | `boolean` | `false` | Whether to display as a text button. |
| text-color | `string` | `undefined` | Button text color (support `#FFF`, `#FFFFFF`, `yellow`,`rgb(0, 0, 0)` formatted colors). |
| type | `'default' \| 'primary' \| 'success' \| 'info' \| 'warning' \| 'error'` | `'default'` | Button type. |
| tag | `string` | `'button'` | What tag need the button be rendered as. |
@ -58,7 +59,7 @@ icon-button
| Name | Parameters | Description |
| ------- | ---------- | ---------------------------------- |
| default | `()` | The default content of the button. |
| icon | `()` | The icon of the button. |
| icon | `()` | The icon of the button. |
### Button Group Slots

View File

@ -43,6 +43,7 @@ debug
| round | `boolean` | `false` | 按钮是否显示圆角 |
| size | `'tiny' \| 'small' \| 'medium' \| 'large'` | `'medium'` | 按钮的尺寸 |
| text | `boolean` | `false` | 是否显示为文本按钮 |
| text-color | `string` | `undefined` | 按钮文字颜色(支持形如 `#FFF` `#FFFFFF` `yellow``rgb(0, 0, 0)` 的颜色) |
| type | `'default' \| 'primary' \| 'success' \| 'info' \| 'warning' \| 'error'` | `'default'` | 按钮的类型 |
| tag | `string` | `'button'` | 按钮需要被渲染为什么标签 |

View File

@ -33,6 +33,7 @@ import useRtl from '../../_mixins/use-rtl'
const buttonProps = {
...(useTheme.props as ThemeProps<ButtonTheme>),
color: String,
textColor: String,
text: Boolean,
block: Boolean,
loading: Boolean,
@ -214,7 +215,8 @@ const Button = defineComponent({
fontWeight
} = self
const size = mergedSizeRef.value
const { dashed, type, ghost, text, color, round, circle } = props
const { dashed, type, ghost, text, color, round, circle, textColor } =
props
// font
const fontProps = {
fontWeight: text
@ -239,8 +241,9 @@ const Button = defineComponent({
}
if (text) {
const { depth } = props
const textColor =
color ||
const propTextColor = textColor || color
const mergedTextColor =
propTextColor ||
(type === 'default' && depth !== undefined
? self[
createKey(
@ -256,20 +259,21 @@ const Button = defineComponent({
'--color-focus': '#0000',
'--color-disabled': '#0000',
'--ripple-color': '#0000',
'--text-color': textColor,
'--text-color-hover': color
? createHoverColor(color)
'--text-color': mergedTextColor,
'--text-color-hover': propTextColor
? createHoverColor(propTextColor)
: self[createKey('textColorTextHover', type)],
'--text-color-pressed': color
? createPressedColor(color)
'--text-color-pressed': propTextColor
? createPressedColor(propTextColor)
: self[createKey('textColorTextPressed', type)],
'--text-color-focus': color
? createHoverColor(color)
'--text-color-focus': propTextColor
? createHoverColor(propTextColor)
: self[createKey('textColorTextHover', type)],
'--text-color-disabled':
color || self[createKey('textColorTextDisabled', type)]
propTextColor || self[createKey('textColorTextDisabled', type)]
}
} else if (ghost || dashed) {
const mergedTextColor = textColor || color
colorProps = {
'--color': '#0000',
'--color-hover': '#0000',
@ -277,18 +281,19 @@ const Button = defineComponent({
'--color-focus': '#0000',
'--color-disabled': '#0000',
'--ripple-color': color || self[createKey('rippleColor', type)],
'--text-color': color || self[createKey('textColorGhost', type)],
'--text-color-hover': color
? createHoverColor(color)
'--text-color':
mergedTextColor || self[createKey('textColorGhost', type)],
'--text-color-hover': mergedTextColor
? createHoverColor(mergedTextColor)
: self[createKey('textColorGhostHover', type)],
'--text-color-pressed': color
? createPressedColor(color)
'--text-color-pressed': mergedTextColor
? createPressedColor(mergedTextColor)
: self[createKey('textColorGhostPressed', type)],
'--text-color-focus': color
? createHoverColor(color)
'--text-color-focus': mergedTextColor
? createHoverColor(mergedTextColor)
: self[createKey('textColorGhostHover', type)],
'--text-color-disabled':
color || self[createKey('textColorGhostDisabled', type)]
mergedTextColor || self[createKey('textColorGhostDisabled', type)]
}
} else {
colorProps = {
@ -304,21 +309,31 @@ const Button = defineComponent({
: self[createKey('colorFocus', type)],
'--color-disabled': color || self[createKey('colorDisabled', type)],
'--ripple-color': color || self[createKey('rippleColor', type)],
'--text-color': color
? self.textColorPrimary
: self[createKey('textColor', type)],
'--text-color-hover': color
? self.textColorHoverPrimary
: self[createKey('textColorHover', type)],
'--text-color-pressed': color
? self.textColorPressedPrimary
: self[createKey('textColorPressed', type)],
'--text-color-focus': color
? self.textColorFocusPrimary
: self[createKey('textColorFocus', type)],
'--text-color-disabled': color
? self.textColorDisabledPrimary
: self[createKey('textColorDisabled', type)]
'--text-color':
textColor ||
(color
? self.textColorPrimary
: self[createKey('textColor', type)]),
'--text-color-hover':
textColor ||
(color
? self.textColorHoverPrimary
: self[createKey('textColorHover', type)]),
'--text-color-pressed':
textColor ||
(color
? self.textColorPressedPrimary
: self[createKey('textColorPressed', type)]),
'--text-color-focus':
textColor ||
(color
? self.textColorFocusPrimary
: self[createKey('textColorFocus', type)]),
'--text-color-disabled':
textColor ||
(color
? self.textColorDisabledPrimary
: self[createKey('textColorDisabled', type)])
}
}
// border

View File

@ -233,6 +233,24 @@ describe('n-button', () => {
expect(colorStyle.every((i) => buttonStyle.includes(i))).toBe(true)
})
it('should work with `text-color` prop', () => {
const wrapper = mount(NButton, {
props: {
'text-color': '#8a2be2'
},
slots: {
default: () => 'test'
}
})
const buttonStyle = wrapper.find('button').attributes('style')
expect(
(
['--text-color: #8a2be2;', '--text-color-disabled: #8a2be2;'] as const
).every((i) => buttonStyle.includes(i))
).toBe(true)
})
it('should work with `button group`', async () => {
const wrapper = mount(NButtonGroup, {
slots: {

View File

@ -348,15 +348,21 @@ export function useTableData (
})
function doUpdatePage (page: number): void {
const { 'onUpdate:page': onUpdatePage, onPageChange } = props
const { 'onUpdate:page': _onUpdatePage, onPageChange, onUpdatePage } = props
if (onUpdatePage) call(onUpdatePage, page)
if (onPageChange) call(onPageChange, page)
if (_onUpdatePage) call(_onUpdatePage, page)
uncontrolledCurrentPageRef.value = page
}
function doUpdatePageSize (pageSize: number): void {
const { 'onUpdate:pageSize': onUpdatePageSize, onPageSizeChange } = props
const {
'onUpdate:pageSize': _onUpdatePageSize,
onPageSizeChange,
onUpdatePageSize
} = props
if (onPageSizeChange) call(onPageSizeChange, pageSize)
if (onUpdatePageSize) call(onUpdatePageSize, pageSize)
if (_onUpdatePageSize) call(_onUpdatePageSize, pageSize)
uncontrolledPageSizeRef.value = pageSize
}
function doUpdateSorter (sortState: SortState | null): void {

View File

@ -79,14 +79,14 @@ Accept all props from FormItem & [GridItem](grid#GridItem-Props)
| Name | Type | Description |
| --- | --- | --- |
| validate | `(validateCallback?: (errors?: Array<ValidationError>) => void, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<void>` | Validate the form. The rejection value type of returned promise is `Array<ValidationError>`. |
| validate | `(validateCallback?: (errors?: Array<FormValidationError>) => void, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<void>` | Validate the form. The rejection value type of returned promise is `Array<FormValidationError>`. |
| restoreValidation | `() => void` | Restore validate. |
### FormItem, FormItemGi Methods
| Name | Type | Description |
| --- | --- | --- |
| validate | `(options: { trigger?: string, callback?: (errors?: Array<ValidationError>) => void, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<void>` | Validate the form item. The rejection value type of returned promise is `Array<ValidationError>`. If trigger is not set, all rules of the item will be applied. `shouldRuleBeApplied` can filter rules after they are filtered by the trigger. |
| validate | `(options: { trigger?: string, callback?: (errors?: Array<FormValidationError>) => void, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<void>` | Validate the form item. The rejection value type of returned promise is `Array<FormValidationError>`. If trigger is not set, all rules of the item will be applied. `shouldRuleBeApplied` can filter rules after they are filtered by the trigger. |
| restoreValidation | `() => void` | Restore validate. |
About AsyncValidatorOptions, see <n-a href="https://github.com/yiminghe/async-validator">async-validator</n-a>.

View File

@ -80,14 +80,14 @@ validator-debug
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| validate | `(validateCallback?: (errors?: Array<ValidationError>) => void, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<void>` | 验证表单Promise rejection 的返回值类型是 `Array<ValidationError>` |
| validate | `(validateCallback?: (errors?: Array<FormValidationError>) => void, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<void>` | 验证表单Promise rejection 的返回值类型是 `Array<FormValidationError>` |
| restoreValidation | `() => void` | 还原到未校验的状态 |
### FormItem, FormItemGi Methods
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| validate | `(options: { trigger?: string, callback?: (errors?: Array<ValidationError>) => void, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<void>` | 验证表项Promise rejection 的返回值类型是 `Array<ValidationError>`。如果设定 `trigger`,这一个表项全部的规则都会被使用。`shouldRuleBeApplied` 可以用来进一步过滤已经经过 `trigger` 筛选的规则 |
| validate | `(options: { trigger?: string, callback?: (errors?: Array<FormValidationError>) => void, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<void>` | 验证表项Promise rejection 的返回值类型是 `Array<FormValidationError>`。如果设定 `trigger`,这一个表项全部的规则都会被使用。`shouldRuleBeApplied` 可以用来进一步过滤已经经过 `trigger` 筛选的规则 |
| restoreValidation | `() => void` | 还原到未校验的状态 |
关于 AsyncValidatorOptions参考 <n-a href="https://github.com/yiminghe/async-validator">async-validator</n-a>

View File

@ -14,7 +14,8 @@ export type {
FormInst,
FormItemInst,
FormItemRule,
FormRules
FormRules,
FormValidationError
} from './src/interface'
// deprecated

View File

@ -75,6 +75,8 @@ export type FormValidateCallback = (errors?: ErrorList[]) => void
export type FormValidate = ((callback?: FormValidateCallback) => void) &
(() => Promise<void>)
export type FormValidationError = ErrorList
export interface FormInst {
validate: FormValidate
restoreValidation: () => void

View File

@ -41,6 +41,12 @@ basic
## API
### LoadingBarProvider Props
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| loading-bar-style | `{ loading?: string \| object, error?: string \| object }` | `undefined` | Style of the loading bar. |
### `loadingBar` Injection Methods
| Name | Type | Description |

View File

@ -41,6 +41,12 @@ basic
## API
### LoadingBarProvider Props
| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| loading-bar-style | `{ loading?: string \| object, error?: string \| object }` | `undefined` | 加载条样式 |
### `loadingBar` Injection Methods
| 名称 | 类型 | 说明 |

View File

@ -6,7 +6,6 @@ import {
inject,
withDirectives,
vShow,
CSSProperties,
ref,
nextTick
} from 'vue'
@ -35,12 +34,17 @@ export default defineComponent({
const loadingRef = ref(false)
const transitionDisabledRef = ref(false)
let finishing = false
let erroring = false
const erroringRef = ref(false)
const mergedLoadingBarStyle = computed(() => {
const { loadingBarStyle } = providerProps
if (!loadingBarStyle) return ''
return loadingBarStyle[erroringRef.value ? 'error' : 'loading']
})
async function init (): Promise<void> {
enteringRef.value = false
loadingRef.value = false
finishing = false
erroring = false
erroringRef.value = false
transitionDisabledRef.value = true
await nextTick()
transitionDisabledRef.value = false
@ -63,7 +67,7 @@ export default defineComponent({
el.style.maxWidth = `${toProgress}%`
}
function finish (): void {
if (finishing || erroring) return
if (finishing || erroringRef.value) return
finishing = true
const el = loadingBarRef.value
if (!el) return
@ -73,10 +77,10 @@ export default defineComponent({
loadingRef.value = false
}
function error (): void {
if (finishing || erroring) return
if (finishing || erroringRef.value) return
if (!loadingRef.value) {
void start(100, 100, 'error').then(() => {
erroring = true
erroringRef.value = true
const el = loadingBarRef.value
if (!el) return
el.className = createClassName('error', mergedClsPrefixRef.value)
@ -84,7 +88,7 @@ export default defineComponent({
loadingRef.value = false
})
} else {
erroring = true
erroringRef.value = true
const el = loadingBarRef.value
if (!el) return
el.className = createClassName('error', mergedClsPrefixRef.value)
@ -122,6 +126,7 @@ export default defineComponent({
handleEnter,
handleAfterEnter,
handleAfterLeave,
mergedLoadingBarStyle,
cssVars: computed(() => {
const {
self: { height, colorError, colorLoading }
@ -157,7 +162,10 @@ export default defineComponent({
<div
ref="loadingBarRef"
class={`${mergedClsPrefix}-loading-bar`}
style={this.cssVars as CSSProperties}
style={[
this.cssVars as any,
this.mergedLoadingBarStyle as any
]}
/>
</div>,
[[vShow, this.loading || (!this.loading && this.entering)]]

View File

@ -10,7 +10,8 @@ import {
ExtractPropTypes,
InjectionKey,
renderSlot,
Ref
Ref,
CSSProperties
} from 'vue'
import { useIsMounted } from 'vooks'
import { useConfig, useTheme } from '../../_mixins'
@ -33,6 +34,12 @@ const loadingBarProps = {
to: {
type: [String, Object] as PropType<string | HTMLElement>,
default: undefined
},
loadingBarStyle: {
type: [String, Object, Function] as PropType<{
loading?: string | CSSProperties
error?: string | CSSProperties
}>
}
}
@ -49,9 +56,8 @@ export const loadingBarProviderInjectionKey: InjectionKey<{
mergedClsPrefixRef: Ref<string>
}> = Symbol('loadingBar')
export const loadingBarApiInjectionKey: InjectionKey<LoadingBarApiInjection> = Symbol(
'loadingBarApi'
)
export const loadingBarApiInjectionKey: InjectionKey<LoadingBarApiInjection> =
Symbol('loadingBarApi')
export default defineComponent({
name: 'LoadingBarProvider',

View File

@ -21,23 +21,23 @@ export default cB('loading-bar-container', `
width: 100%;
transition:
max-width 4s linear,
background-color .2s linear;
background .2s linear;
height: var(--height);
`, [
cM('starting', `
background-color: var(--color-loading);
background: var(--color-loading);
`),
cM('finishing', `
background-color: var(--color-loading);
background: var(--color-loading);
transition:
max-width .2s linear,
background-color .2s linear;
background .2s linear;
`),
cM('error', `
background-color: var(--color-error);
background: var(--color-error);
transition:
max-width .2s linear,
background-color .2s linear;
background .2s linear;
`)
])
])

View File

@ -12,6 +12,7 @@ custom-position
preset-card
preset-confirm
preset-confirm-slot
raw-debug
dark-1-debug
dark-2-debug
dark-3-debug

View File

@ -0,0 +1,20 @@
# Raw Debug
```html
<n-button @click="showModal = true"> 来吧 </n-button>
<n-modal v-model:show="showModal">
<div class="box1">
<div class="box2">123</div>
</div>
</n-modal>
```
```js
export default {
data () {
return {
showModal: false
}
}
}
```

View File

@ -13,7 +13,8 @@ import {
Transition,
VNode,
ComponentPublicInstance,
mergeProps
mergeProps,
cloneVNode
} from 'vue'
import { clickoutside } from 'vdirs'
import { dialogPropKeys } from '../../dialog/src/Dialog'
@ -173,6 +174,7 @@ export default defineComponent({
warn('modal', 'default slot is empty')
return
}
childNode = cloneVNode(childNode)
childNode.props = mergeProps(
{
class: `${mergedClsPrefix}-modal`

View File

@ -28,10 +28,7 @@ import style from './styles/index.cssr'
const modalProps = {
...(useTheme.props as ThemeProps<ModalTheme>),
show: {
type: Boolean,
default: false
},
show: Boolean,
unstableShowMask: {
type: Boolean,
default: true

View File

@ -35,7 +35,7 @@ export default defineComponent({
railStyle: [String, Object] as PropType<string | CSSProperties>,
percentage: {
type: Number,
required: true
default: 0
},
showIndicator: {
type: Boolean,

View File

@ -25,7 +25,7 @@ export default defineComponent({
},
percentage: {
type: Number,
required: true
default: 0
},
railColor: String,
railStyle: [String, Object] as PropType<string | CSSProperties>,

View File

@ -19,7 +19,7 @@ export default defineComponent({
},
percentage: {
type: Array as PropType<number[]>,
required: true
default: [0]
},
strokeWidth: {
type: Number,

View File

@ -34,10 +34,7 @@ const progressProps = {
type: Number,
default: 7
},
percentage: {
type: [Number, Array] as PropType<number | number[]>,
default: 0
},
percentage: [Number, Array] as PropType<number | number[]>,
unit: {
type: String,
default: '%'

View File

@ -5,4 +5,85 @@ describe('n-progress', () => {
it('should work with import on demand', () => {
mount(NProgress)
})
it('should work with `type` prop', async () => {
;(['line', 'circle', 'multiple-circle'] as const).forEach((item) => {
const wrapper = mount(NProgress, { props: { type: item } })
expect(wrapper.find('.n-progress').classes()).toContain(
`n-progress--${item}`
)
})
})
it('should work with `color`, `rail-color`, `indicator-text-color` prop', async () => {
const wrapper = mount(NProgress, {
props: {
color: 'rgb(51, 51, 51)',
'rail-color': 'rgb(68, 68, 68)',
'indicator-text-color': 'rgb(85, 85, 85)'
},
slots: {
default: () => 'test'
}
})
expect(
wrapper.find('.n-progress-graph-line-fill').attributes('style')
).toContain('background-color: rgb(51, 51, 51);')
expect(
wrapper.find('.n-progress-graph-line-rail').attributes('style')
).toContain('background-color: rgb(68, 68, 68);')
expect(
wrapper.find('.n-progress-custom-content').attributes('style')
).toContain('color: rgb(85, 85, 85);')
})
it('should work with `border-radius`, `fill-border-radius` prop', async () => {
const wrapper = mount(NProgress, {
props: {
'border-radius': '12px',
'fill-border-radius': '13px'
},
slots: {
default: () => 'test'
}
})
expect(
wrapper.find('.n-progress-graph-line-rail').attributes('style')
).toContain('border-radius: 12px')
expect(
wrapper.find('.n-progress-graph-line-fill').attributes('style')
).toContain('border-radius: 13px')
})
it('should work with `height` prop', async () => {
const wrapper = mount(NProgress, {
props: {
height: 24
}
})
expect(
wrapper.find('.n-progress-graph-line-rail').attributes('style')
).toContain('height: 24')
})
it('should work with `processing` prop', async () => {
const wrapper = mount(NProgress, {
props: {
processing: true
}
})
expect(wrapper.find('.n-progress-graph-line-fill').classes()).toContain(
'n-progress-graph-line-fill--processing'
)
})
it('should work with slot', async () => {
const wrapper = mount(NProgress, {
slots: {
default: () => 'test'
}
})
expect(wrapper.find('.n-progress-custom-content').exists()).toBe(true)
expect(wrapper.find('.n-progress-custom-content').text()).toBe('test')
})
})

View File

@ -5,4 +5,41 @@ describe('n-result', () => {
it('should work with import on demand', () => {
mount(NResult)
})
it('should work with `description` prop', async () => {
const wrapper = mount(NResult, {
props: { description: 'test-description' }
})
expect(wrapper.find('.n-result-header__description').exists()).toBe(true)
expect(wrapper.find('.n-result-header__description').text()).toBe(
'test-description'
)
})
it('should work with `title` prop', async () => {
const wrapper = mount(NResult, {
props: { title: 'test-title' }
})
expect(wrapper.find('.n-result-header__title').exists()).toBe(true)
expect(wrapper.find('.n-result-header__title').text()).toBe('test-title')
})
it('should work with `size` prop', async () => {
;(['small', 'medium', 'large', 'huge'] as const).forEach((item) => {
const wrapper = mount(NResult, {
props: { size: item }
})
expect(wrapper.find('.n-result').attributes('style')).toMatchSnapshot()
})
})
it('should work with slots', async () => {
const wrapper = mount(NResult, {
slots: { default: () => 'test-default', footer: () => 'test-footer' }
})
expect(wrapper.find('.n-result-content').exists()).toBe(true)
expect(wrapper.find('.n-result-content').text()).toBe('test-default')
expect(wrapper.find('.n-result-footer').exists()).toBe(true)
expect(wrapper.find('.n-result-footer').text()).toBe('test-footer')
})
})

View File

@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`n-result should work with \`size\` prop 1`] = `"--bezier: cubic-bezier(.4, 0, .2, 1); --font-size: 14px; --icon-size: 64px; --line-height: 1.6; --text-color: rgb(51, 54, 57); --title-font-size: 26px; --title-font-weight: 500; --title-text-color: rgb(31, 34, 37); --icon-color: #2080f0;"`;
exports[`n-result should work with \`size\` prop 2`] = `"--bezier: cubic-bezier(.4, 0, .2, 1); --font-size: 14px; --icon-size: 80px; --line-height: 1.6; --text-color: rgb(51, 54, 57); --title-font-size: 32px; --title-font-weight: 500; --title-text-color: rgb(31, 34, 37); --icon-color: #2080f0;"`;
exports[`n-result should work with \`size\` prop 3`] = `"--bezier: cubic-bezier(.4, 0, .2, 1); --font-size: 15px; --icon-size: 100px; --line-height: 1.6; --text-color: rgb(51, 54, 57); --title-font-size: 40px; --title-font-weight: 500; --title-text-color: rgb(31, 34, 37); --icon-color: #2080f0;"`;
exports[`n-result should work with \`size\` prop 4`] = `"--bezier: cubic-bezier(.4, 0, .2, 1); --font-size: 16px; --icon-size: 125px; --line-height: 1.6; --text-color: rgb(51, 54, 57); --title-font-size: 48px; --title-font-weight: 500; --title-text-color: rgb(31, 34, 37); --icon-color: #2080f0;"`;

View File

@ -15,7 +15,7 @@ import { defineComponent, ref } from 'vue'
export default defineComponent({
setup () {
return {
value: ref(null),
value: ref(['song3']),
options: [
{
label: "Everybody's Got Something to Hide Except Me and My Monkey",

View File

@ -15,7 +15,7 @@ import { defineComponent, ref } from 'vue'
export default defineComponent({
setup () {
return {
value: ref(null),
value: ref(['song3']),
options: [
{
label: "Everybody's Got Something to Hide Except Me and My Monkey",

View File

@ -114,6 +114,13 @@ export default defineComponent({
const railRef = ref<HTMLElement | null>(null)
const followerRef1 = ref<FollowerInst | null>(null)
const followerRef2 = ref<FollowerInst | null>(null)
const precisionRef = computed(() => {
const precisions = [props.min, props.max, props.step].map((item) => {
const fraction = String(item).split('.')[1]
return fraction ? fraction.length : 0
})
return Math.max(...precisions)
})
const uncontrolledValueRef = ref(props.defaultValue)
const controlledValueRef = toRef(props, 'value')
@ -459,6 +466,7 @@ export default defineComponent({
justifiedValue = Math.max(min, justifiedValue)
justifiedValue = Math.min(max, justifiedValue)
justifiedValue = Math.round((justifiedValue - min) / step) * step + min
justifiedValue = parseFloat(justifiedValue.toFixed(precisionRef.value))
if (marks) {
const closestMarkValue = getClosestMarkValue(value)
if (

View File

@ -1 +1 @@
export default '2.16.0'
export default '2.16.1'