mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-03-07 13:48:31 +08:00
commit
7ab5e0b32a
@ -1,5 +1,15 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 2.19.11 (2021-10-21)
|
||||
|
||||
## Fixes
|
||||
|
||||
- Fix `n-upload`'s file can't be removed when file count limit is reached, closes [#1401](https://github.com/TuSimple/naive-ui/issues/1401).
|
||||
|
||||
### Feats
|
||||
|
||||
- `n-tabs` add `on-before-leave` prop, closes [#1337](https://github.com/TuSimple/naive-ui/issues/1337).
|
||||
|
||||
## 2.19.9 (2021-10-18)
|
||||
|
||||
### Fixes
|
||||
|
@ -1,10 +1,20 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 2.19.11 (2021-10-21)
|
||||
|
||||
## Fixes
|
||||
|
||||
- 修复 `n-upload` 在达到最大文件数量后无法删除文件,关闭 [#1401](https://github.com/TuSimple/naive-ui/issues/1401)
|
||||
|
||||
### Feats
|
||||
|
||||
- `n-tabs` 新增 `on-before-leave` 属性,关闭 [#1337](https://github.com/TuSimple/naive-ui/issues/1337)
|
||||
|
||||
## 2.19.9 (2021-10-18)
|
||||
|
||||
### Fixes
|
||||
|
||||
- 修复 `n-collapse` 在 `n-collapse-item` 使用 `v-if` 是展开状态丢失,关闭 [#1387](https://github.com/TuSimple/naive-ui/issues/1387)
|
||||
- 修复 `n-collapse` 在 `n-collapse-item` 使用 `v-if` 时展开状态丢失,关闭 [#1387](https://github.com/TuSimple/naive-ui/issues/1387)
|
||||
- 修复 `n-dialog` 的关闭按钮会被内容遮盖,关闭 [#1381](https://github.com/TuSimple/naive-ui/issues/1381)
|
||||
- 修复 `n-upload` 上传失败后重试时文件为 `null`,关闭 [#1316](https://github.com/TuSimple/naive-ui/issues/1316)
|
||||
- 修复 `n-cascader` 的 `filter` 属性不生效
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "naive-ui",
|
||||
"version": "2.19.9",
|
||||
"version": "2.19.11",
|
||||
"description": "A Vue 3 Component Library. Fairly Complete, Customizable Themes, Uses TypeScript, Not Too Slow",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -96,7 +96,6 @@
|
||||
"eslint-plugin-markdown": "^2.0.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-standard": "^5.0.0",
|
||||
"eslint-plugin-vue": "^7.6.0",
|
||||
"express": "^4.17.1",
|
||||
"fs-extra": "^10.0.0",
|
||||
|
@ -59,6 +59,36 @@ describe('n-carousel', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('should work with `interval` prop', async () => {
|
||||
const wrapper = mount(NCarousel, {
|
||||
props: {
|
||||
interval: 100,
|
||||
autoplay: true
|
||||
},
|
||||
slots: {
|
||||
default: () => {
|
||||
return [...Array(3).keys()].map((i) => {
|
||||
return h('div', {}, i.toString())
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
await sleep(100)
|
||||
expect(
|
||||
wrapper
|
||||
.find('.n-carousel__slides')
|
||||
.find('[data-index="2"]')
|
||||
.attributes('aria-hidden')
|
||||
).toBe('false')
|
||||
expect(
|
||||
wrapper
|
||||
.find('.n-carousel__dots')
|
||||
.findAll('.n-carousel__dot')[1]
|
||||
.attributes('aria-selected')
|
||||
).toBe('true')
|
||||
})
|
||||
|
||||
it('should work with `showArrow` prop', async () => {
|
||||
const wrapper = mount(NCarousel)
|
||||
|
||||
@ -113,20 +143,18 @@ describe('n-carousel', () => {
|
||||
|
||||
expect(slidesDOMArray[1].attributes('aria-hidden')).toBe('false')
|
||||
|
||||
wrapper
|
||||
.find('.n-carousel__arrow--right')
|
||||
await wrapper.find('.n-carousel__arrow--right').trigger('click')
|
||||
|
||||
expect(slidesDOMArray[2].attributes('aria-hidden')).toBe('false')
|
||||
|
||||
await sleep(1000)
|
||||
await nextTick()
|
||||
|
||||
void wrapper
|
||||
.find('.n-carousel__arrow--left')
|
||||
.trigger('click')
|
||||
.then(async () => {
|
||||
expect(slidesDOMArray[2].attributes('aria-hidden')).toBe('false')
|
||||
await sleep(1000)
|
||||
nextTick(() => {
|
||||
wrapper
|
||||
.find('.n-carousel__arrow--left')
|
||||
.trigger('click')
|
||||
.then(() => {
|
||||
expect(slidesDOMArray[1].attributes('aria-hidden')).toBe('false')
|
||||
})
|
||||
})
|
||||
.then(() => {
|
||||
expect(slidesDOMArray[1].attributes('aria-hidden')).toBe('false')
|
||||
})
|
||||
})
|
||||
})
|
@ -21,6 +21,50 @@ describe('n-collapse', () => {
|
||||
expect(wrapper.find('.my-icon').exists()).toEqual(true)
|
||||
})
|
||||
|
||||
it('should work with `accordion` prop', async () => {
|
||||
const wrapper = mount(NCollapse, {
|
||||
slots: {
|
||||
default: () => [
|
||||
<NCollapseItem name="1">
|
||||
{{ default: () => <div class="ci1">ci1</div> }}
|
||||
</NCollapseItem>,
|
||||
<NCollapseItem name="2">
|
||||
{{ default: () => <div class="ci2">ci2</div> }}
|
||||
</NCollapseItem>,
|
||||
<NCollapseItem name="3">
|
||||
{{ default: () => <div class="ci3">ci3</div> }}
|
||||
</NCollapseItem>
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const headerMains = wrapper.findAll('.n-collapse-item__header-main')
|
||||
await headerMains[0].trigger('click')
|
||||
await headerMains[1].trigger('click')
|
||||
|
||||
expect(wrapper.findAll('.n-collapse-item__header')[0].classes()).toContain(
|
||||
'n-collapse-item__header--active'
|
||||
)
|
||||
expect(wrapper.findAll('.n-collapse-item__header')[1].classes()).toContain(
|
||||
'n-collapse-item__header--active'
|
||||
)
|
||||
|
||||
await wrapper.setProps({
|
||||
accordion: true
|
||||
})
|
||||
|
||||
await headerMains[2].trigger('click')
|
||||
expect(
|
||||
wrapper.findAll('.n-collapse-item__header')[0].classes()
|
||||
).not.toContain('n-collapse-item__header--active')
|
||||
expect(
|
||||
wrapper.findAll('.n-collapse-item__header')[1].classes()
|
||||
).not.toContain('n-collapse-item__header--active')
|
||||
expect(wrapper.findAll('.n-collapse-item__header')[2].classes()).toContain(
|
||||
'n-collapse-item__header--active'
|
||||
)
|
||||
})
|
||||
|
||||
it('should work with `arrow-placement` prop', async () => {
|
||||
const wrapper = mount(NCollapse, {
|
||||
slots: {
|
||||
@ -38,28 +82,40 @@ describe('n-collapse', () => {
|
||||
})
|
||||
|
||||
it('should work with nested structure', async () => {
|
||||
mount(NCollapse, {
|
||||
const wrapper = mount(NCollapse, {
|
||||
slots: {
|
||||
default: () =>
|
||||
h(
|
||||
NCollapseItem,
|
||||
{ name: '1', title: 'test1' },
|
||||
{ name: '1' },
|
||||
{
|
||||
default: () =>
|
||||
h(NCollapse, null, {
|
||||
default: () => h(NCollapseItem, { name: '2', title: 'test2' })
|
||||
default: () => h(NCollapseItem, { name: '2' })
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
// todo: test display-directive
|
||||
// I wanted to test this function, but I was bothered by the <transition-stub>
|
||||
await wrapper.find('.n-collapse-item__header-main').trigger('click')
|
||||
expect(wrapper.find('.n-collapse-item__header').classes()).toContain(
|
||||
'n-collapse-item__header--active'
|
||||
)
|
||||
await wrapper
|
||||
.find('.n-collapse-item__content-wrapper')
|
||||
.find('.n-collapse-item__header-main')
|
||||
.trigger('click')
|
||||
expect(
|
||||
wrapper
|
||||
.find('.n-collapse-item__content-wrapper')
|
||||
.find('.n-collapse-item__header')
|
||||
.classes()
|
||||
).toContain('n-collapse-item__header--active')
|
||||
})
|
||||
|
||||
it('should work with `display-directive` prop', async () => {
|
||||
mount(NCollapse, {
|
||||
const wrapper = mount(NCollapse, {
|
||||
props: {
|
||||
displayDirective: 'show'
|
||||
},
|
||||
@ -67,13 +123,27 @@ describe('n-collapse', () => {
|
||||
default: () =>
|
||||
h(
|
||||
NCollapseItem,
|
||||
{ name: '1', title: 'test' },
|
||||
{ name: '1' },
|
||||
{ default: () => h('div', null, { default: () => 'test' }) }
|
||||
)
|
||||
}
|
||||
// todo: test display-directive
|
||||
// I wanted to test this function, but I was bothered by the <transition-stub>
|
||||
})
|
||||
|
||||
await wrapper.find('.n-collapse-item__header-main').trigger('click')
|
||||
await wrapper.find('.n-collapse-item__header-main').trigger('click')
|
||||
expect(
|
||||
wrapper.find('.n-collapse-item__content-wrapper').attributes('style')
|
||||
).toBe('display: none;')
|
||||
|
||||
await wrapper.setProps({
|
||||
displayDirective: 'if'
|
||||
})
|
||||
|
||||
await wrapper.find('.n-collapse-item__header-main').trigger('click')
|
||||
await wrapper.find('.n-collapse-item__header-main').trigger('click')
|
||||
expect(wrapper.find('.n-collapse-item__content-wrapper').exists()).toBe(
|
||||
false
|
||||
)
|
||||
})
|
||||
|
||||
it('should work with `on-item-header-click` prop', async () => {
|
||||
@ -149,4 +219,15 @@ describe('n-collapse', () => {
|
||||
expect(wrapper.find('.ci1').isVisible()).toEqual(true)
|
||||
expect(wrapper.find('.ci2').exists()).toEqual(false)
|
||||
})
|
||||
|
||||
it('should work with collapseItem component `title` prop', async () => {
|
||||
const wrapper = mount(NCollapse, {
|
||||
slots: {
|
||||
default: () => <NCollapseItem title="test"></NCollapseItem>
|
||||
}
|
||||
})
|
||||
|
||||
await wrapper.find('.n-collapse-item__header-main').trigger('click')
|
||||
expect(wrapper.find('.n-collapse-item__header-main').text()).toBe('test')
|
||||
})
|
||||
})
|
||||
|
@ -1087,4 +1087,26 @@ describe('props.columns', () => {
|
||||
'test-age'
|
||||
)
|
||||
})
|
||||
|
||||
it('should work with `render` prop', async () => {
|
||||
const columns: DataTableColumns = [
|
||||
{
|
||||
title: 'Name',
|
||||
key: 'name',
|
||||
render (rowData: any, rowIndex: number) {
|
||||
return `${String(rowData.name)}-${rowIndex}`
|
||||
}
|
||||
}
|
||||
]
|
||||
const data = new Array(5).fill(0).map((_, index) => {
|
||||
return {
|
||||
name: index
|
||||
}
|
||||
})
|
||||
const rowKey = (row: any): number => row.name
|
||||
const wrapper = mount(() => (
|
||||
<NDataTable columns={columns} data={data} row-key={rowKey} />
|
||||
))
|
||||
expect(wrapper.find('tbody [data-col-key="name"]').text()).toContain('0-0')
|
||||
})
|
||||
})
|
||||
|
@ -206,6 +206,8 @@ export default defineComponent({
|
||||
return localeRef.value.datePlaceholder
|
||||
} else if (props.type === 'datetime') {
|
||||
return localeRef.value.datetimePlaceholder
|
||||
} else if (props.type === 'month') {
|
||||
return localeRef.value.monthPlaceholder
|
||||
}
|
||||
return props.placeholder
|
||||
} else {
|
||||
|
@ -129,6 +129,7 @@ describe('n-descriptions', () => {
|
||||
expect(wrapper.find('.n-descriptions-header').exists()).toBe(true)
|
||||
expect(wrapper.find('.n-descriptions-header').text()).toBe('test')
|
||||
})
|
||||
|
||||
it('should work with `separator` prop', async () => {
|
||||
const wrapper = mount(NDescriptions, {
|
||||
props: {
|
||||
@ -141,4 +142,34 @@ describe('n-descriptions', () => {
|
||||
await wrapper.setProps({ separator: '/' })
|
||||
expect(wrapper.find('.n-descriptions-separator').text()).toEqual('/')
|
||||
})
|
||||
|
||||
it('should work with `content-style` prop', () => {
|
||||
const wrapper = mount(NDescriptions, {
|
||||
props: {
|
||||
contentStyle: { backgroundColor: 'red' }
|
||||
},
|
||||
slots: {
|
||||
default: () => h(NDescriptionsItem, {}, 'test')
|
||||
}
|
||||
})
|
||||
|
||||
expect(
|
||||
wrapper.find('.n-descriptions-table-content').attributes('style')
|
||||
).toBe('background-color: red;')
|
||||
})
|
||||
|
||||
it('should work with `label-style` prop', () => {
|
||||
const wrapper = mount(NDescriptions, {
|
||||
props: {
|
||||
labelStyle: { fontSize: '30px' }
|
||||
},
|
||||
slots: {
|
||||
default: () => h(NDescriptionsItem, {}, 'test')
|
||||
}
|
||||
})
|
||||
|
||||
expect(
|
||||
wrapper.find('.n-descriptions-table-header').attributes('style')
|
||||
).toBe('font-size: 30px;')
|
||||
})
|
||||
})
|
||||
|
@ -30,6 +30,7 @@ const enUS = {
|
||||
selectDate: 'Select Date',
|
||||
datePlaceholder: 'Select Date',
|
||||
datetimePlaceholder: 'Select Date and Time',
|
||||
monthPlaceholder: 'Select Month',
|
||||
startDatePlaceholder: 'Start Date',
|
||||
endDatePlaceholder: 'End Date',
|
||||
startDatetimePlaceholder: 'Start Date and Time',
|
||||
|
@ -32,6 +32,7 @@ const jaJP: NLocale = {
|
||||
selectDate: '日付を選択',
|
||||
datePlaceholder: '日付を選択',
|
||||
datetimePlaceholder: '選択',
|
||||
monthPlaceholder: '月を選択',
|
||||
startDatePlaceholder: '開始日',
|
||||
endDatePlaceholder: '終了日',
|
||||
startDatetimePlaceholder: '開始時間',
|
||||
|
@ -32,6 +32,7 @@ const ruRu: NLocale = {
|
||||
selectDate: 'Выбрать дату',
|
||||
datePlaceholder: 'Выбрать дату',
|
||||
datetimePlaceholder: 'Выбрать дату и время',
|
||||
monthPlaceholder: 'Выберите месяц',
|
||||
startDatePlaceholder: 'Дата начала',
|
||||
endDatePlaceholder: 'Дата окончания',
|
||||
startDatetimePlaceholder: 'Дата и время начала',
|
||||
|
@ -32,6 +32,7 @@ const ukUA: NLocale = {
|
||||
selectDate: 'Обрати дату',
|
||||
datePlaceholder: 'Обрати дату',
|
||||
datetimePlaceholder: 'Обрати дату і час',
|
||||
monthPlaceholder: 'Виберіть місяць',
|
||||
startDatePlaceholder: 'Дата початку',
|
||||
endDatePlaceholder: 'Дата завершення',
|
||||
startDatetimePlaceholder: 'Дата і час початку',
|
||||
|
@ -32,6 +32,7 @@ const zhCN: NLocale = {
|
||||
selectDate: '选择日期',
|
||||
datePlaceholder: '选择日期',
|
||||
datetimePlaceholder: '选择日期时间',
|
||||
monthPlaceholder: '选择月份',
|
||||
startDatePlaceholder: '开始日期',
|
||||
endDatePlaceholder: '结束日期',
|
||||
startDatetimePlaceholder: '开始日期时间',
|
||||
|
49
src/tabs/demos/enUS/before-leave.demo.md
Normal file
49
src/tabs/demos/enUS/before-leave.demo.md
Normal file
@ -0,0 +1,49 @@
|
||||
# Hook before tab switching
|
||||
|
||||
You can prevent or postpone tab switching.
|
||||
|
||||
```html
|
||||
<n-tabs
|
||||
type="line"
|
||||
default-value="okay"
|
||||
@before-leave="handleBeforeLeave"
|
||||
@update:value="handleUpdateValue"
|
||||
>
|
||||
<n-tab-pane name="wait" tab="Wait for 1s"> +1s </n-tab-pane>
|
||||
<n-tab-pane name="not-allowed" tab="Not allowed"> ??? </n-tab-pane>
|
||||
<n-tab-pane name="okay" tab="Okay"> Just so so </n-tab-pane>
|
||||
</n-tabs>
|
||||
```
|
||||
|
||||
```js
|
||||
import { defineComponent } from 'vue'
|
||||
import { useMessage } from 'naive-ui'
|
||||
|
||||
export default defineComponent({
|
||||
setup () {
|
||||
const message = useMessage()
|
||||
return {
|
||||
handleBeforeLeave: (tabName) => {
|
||||
switch (tabName) {
|
||||
case 'not-allowed':
|
||||
message.error('Not allowed')
|
||||
return false
|
||||
case 'wait':
|
||||
return new Promise((resolve) => {
|
||||
const messageInstance = message.loading('Wait for 1s')
|
||||
setTimeout(() => {
|
||||
messageInstance.destroy()
|
||||
resolve(true)
|
||||
}, 1000)
|
||||
})
|
||||
default:
|
||||
return true
|
||||
}
|
||||
},
|
||||
handleUpdateValue: (value) => {
|
||||
message.info(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
@ -1,4 +1,4 @@
|
||||
# Card Type
|
||||
# Card type
|
||||
|
||||
Set `type='card'`.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Display Directive
|
||||
# Display directive
|
||||
|
||||
You can set tab-panel's display directive to `if` or `show`. When use show, the tab-panel's content won't be reset after tab changes.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Flex Tabs
|
||||
# Flex tabs
|
||||
|
||||
Only works with `line` typed tabs.
|
||||
|
||||
|
@ -14,6 +14,7 @@ prefix
|
||||
display-directive
|
||||
addable
|
||||
line-debug
|
||||
before-leave
|
||||
```
|
||||
|
||||
## API
|
||||
@ -33,6 +34,7 @@ line-debug
|
||||
| type | `'bar' \| 'line' \| 'card' \| 'segment'` | `'bar'` | Tabs type. |
|
||||
| value | `string \| number` | `undefined` | Value in controlled mode. |
|
||||
| on-add | `() => void` | `undefined` | Callback function triggered when add tag. |
|
||||
| on-before-leave | `(activeName: string \| number, oldActiveName: string \| number \| null) => boolean \| Promise<boolean>` | `undefined` | Hook function before switching tab. Returning `false` or promise resolving `false` or promise rejection will prevent tab switching. |
|
||||
| on-close | `(name: string \| number) => void` | `undefined` | Callback function triggered when close tag. |
|
||||
| on-update:value | `(value: string \| number) => void` | `undefined` | Callback function triggered when the value changes. |
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Line Debug
|
||||
# Line debug
|
||||
|
||||
```html
|
||||
<n-button @click="name = 'the beatles'">Set Name to the Beatles</n-button>
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Prefix & Suffix
|
||||
# Prefix & suffix
|
||||
|
||||
Use `prefix` & `suffix` slot to add prefix & suffix.
|
||||
|
||||
|
49
src/tabs/demos/zhCN/before-leave.demo.md
Normal file
49
src/tabs/demos/zhCN/before-leave.demo.md
Normal file
@ -0,0 +1,49 @@
|
||||
# 切换 Tab 前的回调
|
||||
|
||||
你可以延迟或阻止 Tab 切换。
|
||||
|
||||
```html
|
||||
<n-tabs
|
||||
type="line"
|
||||
default-value="okay"
|
||||
@before-leave="handleBeforeLeave"
|
||||
@update:value="handleUpdateValue"
|
||||
>
|
||||
<n-tab-pane name="wait" tab="等 1 秒"> +1s </n-tab-pane>
|
||||
<n-tab-pane name="not-allowed" tab="不许进来"> ??? </n-tab-pane>
|
||||
<n-tab-pane name="okay" tab="可以">就那么回事吧</n-tab-pane>
|
||||
</n-tabs>
|
||||
```
|
||||
|
||||
```js
|
||||
import { defineComponent } from 'vue'
|
||||
import { useMessage } from 'naive-ui'
|
||||
|
||||
export default defineComponent({
|
||||
setup () {
|
||||
const message = useMessage()
|
||||
return {
|
||||
handleBeforeLeave: (tabName) => {
|
||||
switch (tabName) {
|
||||
case 'not-allowed':
|
||||
message.error('不许进来')
|
||||
return false
|
||||
case 'wait':
|
||||
return new Promise((resolve) => {
|
||||
const messageInstance = message.loading('Wait for 1s')
|
||||
setTimeout(() => {
|
||||
messageInstance.destroy()
|
||||
resolve(true)
|
||||
}, 1000)
|
||||
})
|
||||
default:
|
||||
return true
|
||||
}
|
||||
},
|
||||
handleUpdateValue: (value) => {
|
||||
message.info(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
@ -16,6 +16,7 @@ addable
|
||||
line-debug
|
||||
style-inherit-debug
|
||||
shadow-debug
|
||||
before-leave
|
||||
```
|
||||
|
||||
## API
|
||||
@ -35,6 +36,7 @@ shadow-debug
|
||||
| type | `'bar' \| 'line' \| 'card' \| 'segment'` | `'bar'` | 标签类型 |
|
||||
| value | `string \| number` | `undefined` | 受控模式下的值 |
|
||||
| on-add | `() => void` | `undefined` | 添加标签的回调函数 |
|
||||
| on-before-leave | `(name: string \| number, oldName: string \| number \| null) => boolean \| Promise<boolean>` | `undefined` | 切换标签之前的钩子函数,返回 `false` 或 promise resolve `false` 或 promise reject 会组织切换 |
|
||||
| on-close | `(name: string \| number) => void` | `undefined` | 关闭标签的回调函数 |
|
||||
| on-update:value | `(value: string \| number) => void` | `undefined` | 选中发生改变时的回调函数 |
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { h, defineComponent, inject, computed } from 'vue'
|
||||
import { AddIcon } from '../../_internal/icons'
|
||||
import { NBaseClose, NBaseIcon } from '../../_internal'
|
||||
import { render } from '../../_utils'
|
||||
import { tabsInjectionKey } from './interface'
|
||||
import { OnBeforeLeaveImpl, tabsInjectionKey } from './interface'
|
||||
import { tabPaneProps } from './TabPane'
|
||||
|
||||
export default defineComponent({
|
||||
@ -21,6 +21,8 @@ export default defineComponent({
|
||||
typeRef,
|
||||
closableRef,
|
||||
tabStyleRef,
|
||||
nextTabNameRef,
|
||||
onBeforeLeaveRef,
|
||||
handleAdd,
|
||||
handleTabClick,
|
||||
handleClose
|
||||
@ -48,7 +50,23 @@ export default defineComponent({
|
||||
handleAdd()
|
||||
return
|
||||
}
|
||||
handleTabClick(props.name)
|
||||
const { name: nameProp } = props
|
||||
if (nameProp !== valueRef.value) {
|
||||
if (nameProp === nextTabNameRef.value) return
|
||||
nextTabNameRef.value = nameProp
|
||||
const { value: onBeforeLeave } = onBeforeLeaveRef
|
||||
if (!onBeforeLeave) {
|
||||
handleTabClick(nameProp)
|
||||
} else {
|
||||
void Promise.resolve(
|
||||
(onBeforeLeave as OnBeforeLeaveImpl)(props.name, valueRef.value)
|
||||
).then((allowLeave) => {
|
||||
if (allowLeave) {
|
||||
handleTabClick(nameProp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -28,6 +28,7 @@ import {
|
||||
Addable,
|
||||
OnClose,
|
||||
OnCloseImpl,
|
||||
OnBeforeLeave,
|
||||
tabsInjectionKey,
|
||||
TabsType
|
||||
} from './interface'
|
||||
@ -58,6 +59,7 @@ const tabsProps = {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
onBeforeLeave: Function as PropType<OnBeforeLeave>,
|
||||
onAdd: Function as PropType<() => void>,
|
||||
'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,
|
||||
onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,
|
||||
@ -136,6 +138,8 @@ export default defineComponent({
|
||||
uncontrolledValueRef
|
||||
)
|
||||
|
||||
const nextTabNameRef = { value: mergedValueRef.value }
|
||||
|
||||
const tabWrapperStyleRef = computed(() => {
|
||||
if (!props.justifyContent || props.type === 'card') return undefined
|
||||
return {
|
||||
@ -275,6 +279,8 @@ export default defineComponent({
|
||||
typeRef: toRef(props, 'type'),
|
||||
closableRef: toRef(props, 'closable'),
|
||||
valueRef: mergedValueRef,
|
||||
nextTabNameRef,
|
||||
onBeforeLeaveRef: toRef(props, 'onBeforeLeave'),
|
||||
handleTabClick,
|
||||
handleClose,
|
||||
handleAdd
|
||||
|
@ -8,6 +8,15 @@ export type OnUpdateValueImpl = (value: string | number) => void
|
||||
export type OnClose = (name: string & number) => void
|
||||
export type OnCloseImpl = (name: string | number) => void
|
||||
|
||||
export type OnBeforeLeave = (
|
||||
name: string & number,
|
||||
oldName: string & number & null
|
||||
) => boolean | Promise<boolean>
|
||||
export type OnBeforeLeaveImpl = (
|
||||
name: string | number,
|
||||
oldName: string | number | null
|
||||
) => boolean | Promise<boolean>
|
||||
|
||||
export interface TabsInjection {
|
||||
mergedClsPrefixRef: Ref<string>
|
||||
valueRef: Ref<string | number | null>
|
||||
@ -15,6 +24,8 @@ export interface TabsInjection {
|
||||
closableRef: Ref<boolean>
|
||||
tabStyleRef: Ref<string | CSSProperties | undefined>
|
||||
paneStyleRef: Ref<string | CSSProperties | undefined>
|
||||
nextTabNameRef: { value: string | number | null }
|
||||
onBeforeLeaveRef: Ref<OnBeforeLeave | undefined>
|
||||
handleTabClick: (panelName: string | number) => void
|
||||
handleClose: (panelName: string | number) => void
|
||||
handleAdd: () => void
|
||||
|
@ -282,11 +282,8 @@ export default defineComponent({
|
||||
mergedClsPrefixRef
|
||||
)
|
||||
const formItem = useFormItem(props)
|
||||
const mergedDisabledRef = computed(() => {
|
||||
const maxReachedRef = computed(() => {
|
||||
const { max } = props
|
||||
if (formItem.mergedDisabledRef.value) {
|
||||
return true
|
||||
}
|
||||
if (max !== undefined) {
|
||||
return mergedFileListRef.value.length >= max
|
||||
}
|
||||
@ -515,7 +512,8 @@ export default defineComponent({
|
||||
openFileDialog,
|
||||
draggerInsideRef,
|
||||
handleFileAddition,
|
||||
mergedDisabledRef,
|
||||
mergedDisabledRef: formItem.mergedDisabledRef,
|
||||
maxReachedRef,
|
||||
fileListStyleRef: toRef(props, 'fileListStyle'),
|
||||
abstractRef: toRef(props, 'abstract'),
|
||||
cssVarsRef
|
||||
|
@ -22,6 +22,7 @@ export default defineComponent({
|
||||
const {
|
||||
mergedClsPrefixRef,
|
||||
mergedDisabledRef,
|
||||
maxReachedRef,
|
||||
listTypeRef,
|
||||
dragOverRef,
|
||||
openFileDialog,
|
||||
@ -34,7 +35,7 @@ export default defineComponent({
|
||||
)
|
||||
|
||||
function handleTriggerClick (): void {
|
||||
if (mergedDisabledRef.value) return
|
||||
if (mergedDisabledRef.value || maxReachedRef.value) return
|
||||
openFileDialog()
|
||||
}
|
||||
function handleTriggerDragOver (e: DragEvent): void {
|
||||
@ -51,7 +52,13 @@ export default defineComponent({
|
||||
}
|
||||
function handleTriggerDrop (e: DragEvent): void {
|
||||
e.preventDefault()
|
||||
if (!draggerInsideRef.value || mergedDisabledRef.value) return
|
||||
if (
|
||||
!draggerInsideRef.value ||
|
||||
mergedDisabledRef.value ||
|
||||
maxReachedRef.value
|
||||
) {
|
||||
return
|
||||
}
|
||||
const dataTransfer = e.dataTransfer
|
||||
const files = dataTransfer?.files
|
||||
if (files) {
|
||||
@ -74,7 +81,7 @@ export default defineComponent({
|
||||
<div
|
||||
class={[
|
||||
`${mergedClsPrefix}-upload-trigger`,
|
||||
mergedDisabledRef.value &&
|
||||
(mergedDisabledRef.value || maxReachedRef.value) &&
|
||||
`${mergedClsPrefix}-upload-trigger--disabled`,
|
||||
isImageCardTypeRef.value &&
|
||||
`${mergedClsPrefix}-upload-trigger--image-card`
|
||||
|
@ -72,6 +72,7 @@ export interface UploadInjection {
|
||||
draggerInsideRef: { value: boolean }
|
||||
fileListStyleRef: Ref<string | CSSProperties | undefined>
|
||||
mergedDisabledRef: Ref<boolean>
|
||||
maxReachedRef: Ref<boolean>
|
||||
abstractRef: Ref<boolean>
|
||||
cssVarsRef: Ref<CSSProperties>
|
||||
submit: (fileId?: string) => void
|
||||
|
@ -1 +1 @@
|
||||
export default '2.19.9'
|
||||
export default '2.19.11'
|
||||
|
Loading…
Reference in New Issue
Block a user