Merge remote-tracking branch 'origin/main' into feat-v3.3
commit
d64c6a8d53
|
@ -3,18 +3,21 @@ const pkg = require('../../package.json');
|
||||||
const { parseAndWrite } = require('./lib/index.js');
|
const { parseAndWrite } = require('./lib/index.js');
|
||||||
const rootPath = path.resolve(__dirname, '../../');
|
const rootPath = path.resolve(__dirname, '../../');
|
||||||
|
|
||||||
try {
|
|
||||||
parseAndWrite({
|
parseAndWrite({
|
||||||
version: pkg.version,
|
version: pkg.version,
|
||||||
name: 'ant-design-vue',
|
name: 'ant-design-vue',
|
||||||
path: path.resolve(rootPath, './components'),
|
path: path.resolve(rootPath, './components'),
|
||||||
|
typingsPath: path.resolve(rootPath, './typings/global.d.ts'),
|
||||||
// default match lang
|
// default match lang
|
||||||
test: /en-US\.md/,
|
test: /en-US\.md/,
|
||||||
outputDir: path.resolve(rootPath, './vetur'),
|
outputDir: path.resolve(rootPath, './vetur'),
|
||||||
tagPrefix: 'a-',
|
tagPrefix: 'a-',
|
||||||
});
|
})
|
||||||
|
.then(result => {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('generator types success');
|
console.log(`generator types success: ${result} tags generated`);
|
||||||
} catch (e) {
|
})
|
||||||
console.error('generator types error', e);
|
.catch(error => {
|
||||||
}
|
console.error('generator types error', error);
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
|
|
@ -34,14 +34,19 @@ function parserProps(tag: VueTag, line: any) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatter(articals: Articals, componentName: string, tagPrefix = '') {
|
export function formatter(
|
||||||
|
articals: Articals,
|
||||||
|
componentName: string,
|
||||||
|
kebabComponentName: string,
|
||||||
|
tagPrefix = '',
|
||||||
|
) {
|
||||||
if (!articals.length) {
|
if (!articals.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tags: VueTag[] = [];
|
const tags: VueTag[] = [];
|
||||||
const tag: VueTag = {
|
const tag: VueTag = {
|
||||||
name: getComponentName(componentName, tagPrefix),
|
name: kebabComponentName,
|
||||||
slots: [],
|
slots: [],
|
||||||
events: [],
|
events: [],
|
||||||
attributes: [],
|
attributes: [],
|
||||||
|
@ -80,9 +85,13 @@ export function formatter(articals: Articals, componentName: string, tagPrefix =
|
||||||
}
|
}
|
||||||
|
|
||||||
// 额外的子组件
|
// 额外的子组件
|
||||||
if (tableTitle.includes(componentName) && !tableTitle.includes('events')) {
|
if (
|
||||||
|
tableTitle.includes(componentName) &&
|
||||||
|
!tableTitle.includes('events') &&
|
||||||
|
!tableTitle.includes('()')
|
||||||
|
) {
|
||||||
const childTag: VueTag = {
|
const childTag: VueTag = {
|
||||||
name: getComponentName(tableTitle.replace('.', ''), tagPrefix),
|
name: getComponentName(tableTitle.replaceAll('.', '').replaceAll('/', ''), tagPrefix),
|
||||||
slots: [],
|
slots: [],
|
||||||
events: [],
|
events: [],
|
||||||
attributes: [],
|
attributes: [],
|
||||||
|
@ -93,6 +102,7 @@ export function formatter(articals: Articals, componentName: string, tagPrefix =
|
||||||
tags.push(childTag);
|
tags.push(childTag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 额外的子组件事件
|
// 额外的子组件事件
|
||||||
if (tableTitle.includes(componentName) && tableTitle.includes('events')) {
|
if (tableTitle.includes(componentName) && tableTitle.includes('events')) {
|
||||||
const childTagName = getComponentName(
|
const childTagName = getComponentName(
|
||||||
|
|
|
@ -1,52 +1,91 @@
|
||||||
import glob from 'fast-glob';
|
import glob from 'fast-glob';
|
||||||
import { join, dirname } from 'path';
|
import { dirname, join } from 'path';
|
||||||
import { mdParser } from './parser';
|
import { mdParser } from './parser';
|
||||||
import { formatter } from './formatter';
|
import { formatter } from './formatter';
|
||||||
import { genWebTypes } from './web-types';
|
import { genWebTypes } from './web-types';
|
||||||
import { readFileSync, outputFileSync } from 'fs-extra';
|
import { outputFileSync, readFileSync } from 'fs-extra';
|
||||||
import type { Options, VueTag } from './type';
|
import type { Options, VueTag } from './type';
|
||||||
import { normalizePath, getComponentName } from './utils';
|
import { getComponentName, normalizePath, toKebabCase } from './utils';
|
||||||
import { genVeturTags, genVeturAttributes } from './vetur';
|
import { genVeturAttributes, genVeturTags } from './vetur';
|
||||||
|
|
||||||
async function readMarkdown(options: Options) {
|
async function readMarkdown(options: Options): Promise<Map<String, VueTag>> {
|
||||||
// const mds = await glob(normalizePath(`${options.path}/**/*.md`))
|
const mdPaths = await glob(normalizePath(`${options.path}/**/*.md`));
|
||||||
const mds = await glob(normalizePath(`${options.path}/**/*.md`));
|
const data = mdPaths
|
||||||
return mds
|
|
||||||
.filter(md => options.test.test(md))
|
.filter(md => options.test.test(md))
|
||||||
.map(path => {
|
.map(path => {
|
||||||
const docPath = dirname(path);
|
const docPath = dirname(path);
|
||||||
const componentName = docPath.substring(docPath.lastIndexOf('/') + 1);
|
const kebabComponentName =
|
||||||
return {
|
options.tagPrefix + docPath.substring(docPath.lastIndexOf('/') + 1) || '';
|
||||||
componentName: getComponentName(componentName || ''),
|
const componentName = getComponentName(docPath.substring(docPath.lastIndexOf('/') + 1) || '');
|
||||||
md: readFileSync(path, 'utf-8'),
|
const fileContent = readFileSync(path, 'utf-8');
|
||||||
};
|
return formatter(mdParser(fileContent), componentName, kebabComponentName, options.tagPrefix);
|
||||||
});
|
})
|
||||||
|
.filter(item => item) as VueTag[][];
|
||||||
|
const tags: Map<String, VueTag> = new Map();
|
||||||
|
data.flatMap(item => item).forEach(mergedTag => mergeTag(tags, mergedTag));
|
||||||
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parseAndWrite(options: Options) {
|
function readTypings(options: Options): Map<String, VueTag> {
|
||||||
|
const tags: Map<String, VueTag> = new Map();
|
||||||
|
const fileContent = readFileSync(options.typingsPath, 'utf-8');
|
||||||
|
fileContent
|
||||||
|
.split('\n')
|
||||||
|
.filter(line => line && line.includes('typeof'))
|
||||||
|
.map(line => {
|
||||||
|
const l = line.trim();
|
||||||
|
return toKebabCase(l.substring(0, l.indexOf(':')));
|
||||||
|
})
|
||||||
|
.forEach(tagName =>
|
||||||
|
tags.set(tagName, {
|
||||||
|
name: tagName,
|
||||||
|
slots: [],
|
||||||
|
events: [],
|
||||||
|
attributes: [],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeTag(tags: Map<String, VueTag>, mergedTag: VueTag) {
|
||||||
|
const tagName = mergedTag.name;
|
||||||
|
const vueTag = tags.get(tagName);
|
||||||
|
if (vueTag) {
|
||||||
|
vueTag.slots = [...vueTag.slots, ...mergedTag.slots];
|
||||||
|
vueTag.events = [...vueTag.events, ...mergedTag.events];
|
||||||
|
vueTag.attributes = [...vueTag.attributes, ...mergedTag.attributes];
|
||||||
|
} else {
|
||||||
|
tags.set(tagName, mergedTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeTags(mergedTagsArr: Map<String, VueTag>[]): VueTag[] {
|
||||||
|
if (mergedTagsArr.length === 1) return [...mergedTagsArr[0].values()];
|
||||||
|
const tags: Map<String, VueTag> = new Map();
|
||||||
|
if (mergedTagsArr.length === 0) return [];
|
||||||
|
mergedTagsArr.forEach(mergedTags => {
|
||||||
|
mergedTags.forEach(mergedTag => mergeTag(tags, mergedTag));
|
||||||
|
});
|
||||||
|
return [...tags.values()];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parseAndWrite(options: Options): Promise<Number> {
|
||||||
if (!options.outputDir) {
|
if (!options.outputDir) {
|
||||||
throw new Error('outputDir can not be empty.');
|
throw new Error('outputDir can not be empty.');
|
||||||
}
|
}
|
||||||
|
const tagsFromMarkdown = await readMarkdown(options);
|
||||||
const docs = await readMarkdown(options);
|
const tagsFromTypings = await readTypings(options);
|
||||||
const datas = docs
|
const tags = mergeTags([tagsFromMarkdown, tagsFromTypings]);
|
||||||
.map(doc => formatter(mdParser(doc.md), doc.componentName, options.tagPrefix))
|
|
||||||
.filter(item => item) as VueTag[][];
|
|
||||||
const tags: VueTag[] = [];
|
|
||||||
datas.forEach(arr => {
|
|
||||||
tags.push(...arr);
|
|
||||||
});
|
|
||||||
|
|
||||||
const webTypes = genWebTypes(tags, options);
|
const webTypes = genWebTypes(tags, options);
|
||||||
const veturTags = genVeturTags(tags);
|
const veturTags = genVeturTags(tags);
|
||||||
const veturAttributes = genVeturAttributes(tags);
|
const veturAttributes = genVeturAttributes(tags);
|
||||||
|
|
||||||
outputFileSync(join(options.outputDir, 'tags.json'), JSON.stringify(veturTags, null, 2));
|
outputFileSync(join(options.outputDir, 'tags.json'), JSON.stringify(veturTags, null, 2));
|
||||||
outputFileSync(
|
outputFileSync(
|
||||||
join(options.outputDir, 'attributes.json'),
|
join(options.outputDir, 'attributes.json'),
|
||||||
JSON.stringify(veturAttributes, null, 2),
|
JSON.stringify(veturAttributes, null, 2),
|
||||||
);
|
);
|
||||||
outputFileSync(join(options.outputDir, 'web-types.json'), JSON.stringify(webTypes, null, 2));
|
outputFileSync(join(options.outputDir, 'web-types.json'), JSON.stringify(webTypes, null, 2));
|
||||||
|
return tags.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { parseAndWrite };
|
export default { parseAndWrite };
|
||||||
|
|
|
@ -27,7 +27,7 @@ function readLine(input: string) {
|
||||||
function splitTableLine(line: string) {
|
function splitTableLine(line: string) {
|
||||||
line = line.replace(/\\\|/g, 'JOIN');
|
line = line.replace(/\\\|/g, 'JOIN');
|
||||||
|
|
||||||
const items = line.split('|').map(item => item.trim().replace('JOIN', '|'));
|
const items = line.split('|').map(item => item.trim().replaceAll('JOIN', '|'));
|
||||||
|
|
||||||
// remove pipe character on both sides
|
// remove pipe character on both sides
|
||||||
items.pop();
|
items.pop();
|
||||||
|
@ -77,11 +77,6 @@ export function mdParser(input: string): Articals {
|
||||||
const artical = [];
|
const artical = [];
|
||||||
let start = 0;
|
let start = 0;
|
||||||
const end = input.length;
|
const end = input.length;
|
||||||
// artical.push({
|
|
||||||
// type: 'title',
|
|
||||||
// content: title,
|
|
||||||
// level: 0,
|
|
||||||
// });
|
|
||||||
|
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
const target = input.substr(start);
|
const target = input.substr(start);
|
||||||
|
@ -108,6 +103,5 @@ export function mdParser(input: string): Articals {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// artical[0].content = title
|
|
||||||
return artical;
|
return artical;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,9 @@ export type VueAttribute = {
|
||||||
|
|
||||||
export type VueTag = {
|
export type VueTag = {
|
||||||
name: string;
|
name: string;
|
||||||
slots?: VueSlot[];
|
slots: VueSlot[];
|
||||||
events?: VueEvent[];
|
events: VueEvent[];
|
||||||
attributes?: VueAttribute[];
|
attributes: VueAttribute[];
|
||||||
description?: string;
|
description?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ export type VeturResult = {
|
||||||
export type Options = {
|
export type Options = {
|
||||||
name: string;
|
name: string;
|
||||||
path: PathLike;
|
path: PathLike;
|
||||||
|
typingsPath: PathLike;
|
||||||
test: RegExp;
|
test: RegExp;
|
||||||
version: string;
|
version: string;
|
||||||
outputDir?: string;
|
outputDir?: string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// myName -> my-name
|
// myName -> my-name
|
||||||
export function toKebabCase(input: string): string {
|
export function toKebabCase(camel: string): string {
|
||||||
return input.replace(/[A-Z]/g, (val, index) => (index === 0 ? '' : '-') + val.toLowerCase());
|
return camel.replace(/((?<=[a-z\d])[A-Z]|(?<=[A-Z\d])[A-Z](?=[a-z]))/g, '-$1').toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
// name `v2.0.0` -> name
|
// name `v2.0.0` -> name
|
||||||
|
|
|
@ -3,11 +3,12 @@ import type { VNode, VNodeProps } from 'vue';
|
||||||
import { cloneVNode } from 'vue';
|
import { cloneVNode } from 'vue';
|
||||||
import warning from './warning';
|
import warning from './warning';
|
||||||
import type { RefObject } from './createRef';
|
import type { RefObject } from './createRef';
|
||||||
|
type NodeProps = Record<string, any> &
|
||||||
|
Omit<VNodeProps, 'ref'> & { ref?: VNodeProps['ref'] | RefObject };
|
||||||
|
|
||||||
export function cloneElement<T, U>(
|
export function cloneElement<T, U>(
|
||||||
vnode: VNode<T, U> | VNode<T, U>[],
|
vnode: VNode<T, U> | VNode<T, U>[],
|
||||||
nodeProps: Record<string, any> &
|
nodeProps: NodeProps = {},
|
||||||
Omit<VNodeProps, 'ref'> & { ref?: VNodeProps['ref'] | RefObject } = {},
|
|
||||||
override = true,
|
override = true,
|
||||||
mergeRef = false,
|
mergeRef = false,
|
||||||
): VNode<T, U> {
|
): VNode<T, U> {
|
||||||
|
@ -29,3 +30,20 @@ export function cloneElement<T, U>(
|
||||||
export function cloneVNodes(vnodes, nodeProps = {}, override = true) {
|
export function cloneVNodes(vnodes, nodeProps = {}, override = true) {
|
||||||
return vnodes.map(vnode => cloneElement(vnode, nodeProps, override));
|
return vnodes.map(vnode => cloneElement(vnode, nodeProps, override));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function deepCloneElement<T, U>(
|
||||||
|
vnode: VNode<T, U> | VNode<T, U>[],
|
||||||
|
nodeProps: NodeProps = {},
|
||||||
|
override = true,
|
||||||
|
mergeRef = false,
|
||||||
|
) {
|
||||||
|
if (Array.isArray(vnode)) {
|
||||||
|
return vnode.map(item => deepCloneElement(item, nodeProps, override, mergeRef));
|
||||||
|
} else {
|
||||||
|
const cloned = cloneElement(vnode, nodeProps, override, mergeRef);
|
||||||
|
if (Array.isArray(cloned.children)) {
|
||||||
|
cloned.children = deepCloneElement(cloned.children as VNode<T, U>[]);
|
||||||
|
}
|
||||||
|
return cloned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -173,7 +173,7 @@ The following APIs are shared by DatePicker, RangePicker.
|
||||||
| disabledTime | To specify the time that cannot be selected | function(date: dayjs, partial: `start` \| `end`) | - | |
|
| disabledTime | To specify the time that cannot be selected | function(date: dayjs, partial: `start` \| `end`) | - | |
|
||||||
| format | To set the date format, refer to [dayjs](https://day.js.org/). When an array is provided, all values are used for parsing and first value is used for formatting | string \| string\[] | `YYYY-MM-DD HH:mm:ss` | |
|
| format | To set the date format, refer to [dayjs](https://day.js.org/). When an array is provided, all values are used for parsing and first value is used for formatting | string \| string\[] | `YYYY-MM-DD HH:mm:ss` | |
|
||||||
| ranges | The preseted ranges for quick selection | { \[range: string]: [dayjs](https://day.js.org/)\[] } \| { \[range: string]: () => [dayjs](https://day.js.org/)\[] } | - | |
|
| ranges | The preseted ranges for quick selection | { \[range: string]: [dayjs](https://day.js.org/)\[] } \| { \[range: string]: () => [dayjs](https://day.js.org/)\[] } | - | |
|
||||||
| renderExtraFooter | Render extra footer in panel | v-slot:renderExtraFooter | - | |
|
| renderExtraFooter | Render extra footer in panel | v-slot:renderExtraFooter="mode" | - | |
|
||||||
| separator | Set separator between inputs | string \| v-slot:separator | `<SwapRightOutlined />` | |
|
| separator | Set separator between inputs | string \| v-slot:separator | `<SwapRightOutlined />` | |
|
||||||
| showTime | To provide an additional time selection | object \| boolean | [TimePicker Options](/components/time-picker/#API) | |
|
| showTime | To provide an additional time selection | object \| boolean | [TimePicker Options](/components/time-picker/#API) | |
|
||||||
| showTime.defaultValue | To set default time of selected date, [demo](#components-date-picker-demo-disabled-date) | [dayjs](https://day.js.org/)\[] | \[dayjs(), dayjs()] | |
|
| showTime.defaultValue | To set default time of selected date, [demo](#components-date-picker-demo-disabled-date) | [dayjs](https://day.js.org/)\[] | \[dayjs(), dayjs()] | |
|
||||||
|
|
|
@ -174,7 +174,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/RT_USzA48/DatePicker.svg
|
||||||
| disabledTime | 不可选择的时间 | function(date: dayjs, partial: `start` \| `end`) | - | |
|
| disabledTime | 不可选择的时间 | function(date: dayjs, partial: `start` \| `end`) | - | |
|
||||||
| format | 展示的日期格式 | string | `YYYY-MM-DD HH:mm:ss` | |
|
| format | 展示的日期格式 | string | `YYYY-MM-DD HH:mm:ss` | |
|
||||||
| ranges | 预设时间范围快捷选择 | { \[range: string]: [dayjs](https://day.js.org/)\[] } \| { \[range: string]: () => [dayjs](https://day.js.org/)\[] } | - | |
|
| ranges | 预设时间范围快捷选择 | { \[range: string]: [dayjs](https://day.js.org/)\[] } \| { \[range: string]: () => [dayjs](https://day.js.org/)\[] } | - | |
|
||||||
| renderExtraFooter | 在面板中添加额外的页脚 | () => React.ReactNode | - | |
|
| renderExtraFooter | 在面板中添加额外的页脚 | v-slot:renderExtraFooter="mode" | - | |
|
||||||
| separator | 设置分隔符 | string \| v-slot:separator | `<SwapRightOutlined />` | |
|
| separator | 设置分隔符 | string \| v-slot:separator | `<SwapRightOutlined />` | |
|
||||||
| showTime | 增加时间选择功能 | Object\|boolean | [TimePicker Options](/components/time-picker/#API) | |
|
| showTime | 增加时间选择功能 | Object\|boolean | [TimePicker Options](/components/time-picker/#API) | |
|
||||||
| showTime.defaultValue | 设置用户选择日期时默认的时分秒,[例子](#components-date-picker-demo-disabled-date) | [dayjs](https://day.js.org/)\[] | \[dayjs(), dayjs()] | |
|
| showTime.defaultValue | 设置用户选择日期时默认的时分秒,[例子](#components-date-picker-demo-disabled-date) | [dayjs](https://day.js.org/)\[] | \[dayjs(), dayjs()] | |
|
||||||
|
|
|
@ -56,7 +56,7 @@ or use `valueFormat` to format.
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item name="time-picker" label="TimePicker" v-bind="config">
|
<a-form-item name="time-picker" label="TimePicker" v-bind="config">
|
||||||
<a-time-picker v-model:value="formState['time-picker']" value-format="HH:mm:ss" />
|
<a-time-picker v-model:value="formState['time-picker']" format="HH:mm:ss" value-format="HH:mm:ss" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:wrapper-col="{
|
:wrapper-col="{
|
||||||
|
|
|
@ -60,8 +60,8 @@ Select component to select value from options.
|
||||||
| placement | The position where the selection box pops up | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | 3.3.0 |
|
| placement | The position where the selection box pops up | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | 3.3.0 |
|
||||||
| removeIcon | The custom remove icon | VNode \| slot | - | |
|
| removeIcon | The custom remove icon | VNode \| slot | - | |
|
||||||
| searchValue | The current input "search" text | string | - | |
|
| searchValue | The current input "search" text | string | - | |
|
||||||
| showArrow | Whether to show the drop-down arrow | boolean | true | |
|
| showArrow | Whether to show the drop-down arrow | boolean | single:true, multiple:false | |
|
||||||
| showSearch | Whether show search input in single mode. | boolean | false | |
|
| showSearch | Whether select is searchable | boolean | single:false, multiple:true | |
|
||||||
| size | Size of Select input. `default` `large` `small` | string | default | |
|
| size | Size of Select input. `default` `large` `small` | string | default | |
|
||||||
| status | Set validation status | 'error' \| 'warning' | - | 3.3.0 |
|
| status | Set validation status | 'error' \| 'warning' | - | 3.3.0 |
|
||||||
| suffixIcon | The custom suffix icon | VNode \| slot | - | |
|
| suffixIcon | The custom suffix icon | VNode \| slot | - | |
|
||||||
|
|
|
@ -60,8 +60,8 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
|
||||||
| placement | 选择框弹出的位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | 3.3.0 |
|
| placement | 选择框弹出的位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | 3.3.0 |
|
||||||
| removeIcon | 自定义的多选框清除图标 | VNode \| slot | - | |
|
| removeIcon | 自定义的多选框清除图标 | VNode \| slot | - | |
|
||||||
| searchValue | 控制搜索文本 | string | - | |
|
| searchValue | 控制搜索文本 | string | - | |
|
||||||
| showArrow | 是否显示下拉小箭头 | boolean | true | |
|
| showArrow | 是否显示下拉小箭头 | boolean | 单选为true,多选为false | |
|
||||||
| showSearch | 使单选模式可搜索 | boolean | false | |
|
| showSearch | 配置是否可搜索 | boolean | 单选为false,多选为true | |
|
||||||
| size | 选择框大小,可选 `large` `small` | string | default | |
|
| size | 选择框大小,可选 `large` `small` | string | default | |
|
||||||
| status | 设置校验状态 | 'error' \| 'warning' | - | 3.3.0 |
|
| status | 设置校验状态 | 'error' \| 'warning' | - | 3.3.0 |
|
||||||
| suffixIcon | 自定义的选择框后缀图标 | VNode \| slot | - | |
|
| suffixIcon | 自定义的选择框后缀图标 | VNode \| slot | - | |
|
||||||
|
|
|
@ -46,9 +46,10 @@ export default defineComponent<NoticeProps>({
|
||||||
] as any,
|
] as any,
|
||||||
setup(props, { attrs, slots }) {
|
setup(props, { attrs, slots }) {
|
||||||
let closeTimer: any;
|
let closeTimer: any;
|
||||||
const duration = computed(() => (props.duration === undefined ? 1.5 : props.duration));
|
let isUnMounted = false;
|
||||||
|
const duration = computed(() => (props.duration === undefined ? 4.5 : props.duration));
|
||||||
const startCloseTimer = () => {
|
const startCloseTimer = () => {
|
||||||
if (duration.value) {
|
if (duration.value && !isUnMounted) {
|
||||||
closeTimer = setTimeout(() => {
|
closeTimer = setTimeout(() => {
|
||||||
close();
|
close();
|
||||||
}, duration.value * 1000);
|
}, duration.value * 1000);
|
||||||
|
@ -79,6 +80,7 @@ export default defineComponent<NoticeProps>({
|
||||||
startCloseTimer();
|
startCloseTimer();
|
||||||
});
|
});
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
isUnMounted = true;
|
||||||
clearCloseTimer();
|
clearCloseTimer();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { createVNode } from 'vue';
|
import { createVNode } from 'vue';
|
||||||
import classnames from '../_util/classNames';
|
import classnames from '../_util/classNames';
|
||||||
import { cloneElement } from '../_util/vnode';
|
|
||||||
import { flattenChildren } from '../_util/props-util';
|
import { flattenChildren } from '../_util/props-util';
|
||||||
import { lazyStartIndex, lazyEndIndex, getPreClones } from './utils/innerSliderUtils';
|
import { lazyStartIndex, lazyEndIndex, getPreClones } from './utils/innerSliderUtils';
|
||||||
|
import { deepCloneElement } from '../_util/vnode';
|
||||||
|
|
||||||
// given specifications/props for a slide, fetch all the classes that need to be applied to the slide
|
// given specifications/props for a slide, fetch all the classes that need to be applied to the slide
|
||||||
const getSlideClasses = spec => {
|
const getSlideClasses = spec => {
|
||||||
|
@ -84,7 +84,6 @@ const renderSlides = function (spec, children) {
|
||||||
const childrenCount = children.length;
|
const childrenCount = children.length;
|
||||||
const startIndex = lazyStartIndex(spec);
|
const startIndex = lazyStartIndex(spec);
|
||||||
const endIndex = lazyEndIndex(spec);
|
const endIndex = lazyEndIndex(spec);
|
||||||
|
|
||||||
children.forEach((elem, index) => {
|
children.forEach((elem, index) => {
|
||||||
let child;
|
let child;
|
||||||
const childOnClickOptions = {
|
const childOnClickOptions = {
|
||||||
|
@ -105,7 +104,7 @@ const renderSlides = function (spec, children) {
|
||||||
let slideClasses = getSlideClasses({ ...spec, index });
|
let slideClasses = getSlideClasses({ ...spec, index });
|
||||||
// push a cloned element of the desired slide
|
// push a cloned element of the desired slide
|
||||||
slides.push(
|
slides.push(
|
||||||
cloneElement(child, {
|
deepCloneElement(child, {
|
||||||
key: 'original' + getKey(child, index),
|
key: 'original' + getKey(child, index),
|
||||||
tabindex: '-1',
|
tabindex: '-1',
|
||||||
'data-index': index,
|
'data-index': index,
|
||||||
|
@ -131,7 +130,7 @@ const renderSlides = function (spec, children) {
|
||||||
}
|
}
|
||||||
slideClasses = getSlideClasses({ ...spec, index: key });
|
slideClasses = getSlideClasses({ ...spec, index: key });
|
||||||
preCloneSlides.push(
|
preCloneSlides.push(
|
||||||
cloneElement(child, {
|
deepCloneElement(child, {
|
||||||
key: 'precloned' + getKey(child, key),
|
key: 'precloned' + getKey(child, key),
|
||||||
class: classnames(slideClasses, slideClass),
|
class: classnames(slideClasses, slideClass),
|
||||||
tabindex: '-1',
|
tabindex: '-1',
|
||||||
|
@ -155,7 +154,7 @@ const renderSlides = function (spec, children) {
|
||||||
}
|
}
|
||||||
slideClasses = getSlideClasses({ ...spec, index: key });
|
slideClasses = getSlideClasses({ ...spec, index: key });
|
||||||
postCloneSlides.push(
|
postCloneSlides.push(
|
||||||
cloneElement(child, {
|
deepCloneElement(child, {
|
||||||
key: 'postcloned' + getKey(child, key),
|
key: 'postcloned' + getKey(child, key),
|
||||||
tabindex: '-1',
|
tabindex: '-1',
|
||||||
'data-index': key,
|
'data-index': key,
|
||||||
|
@ -182,6 +181,7 @@ const renderSlides = function (spec, children) {
|
||||||
|
|
||||||
const Track = (_, { attrs, slots }) => {
|
const Track = (_, { attrs, slots }) => {
|
||||||
const slides = renderSlides(attrs, flattenChildren(slots?.default()));
|
const slides = renderSlides(attrs, flattenChildren(slots?.default()));
|
||||||
|
// const slides = renderSlides(attrs, slots?.default);
|
||||||
const { onMouseenter, onMouseover, onMouseleave } = attrs;
|
const { onMouseenter, onMouseover, onMouseleave } = attrs;
|
||||||
const mouseEvents = { onMouseenter, onMouseover, onMouseleave };
|
const mouseEvents = { onMouseenter, onMouseover, onMouseleave };
|
||||||
const trackProps = {
|
const trackProps = {
|
||||||
|
|
|
@ -230,7 +230,7 @@ export default defineComponent<StickyScrollBarProps>({
|
||||||
onMousedown={onMouseDown}
|
onMousedown={onMouseDown}
|
||||||
ref={scrollBarRef}
|
ref={scrollBarRef}
|
||||||
class={classNames(`${prefixCls}-sticky-scroll-bar`, {
|
class={classNames(`${prefixCls}-sticky-scroll-bar`, {
|
||||||
[`${prefixCls}-sticky-scroll-bar-active`]: isActive,
|
[`${prefixCls}-sticky-scroll-bar-active`]: isActive.value,
|
||||||
})}
|
})}
|
||||||
style={{
|
style={{
|
||||||
width: `${scrollBarWidth.value}px`,
|
width: `${scrollBarWidth.value}px`,
|
||||||
|
|
Loading…
Reference in New Issue