mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-03-07 13:48:31 +08:00
commit
5021deae87
@ -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
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -505,7 +505,7 @@ export default defineComponent({
|
||||
) : (
|
||||
<NTag
|
||||
size={size}
|
||||
closable
|
||||
closable={!option.disabled}
|
||||
disabled={disabled}
|
||||
internalStopClickPropagation
|
||||
onClose={() => this.handleDeleteOption(option)}
|
||||
|
@ -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)
|
||||
})
|
||||
})
|
||||
|
@ -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
|
||||
|
||||
|
@ -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'` | 按钮需要被渲染为什么标签 |
|
||||
|
||||
|
@ -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
|
||||
|
@ -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: {
|
||||
|
@ -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 {
|
||||
|
@ -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>.
|
||||
|
@ -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>。
|
||||
|
@ -14,7 +14,8 @@ export type {
|
||||
FormInst,
|
||||
FormItemInst,
|
||||
FormItemRule,
|
||||
FormRules
|
||||
FormRules,
|
||||
FormValidationError
|
||||
} from './src/interface'
|
||||
|
||||
// deprecated
|
||||
|
@ -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
|
||||
|
@ -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 |
|
||||
|
@ -41,6 +41,12 @@ basic
|
||||
|
||||
## API
|
||||
|
||||
### LoadingBarProvider Props
|
||||
|
||||
| 名称 | 类型 | 默认值 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| loading-bar-style | `{ loading?: string \| object, error?: string \| object }` | `undefined` | 加载条样式 |
|
||||
|
||||
### `loadingBar` Injection Methods
|
||||
|
||||
| 名称 | 类型 | 说明 |
|
||||
|
@ -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)]]
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
`)
|
||||
])
|
||||
])
|
||||
|
@ -12,6 +12,7 @@ custom-position
|
||||
preset-card
|
||||
preset-confirm
|
||||
preset-confirm-slot
|
||||
raw-debug
|
||||
dark-1-debug
|
||||
dark-2-debug
|
||||
dark-3-debug
|
||||
|
20
src/modal/demos/zhCN/raw-debug.demo.md
Normal file
20
src/modal/demos/zhCN/raw-debug.demo.md
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -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`
|
||||
|
@ -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
|
||||
|
@ -35,7 +35,7 @@ export default defineComponent({
|
||||
railStyle: [String, Object] as PropType<string | CSSProperties>,
|
||||
percentage: {
|
||||
type: Number,
|
||||
required: true
|
||||
default: 0
|
||||
},
|
||||
showIndicator: {
|
||||
type: Boolean,
|
||||
|
@ -25,7 +25,7 @@ export default defineComponent({
|
||||
},
|
||||
percentage: {
|
||||
type: Number,
|
||||
required: true
|
||||
default: 0
|
||||
},
|
||||
railColor: String,
|
||||
railStyle: [String, Object] as PropType<string | CSSProperties>,
|
||||
|
@ -19,7 +19,7 @@ export default defineComponent({
|
||||
},
|
||||
percentage: {
|
||||
type: Array as PropType<number[]>,
|
||||
required: true
|
||||
default: [0]
|
||||
},
|
||||
strokeWidth: {
|
||||
type: Number,
|
||||
|
@ -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: '%'
|
||||
|
@ -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')
|
||||
})
|
||||
})
|
||||
|
@ -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')
|
||||
})
|
||||
})
|
||||
|
9
src/result/tests/__snapshots__/Result.spec.ts.snap
Normal file
9
src/result/tests/__snapshots__/Result.spec.ts.snap
Normal 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;"`;
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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 (
|
||||
|
@ -1 +1 @@
|
||||
export default '2.16.0'
|
||||
export default '2.16.1'
|
||||
|
Loading…
Reference in New Issue
Block a user