mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-04-12 14:40:47 +08:00
Merge branch 'main' into docs
This commit is contained in:
commit
49b81c5a52
@ -1,5 +1,23 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 2.38.1
|
||||
|
||||
`2024-02-26`
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fix `n-split`'s `min` attribute does not take effect.
|
||||
- Fix `n-result` built-in icons not re-rendered after hydration.
|
||||
- Fix `n-tabs` whose `type` is `'segment'` has capsule with wrong width and position after resize, closes [#5705](https://github.com/tusen-ai/naive-ui/issues/5705).
|
||||
- Fix `n-tabs`'s capsule wrong width and position after resize within `n-modal`, closes [#5569](https://github.com/tusen-ai/naive-ui/issues/5569).
|
||||
- Fix `n-split` doesn't work with `inline-theme-disabled` prop.
|
||||
- Fix `n-float-button` doesn't work with `inline-theme-disabled` prop.
|
||||
|
||||
### Features
|
||||
|
||||
- `n-date-picker` adds `default-calendar-start-time` props when `type` is `'date'`/`'datetime'` or `'week'`, closes [#4493](https://github.com/tusen-ai/naive-ui/issues/4493).
|
||||
- `n-tree-select` adds `get-children` prop.
|
||||
|
||||
## 2.38.0
|
||||
|
||||
`2024-02-22`
|
||||
@ -27,6 +45,8 @@
|
||||
- `n-split` adds `size` prop and `on-update:size` prop.
|
||||
- `n-split` adds `watch-props` prop, closes [#5526](https://github.com/tusen-ai/naive-ui/issues/5526).
|
||||
- `n-drawer` adds `borderRadius` theme variable.
|
||||
- adds `n-float-button` component.
|
||||
- Provides ES module bundle.
|
||||
|
||||
### i18n
|
||||
|
||||
|
@ -1,5 +1,23 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 2.38.1
|
||||
|
||||
`2024-02-26`
|
||||
|
||||
### Fixes
|
||||
|
||||
- 修复 `n-split` 的 `min` 属性未生效
|
||||
- 修复 `n-result` 内置的 icon 无法在 hydration 之后重渲染
|
||||
- 修复 `n-tabs` 在 `type` 为 `'segment'` 时候,胶囊在 tabs 大小改变后有错误的位置和宽度,关闭 [#5705](https://github.com/tusen-ai/naive-ui/issues/5705)
|
||||
- 修复 `n-tabs` 在 `n-modal` 内部时,胶囊在 tabs 大小改变后有错误的位置和宽度,关闭 [#5569](https://github.com/tusen-ai/naive-ui/issues/5569)
|
||||
- 修复 `n-split` 不支持 `inline-theme-disabled` 属性
|
||||
- 修复 `n-float-button` 不支持 `inline-theme-disabled` 属性
|
||||
|
||||
### Features
|
||||
|
||||
- `n-date-picker` 在 `type` 为 `'date'`、`'datetime'` 或 `'week'` 时新增 `default-calendar-start-time` 属性,关闭 [#4493](https://github.com/tusen-ai/naive-ui/issues/4493)
|
||||
- `n-tree-select` 新增 `get-children` 属性
|
||||
|
||||
## 2.38.0
|
||||
|
||||
`2024-02-22`
|
||||
@ -27,6 +45,8 @@
|
||||
- `n-split` 新增 `size` 和 `on-update:size` 属性
|
||||
- `n-split` 新增 `watch-props` 属性,关闭 [#5526](https://github.com/tusen-ai/naive-ui/issues/5526)
|
||||
- `n-drawer` 新增 `borderRadius` 主题变量
|
||||
- 新增 `n-float-button` 组件
|
||||
- 提供 ES module 打包
|
||||
|
||||
### i18n
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
### Fairly Complete
|
||||
|
||||
There are more than 80 components. Hope they can help you write less code.
|
||||
There are more than 90 components. Hope they can help you write less code.
|
||||
|
||||
What's more, they are all treeshakable.
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
### 比较完整
|
||||
|
||||
有超过 80 个组件,希望能帮你少写点代码。
|
||||
有超过 90 个组件,希望能帮你少写点代码。
|
||||
|
||||
顺便一提,它们全都可以 treeshaking。
|
||||
|
||||
|
@ -10,7 +10,7 @@ It is fairly complete, themeable, written in typescript, not too slow.
|
||||
|
||||
## Fairly Complete
|
||||
|
||||
There are more than 80 components. Hope they can help you write less code.
|
||||
There are more than 90 components. Hope they can help you write less code.
|
||||
|
||||
What's more, they are all treeshakable.
|
||||
|
||||
|
@ -10,7 +10,7 @@ Naive UI 是一个 Vue3 的组件库。
|
||||
|
||||
## 比较完整
|
||||
|
||||
有超过 80 个组件,希望能帮你少写点代码。
|
||||
有超过 90 个组件,希望能帮你少写点代码。
|
||||
|
||||
顺便一提,它们全都可以 treeshaking。
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "naive-ui",
|
||||
"version": "2.38.0",
|
||||
"version": "2.38.1",
|
||||
"description": "A Vue 3 Component Library. Fairly Complete, Theme Customizable, Uses TypeScript, Fast",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.mjs",
|
||||
@ -89,7 +89,7 @@
|
||||
"@types/estree": "^1.0.1",
|
||||
"@types/jest": "^29.5.4",
|
||||
"@typescript-eslint/eslint-plugin": "^6.6.0",
|
||||
"@typescript-eslint/parser": "^6.6.0",
|
||||
"@typescript-eslint/parser": "^7.0.2",
|
||||
"@vicons/fluent": "^0.12.0",
|
||||
"@vicons/ionicons4": "^0.12.0",
|
||||
"@vicons/ionicons5": "^0.12.0",
|
||||
@ -104,7 +104,7 @@
|
||||
"codesandbox": "^2.2.3",
|
||||
"cssnano": "^6.0.1",
|
||||
"deepmerge": "^4.3.1",
|
||||
"esbuild": "0.20.0",
|
||||
"esbuild": "0.20.1",
|
||||
"eslint": "^8.48.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
@ -126,7 +126,7 @@
|
||||
"jest-environment-jsdom": "^29.6.4",
|
||||
"katex": "^0.16.8",
|
||||
"lint-staged": "^15.1.0",
|
||||
"marked": "^11.0.0",
|
||||
"marked": "^12.0.0",
|
||||
"prettier": "^3.0.3",
|
||||
"rimraf": "^5.0.1",
|
||||
"rollup": "^4.3.0",
|
||||
|
@ -73,6 +73,7 @@ panel.vue
|
||||
| Name | Type | Default | Description | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| actions | `Array<'clear' \| 'now'> \| null` | `['clear', 'now']` | Operations supported for the `date` type date picker. | |
|
||||
| default-calendar-start-time | `number` | `undefined` | Default panel calendar start month timestamp. | 2.38.1 |
|
||||
| format | `string` | `'yyyy-MM-dd'` | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). | |
|
||||
| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \| { type: 'month', year: number, month: number } \| { type: 'year', year: number } \| { type: 'quarter', year: number, quarter: number } \| { type: 'input' }) => boolean` | `() => false` | Validator of the date. | `detail` 2.37.1 |
|
||||
| placeholder | `string` | `'Select Date'` | Placeholder. | |
|
||||
@ -84,6 +85,7 @@ panel.vue
|
||||
| Name | Type | Default | Description | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| actions | `Array<'clear' \| 'now' \| 'confirm'> \| null` | `['clear', 'now', 'confirm']` | Operations supported for the `datetime` type date picker. | |
|
||||
| default-calendar-start-time | `number` | `undefined` | Default panel calendar start month timestamp. | 2.38.1 |
|
||||
| default-time | `string` | `undefined` | Default time of the selected date. It's format is `HH:mm:ss`. | 2.22.0 |
|
||||
| format | `string` | `'yyyy-MM-dd HH:mm:ss'` | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). | |
|
||||
| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \| { type: 'month', year: number, month: number } \| { type: 'year', year: number } \| { type: 'quarter', year: number, quarter: number } \| { type: 'input' }) => boolean` | `() => false` | Validator of the date. | `detail` 2.37.1 |
|
||||
@ -174,6 +176,7 @@ panel.vue
|
||||
| Name | Type | Default | Description | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| actions | `Array<'clear' \| 'now'> \| null` | `['clear', 'now']` | Operations supported for the `week` type date picker. | 2.37.0 |
|
||||
| default-calendar-start-time | `number` | `undefined` | Default panel calendar start month timestamp. | 2.38.1 |
|
||||
| format | `string` | `'yyyy-w'` for en-US, Locale specific. | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). | 2.37.0 |
|
||||
| placeholder | `string` | `'Select Week'` for en-US, Locale specific. | Placeholder. | 2.37.0 |
|
||||
| on-update:formatted-value | `(value: string \| null, timestampValue: number \| null) => void` | `undefined` | Formatted value changed callback. | 2.37.0 |
|
||||
|
@ -74,6 +74,7 @@ form-debug.vue
|
||||
| 名称 | 类型 | 默认值 | 说明 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| actions | `Array<'clear' \| 'now'> \| null` | `['clear', 'now']` | Date 类型的 Date Picker 中支持的操作 | |
|
||||
| default-calendar-start-time | `number` | `undefined` | 面板日历默认开始的月份时间戳 | 2.38.1 |
|
||||
| format | `string` | `'yyyy-MM-dd'` | 时间格式化字符串,详情见 [format](https://date-fns.org/v2.23.0/docs/format) | |
|
||||
| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \| { type: 'month', year: number, month: number } \| { type: 'year', year: number } \| { type: 'quarter', year: number, quarter: number } \| { type: 'input' }) => boolean` | `undefined` | 日期禁用的校验函数 | `detail` 2.37.1 |
|
||||
| placeholder | `string` | `'选择日期'` | 没有值时的占位信息 | |
|
||||
@ -85,6 +86,7 @@ form-debug.vue
|
||||
| 名称 | 类型 | 默认值 | 说明 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| actions | `Array<'clear' \| 'now' \| 'confirm'> \| null` | `['clear', 'now', 'confirm']` | DateTime 类型的 Date Picker 中支持的操作 | |
|
||||
| default-calendar-start-time | `number` | `undefined` | 面板日历默认开始的月份时间戳 | 2.38.1 |
|
||||
| default-time | `string` | `undefined` | 默认时间,格式为 `HH:mm:ss` | 2.22.0 |
|
||||
| format | `string` | `'yyyy-MM-dd HH:mm:ss'` | 时间格式化字符串,详情见 [format](https://date-fns.org/v2.23.0/docs/format) | |
|
||||
| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \| { type: 'month', year: number, month: number } \| { type: 'year', year: number } \| { type: 'quarter', year: number, quarter: number } \| { type: 'input' }) => boolean` | `undefined` | 日期禁用的校验函数 | `detail` 2.37.1 |
|
||||
@ -174,6 +176,7 @@ form-debug.vue
|
||||
| 名称 | 类型 | 默认值 | 说明 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| actions | `Array<'clear' \| 'now'> \| null` | `['clear', 'now']` | Week 类型的 Date Picker 中支持的操作 | 2.37.0 |
|
||||
| default-calendar-start-time | `number` | `undefined` | 面板日历默认开始的月份时间戳 | 2.38.1 |
|
||||
| format | `string` | 中文为 `'yyyy-w'`,随语言变化 | 时间格式化字符串,详情见 [format](https://date-fns.org/v2.23.0/docs/format) | 2.37.0 |
|
||||
| placeholder | `string` | 中文为 `'选择周'`,随语言变化 | 没有值时的占位信息 | 2.37.0 |
|
||||
| on-update:formatted-value | `(value: string \| null, timestampValue: number \| null) => void` | `undefined` | 受控数据更新时触发的回调函数 | 2.37.0 |
|
||||
|
@ -1027,7 +1027,12 @@ export default defineComponent({
|
||||
const renderPanel = (): VNode => {
|
||||
const { type } = this
|
||||
return type === 'datetime' ? (
|
||||
<DatetimePanel {...commonPanelProps}>{$slots}</DatetimePanel>
|
||||
<DatetimePanel
|
||||
{...commonPanelProps}
|
||||
defaultCalendarStartTime={this.defaultCalendarStartTime}
|
||||
>
|
||||
{$slots}
|
||||
</DatetimePanel>
|
||||
) : type === 'daterange' ? (
|
||||
<DaterangePanel
|
||||
{...commonPanelProps}
|
||||
@ -1053,7 +1058,11 @@ export default defineComponent({
|
||||
type === 'quarterrange' ? (
|
||||
<MonthRangePanel {...commonPanelProps} type={type} />
|
||||
) : (
|
||||
<DatePanel {...commonPanelProps} type={type}>
|
||||
<DatePanel
|
||||
{...commonPanelProps}
|
||||
type={type}
|
||||
defaultCalendarStartTime={this.defaultCalendarStartTime}
|
||||
>
|
||||
{$slots}
|
||||
</DatePanel>
|
||||
)
|
||||
|
@ -51,6 +51,7 @@ import { MONTH_ITEM_HEIGHT, START_YEAR } from '../config'
|
||||
|
||||
const useCalendarProps = {
|
||||
...usePanelCommonProps,
|
||||
defaultCalendarStartTime: Number,
|
||||
actions: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => ['now', 'clear', 'confirm']
|
||||
@ -100,7 +101,7 @@ function useCalendar (
|
||||
)
|
||||
const calendarValueRef = ref(
|
||||
props.value === null || Array.isArray(props.value)
|
||||
? Date.now()
|
||||
? props.defaultCalendarStartTime ?? Date.now()
|
||||
: props.value
|
||||
)
|
||||
const yearVlRef = ref<VirtualListInst | null>(null)
|
||||
|
@ -118,7 +118,7 @@ export default defineComponent({
|
||||
},
|
||||
common: { cubicBezierEaseInOut }
|
||||
} = themeRef.value
|
||||
const { width, height, type } = props
|
||||
const { type } = props
|
||||
return {
|
||||
'--n-bezier': cubicBezierEaseInOut,
|
||||
'--n-box-shadow': boxShadow,
|
||||
@ -129,8 +129,13 @@ export default defineComponent({
|
||||
'--n-color-hover': type === 'primary' ? colorPrimaryHover : colorHover,
|
||||
'--n-color-pressed':
|
||||
type === 'primary' ? colorPrimaryPressed : colorPressed,
|
||||
'--n-border-radius-square': borderRadiusSquare,
|
||||
position: floatButtonGroupInjection ? '' : props.position,
|
||||
'--n-border-radius-square': borderRadiusSquare
|
||||
}
|
||||
})
|
||||
const inlineStyle = computed<CSSProperties>(() => {
|
||||
const { width, height } = props
|
||||
return {
|
||||
position: floatButtonGroupInjection ? undefined : props.position,
|
||||
width: formatLength(width),
|
||||
minHeight: formatLength(height),
|
||||
...(floatButtonGroupInjection
|
||||
@ -169,10 +174,16 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
const themeClassHandle = inlineThemeDisabled
|
||||
? useThemeClass('float-button', undefined, cssVarsRef, props)
|
||||
? useThemeClass(
|
||||
'float-button',
|
||||
computed(() => props.type[0]),
|
||||
cssVarsRef,
|
||||
props
|
||||
)
|
||||
: undefined
|
||||
|
||||
return {
|
||||
inlineStyle,
|
||||
cssVars: inlineThemeDisabled ? undefined : cssVarsRef,
|
||||
mergedClsPrefix: mergedClsPrefixRef,
|
||||
mergedShape: mergedShapeRef,
|
||||
@ -195,6 +206,7 @@ export default defineComponent({
|
||||
mergedShowMenu,
|
||||
themeClass,
|
||||
$slots,
|
||||
inlineStyle,
|
||||
onRender
|
||||
} = this
|
||||
const dirs: DirectiveArguments = [[mousemoveoutside, this.handleMouseleave]]
|
||||
@ -208,7 +220,7 @@ export default defineComponent({
|
||||
mergedShowMenu && `${mergedClsPrefix}-float-button--show-menu`,
|
||||
themeClass
|
||||
]}
|
||||
style={cssVars as CSSProperties}
|
||||
style={[cssVars as CSSProperties, inlineStyle]}
|
||||
onMouseenter={this.Mouseenter}
|
||||
onMouseleave={this.handleMouseleave}
|
||||
onClick={this.handleClick}
|
||||
|
@ -81,16 +81,8 @@ export function useMenuChild (props: UseMenuChildProps): UseMenuChild {
|
||||
})
|
||||
const paddingLeftRef = computed(() => {
|
||||
if (horizontalRef.value) return undefined
|
||||
const {
|
||||
collapsedWidth,
|
||||
indent: propsIdent,
|
||||
rootIndent: propsRootIdent
|
||||
} = menuProps
|
||||
const { collapsedWidth, indent, rootIndent } = menuProps
|
||||
const { root, isGroup } = props
|
||||
// Fix overflow issue with `n-menu` `root-indent` `indent`, closes (#5616)
|
||||
const indent = propsIdent + 8
|
||||
const rootIndent =
|
||||
propsRootIdent === undefined ? undefined : propsRootIdent + 8
|
||||
const mergedRootIndent = rootIndent === undefined ? indent : rootIndent
|
||||
if (root) {
|
||||
if (mergedCollapsedRef.value) {
|
||||
@ -107,7 +99,8 @@ export function useMenuChild (props: UseMenuChildProps): UseMenuChild {
|
||||
if (NSubmenu && typeof NSubmenu.paddingLeftRef.value === 'number') {
|
||||
return (isGroup ? indent / 2 : indent) + NSubmenu.paddingLeftRef.value
|
||||
}
|
||||
return 8
|
||||
// Shouldn't reach here
|
||||
return 0
|
||||
})
|
||||
const iconMarginRightRef = computed(() => {
|
||||
const { collapsedWidth, indent, rootIndent } = menuProps
|
||||
|
@ -24,15 +24,15 @@ import image418 from './418'
|
||||
import image403 from './403'
|
||||
import style from './styles/index.cssr'
|
||||
|
||||
const iconMap = {
|
||||
403: image403,
|
||||
404: image404,
|
||||
418: image418,
|
||||
500: image500,
|
||||
info: <InfoIcon />,
|
||||
success: <SuccessIcon />,
|
||||
warning: <WarningIcon />,
|
||||
error: <ErrorIcon />
|
||||
const iconRenderMap = {
|
||||
403: () => image403,
|
||||
404: () => image404,
|
||||
418: () => image418,
|
||||
500: () => image500,
|
||||
info: () => <InfoIcon />,
|
||||
success: () => <SuccessIcon />,
|
||||
warning: () => <WarningIcon />,
|
||||
error: () => <ErrorIcon />
|
||||
}
|
||||
|
||||
export const resultProps = {
|
||||
@ -130,7 +130,7 @@ export default defineComponent({
|
||||
<div class={`${mergedClsPrefix}-result-icon`}>
|
||||
{$slots.icon?.() || (
|
||||
<NBaseIcon clsPrefix={mergedClsPrefix}>
|
||||
{{ default: () => iconMap[status] }}
|
||||
{{ default: () => iconRenderMap[status]() }}
|
||||
</NBaseIcon>
|
||||
)}
|
||||
</div>
|
||||
|
@ -9,13 +9,14 @@ import {
|
||||
toRef
|
||||
} from 'vue'
|
||||
import { off, on } from 'evtd'
|
||||
import { useMergedState } from 'vooks'
|
||||
import { type ExtractPublicPropTypes, resolveSlot, call } from '../../_utils'
|
||||
import useConfig from '../../_mixins/use-config'
|
||||
import { type ThemeProps, useTheme, useThemeClass } from '../../_mixins'
|
||||
import style from './styles/index.cssr'
|
||||
import { type ThemeProps, useTheme } from '../../_mixins'
|
||||
import { type SplitTheme, splitLight } from '../styles'
|
||||
import { useMergedState } from 'vooks'
|
||||
import { type SplitOnUpdateSize } from './types'
|
||||
|
||||
export const splitProps = {
|
||||
...(useTheme.props as ThemeProps<SplitTheme>),
|
||||
direction: {
|
||||
@ -172,12 +173,18 @@ export default defineComponent({
|
||||
nextSize = Math.max(newSize, props.min)
|
||||
}
|
||||
if (props.max) {
|
||||
nextSize = Math.min(newSize, props.max)
|
||||
nextSize = Math.min(nextSize, props.max)
|
||||
}
|
||||
doUpdateSize(nextSize)
|
||||
}
|
||||
|
||||
const themeClassHandle = inlineThemeDisabled
|
||||
? useThemeClass('float-button', undefined, cssVarsRef, props)
|
||||
: undefined
|
||||
|
||||
return {
|
||||
themeClass: themeClassHandle?.themeClass,
|
||||
onRender: themeClassHandle?.onRender,
|
||||
cssVars: inlineThemeDisabled ? undefined : cssVarsRef,
|
||||
resizeTriggerElRef,
|
||||
isDragging: isDraggingRef,
|
||||
@ -189,11 +196,13 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
render () {
|
||||
this.onRender?.()
|
||||
return (
|
||||
<div
|
||||
class={[
|
||||
`${this.mergedClsPrefix}-split`,
|
||||
`${this.mergedClsPrefix}-split--${this.direction}`
|
||||
`${this.mergedClsPrefix}-split--${this.direction}`,
|
||||
this.themeClass
|
||||
]}
|
||||
style={this.cssVars as CSSProperties}
|
||||
>
|
||||
|
@ -31,6 +31,7 @@ addable-debug.vue
|
||||
animation-debug.vue
|
||||
animationx-debug.vue
|
||||
none-debug.vue
|
||||
modal-debug.vue
|
||||
```
|
||||
|
||||
## API
|
||||
|
30
src/tabs/demos/zhCN/modal-debug.demo.vue
Normal file
30
src/tabs/demos/zhCN/modal-debug.demo.vue
Normal file
@ -0,0 +1,30 @@
|
||||
<markdown>
|
||||
# Modal debug
|
||||
</markdown>
|
||||
|
||||
<template>
|
||||
<n-button @click="show = true">
|
||||
Show modal
|
||||
</n-button>
|
||||
<n-modal v-model:show="show" preset="card">
|
||||
<n-tabs type="segment">
|
||||
<n-tab v-for="tab in tabs" :key="tab" :name="tab">
|
||||
I'm {{ tab }}
|
||||
</n-tab>
|
||||
</n-tabs>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
setup () {
|
||||
const showRef = ref(false)
|
||||
return {
|
||||
tabs: ['ccccc', 'dddddd'],
|
||||
show: showRef
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
@ -420,33 +420,35 @@ export default defineComponent({
|
||||
const segmentCapsuleElRef = ref<HTMLElement | null>(null)
|
||||
|
||||
function updateSegmentPosition ({
|
||||
disabledTransition
|
||||
transitionDisabled
|
||||
}: {
|
||||
disabledTransition: boolean
|
||||
transitionDisabled: boolean
|
||||
}): void {
|
||||
const tabsEl = tabsElRef.value
|
||||
if (!tabsEl) return
|
||||
disabledTransition && tabsEl.classList.add('transition-disabled')
|
||||
transitionDisabled && tabsEl.classList.add('transition-disabled')
|
||||
const activeTabEl = getCurrentEl()
|
||||
if (activeTabEl && segmentCapsuleElRef.value) {
|
||||
const rect = activeTabEl.getBoundingClientRect()
|
||||
// move segment capsule to match the position of the active tab
|
||||
segmentCapsuleElRef.value.style.width = `${rect.width}px`
|
||||
segmentCapsuleElRef.value.style.height = `${rect.height}px`
|
||||
segmentCapsuleElRef.value.style.width = `${activeTabEl.offsetWidth}px`
|
||||
segmentCapsuleElRef.value.style.height = `${activeTabEl.offsetHeight}px`
|
||||
segmentCapsuleElRef.value.style.transform = `translateX(${
|
||||
rect.left -
|
||||
tabsEl.getBoundingClientRect().left -
|
||||
activeTabEl.offsetLeft -
|
||||
tabsEl.offsetLeft -
|
||||
depx(getComputedStyle(tabsEl).paddingLeft)
|
||||
}px)`
|
||||
if (transitionDisabled) {
|
||||
void segmentCapsuleElRef.value.offsetWidth
|
||||
}
|
||||
}
|
||||
disabledTransition && tabsEl.classList.remove('transition-disabled')
|
||||
transitionDisabled && tabsEl.classList.remove('transition-disabled')
|
||||
}
|
||||
|
||||
watch([mergedValueRef], () => {
|
||||
if (props.type === 'segment') {
|
||||
void nextTick(() => {
|
||||
updateSegmentPosition({
|
||||
disabledTransition: false
|
||||
transitionDisabled: false
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -455,7 +457,7 @@ export default defineComponent({
|
||||
onMounted(() => {
|
||||
if (props.type === 'segment') {
|
||||
updateSegmentPosition({
|
||||
disabledTransition: true
|
||||
transitionDisabled: true
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -602,6 +604,12 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
const handleSegmentResize = (): void => {
|
||||
updateSegmentPosition({
|
||||
transitionDisabled: true
|
||||
})
|
||||
}
|
||||
|
||||
const cssVarsRef = computed(() => {
|
||||
const { value: size } = compitableSizeRef
|
||||
const { type } = props
|
||||
@ -716,6 +724,7 @@ export default defineComponent({
|
||||
animationDirection: animationDirectionRef,
|
||||
renderNameListRef,
|
||||
yScrollElRef,
|
||||
handleSegmentResize,
|
||||
onAnimationBeforeLeave,
|
||||
onAnimationEnter,
|
||||
onAnimationAfterEnter,
|
||||
@ -873,45 +882,53 @@ export default defineComponent({
|
||||
)
|
||||
)}
|
||||
{isSegment ? (
|
||||
<div class={`${mergedClsPrefix}-tabs-rail`} ref="tabsElRef">
|
||||
<div
|
||||
class={`${mergedClsPrefix}-tabs-capsule`}
|
||||
ref="segmentCapsuleElRef"
|
||||
>
|
||||
<div class={`${mergedClsPrefix}-tabs-wrapper`}>
|
||||
<div class={`${mergedClsPrefix}-tabs-tab`} />
|
||||
</div>
|
||||
</div>
|
||||
{showPane
|
||||
? tabPaneChildren.map((tabPaneVNode: any, index: number) => {
|
||||
renderNameListRef.value.push(
|
||||
tabPaneVNode.props.name as string | number
|
||||
)
|
||||
return (
|
||||
<Tab
|
||||
{...tabPaneVNode.props}
|
||||
internalCreatedByPane={true}
|
||||
internalLeftPadded={index !== 0}
|
||||
>
|
||||
{tabPaneVNode.children
|
||||
? {
|
||||
default: tabPaneVNode.children.tab
|
||||
}
|
||||
: undefined}
|
||||
</Tab>
|
||||
)
|
||||
})
|
||||
: tabChildren.map((tabVNode: any, index: number) => {
|
||||
renderNameListRef.value.push(
|
||||
tabVNode.props.name as string | number
|
||||
)
|
||||
if (index === 0) {
|
||||
return tabVNode
|
||||
} else {
|
||||
return createLeftPaddedTabVNode(tabVNode as VNode)
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
<VResizeObserver onResize={this.handleSegmentResize}>
|
||||
{{
|
||||
default: () => (
|
||||
<div class={`${mergedClsPrefix}-tabs-rail`} ref="tabsElRef">
|
||||
<div
|
||||
class={`${mergedClsPrefix}-tabs-capsule`}
|
||||
ref="segmentCapsuleElRef"
|
||||
>
|
||||
<div class={`${mergedClsPrefix}-tabs-wrapper`}>
|
||||
<div class={`${mergedClsPrefix}-tabs-tab`} />
|
||||
</div>
|
||||
</div>
|
||||
{showPane
|
||||
? tabPaneChildren.map(
|
||||
(tabPaneVNode: any, index: number) => {
|
||||
renderNameListRef.value.push(
|
||||
tabPaneVNode.props.name as string | number
|
||||
)
|
||||
return (
|
||||
<Tab
|
||||
{...tabPaneVNode.props}
|
||||
internalCreatedByPane={true}
|
||||
internalLeftPadded={index !== 0}
|
||||
>
|
||||
{tabPaneVNode.children
|
||||
? {
|
||||
default: tabPaneVNode.children.tab
|
||||
}
|
||||
: undefined}
|
||||
</Tab>
|
||||
)
|
||||
}
|
||||
)
|
||||
: tabChildren.map((tabVNode: any, index: number) => {
|
||||
renderNameListRef.value.push(
|
||||
tabVNode.props.name as string | number
|
||||
)
|
||||
if (index === 0) {
|
||||
return tabVNode
|
||||
} else {
|
||||
return createLeftPaddedTabVNode(tabVNode as VNode)
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</VResizeObserver>
|
||||
) : (
|
||||
<VResizeObserver onResize={this.handleNavResize}>
|
||||
{{
|
||||
|
@ -110,7 +110,7 @@ export default cB('tabs', `
|
||||
pointer-events: none;
|
||||
background-color: var(--n-tab-color-segment);
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .08);
|
||||
transition: 0.3s;
|
||||
transition: transform 0.3s var(--n-bezier);
|
||||
`),
|
||||
cB('tabs-tab-wrapper', `
|
||||
flex-basis: 0;
|
||||
@ -138,15 +138,16 @@ export default cB('tabs', `
|
||||
])
|
||||
]),
|
||||
cM('flex', [
|
||||
cB('tabs-nav', {
|
||||
width: '100%'
|
||||
}, [
|
||||
cB('tabs-wrapper', {
|
||||
width: '100%'
|
||||
}, [
|
||||
cB('tabs-tab', {
|
||||
marginRight: 0
|
||||
})
|
||||
cB('tabs-nav', `
|
||||
width: 100%;
|
||||
position: relative;
|
||||
`, [
|
||||
cB('tabs-wrapper', `
|
||||
width: 100%;
|
||||
`, [
|
||||
cB('tabs-tab', `
|
||||
margin-right: 0;
|
||||
`)
|
||||
])
|
||||
])
|
||||
]),
|
||||
|
@ -41,6 +41,7 @@ debug.vue
|
||||
| indeterminate-keys | `Array<string \| number>` | `undefined` | Indeterminate keys of the tree. | |
|
||||
| filterable | `boolean` | `false` | Whether to show a filter. | |
|
||||
| filter | `(pattern: string, option: TreeSelectOption) => boolean` | - | Filter function. | |
|
||||
| get-children | `(option: any) => unknown` | `undefined` | Get children of the option. | 2.38.1 |
|
||||
| key-field | `string` | `'key'` | The key field used for `TreeSelectOption`. | |
|
||||
| label-field | `string` | `'label'` | The label field used for `TreeSelectOption`. | |
|
||||
| disabled-field | `string` | `'disabled'` | The disabled field used for `TreeSelectOption`. | 2.32.2 |
|
||||
|
@ -44,6 +44,7 @@ render-debug.vue
|
||||
| indeterminate-keys | `string \| number` | `undefined` | 部分选中选项的 key | |
|
||||
| filterable | `boolean` | `false` | 是否可过滤 | |
|
||||
| filter | `(pattern: string, option: TreeSelectOption) => boolean` | - | 过滤器函数 | |
|
||||
| get-children | `(option: any) => unknown` | `undefined` | 获取当前选项的子选项 | 2.38.1 |
|
||||
| key-field | `string` | `'key'` | 替代 `TreeSelectOption` 中的 key 字段名 | |
|
||||
| label-field | `string` | `'label'` | 替代 `TreeSelectOption` 中的 label 字段名 | |
|
||||
| disabled-field | `string` | `'disabled'` | 替代 `TreeSelectOption` 中的 disabled 字段名 | 2.32.2 |
|
||||
|
@ -29,7 +29,8 @@ import {
|
||||
type Key,
|
||||
type InternalTreeInst,
|
||||
type TreeOption,
|
||||
type TreeOverrideNodeClickBehaviorReturn
|
||||
type TreeOverrideNodeClickBehaviorReturn,
|
||||
type GetChildren
|
||||
} from '../../tree/src/interface'
|
||||
import type { SelectBaseOption, SelectOption } from '../../select/src/interface'
|
||||
import { createTreeMateOptions, treeSharedProps } from '../../tree/src/Tree'
|
||||
@ -160,6 +161,7 @@ export const treeSelectProps = {
|
||||
watchProps: Array as PropType<
|
||||
Array<'defaultCheckedKeys' | 'defaultSelectedKeys' | 'defaultExpandedKeys'>
|
||||
>,
|
||||
getChildren: Function as PropType<GetChildren>,
|
||||
onBlur: Function as PropType<(e: FocusEvent) => void>,
|
||||
onFocus: Function as PropType<(e: FocusEvent) => void>,
|
||||
onLoad: Function as PropType<OnLoad>,
|
||||
@ -943,6 +945,7 @@ export default defineComponent({
|
||||
showIrrelevantNodes={false}
|
||||
animated={false}
|
||||
pattern={this.pattern}
|
||||
getChildren={this.getChildren}
|
||||
filter={this.mergedFilter}
|
||||
data={options}
|
||||
cancelable={multiple}
|
||||
|
@ -1 +1 @@
|
||||
export default '2.38.0'
|
||||
export default '2.38.1'
|
||||
|
Loading…
x
Reference in New Issue
Block a user